/* ============================================================================
   scrollcraft.css: o piso de bom gosto
   ----------------------------------------------------------------------------
   Duas camadas, e a divisão importa:

     TOKENS   o que você sobrescreve por marca. Papéis de cor, a escala
              tipográfica, a escala de espaçamento, elevação, movimento. Uma
              marca são ~12 valores.
     DEVICES  o que o engine controla. Não reestilize ao seu gosto; eles são
              o mecanismo. Estilize a sua própria marcação em vez disso.

   Nada aqui desenha um "componente". Não há classes de card, badge ou pill,
   porque uma folha de estilo que traz isso é o jeito de toda página construída
   sobre ela acabar com as mesmas formas. Você recebe um piso e um vocabulário;
   a composição é sua.
   ========================================================================== */

/* ---------------------------------------------------------------- tokens -- */
:root {
  /* --- papéis de cor. Sobrescreva estes seis e a página está rebrandeada. - */
  --sc-canvas:      #08090b;   /* o chão da página. O drift interpola isto.   */
  --sc-surface:     #101217;   /* qualquer coisa elevada acima do chão        */
  --sc-ink:         #f4f2ef;   /* texto principal                             */
  --sc-ink-soft:    #9a9ba1;   /* texto secundário. Tingido, nunca cinza chapado. */
  --sc-accent:      #d8ff3e;   /* UM destaque. Ele é dono de uma região, não confete. */
  --sc-accent-ink:  #08090b;   /* texto que fica em cima do destaque          */

  --sc-hairline:    color-mix(in oklab, var(--sc-ink) 12%, transparent);
  --sc-hairline-strong: color-mix(in oklab, var(--sc-ink) 22%, transparent);

  /* --- tipografia. Duas famílias no máximo. Display carrega a voz, texto carrega a prosa. */
  --sc-font-display: "Instrument Sans", "Geist", system-ui, sans-serif;
  --sc-font-text:    "Geist", system-ui, sans-serif;
  --sc-font-mono:    "Geist Mono", ui-monospace, monospace;

  /* Escala fluida. O tracking aperta conforme o tamanho cresce porque uma fonte
     a 6rem com tracking 0 parece frouxa; isto é correção óptica, não decoração. */
  --sc-t-xs:   clamp(0.75rem, 0.72rem + 0.15vw, 0.82rem);
  --sc-t-sm:   clamp(0.875rem, 0.84rem + 0.18vw, 0.95rem);
  --sc-t-base: clamp(1rem, 0.96rem + 0.22vw, 1.125rem);
  --sc-t-lg:   clamp(1.2rem, 1.1rem + 0.5vw, 1.5rem);
  --sc-t-xl:   clamp(1.6rem, 1.35rem + 1.2vw, 2.25rem);
  --sc-t-2xl:  clamp(2.1rem, 1.6rem + 2.4vw, 3.4rem);
  --sc-t-3xl:  clamp(2.8rem, 1.9rem + 4.2vw, 5rem);
  --sc-t-4xl:  clamp(3.4rem, 1.9rem + 6.6vw, 7.5rem);

  --sc-track-tight:  -0.035em;
  --sc-track-snug:   -0.02em;
  --sc-track-normal: -0.005em;
  --sc-track-wide:    0.08em;

  --sc-leading-none: 0.94;
  --sc-leading-tight: 1.06;
  --sc-leading-body: 1.62;

  --sc-measure: 62ch;

  /* --- espaço. Base de 4px: os passos intermediários úteis que uma escala só de 8 perde. */
  --sc-1: 0.25rem;  --sc-2: 0.5rem;   --sc-3: 0.75rem;  --sc-4: 1rem;
  --sc-5: 1.5rem;   --sc-6: 2rem;     --sc-7: 3rem;     --sc-8: 4rem;
  --sc-9: 6rem;     --sc-10: 8rem;    --sc-11: 12rem;

  /* O ritmo das seções é fluido para o celular não herdar o ar do desktop. */
  --sc-section: clamp(4.5rem, 9vw, 11rem);
  --sc-gutter:  clamp(1.25rem, 5vw, 5.5rem);
  --sc-maxw:    82rem;

  /* --- raio. Escolha uma escala para a página e mantenha. ------------------ */
  --sc-r-sm: 6px;  --sc-r-md: 12px;  --sc-r-lg: 20px;  --sc-r-pill: 999px;

  /* --- elevação. Toda sombra tem deslocamento E desfoque suave, e é tingida
         com o matiz do canvas. Um halo colorido sem deslocamento é decoração,
         não profundidade, por isso não existe um aqui. ---------------------- */
  --sc-shadow-color: 220 40% 2%;
  --sc-e1: 0 1px 2px hsl(var(--sc-shadow-color) / 0.28),
           0 2px 6px -1px hsl(var(--sc-shadow-color) / 0.20);
  --sc-e2: 0 2px 4px hsl(var(--sc-shadow-color) / 0.24),
           0 8px 18px -4px hsl(var(--sc-shadow-color) / 0.30);
  --sc-e3: 0 4px 8px hsl(var(--sc-shadow-color) / 0.22),
           0 18px 40px -8px hsl(var(--sc-shadow-color) / 0.38),
           0 48px 90px -24px hsl(var(--sc-shadow-color) / 0.30);

  /* Luz de borda: um realce de 1px no topo vende uma superfície elevada melhor
     que qualquer quantidade de desfoque, porque coisas elevadas de verdade
     pegam luz na beirada. */
  --sc-edge: inset 0 1px 0 color-mix(in oklab, var(--sc-ink) 10%, transparent);

  /* --- movimento. Os easings nativos do CSS são fracos demais para UI. ----- */
  --sc-ease-out:    cubic-bezier(0.23, 1, 0.32, 1);
  --sc-ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --sc-ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
  --sc-d-fast: 160ms;  --sc-d-base: 240ms;  --sc-d-slow: 420ms;

  --sc-z-stage: 1; --sc-z-copy: 20; --sc-z-chrome: 60;
}

