/* ==========================================================================
   XCLUSIVE EVENTS · M1 BLACKOUT · Base: reset, tipografia, chrome global
   ========================================================================== */

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

html {
  background: var(--void);
  scrollbar-width: thin;
  scrollbar-color: var(--hair) var(--ink);
}

html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }

body {
  background: var(--ink);
  color: var(--bone);
  font-family: var(--sans);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
  min-height: 100svh;
}

::selection { background: var(--acc); color: var(--ink); }

img, video { display: block; max-width: 100%; }

a { color: inherit; text-decoration: none; }

/* Excecao ao reset acima: um link DENTRO de um paragrafo precisa de se ver em
   repouso. Nas paginas legais estes contactos herdavam `color: inherit` e
   `text-decoration: none` e ficavam medidos a 1.00:1 contra o proprio
   paragrafo, sem sublinhado, sem borda, sem fundo e sem mudanca no hover: so
   o outline global do :focus-visible os denunciava, e so a quem navega por
   teclado. Cor sozinha nunca chega (WCAG 1.4.1), por isso ha tambem sublinhado.
   A cor de repouso e a mesma dos outros links inline do site e nao uma sexta
   variante: --acc em repouso, como .art-body a (sections.css), .nl-legal a,
   .consent-label a, .form-status a e .cookie-bar a, que convive com estes na
   propria termos.html.
   O sublinhado e `currentColor` e NAO --hair. Com --hair (alpha .12) o
   sublinhado compunha para rgb(35,34,35), 1.25:1 contra o fundo: abaixo dos
   3:1 que o WCAG 1.4.11 pede a um componente e invisivel a 1x, so aparecia
   ampliado quatro vezes. Ou seja, a pista nao-cromatica nao existia e o link
   ficava distinguido do paragrafo apenas por matiz, a 1.31:1 contra o texto
   que o rodeia (o .legal-body p leva opacity .88), contra os 3:1 que a tecnica
   G183 exige nesse caso. Em currentColor o sublinhado herda a cor do proprio
   link, composta pela mesma cadeia de opacity, e mede o mesmo que o texto:
   rgb(58,205,226) = 10.41:1 contra o fundo. O estado de hover/foco deixa de
   poder ser a cor do sublinhado (ja e a do texto) e passa a ser a espessura.
   A mesma correcao esta no .art-body a (sections.css) para nao voltar a haver
   duas convencoes de link inline. */
.legal-body a {
  color: var(--acc);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: currentColor;
  transition: text-decoration-thickness var(--dur-micro) var(--ease-out);
}
.legal-body a:hover,
.legal-body a:focus-visible {
  text-decoration-thickness: 2px;
}

button {
  background: none; border: none; color: inherit;
  font: inherit; cursor: pointer;
}

:focus-visible {
  outline: 1px solid var(--bone);
  outline-offset: 4px;
}

/* ---- Tipografia ------------------------------------------------------- */

.display-xl, .display-l, .display-m {
  font-family: var(--serif);
  font-optical-sizing: auto;
  font-variation-settings: 'opsz' 96;
  font-weight: 400;
}

.display-xl { font-size: clamp(48px, 8.5vw, 150px); line-height: 0.96; letter-spacing: -0.01em; font-weight: 700; }
.display-l  { font-size: clamp(36px, 5.5vw, 88px);  line-height: 1.0; letter-spacing: -0.008em; font-weight: 700; }
.display-m  { font-size: var(--fs-display-m);  line-height: 1.08; letter-spacing: 0; font-weight: 600; }

.lead {
  font-weight: 300;
  font-size: var(--fs-lead);
  line-height: 1.5;
  max-width: 46ch;
  color: var(--bone-dim);
}

.body-copy { max-width: 62ch; color: var(--bone-dim); }

.label {
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--acc);
}

/* ---- Layout ------------------------------------------------------------ */

.container {
  width: 100%;
  max-width: var(--max-w);
  margin-inline: auto;
  padding-inline: var(--margin);
}

