/* ============================================================
   ULTMOST — placa cinematográfica
   Tokens e racional em DESIGN.md. Zero dependência externa, zero JS.
   ============================================================ */

@font-face {
  font-family: "Satoshi";
  src: url("/fonts/Satoshi-Variable.woff2") format("woff2-variations");
  font-weight: 300 900;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Superfícies */
  --ink-000: #050607;
  --ink-100: #0a0c0e;
  --ink-200: #111519;

  /* Texto */
  --silver-100: #f4f6f7;
  --silver-500: #7d868f;

  /* Acento único da página */
  --steel: #9db4c8;
  --hairline: rgba(244, 246, 247, 0.10);

  --gutter: clamp(1.25rem, 4.5vw, 3.5rem);
  --track-wordmark: 0.14em;

  /* Curvas */
  --ease-shutter: cubic-bezier(0.72, 0, 0.16, 1);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-dolly: cubic-bezier(0.16, 0.62, 0.22, 1);

  --font: "Satoshi", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

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

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow: hidden;
  background: var(--ink-000);
}

body {
  font-family: var(--font);
  color: var(--silver-100);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

::selection {
  background: rgba(157, 180, 200, 0.22);
  color: var(--silver-100);
}

/* ------------------------------------------------------------
   Quadro: uma superfície contínua, do topo à base.
   Sem barra sólida e sem borda: qualquer degrau de tom entre duas
   áreas lê como faixa colada, não como enquadramento.
   ------------------------------------------------------------ */

.frame {
  position: relative;
  display: flex;
  align-items: center;
  height: 100vh;
  height: 100dvh;
  padding: 0 var(--gutter);
  background: var(--ink-100);
  overflow: hidden;
  isolation: isolate;
}

/* Camada 1: luz de chave, alta e à esquerda. Respira devagar. */
.wash {
  position: absolute;
  inset: -25%;
  pointer-events: none;
  background:
    radial-gradient(52% 62% at 34% 26%,
      rgba(198, 214, 228, 0.105) 0%,
      rgba(198, 214, 228, 0.038) 44%,
      rgba(198, 214, 228, 0) 74%),
    linear-gradient(180deg, var(--ink-200) 0%, var(--ink-100) 58%, #08090b 100%);
  will-change: transform, opacity;
}

/* Camada 2: grão de película */
.grain {
  position: absolute;
  top: -60%;
  left: -60%;
  width: 220%;
  height: 220%;
  pointer-events: none;
  opacity: 0.058;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.72' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  will-change: transform;
}

/* Camada 3: vinheta. Fecha os cantos e escurece topo e base num
   degradê longo, o que dá a sensação de quadro anamórfico sem
   desenhar nenhuma barra e sem criar emenda. */
.vignette {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(180deg,
      rgba(5, 6, 7, 0.92) 0%,
      rgba(5, 6, 7, 0.46) 11%,
      rgba(5, 6, 7, 0) 27%,
      rgba(5, 6, 7, 0) 73%,
      rgba(5, 6, 7, 0.46) 89%,
      rgba(5, 6, 7, 0.92) 100%),
    radial-gradient(78% 96% at 42% 40%,
      rgba(5, 6, 7, 0) 30%,
      rgba(5, 6, 7, 0.30) 62%,
      rgba(5, 6, 7, 0.72) 100%);
}

/* Camada 4: clarão de projeção. Passa uma vez, depois some. */
.sweep {
  position: absolute;
  top: -30%;
  bottom: -30%;
  left: 0;
  width: 72%;
  pointer-events: none;
  opacity: 0;
  /* Paradas largas e suaves: faixa estreita cria borda dura e lê como
     shimmer de skeleton, não como luz passando na lente. */
  background: linear-gradient(
    100deg,
    rgba(220, 234, 244, 0) 0%,
    rgba(220, 234, 244, 0.012) 24%,
    rgba(220, 234, 244, 0.036) 44%,
    rgba(220, 234, 244, 0.05) 52%,
    rgba(220, 234, 244, 0.028) 62%,
    rgba(220, 234, 244, 0.008) 80%,
    rgba(220, 234, 244, 0) 100%
  );
  transform: translateX(-140%) skewX(-14deg);
  will-change: transform, opacity;
}

/* ------------------------------------------------------------
   Logotipo
   ------------------------------------------------------------ */

.wordmark {
  position: relative;
  z-index: 2;
  margin: 0;
  width: 100%;
  /* Tamanho derivado da métrica real, não de um vw chutado.
     "ULTMOST" em Satoshi 500 com tracking 0.14em mede 5.5494em de
     tinta (medido no navegador). Dividir a largura útil por esse
     fator faz o logotipo encostar nas duas margens em qualquer
     viewport, porque usa a --gutter real em vez de supor que ela
     está no teto. O teto em vh só age em tela muito baixa. */
  --wordmark-ink-ratio: 5.5494;
  font-size: clamp(
    1.75rem,
    min(calc((100vw - 2 * var(--gutter)) / var(--wordmark-ink-ratio)), 38vh),
    24rem
  );
  font-weight: 500;
  line-height: 0.92;
  color: var(--silver-100);
}

.wordmark__inner {
  display: block;
  letter-spacing: var(--track-wordmark);
  /* Compensa o tracking pendurado na última letra, senão a caixa
     fica opticamente deslocada para a esquerda. */
  margin-right: calc(var(--track-wordmark) * -1);
  will-change: transform;
}

.wordmark__l {
  display: inline-block;
  will-change: transform, opacity;
}

/* Índice de cada letra para o escalonamento da entrada.
   Fica no CSS, e não em `style` inline, porque a CSP é
   `style-src 'self'`: atributo style é bloqueado e o --i sumiria,
   derrubando o `calc()` do animation-delay para 0s. As letras
   entrariam todas juntas, e sem erro visível na página. */
.wordmark__l:nth-child(1) { --i: 0; }
.wordmark__l:nth-child(2) { --i: 1; }
.wordmark__l:nth-child(3) { --i: 2; }
.wordmark__l:nth-child(4) { --i: 3; }
.wordmark__l:nth-child(5) { --i: 4; }
.wordmark__l:nth-child(6) { --i: 5; }
.wordmark__l:nth-child(7) { --i: 6; }

/* ------------------------------------------------------------
   Contato: único elemento interativo e único portador de acento.
   ------------------------------------------------------------ */

.contact {
  position: absolute;
  left: var(--gutter);
  bottom: clamp(1.4rem, 4.5vh, 2.75rem);
  z-index: 4;
  /* Piso em 0.72rem: em 375px o vw já está no fundo do clamp, e o
     e-mail é o único elemento acionável da página. Cabe folgado,
     20 caracteres ocupam ~163px dos 335px úteis. */
  font-size: clamp(0.72rem, 1.05vw, 0.8rem);
  font-weight: 500;
  letter-spacing: 0.19em;
  line-height: 1;
  text-transform: uppercase;
  color: var(--silver-500);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 3px;
  transition: color 220ms var(--ease-out), border-color 220ms var(--ease-out);
}

/* Área de toque de ~44px sem mexer no baseline nem no sublinhado. */
.contact::after {
  content: "";
  position: absolute;
  inset: -15px -14px;
}

.contact:hover { color: var(--steel); border-bottom-color: var(--hairline); }
.contact:focus-visible {
  color: var(--steel);
  outline: 1px solid var(--steel);
  outline-offset: 5px;
  border-bottom-color: transparent;
}
.contact:active { color: var(--silver-100); }
.contact:visited { color: var(--silver-500); }

/* ------------------------------------------------------------
   Obturador
   ------------------------------------------------------------ */

.curtain {
  position: fixed;
  left: 0;
  right: 0;
  height: 51vh;
  height: 51dvh;
  background: var(--ink-000);
  z-index: 60;
  pointer-events: none;
  /* Sem animação (reduced-motion ou fallback) já nasce fora de cena. */
  transform: translateY(-101%);
}

.curtain--top { top: 0; }
.curtain--bottom { bottom: 0; transform: translateY(101%); }

/* ------------------------------------------------------------
   Movimento.
   O estado final é o padrão do CSS. O estado inicial escondido só
   existe dentro de no-preference. Consequência: quem pede menos
   movimento, e qualquer navegador que não rode a animação, vê a
   página inteira. Nada aqui revela conteúdo.
   ------------------------------------------------------------ */

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

  /* 1. Obturador abre */
  .curtain--top {
    transform: translateY(0);
    animation: shutter-up 1250ms var(--ease-shutter) 140ms forwards;
  }
  .curtain--bottom {
    transform: translateY(0);
    animation: shutter-down 1250ms var(--ease-shutter) 140ms forwards;
  }
  @keyframes shutter-up   { to { transform: translateY(-101%); } }
  @keyframes shutter-down { to { transform: translateY(101%); } }

  /* 2. A luz acende junto com a abertura, depois respira */
  .wash {
    opacity: 0;
    animation:
      lamp 1700ms var(--ease-out) 300ms forwards,
      breathe 16s ease-in-out 2.2s infinite;
  }
  @keyframes lamp { to { opacity: 1; } }
  @keyframes breathe {
    0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
    50%      { transform: translate3d(1.2%, -0.9%, 0) scale(1.045); }
  }

  /* 3. Dolly lento no logotipo, do fundo para a frente */
  .wordmark__inner {
    animation: dolly 8s var(--ease-dolly) 900ms both;
  }
  @keyframes dolly {
    from { transform: scale(1.06); }
    to   { transform: scale(1); }
  }

  /* 4. Letras assentam uma a uma */
  .wordmark__l {
    opacity: 0;
    transform: translateY(0.44em);
    animation: settle 980ms var(--ease-out) forwards;
    animation-delay: calc(980ms + var(--i) * 72ms);
  }
  @keyframes settle {
    to { opacity: 1; transform: translateY(0); }
  }

  /* 5. Clarão atravessa uma vez, depois do logotipo assentar */
  .sweep {
    animation: flare 2800ms cubic-bezier(0.4, 0, 0.3, 1) 2250ms 1 forwards;
  }
  @keyframes flare {
    0%   { opacity: 0; transform: translateX(-140%) skewX(-14deg); }
    12%  { opacity: 1; }
    82%  { opacity: 1; }
    100% { opacity: 0; transform: translateX(320%) skewX(-14deg); }
  }

  /* 6. Contato entra por último */
  .contact {
    opacity: 0;
    animation: fade 950ms var(--ease-out) 2500ms forwards;
  }
  @keyframes fade { to { opacity: 1; } }

  /* 7. Grão treme na cadência de fotograma, contínuo */
  .grain { animation: flicker 720ms steps(6, end) infinite; }
  @keyframes flicker {
    0%   { transform: translate3d(0, 0, 0); }
    16%  { transform: translate3d(-3%, 2%, 0); }
    33%  { transform: translate3d(2%, -3%, 0); }
    50%  { transform: translate3d(-2%, -2%, 0); }
    66%  { transform: translate3d(3%, 1%, 0); }
    83%  { transform: translate3d(-1%, 3%, 0); }
    100% { transform: translate3d(0, 0, 0); }
  }
}

/* ------------------------------------------------------------
   Responsivo
   ------------------------------------------------------------ */

/* Em pé o quadro é alto: a vinheta fecha mais em cima e embaixo
   para o logotipo não boiar no meio de tanto preto. */
@media (orientation: portrait) {
  .vignette {
    background:
      linear-gradient(180deg,
        rgba(5, 6, 7, 0.95) 0%,
        rgba(5, 6, 7, 0.55) 14%,
        rgba(5, 6, 7, 0) 33%,
        rgba(5, 6, 7, 0) 67%,
        rgba(5, 6, 7, 0.55) 86%,
        rgba(5, 6, 7, 0.95) 100%),
      radial-gradient(96% 54% at 44% 47%,
        rgba(5, 6, 7, 0) 24%,
        rgba(5, 6, 7, 0.32) 60%,
        rgba(5, 6, 7, 0.74) 100%);
  }
}

@media (max-height: 520px) and (orientation: landscape) {
  .contact { bottom: 0.75rem; }
}

@media (max-width: 400px) {
  .contact { letter-spacing: 0.15em; }
}

@media (prefers-contrast: more) {
  :root { --silver-500: #b6bec6; }
  .grain, .sweep { display: none; }
}