/* --------------------------------------------------------------- reset -- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--sc-canvas);
  color: var(--sc-ink);
  font-family: var(--sc-font-text);
  font-size: var(--sc-t-base);
  line-height: var(--sc-leading-body);
  letter-spacing: var(--sc-track-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-synthesis-weight: none;
  overflow-x: clip;
}
img, video, canvas, svg { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; }

/* ------------------------------------------------- as superfícies do navegador --
   As partes que você não desenhou ainda carregam o design. Seleção, cursor de
   texto, anel de foco, barra de rolagem e numerais tabulares vêm com padrões
   que não pertencem a nenhum design system. Tematizá-los é o sinal mais barato
   de que uma página foi construída, e não montada, e é o passo pulado com mais
   frequência. */
::selection { background: var(--sc-accent); color: var(--sc-accent-ink); }
:root { caret-color: var(--sc-accent); accent-color: var(--sc-accent); }
:focus-visible {
  outline: 2px solid var(--sc-accent);
  outline-offset: 3px;
  border-radius: var(--sc-r-sm);
}
:where(a) { color: inherit; text-decoration-thickness: 1px; text-underline-offset: 0.22em; }
@supports (scrollbar-color: auto) {
  html { scrollbar-color: color-mix(in oklab, var(--sc-ink) 26%, transparent) transparent; scrollbar-width: thin; }
}
:where(table, .sc-nums, [data-sc-count]) { font-variant-numeric: tabular-nums; }

/* ----------------------------------------------------------- tipografia -- */
.sc-display {
  font-family: var(--sc-font-display);
  font-weight: 500;
  line-height: var(--sc-leading-none);
  letter-spacing: var(--sc-track-tight);
  text-wrap: balance;
  margin: 0;
}
.sc-display--xl { font-size: var(--sc-t-4xl); }
.sc-display--lg { font-size: var(--sc-t-3xl); }
.sc-display--md { font-size: var(--sc-t-2xl); letter-spacing: var(--sc-track-snug); }
.sc-lede {
  font-size: var(--sc-t-lg);
  line-height: 1.44;
  letter-spacing: var(--sc-track-snug);
  color: var(--sc-ink);
  max-width: 46ch;
  text-wrap: pretty;
  margin: 0;
}
.sc-body { max-width: var(--sc-measure); color: var(--sc-ink-soft); text-wrap: pretty; margin: 0; }
.sc-label {
  font-family: var(--sc-font-mono);
  font-size: var(--sc-t-xs);
  letter-spacing: var(--sc-track-wide);
  text-transform: uppercase;
  color: var(--sc-ink-soft);
}

/* ---------------------------------------------------------------- layout -- */
.sc-wrap { width: 100%; max-width: var(--sc-maxw); margin-inline: auto; padding-inline: var(--sc-gutter); }
.sc-section { padding-block: var(--sc-section); }
/* Mais espaço acima de um título do que abaixo: o vão pertence à fronteira,
   não ao par. */