.section { padding-block: var(--section-gap); position: relative; }

/* O .site-head e fixed (102px de altura a 1440, 74px a 390) e nao ocupa espaco
   no fluxo. As paginas com heroi resolvem isto sozinhas e seis paginas de
   conteudo trazem um padding-top inline de clamp(140px, 22vh, 260px); as
   quatro que nao o traziam (404, faqs, termos, privacidade) imprimiam o
   primeiro <p class="label"> por cima do wordmark: medido na 404 a 1440,
   logo 32-70px em y contra label 59-81px, 11.5px de sobreposicao, e a 390 a
   sobreposicao era total. A regra da o mesmo recuo por defeito; onde o inline
   ja existe, o inline continua a ganhar e nada muda. */
main > .section:first-child { padding-top: clamp(140px, 22vh, 260px); }

/* Régua de secção (M10): desenha-se ao entrar em viewport via JS */
.rule {
  height: 1px;
  background: var(--hair);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 900ms var(--ease-out);
}
.rule.is-drawn { transform: scaleX(1); }

/* ---- Header ------------------------------------------------------------ */

/* O cabeçalho usava mix-blend-mode: difference para se defender do que passa por
   baixo dele. Sob difference pinta-se |fundo - cor|, e com tinta clara isso tem
   um ponto de invisibilidade GARANTIDO: para o --bone a alfa 0.72 a igualdade
   0.72*|B - 244| + 0.28*B = B resolve-se em B = 122. Ou seja, sobre qualquer
   pixel a meio cinzento o texto do cabeçalho desaparece por construção, e não há
   valor de cor que o evite. É o que se mede nas duas páginas que têm media por
   baixo do cabeçalho. Por pixel de núcleo de glifo, 1440x900, método
   REAL/FUNDO/MÁSCARA: no evento-wild o "Journal" dava mínimo 1.00:1 e mediana
   1.74:1 com 99.5% dos pixeis abaixo de 4.5:1, "Experiências" mediana 2.25:1 com
   100%, e o próprio logótipo mínimo 1.22:1; no index "Experiências" mediana
   2.58:1 e o logótipo mediana 1.09:1 com 100% dos pixeis abaixo de 3:1. Nas
   páginas sem foto no topo os mesmos links davam 7.8 a 16:1, o que confirma que
   o defeito é exclusivamente texto sobre media.

   A blend sai e entra um véu, que é o mesmo remédio já aplicado ao .ht-sub da
   home e ao .eh-label do evento-wild: sobre media a legibilidade decide-se no
   fundo, não na cor da letra. O véu é quase opaco na faixa onde o texto vive e
   desvanece para nada abaixo dela, portanto sobre o #0A0A0B do corpo (13 das 15
   páginas) não se vê. A paragem de 0.86 é dimensionada pelo pior fundo medido
   por baixo de tinta do cabeçalho, 213 de 255 no vestido claro do evento-wild, e
   ainda deixa folga para um fundo branco puro. */
.site-head {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: clamp(18px, 2.6vw, 32px) var(--margin);
}
/* absolute e não um filho de flex: o ::before de um flex container seria um item
   de flex e entrava na distribuição do space-between. */
.site-head::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 200%;
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--ink) 88%, transparent) 0%,
    color-mix(in srgb, var(--ink) 86%, transparent) 46%,
    color-mix(in srgb, var(--ink) 40%, transparent) 74%,
    transparent 100%
  );
}

.brand {
  font-family: var(--serif);
  font-size: 19px;
  font-weight: 500;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  white-space: nowrap;
}
.brand em { font-style: italic; }

/* Na home o scrub põe a marca a opacity 0 por estilo inline (até ~55% da
   pista quem faz de logótipo é o wordmark gigante do hero). Isso apagava
   também o foco de teclado: o 2.º Tab caía neste link e não se via nada.
   O !important é preciso para bater o estilo inline que o GSAP escreve. */
.site-head .brand:focus-visible { opacity: 1 !important; }