.sc-stack > * + * { margin-top: var(--sc-4); }
.sc-stack > :is(h1,h2,h3) { margin-top: var(--sc-7); }
.sc-stack > :is(h1,h2,h3):first-child { margin-top: 0; }
.sc-rule { height: 1px; border: 0; background: var(--sc-hairline); margin: 0; }

/* =============================================================== DEVICES ==
   Controlados pelo engine. Reestilize a sua marcação, não estes.             */

.sc-act--pinned { position: relative; }
.sc-stage {
  position: sticky; top: 0;
  height: 100vh; height: 100svh;
  overflow: clip;
  z-index: var(--sc-z-stage);
}

/* mídia de scrub / sequência */
.sc-stage :is(video[data-sc-scrub], canvas[data-sc-sequence], .sc-stage__poster) {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
video[data-sc-scrub] { opacity: 0; transition: opacity 380ms var(--sc-ease-out); }
.sc-has-clip video[data-sc-scrub] { opacity: 1; }
/* O poster é um segurador de quadro vivo, não um placeholder: ele fica no ar até
   um quadro real do vídeo ter sido pintado, e é isso que evita o flash de
   stage em branco. */
.sc-stage__poster { z-index: 0; transition: opacity 380ms var(--sc-ease-out); }
.sc-has-clip .sc-stage__poster { opacity: 0; }

/* Um scrim só onde o texto está. Uma camada de escurecimento no quadro inteiro
   achata a imagem em todo lugar para corrigir contraste em um canto. */
.sc-scrim {
  position: absolute; inset: 0; pointer-events: none; z-index: 1;
  background: linear-gradient(
    var(--sc-scrim-angle, 180deg),
    color-mix(in oklab, var(--sc-canvas) var(--sc-scrim-a, 78%), transparent) 0%,
    color-mix(in oklab, var(--sc-canvas) 30%, transparent) 42%,
    transparent 68%);
}
/* Aponte o scrim para o texto. Um gradiente de scrim que escurece o topo enquanto
   o texto fica embaixo não corrige contraste em lugar nenhum e achata a imagem
   em todo lugar, que é o jeito mais comum de texto sobre vídeo dar errado. */
.sc-scrim--bottom { --sc-scrim-angle: 0deg; }
.sc-scrim--left   { --sc-scrim-angle: 90deg; }
.sc-scrim--right  { --sc-scrim-angle: 270deg; }

/* Scrims de canto, para texto ancorado em um canto. Um gradiente de borda
   precisa escurecer uma faixa inteira do quadro para cobrir um canto; um
   gradiente de canto coloca a densidade onde o texto está e deixa o resto da
   imagem em paz. Combine com .sc-copy--lead / .sc-copy--trail. */
.sc-scrim--lead {
  background: linear-gradient(to top right,
    color-mix(in oklab, var(--sc-canvas) 94%, transparent) 0%,
    color-mix(in oklab, var(--sc-canvas) 72%, transparent) 30%,
    color-mix(in oklab, var(--sc-canvas) 30%, transparent) 52%,
    transparent 72%);
}
.sc-scrim--trail {
  background: linear-gradient(to top left,
    color-mix(in oklab, var(--sc-canvas) 94%, transparent) 0%,
    color-mix(in oklab, var(--sc-canvas) 72%, transparent) 30%,
    color-mix(in oklab, var(--sc-canvas) 30%, transparent) 52%,
    transparent 72%);
}
/* Uma faixa na base, para texto que ocupa toda a largura do quadro. É nisso que
   as duas âncoras de canto se transformam abaixo de 860px, e é também a forma
   certa sempre que o bloco de texto for mais largo que um canto. */
.sc-scrim--band {
  background: linear-gradient(to top,
    color-mix(in oklab, var(--sc-canvas) 94%, transparent) 0%,
    color-mix(in oklab, var(--sc-canvas) 74%, transparent) 22%,
    color-mix(in oklab, var(--sc-canvas) 30%, transparent) 42%,
    transparent 58%);
}
.sc-scrim--vignette {
  background: radial-gradient(120% 90% at 50% 45%, transparent 40%,
              color-mix(in oklab, var(--sc-canvas) 70%, transparent) 100%);
}

/* texto sobre um stage.
   max-width é em rem, nunca em ch. Um `ch` neste contêiner é resolvido contra o
   font-size do CONTÊINER (tamanho do body), não contra o tamanho display do
   título dentro dele, então `max-width: 20ch` aqui produz em silêncio uma coluna
   de ~180px e quebra um título de hero em seis linhas. Defina a medida em ch no
   próprio elemento de texto. */
.sc-copy {
  position: absolute; z-index: var(--sc-z-copy);
  inset-inline: var(--sc-gutter);
  max-width: min(46rem, 76vw);
  will-change: opacity, transform;
}
.sc-copy--lead   { left: var(--sc-gutter); bottom: clamp(3rem, 12vh, 9rem); }
/* inset-inline PRIMEIRO. É o atalho para left+right, então declará-lo depois de
   `left: 50%` zera left para auto e o bloco escapa pela borda esquerda. */
.sc-copy--center { inset-inline: auto; left: 50%; top: 50%; translate: -50% -50%; text-align: center; }
.sc-copy--trail  { inset-inline: auto; right: var(--sc-gutter); bottom: clamp(3rem, 12vh, 9rem); text-align: right; }

/* padrões de deixa: o engine escreve opacity/transform inline, estes são o
   estado pré-pintura para nada piscar antes do primeiro read() */
[data-sc-cue] { opacity: 0; will-change: opacity, transform; }
.sc-ready [data-sc-cue] { transition: none; }

/* divisão cinética */
.sc-split { display: inline-block; overflow: hidden; vertical-align: top; }
/* Descendentes vivem abaixo da linha de base; uma máscara de linha cortada na
   caixa da linha come as caudas de g, y, p, j. O padding devolve o espaço. */
.sc-split--line { display: block; padding-bottom: 0.14em; margin-bottom: -0.14em; }
.sc-split__i { display: inline-block; will-change: transform, opacity; }
.sc-is-split { opacity: 1 !important; }

/* trilho horizontal */
[data-sc-pan] { display: flex; will-change: transform; }

/* reveal + parallax */
[data-sc-reveal] { will-change: clip-path; }
[data-sc-parallax] { will-change: transform; }

/* reveal de flow (dispara uma vez) */
[data-sc-in], [data-sc-stagger] > * {
  opacity: 0;
  transform: translate3d(0, 14px, 0);
  transition: opacity 620ms var(--sc-ease-out), transform 620ms var(--sc-ease-out);
}
[data-sc-in].sc-in, [data-sc-stagger] > .sc-in { opacity: 1; transform: none; }

/* dispositivos de ponteiro */
[data-sc-tilt] { transform-style: preserve-3d; will-change: transform; }
[data-sc-magnet] { will-change: transform; }
/* isolation sempre; position só se nada mais específico já definiu.
   Escrito com :where() (especificidade zero) de propósito: um `position:
   relative` simples aqui tem o mesmo peso de `.sc-stage` e, por vir depois no
   arquivo, vence em silêncio. Um stage com os dois atributos então deixa de ser
   sticky e o ato inteiro rola para fora em vez de pinar. */
[data-sc-spotlight] { isolation: isolate; }
:where([data-sc-spotlight]) { position: relative; }
[data-sc-spotlight]::after {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 2;
  background: radial-gradient(
    28rem 28rem at calc(var(--sc-mx, 0.5) * 100%) calc(var(--sc-my, 0.5) * 100%),
    color-mix(in oklab, var(--sc-accent) 16%, transparent), transparent 70%);
  opacity: 0; transition: opacity var(--sc-d-slow) var(--sc-ease-out);
}
[data-sc-spotlight]:hover::after { opacity: 1; }

/* =========================================================== WORLDFLIGHT ==
   Um stage fixo para a página inteira. A única coisa no fluxo do documento é o
   espaçador, e ele está vazio. Se você se pegar adicionando uma seção aqui, o
   que você quer é o modo de atos: no momento em que um bloco real rola por cima
   do stage fixo, a página tem uma costura de novo e o sentido todo se perde.  */

[data-sc-mode="worldflight"] { position: relative; }

.sc-world {
  position: fixed; inset: 0;
  overflow: clip;
  z-index: var(--sc-z-stage);
  background: var(--sc-canvas);
}

/* Toda perna fica montada durante a vida inteira da página e empilhada na mesma
   caixa. O engine é dono de opacity, visibility e z-index aqui; não os defina. */
.sc-world__seg {
  position: absolute; inset: 0;
  opacity: 0;
  will-change: opacity;
}
.sc-world__seg > :is(video, img, canvas) {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
/* O poster é o segurador de quadro E o primeiro movimento de câmera: o engine o
   empurra para dentro devagar até um quadro decodificado de verdade estar
   disponível para substituí-lo. */
.sc-world__poster {
  z-index: 0;
  transform-origin: 50% 50%;
  transition: opacity 420ms var(--sc-ease-out);
}
.sc-world__seg > video { z-index: 1; }
.sc-world__seg.sc-has-clip .sc-world__poster { opacity: 0; }
/* A folha de estilo de atos acende um clipe pelo ato ancestral. Uma perna de
   worldflight não tem ato, então casamos a classe que o engine também escreve no
   próprio clipe. */
video[data-sc-scrub].sc-has-clip { opacity: 1; }

/* A camada de texto também é fixa, e inerte por padrão: o engine devolve
   pointer-events a um bloco só enquanto ele está de fato legível. */
.sc-world__copy {
  position: fixed; inset: 0;
  z-index: var(--sc-z-copy);
  pointer-events: none;
}
.sc-world__scrim { position: absolute; inset: 0; pointer-events: none; z-index: 0; }
[data-sc-copy] {
  opacity: 0;
  pointer-events: none;
  will-change: opacity, transform;
}
.sc-ready [data-sc-copy] { transition: none; }

/* A trilha. Vazia de propósito. */
.sc-world__spacer { pointer-events: none; }

/* progresso do scroll */
[data-sc-progress] {
  position: fixed; inset: 0 0 auto 0; height: 2px; z-index: var(--sc-z-chrome);
  background: var(--sc-accent); transform-origin: 0 50%; transform: scaleX(0);
  will-change: transform;
}

/* ----------------------------------------------------------- atmosfera --
   Profundidade não é só sombra. O grão impede que um chão escuro e chapado
   crie faixas, e é a diferença entre "uma página escura" e "uma sala iluminada". */
.sc-grain { position: fixed; inset: 0; pointer-events: none; z-index: 3; opacity: 0.045; }
.sc-grain::before {
  content: ""; position: absolute; inset: -50%;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/></filter><rect width='140' height='140' filter='url(%23n)'/></svg>");
}

/* ------------------------------------------------------ movimento reduzido -- */
@media (prefers-reduced-motion: reduce) {
  /* Menos e mais suave, não zero. A opacidade ainda carrega o reveal para a
     página continuar compreensível; toda mudança de posição é descartada. */
  [data-sc-in], [data-sc-stagger] > * { transform: none; transition-duration: 220ms; }
  [data-sc-parallax], [data-sc-pan], .sc-split__i { transform: none !important; }
  /* Um wipe também é mudança de posição. Mostre o conteúdo do reveal assentado. */
  [data-sc-reveal] { clip-path: none !important; }
  /* O transform de um trilho É a navegação dele, não decoração. Zerá-lo como se
     zera o parallax e a tipografia cinética estaciona o ato na primeira tela e
     torna tudo depois da dobra inalcançável: um dispositivo degradando em
     conteúdo faltando. Em vez disso, devolva o percurso ao leitor como uma
     região de scroll comum, para que os mesmos itens continuem alcançáveis sem
     movimento. Uma build que preferir rearranjar o trilho como grade ainda pode
     fazer isso; este é o piso, não o teto. */
  [data-sc-act="pan"] .sc-stage,
  [data-sc-act="pan"] [data-sc-stage] {
    overflow-x: auto; overflow-y: hidden;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
  }
  [data-sc-pan] > * { scroll-snap-align: center; }
  [data-sc-spotlight]::after { display: none; }
  /* Um worldflight mantém a história inteira aqui. Nenhum clipe é baixado, então
     os posters são o filme, e eles fazem cross-dissolve exatamente nas mesmas
     costuras, exatamente nas mesmas posições de scroll. O push-in e o drift do
     texto são as únicas coisas que saem. */
  .sc-world__poster, [data-sc-copy] { transform: none !important; }
}

/* --------------------------------------------------------------- mobile -- */
@media (max-width: 860px) {
  .sc-copy { inset-inline: var(--sc-gutter); max-width: none; }
  .sc-copy--trail { text-align: left; }
  .sc-stage { height: 100svh; }
  /* .sc-copy--trail volta a ancorar à esquerda e ocupa toda a largura aqui, então
     um gradiente no canto inferior DIREITO escurece justamente o canto que o
     texto acabou de deixar e garante uma falha de contraste sobre qualquer clipe
     claro. Aponte a densidade para o texto: a mesma faixa que .sc-scrim--band pinta. */
  .sc-scrim--trail {
    background: linear-gradient(to top,
      color-mix(in oklab, var(--sc-canvas) 94%, transparent) 0%,
      color-mix(in oklab, var(--sc-canvas) 74%, transparent) 22%,
      color-mix(in oklab, var(--sc-canvas) 30%, transparent) 42%,
      transparent 58%);
  }
}