.site-nav { display: flex; gap: clamp(18px, 2.4vw, 40px); }

.site-nav a {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  position: relative;
  padding-block: 4px;
  opacity: 0.72;
  transition: opacity var(--dur-micro) var(--ease-out);
}
.site-nav a::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 2px;
  background: var(--acc);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 500ms var(--ease-out);
}
.site-nav a:hover, .site-nav a.is-active { opacity: 1; }
.site-nav a:hover::after, .site-nav a.is-active::after { transform: scaleX(1); }

.lang { display: flex; gap: 10px; }
.lang a, .lang span { font-size: var(--fs-label); letter-spacing: 0.2em; }
.lang .is-current { opacity: 1; }
/* Mesmo remédio que o .foot-links a já usa: token opaco quanto baste e opacity a
   1, em vez de apagar tinta opaca com opacity. O critério tem de ser o mesmo no
   rodapé e no cabeçalho. Medido por getComputedStyle com composição de alfa
   acumulado, nas 15 páginas x 1440/768/390: o "EN" a opacity 0.4 dava 3.47:1 em
   45 de 45 combinações e o separador "/" a 0.3 dava 2.43:1, e é um <a>, portanto
   reprovava AA em repouso e só cumpria ao passar o rato (11.22:1). Com o
   --bone-dim ficam ambos em 5.84:1 sobre o #0A0A0B, e o hover passa a ir a
   --bone (17.54:1) em vez de parar a meio caminho. A hierarquia da caixa
   mantém-se: o idioma corrente é o único a tinta cheia. */
.lang .sep { color: var(--bone-dim); opacity: 1; }
.lang a { color: var(--bone-dim); opacity: 1; }
.lang a:hover { color: var(--bone); opacity: 1; }

/* ---- Footer ------------------------------------------------------------ */

/* O padding-bottom nao e folga decorativa: e a reserva do canto onde vive o
   .progress, que e position:fixed em `inset: auto var(--margin) 20px auto`
   (ver "Indicador de percurso", mais abaixo neste ficheiro) e por isso assenta
   por cima do fim do documento quando o visitante chega ao fundo. Medido com
   os 32px antigos, cookies aceites e scroll ao fundo: a 1440x900 a caixa do
   .progress dava {y:863, bottom:880, right:1382.4} contra .foot-links a acabar
   em bottom=867.7, right=1254, ou seja 4.7px de sobreposicao vertical e 178.6px
   de horizontal, nas 13 paginas de conteudo. A 768 e a 390 o .p-label esconde-se
   e sobra a regua de 120x1px, que ficava 11.2px e 10.7px por baixo do ultimo
   link e se lia como um sublinhado solto de "Desenvolvido por UpWeGo".
   O .progress ocupa de 20px a 37px acima do fundo da janela (17px de caixa em
   desktop, 1px de regua nos outros dois); 72px poe a ultima linha do rodape
   35px acima do topo dele. A reserva de 240px que esta no sections.css e a da
   barra de cookies, que e mais alta e so vale enquanto o aviso esta de pe;
   esta vale sempre, porque o .progress nunca se vai embora. */
.site-foot {
  border-top: 1px solid var(--hair);
  padding: clamp(48px, 7vh, 96px) var(--margin) 72px;
}

.foot-grid {
  display: grid;
  /* 280px e o minimo que aloja o email sem ele transbordar para a coluna do
     lado: max-content do endereco = 267px a 30px de corpo. Com 200px a coluna
     descia a 204.8px em larguras de tablet e o email era impresso por cima da
     morada da coluna Estudio. */
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 40px var(--gutter);
  max-width: var(--max-w);
  margin-inline: auto;
}

/* line-height 1.25 e nao o 1.08 global: a caixa da fonte da Syne mede ate
   1.25em (medido: 25px a 20px de corpo, 35px a 28.8px), portanto com 1.08 a
   caixa de texto de cada linha transbordava para a linha seguinte. Como aqui
   estas duas linhas sao ancoras (tel: e mailto:), esse transbordo dava o hit
   test do fundo dos digitos ao email. */
/* Espacamento do rotulo de cada coluna do rodape. Vivia em 45 atributos
   style="margin-bottom: 14px" espalhados por quinze paginas, todos a dizer o
   mesmo; passa a viver aqui, ao lado das outras regras do rodape. */
.foot-grid .label { margin-bottom: 14px; }
.foot-grid .display-m { font-size: clamp(20px, 2vw, 30px); line-height: 1.25; }
.foot-grid a:hover, .foot-grid a:focus-visible { color: var(--acc); }
/* Estas duas linhas display-m consecutivas sao ancoras (tel: e mailto:). Com o
   line-height antigo as caixas de texto sobrepunham-se 3.9px e o mailto, por ser
   o ultimo no DOM, ganhava o hit test na ultima linha de tinta dos digitos: ou
   seja, clicar no numero abria o cliente de email. O line-height acima resolve a
   sobreposicao; o inline-block faz a caixa da ancora coincidir com a line box,
   para o alvo de clique ser exatamente a linha; o overflow-wrap deixa o endereco
   quebrar em vez de transbordar da coluna em ecras estreitos. */
.foot-grid .display-m a {
  display: inline-block;
  max-width: 100%;
  overflow-wrap: anywhere;
}
.foot-grid .display-m a:focus-visible { outline-offset: 2px; }
/* --bone-dim e nao --bone-faint: esta linha leva o copyright e os cinco links
   legais, incluindo o Livro de Reclamacoes, que e obrigacao legal. Com
   --bone-faint (alpha .24) o copyright media 1.8:1 contra o --ink e os links,
   que ainda levavam opacity .7 por cima, 1.44:1 em pixeis renderizados. O
   minimo do WCAG para texto de corpo e 4.5:1. --bone-dim (alpha .56) da
   rgb(141,139,136) sobre rgb(10,10,11) = 5.8:1, que e o valor a que o Journal
   ja estava. */
.foot-meta {
  max-width: var(--max-w);
  margin: 64px auto 0;
  display: flex;
  flex-wrap: wrap;
  gap: 16px 32px;
  justify-content: space-between;
  font-size: var(--fs-label);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--bone-dim);
}


/* ---- Indicador de percurso (M9) ---------------------------------------- */

/* O mix-blend-mode: difference estava no .progress inteiro. Isso resolvia a
   legibilidade da ETIQUETA sobre qualquer fundo, mas partia a barra: sob
   difference o que se pinta e |fundo - cor|, portanto o racio entre a parte
   cheia e a parte vazia deixava de ser uma propriedade do componente e passava
   a ser uma propriedade da foto por tras. Medido nos mesmos pontos de scroll:
   1.63:1 nas experiencias e 2.80:1 no evento-wild, ambos abaixo do minimo de
   3:1 para componentes, num elemento fixo que existe nas 15 paginas.
   O trilho e por isso opaco (--rail, o mesmo cinzento que o --hair ja pintava
   sobre o preto) e a parte cheia continua a ser o acento: o racio cheio/vazio
   fica fixo em 6.2:1 em qualquer pagina e com qualquer dos quatro acentos.

   Mudar a blend para a ETIQUETA nao resolvia a legibilidade dela: desligava-a.
   O .progress e position:fixed com z-index 60, ou seja e um contexto de
   empilhamento e, para efeitos de composicao, um grupo ISOLADO. A blend de um
   filho compoe contra o interior do grupo, que aqui e transparente, e nunca
   chega a pagina por tras. Medido no evento-wild a 1440x900, 40% do percurso,
   por pixel de nucleo de glifo: a etiqueta #WILD ficava com minimo 1.17:1 e
   mediana 1.24:1, 100% dos pixeis abaixo de 3:1, branco sobre branco.

   O que a etiqueta precisa e da mesma coisa que o cabecalho: um fundo proprio.
   Um veu radial ancorado no canto inferior direito, quase opaco por cima do
   componente e desvanecido para nada a duas dezenas de pixeis dele. Sobre o
   preto do corpo nao se ve; sobre foto le-se como vinheta de canto. O pior
   fundo medido por baixo desta etiqueta e 213 de 255 (evento-wild a 40%), e a
   0.93 de veu isso da 8.4:1 previstos. A blend inerte sai. */
.progress {
  position: fixed;
  inset: auto var(--margin) 20px auto;
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 14px;
}
/* As medidas nao sao decorativas, resolvem duas restricoes que puxam em sentidos
   contrarios.
   1) O degrade tem de chegar a ZERO antes do bordo da caixa, senao o bordo da
      caixa ve-se como um degrau. Com o centro a 50% 50% e raios de 50% x 50%,
      qualquer ponto do bordo esta a distancia >= 1, ou seja ja a zero.
   2) A MESETA opaca tem de ser tao pequena quanto possivel, porque o que estiver
      por baixo dela e apagado: a 0.92 de veu, texto --bone sobre --ink cai de
      17.54:1 para 1.16:1. Uma primeira versao desta regra usou uma caixa de
      470x139 ancorada no canto e lavou o quarto inferior direito das
      experiencias, incluindo duas linhas da lista de servicos. A meseta acaba
      aos 74% do raio, o que da uma elipse de 258x67, ou seja pouco mais do que
      o proprio componente (244x15), que ja tapava o que la estivesse. O
      desvanecimento seguinte tem 45px na horizontal e 12px na vertical.
   O ponto de conteudo mais afastado do centro (o bordo esquerdo da etiqueta, a
   122px e 7.5px) cai a 0.720 do raio, dentro da meseta. */
.progress::before {
  content: '';
  position: absolute;
  inset: -38px -52px;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
    50% 50% at 50% 50%,
    color-mix(in srgb, var(--ink) 94%, transparent) 0%,
    color-mix(in srgb, var(--ink) 92%, transparent) 74%,
    transparent 100%
  );
}
.progress .p-label {
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  opacity: 0.7;
  transition: opacity var(--dur-micro) linear;
  min-width: 110px;
  text-align: right;
}
.progress .p-label.is-swapping { opacity: 0; }
.progress .p-track {
  width: 120px; height: 1px;
  background: var(--rail);
  position: relative;
  overflow: hidden;
}
.progress .p-fill {
  position: absolute; inset: 0;
  background: var(--acc);
  transform: scaleX(0);
  transform-origin: left;
}

/* ---- Corte a negro (M5) ------------------------------------------------- */

.shutter {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--void);
  clip-path: inset(0 0 100% 0);
  pointer-events: none;
}
.shutter.is-covering { clip-path: inset(0 0 0 0); }
.shutter.is-closing {
  transition: clip-path var(--dur-cut) var(--ease-in);
  clip-path: inset(0 0 0 0);
}
.shutter.is-open {
  transition: clip-path 620ms var(--ease-out);
  clip-path: inset(100% 0 0 0);
}

/* ---- Cursor de luz (M6) ------------------------------------------------- */

@media (hover: hover) and (pointer: fine) {
  .cursor {
    position: fixed;
    top: 0; left: 0;
    z-index: 110;
    width: 8px; height: 8px;
    border-radius: 50%;
    background: var(--glow);
    mix-blend-mode: difference;
    pointer-events: none;
    display: grid;
    place-items: center;
    transition:
      width 380ms var(--ease-out),
      height 380ms var(--ease-out),
      background-color 380ms var(--ease-out),
      border-color 380ms var(--ease-out);
    border: 1px solid transparent;
    will-change: transform;
  }
  .cursor .c-text {
    font-size: 9px;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--glow);
    opacity: 0;
    transition: opacity var(--dur-micro) linear;
  }
  .cursor.is-hover {
    width: 56px; height: 56px;
    background: transparent;
    border-color: var(--glow);
  }
  .cursor.is-media { width: 72px; height: 72px; background: transparent; border-color: var(--glow); }
  .cursor.is-media .c-text { opacity: 1; }
  body.has-cursor, body.has-cursor a, body.has-cursor button { cursor: none; }
  body.has-cursor .cookie-bar, body.has-cursor .cookie-bar a { cursor: auto; }
  body.has-cursor .cookie-bar button { cursor: pointer; }
  .cursor.is-off { opacity: 0; }
  /* teclado devolve o cursor nativo */
  body.kb-nav, body.kb-nav a, body.kb-nav button { cursor: auto; }
  body.kb-nav .cursor { display: none; }
}
@media (hover: none), (pointer: coarse) {
  .cursor { display: none; }
}

/* ---- Split-text (M3) ---------------------------------------------------- */

.split-line { display: block; overflow: hidden; }
/* A mascara tem de ser MAIS ALTA do que a caixa da linha. Com a Syne a
   lh/fs 0.96 a tinta sai 0.098em acima do topo e 0.098em abaixo do fundo
   (maximo medido em 516 combinacoes elemento x largura), e um overflow que
   corta na caixa come a cedilha do "c" e a perna do "g". O corte passa entao
   a ser feito por clip-path de insets NEGATIVOS, que afasta a lamina da
   caixa sem mexer no layout. Por padding + margem negativa nao dava: as
   margens de irmaos colapsam, so uma das duas conta, e cada linha ganhava
   entrelinha a mais.
   Nos lados o corte fica EXATAMENTE onde estava (inset 0): quem transborda
   na horizontal e uma palavra maior do que a coluna a 320px, e isso e
   tipografia, nao mascara. */
@supports (clip-path: inset(1px)) {
  .split-line { overflow: visible; clip-path: inset(-0.12em 0 -0.14em); }
}
.split-line > .sl-inner {
  display: block;
  /* Nasce escondido ATRAS da lamina de baixo, que agora esta 0.14em mais
     abaixo: uma caixa de linha (100%) + essa folga + a tinta que ainda sobe
     0.098em acima do topo da propria linha. Duracao, curva e stagger ficam
     exatamente como estavam; so a distancia acompanha a mascara. */
  transform: translateY(calc(100% + 0.28em));
  opacity: 0;
}
.is-revealed .split-line > .sl-inner {
  transform: translateY(0);
  opacity: 1;
  transition:
    transform 900ms var(--ease-out),
    opacity 500ms linear;
  /* Stagger de 90ms por linha, sem tecto. O indice vem do buildLines() em
     --sl-i: com nth-child o stagger parava na 6a linha, e o h1 do artigo
     "O momento em que a sala muda" parte em 7 linhas a 320px (iPhone SE, e a
     largura que a WCAG 1.4.10 exige) -- a 7a ficava com atraso 0s e subia ao
     mesmo tempo que a 1a, com um buraco no meio. */
  transition-delay: calc(var(--sl-i, 0) * 90ms);
}

/* fade simples para leads */
.fade-up { opacity: 0; transform: translateY(16px); }
.fade-up.is-revealed {
  opacity: 1; transform: translateY(0);
  transition: opacity 700ms linear, transform 700ms var(--ease-out);
}

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

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .split-line > .sl-inner { transform: none; opacity: 1; }
  .fade-up { opacity: 1; transform: none; }
  .rule { transform: scaleX(1); }
}

.skip-link {
  position: absolute;
  top: -48px; left: 16px;
  z-index: 200;
  background: var(--bone); color: var(--ink);
  padding: 10px 18px;
  font-size: 12px;
  letter-spacing: 0.1em;
  transition: top 200ms var(--ease-out);
}
.skip-link:focus { top: 16px; }

/* Header auto-hide */
.site-head {
  transition: transform 480ms var(--ease-out);
}
.site-head.is-hidden { transform: translateY(-110%); }
@media (prefers-reduced-motion: reduce) {
  .site-head { transition: none; }
}
