/* ===== ludus-tokens.css ===== */
/* ==========================================================================
   LUDUS ACTIUS — TOKENS
   Onda 1, item 1. Nenhum valor solto pode existir fora deste arquivo.

   ARQUITETURA
   -----------
   Não há light mode e dark mode. Há UMA paleta com DUAS superfícies, e cada
   uma tem um trabalho:

     .lx-deep   #131315   onde a imagem manda      (hero, espinha, retratos)
     .lx-lite   #f4f2ef   onde se lê e se decide   (método, preço, formulário)

   A superfície é declarada na SEÇÃO, não na página. Todo componente é escrito
   uma vez e resolve as cores da superfície em que está. Trocar o fundo de uma
   seção é trocar uma classe.

   Por isso não usamos prefers-color-scheme: a superfície aqui é decisão de
   composição, não preferência de sistema.

   CONTRASTE
   ---------
   Todos os pares abaixo foram medidos, não estimados. Os valores estão
   anotados em cada linha. Nenhum par de texto fica abaixo de 4.5:1 e nenhuma
   borda de campo fica abaixo de 3:1.
   ========================================================================== */

:root {

  /* ---------------------------------------------------------------------
     MARCA — constantes que não mudam com a superfície
     --------------------------------------------------------------------- */

  /* A escala do vermelho existe porque #c02428 sobre #131315 dá 3.11:1.
     Passa para título grande e elemento de interface, falha para corpo de
     texto. Cada degrau tem um uso definido. Não improvisar. */
  --red-900: #951c1f;   /*  7.63:1 sobre clara — hover no claro          */
  --red-700: #c02428;   /*  5.33:1 sobre clara — a cor da marca          */
  --red-500: #d8383c;   /*  4.02:1 sobre profunda — filete, título grande */
  --red-400: #e8564f;   /*  5.19:1 sobre profunda — link e texto no escuro */
  --red-300: #f0736b;   /*  6.51:1 sobre profunda — anel de foco no escuro */

  --charcoal:  #131315;
  --bone:      #f4f2ef;

  /* ---------------------------------------------------------------------
     TIPOGRAFIA
     Lora nos títulos: já é da marca, e o calor dela é o que sustenta a
     inversão do gladiador para inclusão. Archivo no corpo e nos dados:
     substitui a Noto Sans, que era fallback do tema e não escolha.
     Duas famílias. É o limite.
     --------------------------------------------------------------------- */
  --font-display: "Lora", Georgia, "Times New Roman", serif;
  --font-body:    "Archivo", "Helvetica Neue", Arial, sans-serif;

  /* O meio de cada clamp é calculado para o máximo ser atingido perto de
     1650px de viewport, não por volta de 1100. Com a curva antiga, um notebook
     de 1280 recebia exatamente o mesmo corpo de um monitor de 1920, e com
     640px a menos de tela em volta. Fórmula: vw = maxpx / 1650 * 100. */
  --t-display: clamp(2.50rem, 5.10vw, 5.25rem);
  --t-h1:      clamp(1.95rem, 3.40vw, 3.50rem);
  --t-h2:      clamp(1.50rem, 2.30vw, 2.35rem);
  --t-h3:      clamp(1.15rem, 1.40vw, 1.45rem);
  --t-lead:    clamp(1.00rem, 1.20vw, 1.25rem);
  --t-body:    1.0625rem;   /* 17px */
  --t-sm:      0.9375rem;   /* 15px */
  --t-xs:      0.8125rem;   /* 13px */
  --t-label:   0.6875rem;   /* 11px, sempre em caixa alta com tracking */

  --lh-display: 1.02;
  --lh-title:   1.12;
  --lh-lead:    1.45;
  --lh-body:    1.65;

  --tr-display: -0.022em;
  --tr-title:   -0.014em;
  --tr-body:     0;
  --tr-label:    0.16em;

  --measure: 66ch;          /* largura máxima de linha de leitura */
  --measure-tight: 46ch;    /* para lead e citação */

  /* ---------------------------------------------------------------------
     ESPAÇO
     --------------------------------------------------------------------- */
  --sp-1:  4px;
  --sp-2:  8px;
  --sp-3:  12px;
  --sp-4:  16px;
  --sp-6:  24px;
  --sp-8:  32px;
  /* Os tres degraus grandes foram recalibrados em 21/08, junto com o ritmo de
     secao abaixo. Eles nao sao padding de componente, sao VAO DE LAYOUT:
     margem entre bloco e bloco, gap de grade de duas colunas, respiro antes de
     um fechamento. Foram a 60% e arredondados de volta para a grade de 4px.

     DIVIDA DE NOME, e ela e real: o sufixo desta escala codificava o valor em
     unidades de 4px, entao --sp-12 significava 12 x 4 = 48. Com 28px o nome
     passou a ser historico. Renomear para --sp-7 / --sp-10 / --sp-14 exige
     varrer os cinco arquivos de CSS e nao cabia nesta sessao; esta anotado no
     CONTINUAR-AQUI como limpeza. O comportamento esta certo, o nome e que
     envelheceu. Do --sp-1 ao --sp-8 nada mudou: ali o sufixo continua exato. */
  --sp-12: 28px;   /* era 48 */
  --sp-16: 40px;   /* era 64 */
  --sp-24: 56px;   /* era 96 */
  --sp-32: 128px;

  /* Três ritmos de seção, não um. Cinco seções da mesma altura em sequência
     é o anti-padrão estrutural número um. A variação é decisão, não acaso.

     Reduzidos duas vezes, e a proporção entre os três foi mantida nas duas.
     O que muda é a densidade da página, não o ritmo.

       original       48/7/80    ·  72/10/128  ·  96/14/176
       20/08, a 2/3   32/3.3/54  ·  48/5.2/86  ·  64/7.2/118
       21/08, a 60%   19/2/32    ·  29/3.1/52  ·  38/4.3/71

     A segunda passada nasceu na /membership, que tem sete seções e é a página
     mais longa do site: o mesmo ar que compõe uma home de oito seções virava
     rolagem morta com o visitante comparando preço. Ficou melhor nas três, e
     por isso desceu para cá em vez de continuar um escopo de página. */
  --sec-tight: clamp(19px, 1.98vw, 32px);
  --sec-base:  clamp(29px, 3.12vw, 52px);
  --sec-tall:  clamp(38px, 4.32vw, 71px);

  --container: 1240px;
  --container-narrow: 860px;
  --gutter: clamp(20px, 5vw, 48px);

  /* ---------------------------------------------------------------------
     FORMA
     Quase reto. A marca é inscricional, romana. Canto arredondado em tudo é
     o default que achata identidade. Um sistema só, aplicado em todo lugar.
     --------------------------------------------------------------------- */
  --radius-sm: 2px;   /* campo, badge, botão */
  --radius-md: 4px;   /* card, painel */
  --radius-lg: 4px;   /* modal — mesmo valor, de propósito */

  --hair: 1px;        /* espessura do filete e dos divisores */
  --rule: 2px;        /* espessura do filete vermelho estrutural */

  --tap: 44px;        /* alvo mínimo de toque */

  /* A ESPIADA DOS CARROSSÉIS
     Todo carrossel do site mostra um pedaço do próximo item pela borda direita:
     é o aviso de que há mais, sem bolinha e sem seta. O problema aparece quando
     esse pedaço fica LEGÍVEL: na grade da semana dava para ler "7:00" e "8:15"
     do dia seguinte, e duas colunas de número brigavam pela leitura.

     Estreitar o cartão resolveria a legibilidade e mataria o aviso junto. A
     máscara separa as duas coisas: a espiada continua larga, e o conteúdo dela
     se dissolve antes de virar informação que se lê.

     Vive aqui, e não em cada componente, porque já são quatro lugares. Um valor,
     uma decisão. */
  --mask-peek: linear-gradient(to right, #000 calc(100% - 64px), transparent);

  /* ---------------------------------------------------------------------
     MOVIMENTO
     --------------------------------------------------------------------- */
  --dur-micro: 160ms;   /* hover, foco */
  --dur-state: 280ms;   /* transição de elemento */
  --dur-enter: 560ms;   /* entrada de seção, só abaixo da dobra */
  --ease:       cubic-bezier(0.4, 0, 0.2, 1);
  --ease-out:   cubic-bezier(0.16, 1, 0.3, 1);

  /* ---------------------------------------------------------------------
     CAMADAS — escala documentada, nada de z-index solto
     --------------------------------------------------------------------- */
  --z-base:    0;
  --z-raised:  10;
  --z-sticky:  100;
  --z-header:  200;
  /* A GAVETA FICA ABAIXO DO CABECALHO, E ISSO E DESENHO E NAO ACIDENTE
     Ela abre com 88px de recuo no topo justamente para nao tapar a barra: o
     hamburguer continua na tela e vira um X, que e como se fecha. Com a gaveta
     em --z-overlay ela passava POR CIMA da barra e enterrava o proprio botao de
     fechar; o X existia no CSS e ninguem conseguia alcancar.

     Por isso o degrau proprio, entre o sticky e o cabecalho. Modal de verdade,
     se um dia existir, usa --z-modal e ai sim cobre tudo. */
  --z-drawer:  150;
  --z-overlay: 300;
  --z-modal:   400;
}

/* ==========================================================================
   SUPERFÍCIE CLARA — onde se lê e se decide
   about · training · membership · schedule · contact · blog · legal
   ========================================================================== */

:root,
.lx-lite {
  --bg:          #f4f2ef;
  --bg-elevated: #ffffff;
  --bg-sunken:   #eceae6;

  --ink:       #1a1a1c;   /* 15.55:1 — corpo e título                */
  --ink-soft:  #57524e;   /*  6.90:1 — texto secundário              */
  --ink-faint: #6b655f;   /*  5.15:1 — legenda, label, metadado      */

  --line:        #ddd8d3;   /* divisor decorativo                    */
  --line-strong: #8f8781;   /*  3.16:1 — borda de campo de formulário */

  --accent:       var(--red-700);   /* 5.33:1 — link e texto */
  --accent-hover: var(--red-900);   /* 7.63:1                */
  --accent-rule:  var(--red-700);   /* o filete estrutural   */
  --accent-fg:    #ffffff;          /* 5.96:1 sobre o vermelho */

  --focus: var(--red-700);          /* 5.33:1 */

  --ok:   #2f6b3d;   /* 5.71:1 */
  --warn: #7a5a12;   /* 5.70:1 */
  --err:  #951c1f;   /* 7.63:1 */

  /* Sombra existe só na superfície clara. No escuro ela não lê, e o que
     separa plano lá é a borda. Um nível só, usado pouco. */
  --elev: 0 1px 2px rgba(26,26,28,.05), 0 14px 32px -22px rgba(26,26,28,.40);
  --elev-none: none;

  color-scheme: light;
}

/* ==========================================================================
   SUPERFÍCIE PROFUNDA — onde a imagem manda
   home · testimonials · diogo · os 4 programas · our-facility
   ========================================================================== */

.lx-deep {
  --bg:          #131315;
  --bg-elevated: #1a1a1d;
  --bg-sunken:   #0d0d0f;

  --ink:       #e9e5e2;   /* 14.82:1 */
  --ink-soft:  #a8a29d;   /*  7.35:1 */
  --ink-faint: #948d88;   /*  5.68:1 */

  --line:        #2e2e33;   /* divisor decorativo                    */
  --line-strong: #6b666f;   /*  3.32:1 — borda de campo de formulário */

  --accent:       var(--red-400);   /* 5.19:1 — link e texto no escuro */
  --accent-hover: var(--red-300);   /* 6.51:1                          */
  --accent-rule:  var(--red-500);   /* 4.02:1 — o filete estrutural    */
  --accent-fg:    #ffffff;

  --focus: var(--red-300);          /* 6.51:1 */

  --ok:   #6fb37c;   /* 7.44:1 */
  --warn: #d9a94a;   /* 8.59:1 */
  --err:  #e8564f;   /* 5.19:1 */

  --elev: none;
  --elev-none: none;

  color-scheme: dark;
}

/* Regra dura, e a razão de a escala do vermelho existir:
   na superfície profunda, --red-700 NUNCA carrega texto. Ele só aparece
   como preenchimento de botão (com --accent-fg branco em cima, 5.96:1).
   Para texto no escuro é --accent (--red-400). Para filete é --accent-rule. */


/* ===== ludus-base.css ===== */
/* ==========================================================================
   LUDUS ACTIUS — BASE
   Depende de ludus-tokens.css. Carregar sempre depois dele.

   Escopo: elementos globais, tipografia aplicada, botão, formulário, foco,
   ritmo de seção, e o filete. Tudo com prefixo .lx- para não brigar com o
   Elementor.

   Sobre especificidade: o Elementor gera CSS próprio com peso alto. Os
   valores de fonte e cor de título devem ser espelhados em
   Elementor > Configurações do site > Fontes globais / Cores globais.
   Este arquivo cuida do que é bloco HTML custom e do que é elemento nativo.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. FUNDAÇÃO
   -------------------------------------------------------------------------- */

*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis-weight: none;
}

/* Toda seção que declara superfície pinta o próprio fundo. Sem isso, uma
   seção .lx-deep herdaria o fundo claro do body e só o texto mudaria. */
.lx-deep,
.lx-lite {
  background-color: var(--bg);
  color: var(--ink);
}

img, picture, video, canvas, svg {
  display: block;
  max-width: 100%;
  height: auto;
}

/* Toda imagem de conteúdo leva width e height no HTML, para reservar espaço e
   não gerar layout shift.

   NÃO acrescentar aqui uma regra img[width][height]. Ela tem especificidade
   (0,2,1) e passa por cima de qualquer componente que defina altura por classe:
   .lx-brand__mark (0,1,0), .lx-photo img (0,1,1), .lx-coach__photo img (0,1,1).
   O height:auto da regra genérica acima já resolve, e perde para as classes,
   que é exatamente o comportamento desejado. */

/* --------------------------------------------------------------------------
   2. TIPOGRAFIA APLICADA
   -------------------------------------------------------------------------- */

.lx-display,
.lx-h1, .lx-h2, .lx-h3,
h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--ink);
  text-wrap: balance;
  margin: 0;
}

.lx-display { font-size: var(--t-display); line-height: var(--lh-display); letter-spacing: var(--tr-display); }
.lx-h1, h1  { font-size: var(--t-h1);      line-height: var(--lh-title);   letter-spacing: var(--tr-title); }
.lx-h2, h2  { font-size: var(--t-h2);      line-height: var(--lh-title);   letter-spacing: var(--tr-title); }
.lx-h3, h3  { font-size: var(--t-h3);      line-height: 1.25;              letter-spacing: -0.008em; }

/* Descendente em itálico corta quando line-height fica em 1.0. */
.lx-display em,
.lx-h1 em, h1 em { font-style: italic; line-height: 1.1; padding-bottom: 0.06em; display: inline-block; }

/* Subtítulo. Não é h4 disfarçado: é texto de apoio ao título. */
.lx-lead {
  font-family: var(--font-body);
  font-size: var(--t-lead);
  line-height: var(--lh-lead);
  color: var(--ink-soft);
  max-width: var(--measure-tight);
  margin: 0;
}

/* Nada de token longo empurrando a linha para fora do container: telefone,
   e-mail, URL. Quebra feia é melhor que rolagem horizontal. */
p, li, dd { overflow-wrap: break-word; }
p, li { max-width: var(--measure); }
p { margin: 0 0 1em; }
p:last-child { margin-bottom: 0; }

/* Label em caixa alta. Usar com parcimônia: no máximo um a cada três seções.
   Um rótulo acima de todo título produz exatamente o ritmo templatizado. */
.lx-label {
  font-family: var(--font-body);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0;
}

.lx-small { font-size: var(--t-sm); }
.lx-xs    { font-size: var(--t-xs); }
.lx-muted { color: var(--ink-soft); }
.lx-faint { color: var(--ink-faint); }

/* Número em tabela e preço: alinhamento vertical de dígito. */
.lx-num { font-variant-numeric: tabular-nums; letter-spacing: 0; }

strong, b { font-weight: 600; color: var(--ink); }

blockquote {
  margin: var(--sp-6) 0;
  padding-left: var(--sp-6);
  border-left: var(--rule) solid var(--accent-rule);
  font-family: var(--font-display);
  font-size: var(--t-lead);
  line-height: 1.5;
  color: var(--ink);
}
blockquote cite {
  display: block;
  margin-top: var(--sp-3);
  font-family: var(--font-body);
  font-style: normal;
  font-size: var(--t-label);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* --------------------------------------------------------------------------
   3. LINK
   -------------------------------------------------------------------------- */

a {
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 34%, transparent);
  transition: color var(--dur-micro) var(--ease),
              border-color var(--dur-micro) var(--ease);
}
a:hover { color: var(--accent-hover); border-bottom-color: currentColor; }

/* Link dentro de bloco de navegação ou card não recebe sublinhado. */
.lx-nav a,
.lx-plain a,
a.lx-plain { border-bottom: 0; }

/* --------------------------------------------------------------------------
   4. FOCO
   Nunca outline:none sem substituto. O anel precisa ler sobre fundo chapado
   e sobre foto: por isso outline + sombra de contorno oposto.
   -------------------------------------------------------------------------- */

:focus { outline: none; }

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Sobre imagem, o anel sozinho pode sumir. Este modificador adiciona um
   contorno de separação. Aplicar em controle que fica sobre foto. */
.lx-on-media:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px rgba(0,0,0,.55);
}

/* --------------------------------------------------------------------------
   5. O FILETE
   O elemento do logo, agora estrutural. É a única linguagem de movimento do
   site: costura a espinha e conduz o método.
   -------------------------------------------------------------------------- */

.lx-rule {
  display: block;
  width: 100%;
  height: var(--rule);
  background: var(--accent-rule);
  border: 0;
  margin: 0;
  transform-origin: left center;
}

.lx-rule--short { width: 64px; }
.lx-rule--hair  { height: var(--hair); background: var(--line); }

/* O FILETE QUE RISCA
   O mesmo elemento, agora argumentando: ele corta a objeção quando a história
   que a desmente entra em vista. Usado na espinha da home e nas quatro
   histórias da /testimonials.

   POR QUE NÃO É UM ::after COM top: 52%
   -------------------------------------
   Porque uma régua única desenhada sobre a caixa do parágrafo só funciona
   quando a objeção cabe em uma linha. Em duas, e é o caso de metade delas, a
   régua cai no vão entre as linhas: lê como sublinhado da primeira, com a
   segunda intacta logo abaixo. Foi assim na home até 21/08.

   O filete precisa cortar CADA linha. A forma de conseguir isso sem quebrar o
   texto em um elemento por linha é pintá-lo como fundo de um elemento inline
   e mandar clonar a decoração em cada fragmento de linha. O desenho continua
   sendo desenho: cresce de 0% a 100% da largura de cada fragmento, no mesmo
   tempo e na mesma curva do resto do site.

   O deslocamento é em em, então ele acompanha qualquer corpo de texto. O valor
   foi medido em captura, no meio da altura-de-x da Lora itálica, não estimado.

   Markup: <p class="..."><span class="lx-strike">&ldquo;...&rdquo;</span></p>
   O estado vem de .is-resolved em qualquer ancestral, que é o que o
   ludus-motion.js escreve nos [data-lx-spine-item]. */
.lx-strike {
  display: inline;
  -webkit-box-decoration-break: clone;
          box-decoration-break: clone;
  background-image: linear-gradient(var(--accent-rule), var(--accent-rule));
  background-repeat: no-repeat;
  background-position: 0 0.80em;
  background-size: 0% var(--rule);
  transition: background-size var(--dur-enter) var(--ease-out);
}
.is-resolved .lx-strike { background-size: 100% var(--rule); }

/* Estado inicial quando o filete é animado. O JS remove ao entrar em vista.
   Sem JS, ou com movimento reduzido, o filete já nasce desenhado. */
.lx-rule[data-lx-draw] { transform: scaleX(0); }
.lx-js .lx-rule[data-lx-draw] { transition: transform var(--dur-enter) var(--ease-out); }
.lx-rule[data-lx-draw].is-drawn { transform: scaleX(1); }

/* --------------------------------------------------------------------------
   6. BOTÃO
   Quatro estados obrigatórios em cada variante. Retangular por decisão:
   a marca é inscricional.
   -------------------------------------------------------------------------- */

.lx-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--tap);
  padding: var(--sp-3) var(--sp-8);
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--t-sm);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;      /* rótulo de CTA nunca quebra em duas linhas */
  cursor: pointer;
  transition: background-color var(--dur-micro) var(--ease),
              border-color var(--dur-micro) var(--ease),
              color var(--dur-micro) var(--ease),
              transform var(--dur-micro) var(--ease);
}

/* NO TELEFONE O BOTAO CEDE MARGEM, NAO TEXTO
   O nowrap acima e deliberado, e continua. O efeito colateral dele so aparece
   na coluna mais estreita do site: um rotulo longo vira um bloco indivisivel
   que empurra a grade inteira e a pagina ganha rolagem horizontal. Aconteceu em
   28/08, quando "Open the booking calendar" virou "Book my free visit and
   class": a home passou a ter 410px de conteudo num viewport de 390, e o fundo
   da secao parava antes do texto.

   Cortar o rotulo resolveria este caso e nao o proximo. Aqui quem cede sao os
   32px de respiro lateral, que existem para o botao ter presenca numa linha
   larga e nao fazem falta quando ele e a largura da tela. Sao 32px de folga
   para o rotulo, mais que os 20 que faltavam.

   A auditoria de estouro na captura.py existe para o proximo caso: ela mede a
   pagina a 390 e acusa se sobrar um pixel. */
@media (max-width: 520px) {
  .lx-btn {
    padding-inline: var(--sp-4);
    /* E AQUI O nowrap CEDE, PORQUE ELE NAO TEM COMO GANHAR
       Cortar so o respiro resolveu a 390 e nao resolveu a 320: com o rotulo
       inteiro indivisivel, "Book my free visit and class" mede 260px, o painel
       do calendario soma 66px de moldura, e o bloco inteiro fica com um PISO de
       358px. Num aparelho de 320 sobram 280 depois da goteira. Nao existe
       ajuste de padding que caiba nisso.

       O comentario la em cima, "rotulo de CTA nunca quebra em duas linhas",
       vale numa linha larga, onde quebrar e escolha. Numa tela de 320 a escolha
       nao existe: ou o rotulo quebra, ou a pagina inteira ganha rolagem
       lateral e o fundo da secao para antes do texto. Botao de largura cheia
       com duas linhas centralizadas e o padrao em telefone, e o defeito que
       isto substitui nao tem defesa.

       De quebra, isto mata a classe inteira do bug em vez deste caso: com
       quebra permitida, o minimo do botao passa a ser a palavra mais longa do
       rotulo, e nao o rotulo. Nenhum texto futuro empurra a grade de novo. */
    white-space: normal;
    text-align: center;
  }
}

/* PRIMÁRIO — vermelho sólido com texto branco. 5.96:1 nas duas superfícies,
   porque o preenchimento é a mesma cor nos dois lados. */
.lx-btn--primary {
  background: var(--red-700);
  color: #ffffff;
  border-color: var(--red-700);
}
.lx-btn--primary:hover  { background: var(--red-900); border-color: var(--red-900); }
.lx-btn--primary:active { transform: translateY(1px); }

/* ==========================================================================
   MOLDURA
   Fundo elevado, filete de 1px e um respiro entre a borda e o conteudo. E o
   que impede foto e video de flutuarem soltos sobre a superficie: sem ela a
   imagem termina no nada e o olho nao sabe onde acaba o conteudo e comeca a
   pagina.

   Vive aqui, no base, e nao no CSS de uma pagina, porque ja tem dois donos: os
   videos da /testimonials e as fotos de programa da /training. Duas definicoes
   com as mesmas quatro propriedades e nomes diferentes significa que mudar a
   espessura do filete um dia exigiria lembrar das duas.
   ========================================================================== */

.lx-frame {
  background: var(--bg-elevated);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: var(--sp-3);
}

/* SECUNDÁRIO — contorno. Herda a cor do texto da superfície. */
.lx-btn--secondary {
  background: transparent;
  color: var(--ink);
  border-color: var(--line-strong);
}
.lx-btn--secondary:hover  { border-color: var(--ink); background: color-mix(in srgb, var(--ink) 6%, transparent); }
.lx-btn--secondary:active { transform: translateY(1px); }

/* GHOST — só texto com filete embaixo. Para ação terciária. */
.lx-btn--ghost {
  background: transparent;
  color: var(--accent);
  border: 0;
  border-bottom: var(--rule) solid var(--accent-rule);
  border-radius: 0;
  padding: var(--sp-2) 0;
  min-height: auto;
}
.lx-btn--ghost:hover { color: var(--accent-hover); }

.lx-btn[disabled],
.lx-btn[aria-disabled="true"] {
  opacity: .45;
  cursor: not-allowed;
  pointer-events: none;
}

/* Carregando. O rótulo permanece legível; nada de spinner substituindo texto. */
.lx-btn[data-loading="true"] { pointer-events: none; opacity: .7; }
.lx-btn[data-loading="true"]::after {
  content: "";
  width: 14px; height: 14px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: lx-spin 700ms linear infinite;
}
@keyframes lx-spin { to { transform: rotate(360deg); } }

/* --------------------------------------------------------------------------
   7. FORMULÁRIO
   Label acima do campo, sempre. Placeholder não é label.
   Erro comunicado por texto, não só por cor.
   -------------------------------------------------------------------------- */

.lx-field { display: flex; flex-direction: column; gap: var(--sp-2); margin-bottom: var(--sp-6); }

.lx-field label {
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.lx-field input,
.lx-field textarea,
.lx-field select {
  width: 100%;
  min-height: var(--tap);
  padding: var(--sp-3) var(--sp-4);
  background: var(--bg-elevated);
  color: var(--ink);
  border: 1px solid var(--line-strong);   /* 3.16:1 claro / 3.32:1 escuro */
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: 1.4;
  transition: border-color var(--dur-micro) var(--ease);
}
.lx-field textarea { min-height: 120px; resize: vertical; }

.lx-field input::placeholder,
.lx-field textarea::placeholder { color: var(--ink-faint); opacity: 1; }

.lx-field input:hover,
.lx-field textarea:hover,
.lx-field select:hover { border-color: var(--ink-faint); }

.lx-field input:focus-visible,
.lx-field textarea:focus-visible,
.lx-field select:focus-visible { border-color: var(--focus); outline-offset: 1px; }

.lx-field .lx-hint { font-size: var(--t-xs); color: var(--ink-faint); }

.lx-field[data-invalid="true"] input,
.lx-field[data-invalid="true"] textarea,
.lx-field[data-invalid="true"] select { border-color: var(--err); border-width: 2px; }

.lx-field .lx-error {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  font-size: var(--t-xs);
  font-weight: 600;
  color: var(--err);
}
/* Marcador textual antes da mensagem: a cor sozinha não comunica erro. */
.lx-field .lx-error::before { content: "Erro:"; flex: none; }

/* Grupo de rádio do campo Goal (Health / Fitness / Performance / Accessibility) */
.lx-choice { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.lx-choice label {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  cursor: pointer;
  text-transform: none;
  letter-spacing: 0;
  font-size: var(--t-sm);
  color: var(--ink);
  transition: border-color var(--dur-micro) var(--ease),
              background-color var(--dur-micro) var(--ease);
}
.lx-choice input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.lx-choice input:checked + label { border-color: var(--red-700); background: var(--red-700); color: #ffffff; }
.lx-choice input:focus-visible + label { outline: 2px solid var(--focus); outline-offset: 2px; }

/* Estados do formulário inteiro */
.lx-form-status { padding: var(--sp-4); border-radius: var(--radius-sm); font-size: var(--t-sm); }
.lx-form-status[data-state="ok"]  { border: 1px solid var(--ok);  color: var(--ok);  }
.lx-form-status[data-state="err"] { border: 1px solid var(--err); color: var(--err); }

/* --------------------------------------------------------------------------
   8. LAYOUT
   -------------------------------------------------------------------------- */

.lx-container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.lx-container--narrow { max-width: var(--container-narrow); }

/* Ritmo de seção. Escolher deliberadamente por seção, nunca repetir o mesmo
   em cinco seguidas. */
.lx-sec        { padding-block: var(--sec-base); }
.lx-sec--tight { padding-block: var(--sec-tight); }
.lx-sec--tall  { padding-block: var(--sec-tall); }
.lx-sec--flush { padding-block: 0; }

.lx-measure { max-width: var(--measure); }

/* Conteúdo largo nunca faz a página rolar de lado. */
.lx-scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* --------------------------------------------------------------------------
   9. TRANSIÇÃO ENTRE PÁGINAS
   Nativo, sem biblioteca. Chrome, Edge e Safari 18+ aplicam.
   Firefox ignora e navega normalmente.
   -------------------------------------------------------------------------- */

@view-transition { navigation: auto; }

::view-transition-old(root) { animation-duration: 180ms; }
::view-transition-new(root) { animation-duration: 260ms; }

/* --------------------------------------------------------------------------
   10. MOVIMENTO REDUZIDO
   Obrigatório. Desliga tudo que se move e entrega o estado final.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  /* Estado final, não estado inicial congelado. */
  .lx-rule[data-lx-draw] { transform: scaleX(1); }
  .lx-strike { background-size: 100% var(--rule); }

  @view-transition { navigation: none; }
}

/* --------------------------------------------------------------------------
   11. SEM JAVASCRIPT
   Nada de conteúdo escondido esperando JS que pode não chegar. O .lx-js é
   adicionado pelo ludus-motion.js; até lá, tudo nasce visível.
   -------------------------------------------------------------------------- */

.lx-skip {
  position: absolute;
  left: var(--sp-4);
  top: calc(-1 * var(--tap) - var(--sp-4));
  z-index: var(--z-modal);
  padding: var(--sp-3) var(--sp-6);
  background: var(--red-700);
  color: #ffffff;
  border-radius: var(--radius-sm);
  transition: top var(--dur-micro) var(--ease);
}
.lx-skip:focus { top: var(--sp-4); }


/* ===== ludus-chrome.css ===== */
/* ==========================================================================
   LUDUS ACTIUS — CROMO (cabeçalho e rodapé)
   Onda 1, item 2. Depende de ludus-tokens.css e ludus-base.css.

   DECISÃO DE SUPERFÍCIE
   ---------------------
   O cabeçalho é sempre .lx-deep. Sólido, carvão, um comportamento só.

   A alternativa seria transparente sobre o hero e sólido ao rolar. Fica bonito
   na demonstração e quebra na vida real: quem cai no meio da página por link
   de âncora, quem volta pelo botão do navegador, ou quem chega por uma página
   de superfície clara vê o estado errado por um instante. Barra sólida é
   decisão de masthead, não de falta de ambição.

   ALTURA
   ------
   72px, 60px depois de rolar. Teto do nosso padrão é 80px. Cabeçalho de
   agência que come 15% da viewport é desperdício em site cujo objetivo é lead.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. CABEÇALHO
   -------------------------------------------------------------------------- */

.lx-header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur-state) var(--ease);
  /* Persiste através da transição de página em vez de re-animar. */
  view-transition-name: lx-header;
}

/* Um ancestral com overflow diferente de visible mata o position:sticky.
   No Elementor, conferir a seção-pai do cabeçalho. */

.lx-header.is-scrolled { border-bottom-color: var(--line); }

.lx-header__inner {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
  height: 72px;
  display: flex;
  align-items: center;
  gap: var(--sp-8);
  transition: height var(--dur-state) var(--ease);
}
.lx-header.is-scrolled .lx-header__inner { height: 60px; }

/* Âncora não pode parar embaixo da barra. */
html { scroll-padding-top: 88px; }

/* --------------------------------------------------------------------------
   2. A MARCA
   Símbolo: ludus-mark.png. Desde 26/08 é o CAPACETE RECORTADO DO LOGO OFICIAL
   que o cliente enviou, a versão branca vertical, 280x524 na resolução nativa
   dela. Meia-face branca sólida, meia-face cinza, crista vermelha. Antes disso
   era um derivado feito aqui, guardado em ludus-mark-legacy.png: mesma forma,
   mas com contorno branco em volta da silhueta inteira e o interior esquerdo
   preto. O derivado tinha borda mais forte a 34px; o oficial é o oficial, e a
   40px e a 34px os dois leem. Não voltar ao icon-white.png de 2022, que era
   silhueta vazada de verdade e sumia sobre carvão.

   Só entra em superfície .lx-deep. Nas três aparições que existem hoje
   (cabeçalho, coluna do rodapé, marca d'água do rodapé) o fundo é carvão.
   Em superfície clara este arquivo não serve: a meia-face branca some.

   Nome e MMXIV: texto vivo em Lora com tracking. Escala perfeita em qualquer
   densidade e é selecionável. O wordmark do logo oficial é raster e a marca do
   cabeçalho é horizontal, não vertical: continua valendo o P15, trocar por SVG.

   Altura: 40px, 34px depois de rolar. O símbolo é alto e estreito, com razão
   de 0,53. A 34px ele sai com 18px de largura.
   -------------------------------------------------------------------------- */

.lx-brand {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex: none;
  border-bottom: 0;
  color: var(--ink);
  text-decoration: none;
}
.lx-brand:hover { color: var(--ink); }

/* O SELETOR É DOBRADO PARA GANHAR DO ELEMENTOR, E ISSO NÃO É CAPRICHO.
   O Elementor injeta `.elementor img { height: auto; max-width: 100% }`, que é
   (0,1,1). `.lx-brand__mark` sozinho é (0,1,0) e PERDE: o `height: 40px` não
   aplica, e o capacete volta para os 524px nativos, atravessando o cabeçalho e
   cobrindo o hero. Dobrado, vira (0,2,0) e ganha.

   Só quebrava no WordPress: na prévia não existe `.elementor` em volta, então
   nenhuma captura, PDF ou artifact mostrava. Foi o cliente abrindo o site.

   É a mesma colisão que o comentário do `img[atributo]` no ludus-base.css já
   descrevia, só que desta vez a regra hostil vem de fora e não dá para apagar.
   Há uma auditoria no build-wordpress.py que reclama de regra nossa de imagem
   com especificidade abaixo de (0,1,1). */
.lx-brand__mark.lx-brand__mark {
  width: auto;
  height: 40px;
  flex: none;
  transition: height var(--dur-state) var(--ease);
}
.lx-header.is-scrolled .lx-brand__mark { height: 34px; }

.lx-brand__text { display: flex; flex-direction: column; gap: 2px; }

.lx-brand__name {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.05rem;
  line-height: 1;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
}

.lx-brand__est {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-body);
  font-size: 8.5px;
  font-weight: 600;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--ink-faint);
  white-space: nowrap;
}
/* O filete do logo, em miniatura. Mesma linguagem do filete estrutural. */
.lx-brand__est::before,
.lx-brand__est::after {
  content: "";
  height: 1px;
  flex: 1 1 auto;
  min-width: 10px;
  background: var(--accent-rule);
}

/* --------------------------------------------------------------------------
   3. NAVEGAÇÃO
   Uma linha só no desktop. Se não couber, corta item, não quebra linha.
   -------------------------------------------------------------------------- */

.lx-nav { margin-inline-start: auto; }

.lx-nav ul {
  display: flex;
  align-items: center;
  gap: var(--sp-8);
  list-style: none;
  margin: 0;
  padding: 0;
}
.lx-nav li { margin: 0; max-width: none; }

.lx-nav a {
  display: inline-flex;
  align-items: center;
  height: 40px;
  border-bottom: 0;
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-soft);
  white-space: nowrap;
  position: relative;
  transition: color var(--dur-micro) var(--ease);
}
.lx-nav a:hover { color: var(--ink); }

/* O item ativo carrega o filete. Nada de ponto colorido. */
.lx-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 6px;
  height: var(--rule);
  background: var(--accent-rule);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-state) var(--ease-out);
}
.lx-nav a:hover::after { transform: scaleX(1); }
.lx-nav a[aria-current="page"] { color: var(--ink); }
.lx-nav a[aria-current="page"]::after { transform: scaleX(1); }

/* --------------------------------------------------------------------------
   4. AÇÕES DO CABEÇALHO
   -------------------------------------------------------------------------- */

.lx-header__actions {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
  flex: none;
}

/* Telefone visível no desktop: metade do público de academia de bairro liga
   em vez de preencher formulário. */
.lx-header__tel {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  border-bottom: 0;
  font-size: 0.875rem;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  white-space: nowrap;
}
.lx-header__tel:hover { color: var(--accent-hover); }

.lx-header .lx-btn { padding-inline: var(--sp-6); }

/* --------------------------------------------------------------------------
   5. BOTÃO DO MENU E GAVETA
   -------------------------------------------------------------------------- */

.lx-burger {
  display: none;
  align-items: center;
  justify-content: center;
  width: var(--tap);
  height: var(--tap);
  margin-inline-end: calc(var(--sp-3) * -1);
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--ink);
  cursor: pointer;
}
.lx-burger span {
  display: block;
  position: relative;
  width: 22px;
  height: var(--rule);
  background: currentColor;
  transition: background-color var(--dur-micro) var(--ease);
}
.lx-burger span::before,
.lx-burger span::after {
  content: "";
  position: absolute;
  left: 0;
  width: 22px;
  height: var(--rule);
  background: currentColor;
  transition: transform var(--dur-state) var(--ease);
}
.lx-burger span::before { top: -7px; }
.lx-burger span::after  { top:  7px; }

.lx-burger[aria-expanded="true"] span { background-color: transparent; }
.lx-burger[aria-expanded="true"] span::before { transform: translateY(7px)  rotate(45deg); }
.lx-burger[aria-expanded="true"] span::after  { transform: translateY(-7px) rotate(-45deg); }

.lx-drawer {
  position: fixed;
  inset: 0;
  /* Abaixo do cabecalho de proposito: o padding de 88px no topo deixa a barra
     aparecendo, e e la que fica o X. Ver --z-drawer nos tokens. */
  z-index: var(--z-drawer);
  display: flex;
  flex-direction: column;
  background: var(--bg);
  padding: 88px var(--gutter) var(--sp-12);
  overflow-y: auto;
  overscroll-behavior: contain;
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--dur-state) var(--ease),
              visibility 0s linear var(--dur-state);
}
.lx-drawer[data-open="true"] {
  visibility: visible;
  opacity: 1;
  transition: opacity var(--dur-state) var(--ease), visibility 0s;
}

.lx-drawer ul { list-style: none; margin: 0 0 var(--sp-8); padding: 0; }
.lx-drawer li { margin: 0; max-width: none; border-bottom: 1px solid var(--line); }

.lx-drawer li a {
  display: flex;
  align-items: center;
  min-height: 64px;
  border-bottom: 0;
  font-family: var(--font-display);
  font-size: 1.5rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.lx-drawer li a[aria-current="page"] { color: var(--accent); }

.lx-drawer__foot { margin-top: auto; display: flex; flex-direction: column; gap: var(--sp-4); }
.lx-drawer__foot .lx-btn { width: 100%; }
.lx-drawer__meta { font-size: var(--t-sm); color: var(--ink-soft); }
.lx-drawer__meta a { color: var(--ink); font-weight: 600; }

/* Trava a rolagem do documento com a gaveta aberta. */
body.lx-locked { overflow: hidden; }

/* --------------------------------------------------------------------------
   6. RESPONSIVO DO CABEÇALHO
   -------------------------------------------------------------------------- */

@media (max-width: 1180px) {
  .lx-header__tel { display: none; }   /* vive na gaveta e no rodapé */
  .lx-nav ul { gap: var(--sp-6); }
}

@media (max-width: 1023px) {
  .lx-nav { display: none; }
  .lx-burger { display: inline-flex; }
  .lx-header__inner { gap: var(--sp-4); }

  /* QUEM EMPURRAVA PARA A DIREITA ERA A NAV, E ELA ACABA DE SUMIR
     O `.lx-nav { margin-inline-start: auto }` era o que jogava a navegacao e as
     acoes para o fim da barra. Escondendo a nav aqui, a margem foi junto com
     ela, e o hamburguer passou a se encostar no wordmark com o resto da barra
     vazia a direita: parecia menu solto no meio do nada, e nao um canto.

     Nao da para deixar a margem na nav e resolver, porque display: none tira o
     elemento da distribuicao do flex. A margem precisa mudar de dono junto com
     o ponto de virada. */
  .lx-header__actions { margin-inline-start: auto; }
}

@media (max-width: 560px) {
  .lx-header__actions .lx-btn { display: none; }  /* o CTA vive na gaveta */
  .lx-brand__est { display: none; }
  .lx-brand__name { font-size: 0.95rem; letter-spacing: 0.1em; }
}

/* --------------------------------------------------------------------------
   7. RODAPÉ
   -------------------------------------------------------------------------- */

/* O rodapé tem três planos tonais, do mais claro ao mais escuro. Não é
   gradiente: são três superfícies chapadas com uma hierarquia declarada.

     promessa   --bg-elevated   #1a1a1d   levantada, é onde se quer o olho
     colunas    --bg            #131315   o plano de referência
     legal      --bg-sunken     #0d0d0f   afunda, é rodapé de rodapé

   Rodapé chapado num tom só é o que faz a parte de baixo de todo site parecer
   sobra de layout. */

.lx-footer { padding-top: 0; }

/* A garantia fecha o rodapé. É a última coisa que a pessoa lê antes de sair,
   e é o argumento mais forte que o negócio tem. */
.lx-footer__promise {
  background: var(--bg-elevated);
  border-block: 1px solid var(--line);
  padding-block: var(--sec-tight);
  position: relative;
}
/* Filete vermelho rente ao topo da faixa: assina o bloco sem pesar. */
.lx-footer__promise::before {
  content: "";
  position: absolute;
  left: 0; top: -1px;
  width: clamp(80px, 18vw, 220px);
  height: var(--rule);
  background: var(--accent-rule);
}
.lx-footer__promise .lx-container {
  display: grid;
  gap: var(--sp-6);
  align-items: center;
}
@media (min-width: 900px) {
  .lx-footer__promise .lx-container {
    grid-template-columns: minmax(0, 1fr) auto;
    gap: var(--sp-12);
  }
}
.lx-footer__promise h2 {
  font-size: clamp(1.4rem, 2.05vw, 2.1rem);
  max-width: 20ch;
  margin: 0;
}
.lx-footer__promise p {
  margin: var(--sp-3) 0 0;
  font-size: var(--t-sm);
  color: var(--ink-soft);
  max-width: 56ch;
}

.lx-footer__main { background: var(--bg); padding-block: var(--sec-base); }

/* DUAS ZONAS, E NÃO QUATRO COLUNAS
   Até 28/08 eram quatro: a marca e três listas de link com título e filete
   vermelho em cima. O site encolheu de quatorze páginas para quatro, e três
   categorias para quatro destinos é andaime anunciando um prédio que não
   existe.

   Agora são duas coisas diferentes lado a lado: onde fica o estúdio, e o que
   o site tem. Sem divisor vertical entre elas: com duas zonas o vão já separa,
   e a régua a mais era o que fazia o rodapé parecer cheio de repartição. */
.lx-footer__grid {
  display: grid;
  gap: var(--sp-12) var(--sp-16);
  grid-template-columns: 1fr;
}
@media (min-width: 1000px) { .lx-footer__grid { grid-template-columns: 1fr 1.1fr; } }

/* O título do bloco do app. Ele morava na regra das colunas de link, que saiu
   junto com elas, e ficou órfão: é o único h3 que restou no rodapé. */
/* O vão entre o mapa e o bloco do app é da coluna, e não uma margem no app:
   com margem, mexer no respiro exigiria saber quem está acima. */
.lx-footer__side { display: grid; align-content: start; gap: var(--sp-12); }

.lx-footer__app h3 {
  font-family: var(--font-body);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 var(--sp-4);
  padding-top: var(--sp-4);
  border-top: var(--rule) solid var(--accent-rule);
}

/* --------------------------------------------------------------------------
   O MAPA
   Reescrito em 29/08 depois que a primeira versão errou três coisas de uma vez,
   e as três eram a mesma: eu tratei uma lista de rodapé como se fosse conteúdo
   de página.

   1. OS NOMES DE PÁGINA NÃO PARECIAM CLICÁVEIS. Estavam em 17px, peso 600 e
      tinta cheia, sem sublinhado: isso é exatamente a receita de um TÍTULO
      neste projeto. Eu havia tirado três títulos de categoria e posto quatro
      links com cara de título no lugar, o que é pior que o problema original.
      O sistema já tem um sinal de link, no `a` do ludus-base.css: sublinhado
      fino. Ele volta aqui, em tinta em vez de vermelho, porque quatro links
      vermelhos seguidos brigariam com o botão da faixa logo acima.

   2. ESTAVA SOLTO. Nove linhas com 24px entre elas e nada segurando. Agora são
      quatro fileiras: nome da página à esquerda, âncoras à direita, filete
      entre uma e outra. O filete não é enfeite, é o que transforma quatro
      coisas soltas em um objeto só.

   3. NÃO TINHA CARA DE RODAPÉ. Rodapé se reconhece por densidade: corpo miúdo,
      ritmo curto, cor contida. O mapa estava em corpo de leitura. Caiu para
      15px, que é a medida das outras listas do rodapé.
   -------------------------------------------------------------------------- */

.lx-footer__map { border-top: var(--rule) solid var(--accent-rule); }
.lx-footer__map ul { list-style: none; margin: 0; padding: 0; }
.lx-footer__map li { margin: 0; max-width: none; }

/* A fileira. Duas células no desktop, empilhadas no telefone: numa coluna de
   390px o nome e cinco âncoras lado a lado não cabem. */
.lx-footer__map > ul > li { padding-block: var(--sp-3); }
.lx-footer__map > ul > li + li { border-top: 1px solid var(--line); }

@media (min-width: 760px) {
  .lx-footer__map > ul > li {
    display: grid;
    grid-template-columns: minmax(0, 13rem) minmax(0, 1fr);
    align-items: baseline;
    column-gap: var(--sp-6);
  }
}

.lx-footer__map > ul > li > a {
  display: inline-block;
  /* O link é filho direto da fileira em grade, e filho de grade nasce esticado:
     sem isto o sublinhado atravessa os 13rem da célula inteira e para de ler
     como link para virar régua. */
  justify-self: start;
  font-size: var(--t-sm);
  font-weight: 600;
  color: var(--ink);
  /* O sublinhado é a única coisa aqui que diz "isto abre outra página". Em
     tinta a 30% ele lê como link sem virar risco. */
  border-bottom: 1px solid color-mix(in srgb, var(--ink) 30%, transparent);
}
.lx-footer__map > ul > li > a:hover {
  color: var(--accent);
  border-bottom-color: currentColor;
}

/* As âncoras deitam, e não empilham. Empilhadas faziam uma coluna de 190px com
   300px de vazio à direita. Deitadas ocupam a fileira inteira, e é o mesmo
   desenho do índice que abre a /training: links soltos, um ao lado do outro,
   sem marcador. */
.lx-footer__map ul ul {
  display: flex;
  flex-wrap: wrap;
  gap: 0 var(--sp-6);
  margin-top: var(--sp-1);
}
@media (min-width: 760px) { .lx-footer__map ul ul { margin-top: 0; } }

.lx-footer__map ul ul a {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  border-bottom: 1px solid transparent;
  font-size: var(--t-sm);
  color: var(--ink-soft);
}
.lx-footer__map ul ul a:hover { color: var(--ink); border-bottom-color: currentColor; }

/* Coluna de contato: nome, endereço e telefone consistentes. É o que o
   Google usa para casar o site com o perfil do negócio. */
.lx-footer__nap {
  font-size: var(--t-sm);
  color: var(--ink-soft);
  font-style: normal;
  padding-left: var(--sp-6);
  border-left: var(--rule) solid var(--accent-rule);
}
.lx-footer__nap a { color: var(--ink); font-weight: 600; border-bottom: 0; }
.lx-footer__nap a:hover { color: var(--accent-hover); }
.lx-footer__nap > * + * { margin-top: var(--sp-3); }

/* MARCA E RÓTULO, E NÃO UM OU OUTRO
   A regra dizia "rótulo, não glifo", e o que ela evitava era TROCAR a palavra
   pelo símbolo: num rodapé de negócio local, uma câmera sozinha obriga a
   adivinhar, e leitor de tela não lê desenho. Marca ao lado do rótulo não tem
   esse problema e ganha o reconhecimento imediato que só a forma dá.

   As duas são monocromáticas e herdam currentColor. O pino do Google colorido
   ao lado de um Instagram em cinza quebraria o par, e o par é o que faz os dois
   botões lerem como um controle só. */
.lx-footer__social { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin-top: var(--sp-6); }
/* Dentro do bloco do app a margem de cima vem do respiro do proprio bloco, e a
   de baixo separa o botao da linha da App Store, que ainda esta pendente. */
.lx-footer__app .lx-footer__social { margin: 0 0 var(--sp-4); }
.lx-footer__social a,
.lx-footer__soon {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: var(--tap);
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  border-bottom: 1px solid var(--line);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
  transition: border-color var(--dur-micro) var(--ease), color var(--dur-micro) var(--ease);
}
.lx-footer__social a:hover { border-color: var(--ink-soft); color: var(--ink); }

/* O BOTAO QUE AINDA NAO LEVA A LUGAR NENHUM
   Mesmo desenho dos outros, meio apagado: e o que separa "existe e voce pode
   clicar" de "existe e ainda nao". Sem hover e sem cursor de mao, porque as
   duas coisas prometeriam um clique que nao acontece. Vira <a> quando o link
   da App Store chegar. */
.lx-footer__soon {
  opacity: 0.45;
  cursor: default;
  border-style: dashed;
}

/* Medida fixa nos dois eixos. O `svg` do base tem height:auto, e sem isto uma
   marca de viewBox quadrado ainda assim herda a altura da linha do rótulo, que
   é 13px em caixa alta: as duas sairiam com tamanhos diferentes. */
.lx-footer__social svg,
.lx-footer__soon svg {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  /* O rótulo é caixa alta e a marca é redonda: alinhadas pelo centro
     geométrico, a marca parece alta. Um pixel abaixo resolve. */
  transform: translateY(0.5px);
}

/* O mito de origem, com o capacete atrás em marca d'água. A marca d'água é
   textura, não ornamento: 5% de opacidade, sangrando pela direita, cortada
   pelo overflow da faixa. Em 3% ninguém vê; em 10% vira adesivo. */
.lx-footer__myth {
  position: relative;
  overflow: hidden;
  background: var(--bg-sunken);
  border-top: 1px solid var(--line);
  padding-block: var(--sec-tight);
}
/* Seletor dobrado: ganha do `.elementor img` (0,1,1) do Elementor, que
   senao zera a altura daqui. Ver o comentario do .lx-brand__mark no
   ludus-chrome.css. */
.lx-footer__watermark.lx-footer__watermark {
  position: absolute;
  right: clamp(-40px, -2vw, 0px);
  top: 50%;
  transform: translateY(-50%);
  height: clamp(160px, 26vw, 300px);
  width: auto;
  opacity: 0.05;
  pointer-events: none;
}
.lx-footer__myth p {
  position: relative;
  font-family: var(--font-display);
  font-size: var(--t-lead);
  line-height: 1.55;
  color: var(--ink-soft);
  max-width: 62ch;
  margin: 0;
  padding-left: var(--sp-6);
  border-left: var(--rule) solid var(--accent-rule);
}
.lx-footer__myth em { font-style: italic; color: var(--ink); }

/* A faixa legal precisa sangrar de ponta a ponta. Antes ela estava dentro do
   container e o fundo parava em 1240px, deixando uma tira flutuando no meio
   de telas largas. */
.lx-footer__legal {
  border-top: 1px solid var(--line);
  background: var(--bg-sunken);
}
.lx-footer__legal .lx-container {
  padding-block: var(--sp-6);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-6);
  align-items: center;
  justify-content: space-between;
}
.lx-footer__legal p,
.lx-footer__legal ul { margin: 0; font-size: var(--t-xs); color: var(--ink-faint); }
.lx-footer__legal ul { list-style: none; padding: 0; display: flex; flex-wrap: wrap; gap: var(--sp-6); }
.lx-footer__legal li { margin: 0; max-width: none; }
.lx-footer__legal a { color: var(--ink-faint); border-bottom: 0; }
.lx-footer__legal a:hover { color: var(--ink-soft); }

/* --------------------------------------------------------------------------
   8. MOVIMENTO REDUZIDO
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .lx-header,
  .lx-header__inner,
  .lx-brand__mark,
  .lx-drawer,
  .lx-nav a::after,
  .lx-burger span,
  .lx-burger span::before,
  .lx-burger span::after { transition: none; }

  .lx-header { view-transition-name: none; }
}


/* ===== ludus-page.css ===== */
/* ==========================================================================
   LUDUS ACTIUS — PÁGINA
   Depende de ludus-tokens.css e de ludus-base.css. Carregar depois dos dois
   e antes de qualquer CSS de página.

   O QUE MORA AQUI, E POR QUÊ
   --------------------------
   Componente que aparece em mais de uma página. Nada que seja de uma página
   só: isso fica no arquivo da própria página.

   Este arquivo nasceu quando a /testimonials precisou do bloco de agendamento
   que estava dentro do ludus-home.css. Manter uma segunda cópia lá seria
   garantir que as duas divergem na terceira vez que alguém mexer no formulário.

   Correspondência com o §6 do 01-Sitemap.md, o registro de blocos globais:

     B3   .lx-book       CTA de fechamento + formulário Goal
     ---  .lx-pagehead   abertura de página interna (a home tem hero próprio)

   B1, B2, B4, B5 e B6 entram aqui conforme as páginas que os pedem forem
   construídas. Regra do sitemap que vale para todas: no máximo dois blocos
   globais por página. Foi a repetição de cinco blocos em oito páginas que
   criou a duplicação de conteúdo no site antigo.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. ABERTURA DE PÁGINA INTERNA

   A home abre com hero de vídeo. Nenhuma outra página abre assim: seria
   prometer uma produção audiovisual que não existe para dezenove páginas, e
   empurrar o conteúdo real para baixo da dobra em todas elas.

   Aqui a abertura é tipográfica e curta. O que ela precisa entregar é uma só
   coisa: em que página o visitante está e por que ela vale o scroll.
   -------------------------------------------------------------------------- */

.lx-pagehead { padding-block: var(--sec-tall) var(--sec-base); }

.lx-pagehead__label { margin-bottom: var(--sp-6); }

.lx-pagehead h1 { max-width: 16ch; margin-bottom: var(--sp-6); }

.lx-pagehead .lx-lead { max-width: 54ch; }

/* O filete de abertura. Único elemento animado acima da dobra em página
   interna, e ele é transform-only: não desloca nada e não atrasa o LCP. */
.lx-pagehead__rule { margin-top: var(--sp-12); max-width: 220px; }


/* --------------------------------------------------------------------------
   2. B3 — MARCAR A AULA
   Veio do ludus-home.css §8 sem alteração de valor. Se algo aqui mudar, muda
   para a home junto, que é exatamente o objetivo.
   -------------------------------------------------------------------------- */

.lx-book { padding-block: var(--sec-base); border-top: 1px solid var(--line); background: var(--bg-sunken); }
/* NO TELEFONE A ORDEM E TITULO, PAINEL, CONTATO
   Sao tres pecas no DOM justamente para que a ordem empilhada seja a certa sem
   nenhum `order`: quem depende de order para arrumar leitura no telefone deixa a
   ordem de foco do teclado e a de leitura de tela erradas, porque as duas seguem
   o DOM e nao o CSS. Aqui as tres batem.

   No desktop as areas recolocam tudo onde sempre esteve: titulo e contato
   empilhados a esquerda, painel ocupando a direita inteira. */
.lx-book__grid { display: grid; gap: var(--sp-12); }
@media (min-width: 940px) {
  .lx-book__grid {
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "intro   painel"
      "contato painel";
    column-gap: var(--sp-16);
    /* O respiro entre titulo e contato vira row-gap. Antes era margin-top no
       .lx-book__or, e com o contato virando peca propria a margem brigaria com
       o gap da grade no telefone: dois espacos somados para uma separacao so. */
    row-gap: var(--sp-8);
    align-items: start;
  }
  .lx-book__intro   { grid-area: intro; }
  .lx-book__panel   { grid-area: painel; }
  .lx-book__contato { grid-area: contato; }
}
.lx-book h2 { max-width: 14ch; margin-bottom: var(--sp-6); }
.lx-book__note { font-size: var(--t-sm); color: var(--ink-soft); }
/* O telefone ganha linha própria. Na frase corrida, "(813) 372-1083" é um
   bloco de 14 caracteres que só quebra depois do DDD, e em coluna estreita a
   linha estourava o container. Além disso, telefone de negócio local merece
   estar solto e clicável, não enterrado no meio de um parágrafo. */
.lx-book__or {
  margin-top: 0;
  padding-top: var(--sp-6);
  border-top: 1px solid var(--line);
  font-size: var(--t-sm);
  color: var(--ink-soft);
}
.lx-book__contact { margin: var(--sp-3) 0 0; font-size: var(--t-sm); color: var(--ink-soft); }
.lx-book__contact a {
  display: inline-block;
  font-family: var(--font-display);
  font-size: var(--t-lead);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  border-bottom-color: var(--accent-rule);
  margin-bottom: var(--sp-2);
}
.lx-book__contact a:hover { color: var(--accent-hover); }
/* O PAINEL DO CALENDARIO
   Ocupa o lugar que era do formulario de lead, retirado em 21/08. Sem nada
   aqui a seção fica com metade vazia e o botão perde a ancoragem que tinha
   dentro do formulário: vira um botão solto no branco. O painel devolve o
   peso visual e ainda faz um trabalho que o formulário não fazia, que é
   contar o que vai acontecer depois do clique. */
.lx-book__panel {
  background: var(--bg-elevated);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  padding: var(--sp-8);
  position: relative;
}
/* O filete assina o painel pelo topo, rente à borda. */
.lx-book__panel::before {
  content: "";
  position: absolute;
  left: -1px; top: -1px;
  width: clamp(56px, 10vw, 110px);
  height: var(--rule);
  background: var(--accent-rule);
}
.lx-book__k {
  font-family: var(--font-body);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 var(--sp-3);
}
.lx-book__t {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: 600;
  line-height: 1.2;
  color: var(--ink);
  margin: 0 0 var(--sp-4);
}
.lx-book__d { font-size: var(--t-sm); color: var(--ink-soft); margin: 0 0 var(--sp-8); }
.lx-book__panel .lx-btn { width: 100%; }
.lx-book__fine { margin: var(--sp-4) 0 0; font-size: var(--t-xs); color: var(--ink-faint); }


/* --------------------------------------------------------------------------
   3. B2b — FECHAMENTO COM OS PLANOS

   O outro fim de página possível. O B3 pede um lead; este pede a compra.
   Qual dos dois fecha a página é decisão de cada página, e não deve haver os
   dois na mesma: duas perguntas diferentes no mesmo lugar não somam
   conversão, dividem.

   A escolha na /testimonials foi esta. Quem chega ao fim daquela página leu
   quatro pessoas contando que deu certo; a pergunta certa ali é qual plano,
   não se quer experimentar. A aula grátis continua na página, uma hierarquia
   abaixo, em .lx-close__alt.
   -------------------------------------------------------------------------- */

.lx-close { padding-block: var(--sec-base); border-top: 1px solid var(--line); background: var(--bg-sunken); }

.lx-close__head { margin-bottom: var(--sp-12); }
.lx-close__head h2 { max-width: 20ch; margin-bottom: var(--sp-4); }

/* CINCO CARTOES DESDE 26/08, E O QUINTO NAO E UMA QUINTA COLUNA
   -------------------------------------------------------------
   A primeira tentativa foi obvia: repeat(5, 1fr). Estourou o container na
   captura, com o Kids cortado pela borda direita da tela. O motivo nao e o
   1fr, e o minimo automatico dele: 1fr e minmax(auto, 1fr), e o auto impede
   o cartao de encolher abaixo do proprio min-content. Dentro dos 1144px uteis
   sobram 216px por cartao, menos 48px de padding dao 168px de conteudo, e
   "CHOOSE THIS PLAN" em caixa alta com tracking nao cabe em 168px. Nem com
   minmax(0, 1fr) resolveria: ali o botao pararia de empurrar e passaria a ser
   cortado, que e o mesmo defeito escondido.

   Entao os quatro planos de adulto ficam na linha de quatro, do jeito que
   sempre estiveram, e o Kids ocupa a linha inteira embaixo, deitado: regua,
   nome, descricao, preco e botao no mesmo eixo. Nao e concessao de layout, e
   o que ele e. Os outros quatro sao degraus de uma escada de frequencia e se
   comparam coluna a coluna; o Kids e outro publico, outra hora e outra aula,
   e nao se compara com nenhum deles. Deitado ele para de pedir a comparacao
   que nao existe.

   Preso a .lx-plan--wide e nao a :last-child de proposito: com :last-child a
   regra seria "o ultimo cartao, seja ele qual for", e um sexto plano herdaria
   a linha inteira sem ninguem pedir. */
.lx-plan-grid { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-4); }

@media (min-width: 700px) {
  .lx-plan-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lx-plan--wide { grid-column: 1 / -1; }
}

@media (min-width: 1040px) {
  .lx-plan-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* NO TELEFONE A GRADE DEITA, E QUEM DA O PASSO E O DEDO
   Empilhados, os seis cartoes eram a secao mais alta da pagina no telefone,
   2384px so de preco. Deitados, ocupam a altura de um.

   Ao contrario dos outros dois carrosseis do site, este NAO anda sozinho: e
   preco, e a regra do ludus-motion.js e antiga. Os dois botoes redondos que o
   script cria embaixo sao o passo.

   Os 86% valem aqui pelo mesmo motivo de sempre, e valem em dobro: com seis
   itens, um cartao ocupando a tela inteira esconderia CINCO precos, e a secao
   se chama "Published prices". O proximo espiando pela borda e metade do aviso;
   os botoes sao a outra metade. */
@media (max-width: 699px) {
  .lx-plan-grid {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .lx-plan-grid::-webkit-scrollbar { display: none; }
  /* Mesma razao da semana: a espiada mostrava o "$99" do Beginners ao lado do
     "$20" do Drop In, e dois precos legiveis lado a lado numa tela de telefone
     e a comparacao acontecendo no lugar errado, com um deles cortado. */
  .lx-plan-grid {
    -webkit-mask-image: var(--mask-peek);
    mask-image: var(--mask-peek);
  }
  .lx-plan-grid > li {
    flex: 0 0 86%;
    min-width: 0;
    scroll-snap-align: start;
  }
}

/* Os botoes do slider. Nascem pelo JS, entao nao existem para quem esta sem
   script: la a fila continua deslizavel a dedo, sem controle morto na tela. */
.lx-slider__nav {
  display: flex;
  gap: var(--sp-4);
  margin-top: var(--sp-6);
}
/* O [hidden] precisa estar DEPOIS e ser explicito: display: flex acima ganharia
   do display: none que o atributo traz de fabrica, e a barra apareceria no
   desktop, onde a grade nem e carrossel. */
.lx-slider__nav[hidden] { display: none; }

.lx-slider__btn {
  /* 44px e o minimo de alvo de toque que o resto do site respeita. Botao
     redondo de navegacao costuma sair com 32 e virar armadilha no polegar. */
  width: 44px;
  height: 44px;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: border-color var(--dur-micro) var(--ease),
              color var(--dur-micro) var(--ease);
}
.lx-slider__btn svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.lx-slider__btn:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--accent);
}
/* Apagado na ponta: sem loop infinito, e assim que a fila diz que acabou. */
.lx-slider__btn:disabled {
  opacity: 0.32;
  cursor: default;
}

/* Coluna, e não bloco solto: o botão precisa encostar no fundo do cartão em
   todos os cinco, senão a linha de botões fica escadinha porque "As many
   classes as you can make" ocupa duas linhas e "Two classes a week" ocupa uma. */
.lx-plan {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  margin: 0;
  max-width: none;
  padding: var(--sp-6);
  background: var(--bg-elevated);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  transition: border-color var(--dur-micro) var(--ease);
  position: relative;   /* âncora do selo */
}
.lx-plan:hover { border-color: var(--line-strong); }

/* O plano mais escolhido não muda de tamanho nem sobe: cartão que cresce
   quebra o alinhamento da linha inteira e obriga a inventar respiro em volta.
   Ele se destaca pela borda, pelo selo e por ser o único botão sólido. */
.lx-plan--featured { border-color: var(--accent-rule); }

.lx-plan__rule {
  display: block;
  width: 28px;
  height: var(--rule);
  background: var(--accent-rule);
  margin-bottom: var(--sp-2);
}

/* O selo sai do fluxo de propósito. Dentro da coluna ele empurra nome,
   descrição e régua do preço para baixo, e o cartão em destaque passa a ter
   o preço desalinhado dos outros três. Foi o que a captura mostrou. Fora do
   fluxo, os cinco cartões alinham linha a linha e o selo continua no lugar
   onde o olho procura, no alto do cartão. */
.lx-plan__tag {
  position: absolute;
  top: var(--sp-6);
  right: var(--sp-6);
  padding: 2px 8px;
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}

.lx-plan__name {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: 600;
  line-height: 1.2;
  color: var(--ink);
}

/* Empurra preço e botão para o fim do cartão. */
.lx-plan__what { flex: 1; font-size: var(--t-sm); color: var(--ink-soft); }

.lx-plan__price {
  display: block;
  padding-top: var(--sp-4);
  border-top: 1px solid var(--line);
  font-variant-numeric: tabular-nums;
}
.lx-plan__price b {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 2.1vw, 2.1rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: var(--tr-title);
  color: var(--ink);
}
.lx-plan__price small { display: block; margin-top: var(--sp-2); font-size: var(--t-xs); color: var(--ink-faint); }

.lx-plan .lx-btn { width: 100%; margin-top: var(--sp-2); }

/* Deitado so quando ha largura para isso. Entre 700 e 860 ele ja ocupa a linha
   inteira, mas empilhado: em coluna estreita, nome, descricao, preco e botao no
   mesmo eixo espremem os quatro.

   ESTE BLOCO FICA NO FIM DA SECAO DE PROPOSITO. Ele estava la em cima, junto da
   grade, e duas regras dele perderam calado para as regras base do cartao, que
   vem depois: .lx-plan--wide e .lx-plan empatam em (0,1,0), e .lx-plan--wide
   .lx-btn empata com .lx-plan .lx-btn em (0,2,0). Em empate ganha quem vem
   depois. Na primeira captura o cartao saiu empilhado E centralizado, porque so
   o align-items passou; na segunda ele deitou mas o botao continuou com
   width: 100% e vazou pela borda do container. As duas vezes a captura mostrou.
   Aqui embaixo a ordem trabalha a favor, e o seletor dobrado nas duas regras que
   colidem segura mesmo que alguem mova o bloco de novo. */
@media (min-width: 860px) {
  .lx-plan.lx-plan--wide { flex-direction: row; align-items: center; gap: var(--sp-6); }
  .lx-plan--wide .lx-plan__rule  { margin-bottom: 0; flex: none; }
  /* Faixa de largura para o nome, e aqui ela se justifica, ao contrario da que
     saiu do .lx-promise__n. La era numero solto contra frase, e a faixa virava
     buraco. Aqui sao DUAS faixas empilhadas, Powerlifting e Kids, e sem largura
     comum a descricao de cada uma comeca num x proprio: le como desalinho, nao
     como duas linhas de uma mesma tabela. A medida vem do nome mais longo. */
  .lx-plan--wide .lx-plan__name  { flex: none; min-width: 13ch; }
  /* O min-width entrou em 31/08, com o Personal 1-1. `flex: 1` e `flex: 1 1 0%`:
     base zero, entao a coluna encolhe ate o min-content quando o resto da faixa
     pede espaco. Os dois `small` daquela linha sao muito mais longos que os do
     powerlifting, e a descricao desabou para uma palavra por linha, seis linhas
     de altura. Com um piso ela cede depois dos precos, e nao antes. */
  .lx-plan--wide .lx-plan__what  { flex: 1; min-width: 16ch; }
  /* O filete de cima do preco separa preco de descricao no cartao em pe. Deitado
     nao ha nada acima dele para separar, e a linha vira sujeira no meio da faixa. */
  .lx-plan--wide .lx-plan__price {
    /* Cede antes da descricao: o numero e curto e quem quebra e o `small`. */
    flex: 0 1 auto;
    display: flex;
    align-items: baseline;
    gap: var(--sp-2);
    padding-top: 0;
    border-top: 0;
  }
  .lx-plan--wide .lx-plan__price small { display: inline; margin-top: 0; }
  .lx-plan.lx-plan--wide .lx-btn { width: auto; margin-top: 0; flex: none; }
}


.lx-close__terms { margin: var(--sp-6) 0 0; font-size: var(--t-sm); color: var(--ink-soft); max-width: 64ch; }

/* A saída sem cartão. Fica depois do preço, não antes: oferecer o grátis
   primeiro é ensinar o visitante a não olhar a tabela. */
.lx-close__alt {
  margin-top: var(--sp-12);
  padding-top: var(--sp-6);
  border-top: var(--rule) solid var(--accent-rule);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-6);
  align-items: center;
  justify-content: space-between;
}
.lx-close__alt-text { margin: 0; font-size: var(--t-sm); color: var(--ink-soft); max-width: 52ch; }


/* --------------------------------------------------------------------------
   4. A RUDIS
   Veio do ludus-home.css sem alteracao de valor, quando a /membership passou a
   usar o mesmo bloco. Programa de fidelidade com narrativa dentro, e o unico
   do quarteirao que tem.
   -------------------------------------------------------------------------- */

/* A RUDIS
   Programa de fidelidade com narrativa dentro, e o único do quarteirão que
   tem. Fica no fim da tabela de preço porque é o que se ganha por ficar, não
   o que se paga para entrar. */
.lx-milestone {
  margin-top: var(--sp-8);
  padding: var(--sp-6);
  border: 1px solid var(--line);
  border-left: var(--rule) solid var(--accent-rule);
  border-radius: var(--radius-md);
  background: var(--bg-elevated);
}
.lx-milestone p { margin: 0; font-size: var(--t-sm); color: var(--ink-soft); max-width: 62ch; }
.lx-milestone b { font-family: var(--font-display); font-size: var(--t-lead); font-weight: 600; color: var(--ink); }

/* --------------------------------------------------------------------------
   5. CTA DA ABERTURA DE PAGINA INTERNA
   A home tem .lx-hero__cta no hero; pagina interna precisava do equivalente,
   e usar a classe do hero aqui amarraria a /membership ao CSS da home.
   -------------------------------------------------------------------------- */

.lx-pagehead__cta { display: flex; flex-wrap: wrap; gap: var(--sp-4); margin-top: var(--sp-12); }


/* --------------------------------------------------------------------------
   6. ABERTURA DE PÁGINA COM IMAGEM

   Variante da seção 1. A abertura tipográfica continua sendo o padrão para
   página interna, e esta variante é para as poucas em que a imagem carrega
   argumento em vez de decorar. Na /membership ela carrega: a página promete
   "venha ver antes de pagar", e mostrar a sala é a prova de que há o que ver.

   POR QUE MÁSCARA LINEAR E NÃO A RADIAL DO HERO
   ---------------------------------------------
   A radial do hero da home é centrada num atleta: existe um sujeito para
   manter opaco. Foto de salão não tem sujeito, tem profundidade. Uma máscara
   linear dissolve a aresta esquerda contra o texto sem escolher um centro
   arbitrário, e o resultado é previsível em qualquer foto do acervo.

   No celular a imagem não vira painel: ela desce para baixo do texto e sangra
   de ponta a ponta. Sobrepor texto a foto em coluna estreita obriga a
   escolher entre ler a manchete e ver a sala.
   -------------------------------------------------------------------------- */

.lx-pagehead--media { position: relative; overflow: hidden; }
.lx-pagehead--media .lx-container { position: relative; z-index: 2; }

/* A moldura existe para o véu ter a geometria da FOTO, e não a da seção.
   Tentei primeiro pendurar o véu radial no scrim, que cobre a seção inteira:
   o centro em 62% caía 120px à esquerda do centro da imagem e o anel escuro,
   dimensionado em 96% da largura da seção, terminava fora da tela. O véu
   existia e não escurecia nada. Com a moldura, 62% é 62% da foto. */
.lx-pagehead__frame { display: block; position: relative; }

.lx-pagehead__frame::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* Seletor dobrado: ganha do `.elementor img` (0,1,1) do Elementor, que
   senao zera a altura daqui. Ver o comentario do .lx-brand__mark no
   ludus-chrome.css. */
.lx-pagehead__media.lx-pagehead__media {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* A foto é de celular sob luz fluorescente, como quase todo o acervo. Sem
     graduação ela entra como um retângulo claro boiando no carvão. */
  filter: saturate(0.74) contrast(1.14) brightness(0.82);
}

.lx-pagehead__scrim { display: none; }


/* MOBILE: a imagem é faixa no TOPO, e acaba dentro da manchete.

   Foi o que a home já resolvia e esta variante não fazia. Empurrar a foto
   para baixo do texto responde à pergunta errada: em página que promete
   "venha ver", a sala é o argumento e ela não pode estar depois do botão.

   A GEOMETRIA, que é o que manda aqui, e é a mesma conta da home:
   a foto é quadrada, 1080x1080. Numa faixa de largura cheia a 390px o cover
   escala por largura e a imagem sai com 390px de altura. Qualquer faixa mais
   alta que isso mostra a foto inteira, teto incluído, e object-position não
   tem o que cortar. Para o teto sair, a faixa tem que ser MAIS BAIXA que 390.
   Em ~265px sobram 125px de transbordo, e 58% joga a maior parte no topo.

   A altura que sobra vira o efeito: a faixa é mais alta que a linha 1 da
   grade, então ela avança sobre o texto, e a máscara dissolve justamente ali.
   A imagem não termina numa borda, ela acaba dentro da manchete. */
@media (max-width: 899px) {
  .lx-pagehead--media {
    /* Um valor, dois consumidores: a altura da faixa e a do véu. Soltos, bastava
       mexer num para o véu desalinhar da imagem. */
    --hero-band: clamp(225px, 30svh, 285px);
    display: grid;
    grid-template-rows: clamp(150px, 19svh, 190px) auto;
    padding-block: 0 var(--sec-base);
  }

  /* Sem isto o container cai na linha 1, que é o espaçador, e o texto sobe
     para dentro da foto inteira em vez de começar depois dela. */
  .lx-pagehead--media .lx-container { grid-row: 2; position: relative; z-index: 2; }

  .lx-pagehead__frame {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 0;
    height: var(--hero-band);
  }

  .lx-pagehead__media.lx-pagehead__media {
    object-position: 50% 58%;   /* 58% joga o corte no teto */
    /* A dissolução começa na metade e só termina na base, já dentro da
       manchete. Fade curto entrega borda; fade longo entrega imersão. */
    -webkit-mask-image: linear-gradient(to bottom,
      #000 0%, #000 44%, rgba(0,0,0,.55) 70%, rgba(0,0,0,.18) 88%, transparent 100%);
    mask-image: linear-gradient(to bottom,
      #000 0%, #000 44%, rgba(0,0,0,.55) 70%, rgba(0,0,0,.18) 88%, transparent 100%);
  }

  /* O véu volta, mas só na cauda da faixa. A máscara sozinha não basta: no
     trecho onde a manchete começa, as anilhas e o metal ainda estão com alfa
     alto e brigam com as letras. Máscara tira imagem; véu escurece a que fica.
     Transparente até 34% para não tocar no fundo da sala. */
  .lx-pagehead__frame::after {
    background: linear-gradient(to bottom,
      transparent 0%,
      transparent 34%,
      color-mix(in srgb, var(--bg) 52%, transparent) 66%,
      color-mix(in srgb, var(--bg) 86%, transparent) 86%,
      var(--bg) 100%);
  }
}

@media (min-width: 900px) {
  /* Altura de hero, e o texto centrado nela. Sem isso a seção tem altura de
     padding e a foto vira uma faixa curta: a máscara não tem espaço vertical
     para dissolver e as arestas de cima e de baixo voltam a aparecer. */
  .lx-pagehead--media {
    display: flex;
    align-items: center;
    min-height: min(70svh, 600px);
    padding-block: var(--sp-12);
  }

  /* Larguras por elemento, e não um max-width no container inteiro.
     Um seletor `.lx-pagehead--media .lx-container > *` tem especificidade
     (0,2,0) e passa por cima do `.lx-pagehead h1` (0,1,1) que segura o título
     em 16ch: o H1 saiu de 640px para 1840px, entrou por cima da foto, e os
     dois botões deixaram de caber lado a lado. Cada elemento declara a sua. */
  .lx-pagehead--media h1        { max-width: 13ch; }
  .lx-pagehead--media .lx-lead  { max-width: 38ch; }

  .lx-pagehead__frame {
    position: absolute;
    inset-block: 0;
    right: 0;
    z-index: 0;
    width: 78%;
    max-width: 1180px;
    margin-top: 0;
  }

  /* O véu que faz a foto emergir, e é o que faltava.
     A máscara do hero da home basta lá porque aquela foto já é noturna: as
     bordas dela são pretas de nascença e a aresta some sozinha. Esta é um
     salão de teto branco iluminado por igual de canto a canto, então a
     máscara tira a aresta e o que sobra continua sendo um retângulo aceso.
     O véu escurece o que a máscara deixou, e é aí que a imagem passa a sair
     do carvão em vez de estar colada nele.

     Máscara e véu fazem coisas diferentes, e aqui as duas são necessárias. */
  .lx-pagehead__frame::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    /* A aritmética importa aqui, e foi o que errei duas vezes: a aresta de
       cima está a 46% da altura do centro, então com raio vertical de 92% ela
       cai em 50% do gradiente, que ainda é transparente. O raio precisa ser
       MENOR que a distância que se quer escurecer. Com 56%, a aresta de cima
       cai em 82% e a de baixo em 96%: as duas chegam escuras. */
    background: radial-gradient(74% 56% at 56% 46%,
      transparent 0%,
      transparent 24%,
      color-mix(in srgb, var(--bg) 34%, transparent) 52%,
      color-mix(in srgb, var(--bg) 80%, transparent) 76%,
      var(--bg) 95%);
  }

  .lx-pagehead__media.lx-pagehead__media {
    width: 100%;
    height: 100%;
    margin-top: 0;
    aspect-ratio: auto;
    object-position: 52% 46%;
    /* Bem mais fechada que a da home, e a razão é a foto. A do hero da home
       já nasce noturna: um atleta contra um fundo preto. Esta é um salão de
       teto branco sob fluorescente, e com o mesmo brightness de 0.84 ela
       chega ao carvão como um retângulo aceso. */
    filter: saturate(0.62) contrast(1.20) brightness(0.62);
    /* Radial, como a da home, e não linear. A linear dissolvia só a aresta
       esquerda; as de cima, de baixo e da direita continuavam cortadas a
       régua, e a foto lia como imagem colada em vez de emergir do escuro.
       O centro fica onde a sala tem profundidade, no fundo do corredor. */
    -webkit-mask-image: radial-gradient(86% 76% at 56% 46%,
      #000 18%, rgba(0,0,0,.72) 48%, rgba(0,0,0,.20) 72%, transparent 92%);
    mask-image: radial-gradient(86% 76% at 56% 46%,
      #000 18%, rgba(0,0,0,.72) 48%, rgba(0,0,0,.20) 72%, transparent 92%);
  }

  /* Máscara tira imagem e mata a aresta. Véu escurece a que fica, e é o que
     garante contraste do texto por cima. São trabalhos diferentes.
     Dois gradientes, como no hero da home: um segura a esquerda para o texto,
     o outro assenta a base contra a seção seguinte. */
  .lx-pagehead__scrim {
    display: block;
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background: linear-gradient(to right,
      var(--bg) 0%,
      color-mix(in srgb, var(--bg) 78%, transparent) 26%,
      color-mix(in srgb, var(--bg) 24%, transparent) 46%,
      transparent 62%);
  }
}


/* --------------------------------------------------------------------------
   7. B6 — A GRADE DA SEMANA

   Dado tabular de verdade, e o layout trata como tal: dia à esquerda, aula e
   horários à direita, uma linha por aula. Não virou <table> porque tabela de
   sete linhas com número variável de células por linha exige colspan e vira
   markup pior que o problema; e porque em coluna estreita ela teria de ser
   remontada em grade mesmo.

   Os horários são tabular-nums e separados por meio-ponto, não por travessão:
   travessão entre dois horários lê como intervalo ("das 7 às 8"), e estes são
   aulas soltas, não uma janela contínua. É a diferença entre "tem aula às 7 e
   às 8:15" e "funciona das 7 às 8:15".
   -------------------------------------------------------------------------- */

/* ==========================================================================
   A SEMANA
   Uma FORMA so, em dois recipientes. O dia sempre e um cartao em coluna: nome
   em cima, aula, horarios empilhados embaixo. O que muda com a largura e onde
   os sete cartoes ficam.

     acima de 1000px   sete colunas lado a lado, com regua entre elas
     abaixo            fila deslizavel, um dia por vez, com os dois botoes

   Era o contrario ate 28/08: no telefone o dia era uma LINHA, com o nome a
   esquerda e as aulas a direita, e os horarios corriam separados por ponto.
   Duas formas diferentes para o mesmo dado, e a versao em linha era a que
   crescia sem parar, 1181px de rolagem para sete dias.

   O SEPARADOR DE PONTO SUMIU, E COM ELE UM BUG
   Com os horarios sempre empilhados, nao ha mais o que separar. A regra do
   ponto era um content: com escape, e foi la que um NUL entrou e virou glifo
   quebrado no telefone. Menos uma regra, menos uma superficie de erro.
   ========================================================================== */

.lx-week { list-style: none; margin: 0; padding: 0; }

.lx-day {
  margin: 0;
  max-width: none;
  display: block;
  padding-block: var(--sp-6) var(--sp-8);
}

.lx-day__name {
  font-family: var(--font-body);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 var(--sp-4);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--line);
}

.lx-day__slots { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-6); }

.lx-slot { margin: 0; max-width: none; display: block; }

.lx-slot__class {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: 600;
  line-height: 1.2;
  color: var(--ink);
  display: block;
  margin-bottom: var(--sp-2);
}

.lx-slot__times {
  display: block;
  font-size: var(--t-sm);
  color: var(--ink-soft);
  font-variant-numeric: tabular-nums;
}
.lx-slot__t { display: block; line-height: 1.55; }

/* --------------------------------------------------------------------------
   ATE 999px: FILA DESLIZAVEL, UM DIA POR VEZ
   O cartao vai a 78% para o proximo dia espiar pela borda, que e o mesmo aviso
   dos outros carrosseis do site. Manual, com os dois botoes: grade de horario
   e material de consulta, e quem esta procurando a terca nao quer que a tela
   ande sozinha no meio da leitura.
   -------------------------------------------------------------------------- */
@media (max-width: 999px) {
  .lx-week {
    display: flex;
    gap: var(--sp-4);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .lx-week::-webkit-scrollbar { display: none; }

  /* A ESPIADA SOME NA BORDA, E E ISSO QUE RESOLVE
     So estreitar o cartao nao bastava: com 86% sobram ~39px do dia seguinte, e
     "7:00" cabe em 30. Os horarios de terca continuavam legiveis ao lado dos de
     segunda, e duas colunas de numero brigando e exatamente o que o cliente
     apontou.

     Empurrar mais mataria o aviso junto: cartao a 95% nao mostra que ha proximo.
     A mascara separa as duas coisas. A espiada continua larga o bastante para
     dizer "tem mais aqui", e o conteudo dela se dissolve antes de virar numero
     que se le. Aviso sem competicao.

     Os 64px de dissolucao cobrem a espiada inteira e ainda entram uns 25px no
     cartao em foco, onde nao ha texto: o conteudo do dia e curto e alinhado a
     esquerda. */
  .lx-week {
    -webkit-mask-image: var(--mask-peek);
    mask-image: var(--mask-peek);
  }
  /* 86% e nao 78%, e a diferenca nao e estetica. Com 78% sobravam 70px do dia
     seguinte, o bastante para LER "7:00 am" e "8:15 am" da coluna de tras: os
     horarios de terca disputavam a leitura com os de segunda, e a fileira
     espiando pesava mais que o cartao em foco. Com 86% sobram ~39px, que mostram
     a borda e o filete do proximo dia sem entregar numero nenhum. O aviso de que
     ha mais continua; a competicao acaba.

     E o mesmo 86% do bento e da faixa de fotos, entao o site passa a ter uma
     medida so de espiada. */
  .lx-day {
    flex: 0 0 86%;
    min-width: 0;
    scroll-snap-align: start;
    border-top: 1px solid var(--line);
  }
}

/* --------------------------------------------------------------------------
   DE 1000px PARA CIMA: SETE COLUNAS
   -------------------------------------------------------------------------- */
@media (min-width: 1000px) {
  /* AS DIVISORIAS SAO O QUE FAZ ISTO SER UMA TABELA E NAO SETE LISTAS
     O gap e ZERO e o respiro e padding DENTRO de cada dia, com o filete no
     meio: assim a regua fica exatamente entre dois conteudos, com a mesma folga
     dos dois lados. Com gap, ela grudaria na coluna da direita.

     O margin negativo puxa a grade para fora do container na mesma medida do
     padding, para o texto de segunda-feira continuar alinhado com o titulo da
     secao. */
  .lx-week {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    gap: 0;
    margin-inline: calc(var(--sp-4) * -1);
    border-top: 1px solid var(--line);
  }
  .lx-day {
    padding-inline: var(--sp-4);
    border-left: 1px solid var(--line);
  }
  .lx-day:first-child { border-left: 0; }

  /* Em 150px de coluna, o nome da aula em corpo de subtitulo viraria tres
     linhas de tipo grande. Desce para o corpo do texto e continua dominante,
     porque esta sozinho no alto da coluna. Duas linhas reservadas para todos,
     caiba o nome em uma ou nao: sem isso os horarios de terca comecavam mais
     baixo que os de segunda. */
  .lx-slot__class { font-size: var(--t-body); min-height: 2.4em; }

  /* A SEGUNDA AULA DO DIA COMECA NA MESMA ALTURA EM TODA COLUNA
     O primeiro bloco tem de um a cinco horarios conforme o dia, e sem reserva a
     fileira de "Powerlifting", "Kids Program" e "Saturday Eight Rounds" saia em
     onda. Cinco e o maximo que um dia tem hoje: se virar seis, este numero sobe
     junto, e o sintoma de esquecer e a onda voltar. */
  .lx-slot:first-child .lx-slot__times { min-height: calc(5 * 1.55em); }
}

.lx-slot__tag {
  display: inline-block;
  margin-left: var(--sp-2);
  padding: 1px 7px;
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  vertical-align: middle;
}

.lx-slot__note { font-style: normal; font-size: var(--t-xs); color: var(--ink-faint); }

.lx-day--closed .lx-slot__class { font-family: var(--font-body); font-size: var(--t-sm); font-weight: 400; color: var(--ink-faint); }


/* --------------------------------------------------------------------------
   O QUE O PRECO JA COBRE, E A RUDIS

   Os dois blocos abaixo vieram do ludus-membership.css em 31/08, quando o
   markup deles virou o bloco global assets/html/block-perks.html e a /training
   passou a inserir a mesma secao. CSS de bloco que serve duas paginas mora
   aqui, e nao no arquivo de uma delas: e a mesma regra que ja vale para o B3,
   o B2b e a grade da semana.

   Vieram byte a byte, sem reescrita, e o que mudou depois esta anotado no
   lugar em que acontece.
   -------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------
   3. O QUE VEM JUNTO

   Na home isto é uma faixa de quatro linhas curtas, porque lá o trabalho é
   sinalizar que existe. Aqui cada item é um argumento e ganha um parágrafo:
   é a página onde a pessoa está decidindo, e "body scan mensal" sozinho não
   quer dizer nada para quem nunca fez um.
   -------------------------------------------------------------------------- */

.lx-perks { padding-block: var(--sec-base); border-top: 1px solid var(--line); }
.lx-perks__head { margin-bottom: var(--sp-12); }
.lx-perks__head h2 { max-width: 20ch; }

.lx-perks__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-8); }
/* O NUMERO DE COLUNAS SEGUE O NUMERO DE ITENS, E ELE MUDOU DUAS VEZES EM 31/08
   Tres de manha, dois quando o nutrition app saiu do escopo, e tres de novo
   quando o cliente pediu o "no cancellation fee" de volta para a fila. Coluna
   vazia ao lado de um retrato 9:16 nao le como composicao, le como item que
   faltou carregar — e e por isso que este numero e mexido toda vez, em vez de
   ficar fixo em quatro. */
@media (min-width: 860px)  { .lx-perks__list { grid-template-columns: repeat(3, 1fr); gap: var(--sp-12) var(--sp-16); } }

/* Abaixo de 860 vira fila com os dois botoes. O filete de cima de cada item
   continua sendo o divisor, e deitado ele passa a marcar a coluna em vez da
   linha, que e o mesmo desenho lido de lado. */
@media (max-width: 859px) {
  .lx-perks__list {
    display: flex;
    gap: var(--sp-4);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .lx-perks__list::-webkit-scrollbar { display: none; }
  /* O item seguinte entregava titulo e primeira linha do paragrafo, e o olho ia
     ler o "Nutrition app" cortado em vez do "Monthly body scan" inteiro. */
  .lx-perks__list {
    -webkit-mask-image: var(--mask-peek);
    mask-image: var(--mask-peek);
  }
  .lx-perks__list > li {
    flex: 0 0 78%;
    min-width: 0;
    scroll-snap-align: start;
  }
}

.lx-perk { margin: 0; max-width: none; padding-top: var(--sp-6); border-top: 1px solid var(--line); }

.lx-perk__t {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--sp-3);
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: 600;
  line-height: 1.2;
  color: var(--ink);
  margin-bottom: var(--sp-3);
}

/* O valor de cada item, e o preço do pod. Etiqueta, não texto: o número tem
   de ler como dado no meio de um título. */
.lx-perk__v {
  font-family: var(--font-body);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}
/* O pod não vem incluso, ele é compra. A etiqueta dele é vermelha para a
   diferença ser visível antes de a frase ser lida. */
.lx-perk__v--paid { color: var(--accent); }

.lx-perk__d { font-size: var(--t-sm); color: var(--ink-soft); max-width: 46ch; }


/* --------------------------------------------------------------------------
   7. A RUDIS, COM A PAREDE DOS VALORES

   O bloco da Rudis sozinho deixava a metade direita da seção vazia, e o
   acervo tem a única foto que explica a marca sem uma linha de texto: o
   capacete montado com as palavras que o estúdio escolheu, na parede real.
   Ela não ilustra o parágrafo, ela é o mesmo argumento em outra mídia.
   -------------------------------------------------------------------------- */

.lx-creed { margin-top: var(--sp-16); display: grid; gap: var(--sp-8); align-items: center; }
@media (min-width: 900px) { .lx-creed { grid-template-columns: 1fr 1fr; gap: var(--sp-16); } }

.lx-creed__photo { margin: 0; }
.lx-creed__photo img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: 42% 46%;
  border-radius: var(--radius-md);
  background: var(--bg-sunken);
  filter: saturate(0.82) contrast(1.08);
}
.lx-creed .lx-milestone { margin-top: 0; }


/* --------------------------------------------------------------------------
   O VIDEO DE CADA ITEM, DESDE 31/08

   O cliente pediu o formato dos depoimentos da /testimonials aqui: titulo,
   video, texto. As medidas sao as de la, de proposito — 300px de teto para um
   retrato 9:16, que da 533px de altura, o ponto em que ele para de virar
   parede. Dois blocos que mostram video no mesmo site nao deviam ter dois
   tamanhos de video.

   A fila teve tres itens por algumas horas em 31/08, quando o "no contract"
   desceu para junto da Rudis; a tarde do mesmo dia o nutrition app saiu do
   escopo e ela voltou a dois. As colunas seguiram o numero de itens nas duas
   vezes: coluna vazia ao lado de um retrato alto nao le como composicao.
   -------------------------------------------------------------------------- */

.lx-perk__frame { max-width: 300px; margin-bottom: var(--sp-4); }

.lx-perk__video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 9 / 16;
  border-radius: var(--radius-sm);
  background: var(--bg-sunken);
  object-fit: cover;
}

/* O MARCADOR DOS DOIS VIDEOS QUE AINDA NAO EXISTEM (P39)
   Mesma caixa do video, tracejada e sem controle nenhum: ele se apresenta como
   o que e. E a regra do botao da App Store no rodape — um elemento que parece
   funcionar e nao funciona custa mais confianca do que um que se declara
   pendente. Nao usa .la-hold: o cliente pediu para ver o lugar reservado. */
.lx-perk__soon {
  aspect-ratio: 9 / 16;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--line);
  border-radius: var(--radius-sm);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--ink-faint);
  text-align: center;
}

/* O TERCEIRO ITEM DA FILA NAO TEM VIDEO, E NUNCA VAI TER
   O "no cancellation fee" voltou para a grade em 31/08 a pedido do cliente. Ele
   e o unico dos tres que nao filma: a ausencia de uma taxa nao e uma cena.

   Sem nada no lugar do video o paragrafo dele comecaria uns 500px acima dos
   vizinhos, e uma coluna que comeca no meio le como card que nao carregou —
   exatamente o oposto do alinhamento que o cliente pediu. Entao a peca abaixo
   ocupa o mesmo slot, com a mesma proporcao.

   E ela NAO e o marcador tracejado do heart rate pod, de proposito: aquele
   promete um video que ainda vem, e este nao espera nada. Sem tracejado, sem
   caixa alta de etiqueta, e com a frase na fonte de titulo — le como uma
   afirmacao curta, que e o que ela e. */
/* O TERCEIRO ITEM NAO TEM MIDIA, E RESOLVE POR ALINHAMENTO
   O "no cancellation fee" e o unico dos tres que nao filma. Sem nada no lugar
   do video, titulo e paragrafo ficariam colados no topo e a coluna teria 500px
   de vazio embaixo — que le como card que nao carregou.

   Centrado, o mesmo vazio fica dividido em dois e passa a ler como composicao.
   E a solucao mais barata das tres que este card teve em 31/08, e a unica que
   nao inventa conteudo para preencher slot.

   So no desktop: no carrossel do telefone os cards ja tem alturas proprias e
   nao ha fila com que alinhar. */
@media (min-width: 860px) {
  .lx-perk--middle { display: flex; flex-direction: column; justify-content: center; }
}


/* ===== ludus-home.css ===== */
/* ==========================================================================
   LUDUS ACTIUS — HOME
   Onda 1, item 3. Depende de tokens, base e chrome.

   RITMO
   -----
   Oito seções, oito famílias de layout diferentes. Nenhuma repete o molde da
   anterior, e as alturas variam de propósito. Cinco seções da mesma altura em
   sequência é o anti-padrão estrutural que afundava o site antigo.

     1  hero em vídeo, texto ancorado embaixo à esquerda   alto      profunda
     2  a garantia em números, faixa horizontal            baixo     profunda
     3  prove them wrong, sequência com o filete           muito alto profunda
     4  os quatro programas, bento assimétrico             médio     profunda
     ------------------------------- corte de superfície -------------------
     5  o método, split sem imagem                         médio     clara
     6  preço, quatro cartões                              baixo     clara
     7  marcar, com o calendário do estúdio                médio     clara
     8  quem conduz, retrato sangrando + lista densa       médio     clara
     9  a Rudis, o fecho da marca                          baixo     clara

   A ordem de 6 a 9 mudou em 21/08 a pedido do cliente: preço e agendamento
   vieram para antes do coach. A autoridade não sumiu do topo, ela já está na
   faixa de credenciais da seção 2, logo abaixo do hero; aqui embaixo o coach
   deixa de ser argumento de entrada e vira reforço de quem acabou de ver o
   preço e o calendário.

   UM corte de superfície, no ponto em que o site sai de convencer pela imagem
   e passa a convencer pela leitura. Não é alternância: é composição.

   FOTOGRAFIA
   ----------
   O acervo é desigual. As fotos do dia a dia foram feitas no celular, num
   salão de teto branco e luz fluorescente; só a das crianças é ensaio. Sem
   tratamento, elas entram como retângulos claros boiando no carvão.
   A classe .lx-photo dá a graduação que faz o conjunto parecer um sistema.
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. TRATAMENTO DE FOTO
   -------------------------------------------------------------------------- */

/* O acervo tem quatro exposições diferentes: a das crianças é ensaio, escura e
   fechada; a do kettlebell é celular sob fluorescente. Lado a lado, sem grade,
   elas não parecem do mesmo lugar.

   A graduação resolve em três camadas:
     filtro     dessatura a maior parte, fecha o preto, abre o contraste
     ::before   lavagem vermelha vinda de um canto, que dá viés comum às quatro
     ::after    véu de baixo para cima, que assenta a foto e abre espaço ao texto

   No repouso as quatro viram um conjunto. No hover, a que está sob o cursor
   recupera a cor: é a única forma de contraste entre elas que significa
   alguma coisa, porque responde a uma ação. */

.lx-photo { position: relative; overflow: hidden; background: var(--bg-sunken); }

.lx-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(0.62) saturate(1.15) contrast(1.2) brightness(0.78);
  transition: filter var(--dur-enter) var(--ease),
              transform var(--dur-enter) var(--ease-out);
}

/* Lavagem de canto. Sem mix-blend-mode: em cima de foto de exposição variável
   o resultado do blend é imprevisível, e aqui previsibilidade vale mais. */
.lx-photo::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(148deg, color-mix(in srgb, var(--red-900) 34%, transparent) 0%, transparent 52%),
    color-mix(in srgb, #0d0d0f 20%, transparent);
}

.lx-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: linear-gradient(
    to top,
    color-mix(in srgb, var(--bg) 96%, transparent) 0%,
    color-mix(in srgb, var(--bg) 72%, transparent) 30%,
    color-mix(in srgb, var(--bg) 14%, transparent) 66%,
    transparent 100%
  );
}
.lx-photo--flat::after { display: none; }

/* --------------------------------------------------------------------------
   1. HERO

   A figura emerge do escuro. Não é foto colada num painel.

   O que não funcionou antes, e por quê:

     largura cheia   o cover estica a foto de 709x644 em 2,1 vezes, a borda
                     aparece na direita e o sujeito cai debaixo do texto
     painel a 58%    controla onde ele fica, mas a aresta esquerda vira um
                     corte vertical, e véu por cima só disfarça a emenda:
                     a imagem continua lá, com brilho diferente do fundo

   A saída é máscara, não véu. O mask-image zera o alfa da própria imagem,
   então não existe aresta para aparecer. E a máscara é radial, centrada no
   atleta: ele fica opaco, tudo em volta dissolve no carvão. Resolve as duas
   coisas de uma vez, o recorte e a atmosfera.

   Com a máscara segurando as bordas, a mídia pode ser larga de novo (78%) e
   chegar perto do texto sem risco, porque na altura da manchete o alfa já é
   zero.
   -------------------------------------------------------------------------- */

.lx-hero {
  position: relative;
  display: flex;
  align-items: center;
  min-height: min(74svh, 660px);
  padding-block: var(--sp-12);
  overflow: hidden;
}

/* Seletor dobrado: o `.elementor img` (0,1,1) do Elementor zera a altura
   daqui desde que este elemento virou <img>. Ver o comentario do
   .lx-brand__mark no ludus-chrome.css. */
.lx-hero__media.lx-hero__media {
  position: absolute;
  inset-block: 0;
  right: 0;
  width: 78%;
  /* Teto de largura, e ele existe por causa do object-position abaixo.
     Sem o teto, a 2560px o painel iria a 1997px, o cover escalaria a foto em
     2,8 vezes e o transbordo vertical dobraria. A mesma porcentagem cortaria
     o dobro de pixels e jogaria a cabeça dele para fora do quadro. Com o
     teto, o transbordo fica estável e o enquadramento vale em toda largura. */
  max-width: 1180px;
  height: 100%;
  object-fit: cover;
  /* 39%. Com o transbordo vertical em ~388px na largura travada, cada ponto
     percentual vale ~3,9px de deslocamento. Passou por 20% (cabeça na altura
     da manchete) e por 62% (subiu 90px demais). */
  object-position: 50% 39%;
  /* Menos escuro que antes: quem escurece agora é a máscara, nas bordas.
     Fechar o brilho no arquivo inteiro apagava a nuvem de magnésio. */
  filter: saturate(0.75) contrast(1.16) brightness(0.84);
  /* O centro da máscara acompanha a figura: se ficar longe da cabeça, ela cai
     fora do núcleo opaco e desbota justo onde se quer ver. */
  /* DUAS MASCARAS, COMPOSTAS. E o conserto da emenda visivel de 21/08.

     A radial sozinha tinha raio grande demais para alcancar as bordas: com
     118% na horizontal e o centro em 60%, a aresta esquerda ficava a 51% do
     gradiente, ou seja em alfa 0,76. Nao era transparencia, era um corte
     vertical de imagem a 76% de opacidade, e dava para ver que a foto era um
     retangulo colado. O mesmo na aresta de cima, pior ainda: alfa ~0,9.

     A conta que manda e distancia / raio = posicao no gradiente, e o raio
     precisa ser MENOR que a distancia que se quer dissolver.

     A radial agora fecha em 72% na horizontal, o que leva a aresta esquerda a
     81% do gradiente e a alfa ~0,06. Na vertical ela continua larga, para nao
     comer o atleta, e quem dissolve o topo e a segunda mascara: um degrade
     linear que so apaga a faixa de cima. As duas se combinam por intersecao,
     entao um pixel so aparece se as DUAS deixarem.

     A aresta da direita fica dura de proposito: ela encosta na borda da tela,
     nao existe fundo ao lado dela para a emenda aparecer. */
  -webkit-mask-image:
    radial-gradient(72% 128% at 58% 42%,
      #000 18%, rgba(0,0,0,.74) 46%, rgba(0,0,0,.20) 70%, transparent 90%),
    linear-gradient(to bottom, transparent 0%, rgba(0,0,0,.45) 9%, #000 24%);
  -webkit-mask-composite: source-in;
  mask-image:
    radial-gradient(72% 128% at 58% 42%,
      #000 18%, rgba(0,0,0,.74) 46%, rgba(0,0,0,.20) 70%, transparent 90%),
    linear-gradient(to bottom, transparent 0%, rgba(0,0,0,.45) 9%, #000 24%);
  mask-composite: intersect;
  z-index: 0;
}

/* Com a máscara cuidando das arestas, sobram dois trabalhos para o véu:
   contraste do texto na esquerda, e a emenda com a faixa da garantia. */
.lx-hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    linear-gradient(to right,
      var(--bg) 0%,
      color-mix(in srgb, var(--bg) 76%, transparent) 24%,
      color-mix(in srgb, var(--bg) 22%, transparent) 44%,
      transparent 60%),
    linear-gradient(to top,
      var(--bg) 0%,
      color-mix(in srgb, var(--bg) 28%, transparent) 16%,
      transparent 38%);
}

.lx-hero__inner { position: relative; z-index: 2; }

.lx-hero h1 {
  font-size: clamp(2.2rem, 4.1vw, 4.2rem);
  max-width: 15ch;
  margin-bottom: var(--sp-6);
}

.lx-hero .lx-lead {
  max-width: 40ch;
  color: var(--ink);
  margin-bottom: var(--sp-8);
}

.lx-hero__cta { display: flex; flex-wrap: wrap; gap: var(--sp-4); }

/* MOBILE: a imagem termina dentro do texto.

   Em tela estreita a foto não tem zona vazia: sujeito centralizado em quadro
   quase quadrado. Sobrepor obriga a escolher entre ler a manchete e ver o
   atleta. Então a imagem sai de cima do texto e vira faixa no topo.

   A GEOMETRIA, que é o que manda aqui:
   a foto tem 709x644, razão 1,10. Numa faixa de largura cheia a 390px, o cover
   escala por largura e a imagem sai com 354px de altura. Ou seja: qualquer
   faixa mais alta que 354px mostra a foto inteira, teto incluído, e
   object-position não tem o que cortar. Para o teto sair, a faixa tem que ser
   mais baixa que isso. Em ~250px sobram 100px de transbordo, e 60% joga a
   maior parte do corte no topo.

   E aí a altura que sobra vira o efeito: a mídia é mais alta que a linha da
   grade, então ela avança sobre o texto, e a máscara dissolve justamente ali.
   A imagem não termina numa borda, ela acaba dentro da manchete. */
@media (max-width: 860px) {
  .lx-hero {
    /* Um valor, dois consumidores: a altura da mídia e a do véu. Se os dois
       ficassem soltos, bastava mexer num para o véu desalinhar da imagem. */
    --hero-band: clamp(240px, 31svh, 300px);
    display: grid;
    grid-template-rows: clamp(170px, 22svh, 210px) auto;
    align-items: stretch;
    min-height: auto;
    padding-block: 0 var(--sec-tight);
  }

  .lx-hero__media.lx-hero__media {
    position: absolute;         /* sai da grade: a linha 1 vira só espaçador */
    top: 0;
    left: 0;
    right: 0;
    width: 100%;
    max-width: none;
    /* Mais alta que a linha 1, e abaixo dos 354px que mostrariam a foto
       inteira. A diferença entre as duas é o quanto ela invade o texto. */
    height: var(--hero-band);
    object-position: 50% 60%;   /* 60% joga o corte no teto */
    filter: saturate(0.78) contrast(1.14) brightness(0.92);
    /* A dissolução começa na metade e só termina na base, já dentro da
       manchete. Fade curto entrega borda; fade longo entrega imersão. */
    -webkit-mask-image: linear-gradient(to bottom,
      #000 0%, #000 46%, rgba(0,0,0,.55) 72%, rgba(0,0,0,.18) 88%, transparent 100%);
    mask-image: linear-gradient(to bottom,
      #000 0%, #000 46%, rgba(0,0,0,.55) 72%, rgba(0,0,0,.18) 88%, transparent 100%);
  }

  /* O véu volta, mas só na cauda da faixa.

     A máscara sozinha não bastava: no trecho onde a manchete começa, a barra e
     as anilhas ainda estão com alfa alto, e o brilho do metal briga com as
     letras. Máscara tira imagem; véu escurece a que fica. Aqui o certo é
     escurecer, porque a barra é parte da cena e não sobra.

     Transparente até 38% para não tocar no rosto, e fechando até o carvão
     no ponto exato em que o texto entra. */
  .lx-hero__scrim {
    display: block;
    top: 0;
    left: 0;
    right: 0;
    bottom: auto;
    height: var(--hero-band);
    z-index: 1;
    background: linear-gradient(to bottom,
      transparent 0%,
      transparent 38%,
      color-mix(in srgb, var(--bg) 26%, transparent) 58%,
      color-mix(in srgb, var(--bg) 62%, transparent) 76%,
      color-mix(in srgb, var(--bg) 88%, transparent) 90%,
      var(--bg) 100%);
  }

  .lx-hero__inner {
    position: relative;
    z-index: 2;
    grid-row: 2;
    padding-top: var(--sp-4);
  }

  .lx-hero h1 { max-width: none; }
  .lx-hero .lx-lead { max-width: none; margin-bottom: var(--sp-6); }
}

@media (max-width: 560px) {
  .lx-hero__cta .lx-btn { flex: 1 1 100%; }
}

/* --------------------------------------------------------------------------
   2. A GARANTIA EM NÚMEROS
   Faixa baixa e densa logo depois de um hero alto. A quebra de ritmo é o
   ponto: a promessa vira número antes de virar argumento.
   -------------------------------------------------------------------------- */

.lx-promise { padding-block: var(--sec-tight); border-top: 1px solid var(--line); }

.lx-promise__list {
  list-style: none;
  margin: 0 0 var(--sp-8);
  padding: 0;
  display: grid;
  gap: var(--sp-6);
}
@media (min-width: 720px) {
  .lx-promise__list { grid-template-columns: repeat(3, 1fr); gap: 0; }
  .lx-promise__list li + li {
    border-left: 1px solid var(--line);
    padding-left: var(--sp-8);
    margin-left: var(--sp-8);
  }
}

/* NO TELEFONE OS TRES VIRAM CARROSSEL, E O MOTIVO E ALTURA
   Empilhados, os tres numeros ocupavam quase 400px de rolagem para dizer tres
   frases curtas, e isso logo depois de um hero de tela cheia: a pessoa
   deslizava muito antes de chegar em qualquer coisa acionavel. Deitados num
   carrossel, a faixa passa a ter a altura de UM item.

   Sem JS e sem plugin: e scroll-snap. O navegador ja sabe fazer isso, e a
   biblioteca que faria o mesmo pesaria mais que a pagina inteira.

   OS 84% NAO SAO ESTETICA, SAO O AVISO. Com o item em 100% nada indica que ha
   mais coisa ao lado, e carrossel que nao se anuncia e conteudo escondido.
   Deixando o proximo espiar pela borda, a affordance vem do proprio layout, sem
   bolinha, sem seta e sem script.

   A barra de rolagem some porque no toque ela e sobreposta e temporaria, e numa
   faixa escura estreita ela le como defeito. O espiar faz o trabalho dela.

   Isto NAO cria rolagem lateral na pagina: quem rola e o <ol>, que tem overflow
   proprio, e o scrollWidth do documento nao muda. A auditoria da captura.py
   confirma a 320. */
@media (max-width: 719px) {
  .lx-promise__list {
    display: flex;
    gap: var(--sp-4);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .lx-promise__list::-webkit-scrollbar { display: none; }
  .lx-promise__list li {
    flex: 0 0 84%;
    scroll-snap-align: start;
  }
}
.lx-promise__list li { margin: 0; max-width: none; }

.lx-promise__n {
  /* EMPILHADO, e a faixa de largura fixa foi embora. A faixa nasceu para "3",
     "12" e "100%", que tinham larguras muito diferentes e faziam cada descrição
     começar num x próprio. Com o número agora EM CIMA do texto, todo x de
     partida já é o mesmo por construção: a faixa virou só um buraco de 3,1em
     entre número e frase — e num número de um dígito o buraco era quase o dobro
     do próprio número. Empilhar também mata a escada no mobile, que era o outro
     motivo da faixa.

     O número pode crescer porque não disputa mais a linha com a frase, e a
     frase ganha a coluna inteira: cai de quatro linhas estreitas para duas. */
  display: block;
  margin-bottom: var(--sp-3);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.6rem, 4.2vw, 4.2rem);
  line-height: 0.85;
  letter-spacing: -0.03em;
  color: var(--accent-rule);
  font-variant-numeric: tabular-nums;
}
.lx-promise__t { display: block; font-size: var(--t-sm); color: var(--ink-soft); max-width: 30ch; }

.lx-promise__fine { font-size: var(--t-sm); color: var(--ink-soft); max-width: 68ch; margin: 0; }

/* --------------------------------------------------------------------------
   3. PROVE THEM WRONG — momento 1
   A seção mais alta do site, e a única com sequência conduzida por scroll.
   -------------------------------------------------------------------------- */

.lx-proof { padding-block: var(--sec-tall); border-top: 1px solid var(--line); }

.lx-proof__head { margin-bottom: var(--sec-tight); }
.lx-proof__head h2 { max-width: 14ch; margin-bottom: var(--sp-4); }

.lx-spine { position: relative; }
.lx-spine__rail { position: absolute; left: 6px; top: 0; bottom: 0; width: var(--rule); background: var(--line); }
.lx-spine__line {
  position: absolute; left: 6px; top: 0; height: 100%; width: var(--rule);
  background: var(--accent-rule);
  transform: scaleY(var(--lx-progress, 1));
  transform-origin: top center;
}
.lx-spine__items { list-style: none; margin: 0; padding: 0; position: relative; }
/* O respiro entre as objeções é fixo, e não segue o ritmo de seção. A
   sequência precisa de distância para o scroll resolver uma de cada vez;
   com --sec-tight reduzido, as quatro chegariam quase juntas. */
.lx-spine__item { position: relative; padding: 0 0 var(--sp-16) 44px; max-width: none; }
.lx-spine__item:last-child { padding-bottom: 0; }

.lx-spine__dot {
  position: absolute; left: 0; top: 0.42em;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--bg); border: var(--rule) solid var(--line);
  transition: border-color var(--dur-state) var(--ease), background-color var(--dur-state) var(--ease);
}
.lx-spine__item.is-resolved .lx-spine__dot { border-color: var(--accent-rule); background: var(--accent-rule); }

.lx-spine__objection {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.3rem, 2.05vw, 2.1rem);
  line-height: 1.25;
  color: var(--ink-faint);
  margin: 0;
  max-width: 24ch;
  transition: color var(--dur-state) var(--ease);
}
/* O risco é .lx-strike, do ludus-base.css. Até 21/08 era um ::after em
   top:52% aqui, que só cortava a primeira linha das objeções de duas linhas,
   e três das quatro têm duas. O componente do base corta cada linha. */

.lx-spine__answer { margin-top: var(--sp-4); }
.lx-js .lx-spine__answer {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity var(--dur-enter) var(--ease-out), transform var(--dur-enter) var(--ease-out);
  transition-delay: 180ms;
}
.lx-spine__item.is-resolved .lx-spine__answer { opacity: 1; transform: none; }

.lx-spine__who { font-size: var(--t-lead); font-weight: 600; color: var(--ink); margin: 0; }
.lx-spine__proof { font-size: var(--t-sm); color: var(--ink-soft); margin: var(--sp-1) 0 0; max-width: 46ch; }

/* Retrato dos quatro depoentes. Fica escondido até o cliente responder P05:
   o layout foi desenhado para funcionar sem ele, não para depender dele. */
.lx-spine__portrait { display: none; }

/* O bloco abaixo tem de ficar DEPOIS de todas as regras acima. Ele sobrescreve
   .lx-spine__item, .lx-spine__answer e .lx-spine__proof com a mesma
   especificidade, e em empate quem ganha e a ultima declaracao do arquivo.
   Na primeira tentativa ele estava no meio da secao e o max-width de 62ch
   simplesmente nao aplicava: os 46ch declarados abaixo dele venciam. */

/* DUAS COLUNAS, SÓ NO DESKTOP

   Empilhada, a espinha ocupa uns 45% da largura e deixa metade da seção
   vazia. A objeção não pode crescer para preencher, porque ela já está no
   limite do que cabe antes de virar manchete e brigar com o H1 da seção.

   A resposta é composição, não conteúdo novo: a dúvida fica de um lado e a
   pessoa que a desmente fica do outro, na mesma faixa horizontal. É o que a
   seção afirma, virado em layout. Nada foi inventado para preencher, e no
   celular tudo volta a empilhar na ordem de leitura natural.

   O respiro entre os itens CRESCE aqui, contra a intuição: em duas colunas
   cada item fica uns 40% mais curto, e sem compensar, as quatro objeções
   entrariam em vista quase juntas. A sequência depende de distância. */
@media (min-width: 900px) {
  .lx-spine__item {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--sp-16);
    align-items: start;
    padding-bottom: var(--sp-24);
  }
  .lx-spine__item:last-child { padding-bottom: 0; }
  .lx-spine__answer { margin-top: 0; }

  /* A entrada passa a ser lateral. Não é efeito novo: é o mesmo transform do
     mesmo elemento, na direção que o layout agora tem. A resposta chega do
     lado da objeção, que é de onde ela vem. */
  .lx-js .lx-spine__answer { transform: translateX(-14px); }
  .lx-spine__item.is-resolved .lx-spine__answer { transform: none; }

  /* A medida da prova sobe de 46ch para 62ch. Os 46ch foram calibrados para o
     texto solto na coluna única, e dentro de uma coluna de ~518px eles deixam
     uns 170px vagos na direita, que é a sobra que ainda dava para ver depois
     de o layout virar duas colunas. 62ch enche a coluna e continua abaixo do
     --measure de 66ch, que é o limite de linha legível do sistema. */
  .lx-spine__proof { max-width: 62ch; }
}


/* --------------------------------------------------------------------------
   4. PROGRAMAS — bento assimétrico
   Quatro itens, quatro células, nenhuma vazia. O carro-chefe ocupa a coluna
   alta. Três cards iguais lado a lado seria o molde que estamos evitando.
   -------------------------------------------------------------------------- */

.lx-programs { padding-block: var(--sec-base); border-top: 1px solid var(--line); }
.lx-programs__head { margin-bottom: var(--sp-12); }
.lx-programs__head h2 { max-width: 18ch; }

/* Um alto à esquerda, três empilhados à direita.

   A versão anterior punha Workshops numa célula larga e baixa cruzando as duas
   colunas. O arquivo de Workshops tem 473x822, retrato fechado: numa caixa
   larga e curta ele perdia a cena inteira. Na coluna da direita o corte fica
   dentro do que a foto aguenta.

   O carro-chefe ocupa a coluna inteira, e não por hierarquia inventada: é a
   aula em torno da qual o estúdio foi montado. */

.lx-bento { display: grid; gap: var(--sp-3); grid-template-columns: 1fr; }

/* NO TELEFONE O BENTO DEITA, PELA MESMA RAZAO DA FAIXA DE CREDENCIAIS
   Empilhados, os cinco programas eram cinco fotos altas em coluna, e esta virava
   a secao mais longa da pagina: mais de mil pixels para dizer que existem cinco
   aulas. Deitado, ocupa a altura de UM cartao, e o carrossel do ludus-motion.js
   passa por eles sozinho.

   86% e nao 100% pelo mesmo motivo de la: o proximo cartao espiando pela borda e
   o que avisa que ha mais. Aqui ele importa ainda mais, porque "Five ways in"
   promete cinco no titulo, e um cartao ocupando a tela toda entregaria um.

   O min-width: 0 nao e enfeite. Item de flex nasce com min-width auto e nao
   encolhe abaixo do proprio conteudo: sem ele, a descricao mais longa de um
   cartao esticaria a base do carrossel e a pagina ganharia rolagem lateral, que
   e o defeito que a auditoria a 320 pega. */
@media (max-width: 859px) {
  .lx-bento {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .lx-bento::-webkit-scrollbar { display: none; }
  .lx-bento__cell {
    flex: 0 0 86%;
    min-width: 0;
    scroll-snap-align: start;
  }
}

/* SEIS LINHAS, NÃO TRÊS, desde 24/08. A coluna da esquerda foi partida ao
   meio para receber o Kettlebell Training, e o corte precisa cair no meio da
   coluna, não numa borda da coluna da direita. Com três linhas não havia meio:
   o único ponto de corte era entre a linha 1 e a 2, a um terço da altura. Seis
   linhas dão os dois ritmos ao mesmo tempo, 3+3 à esquerda e 2+2+2 à direita,
   e a altura total do bento não muda. */
@media (min-width: 860px) {
  .lx-bento {
    grid-template-columns: 1.5fr 1fr;
    grid-template-rows: repeat(6, minmax(0, 1fr));
    min-height: clamp(560px, 50vw, 760px);
  }
  .lx-bento__cell { min-height: 0; }
  .lx-bento__cell:nth-child(1) { grid-column: 1; grid-row: 1 / 4; padding: var(--sp-8); }
  .lx-bento__cell:nth-child(2) { grid-column: 1; grid-row: 4 / 7; padding: var(--sp-8); }
  .lx-bento__cell:nth-child(3) { grid-column: 2; grid-row: 1 / 3; }
  .lx-bento__cell:nth-child(4) { grid-column: 2; grid-row: 3 / 5; }
  .lx-bento__cell:nth-child(5) { grid-column: 2; grid-row: 5 / 7; }

  /* Antes era só a célula alta que trazia o nome em corpo de título, e a
     justificativa era o tamanho dela. Agora são duas células do mesmo tamanho:
     dar o corpo grande só à primeira faria a segunda parecer defeito, na mesma
     caixa e com outra escala. Quem manda passou a ser a COLUNA, não a célula.
     O carro-chefe perde o tamanho exclusivo e fica com o primeiro lugar de
     leitura, que no celular é o que sobra de hierarquia de qualquer jeito. */
  .lx-bento__cell:nth-child(-n+2) .lx-bento__name { font-size: var(--t-h2); }
  .lx-bento__cell:nth-child(-n+2) .lx-bento__desc { font-size: var(--t-body); max-width: 34ch; }
  .lx-bento__cell:nth-child(-n+2) .lx-bento__rule { width: 64px; }

  /* O véu padrão sobe até 66% da altura da célula, e foi calibrado quando a
     célula da esquerda tinha três linhas de grade: lá o texto grande ainda
     caía dentro do trecho opaco. Partida ao meio, a mesma pilha de texto passa
     a ocupar quase metade de uma caixa com metade da altura, e o nome sai do
     véu e vai parar em cima da parede clara do salão. O véu destas duas sobe
     junto com o texto. As três da direita não mexem: lá o texto é pequeno e
     continua rente ao pé. */
  .lx-bento__cell:nth-child(-n+2) .lx-photo::after {
    background: linear-gradient(
      to top,
      color-mix(in srgb, var(--bg) 96%, transparent) 0%,
      color-mix(in srgb, var(--bg) 82%, transparent) 48%,
      color-mix(in srgb, var(--bg) 26%, transparent) 80%,
      transparent 100%
    );
  }
}

/* Enquadramento por foto. object-fit:cover com object-position no padrão corta
   pelo centro geométrico, que quase nunca é onde está a cena. */
.lx-photo--top   img { object-position: 50% 34%; }
.lx-photo--upper img { object-position: 48% 40%; }
.lx-photo--mid   img { object-position: 52% 45%; }
.lx-photo--lower img { object-position: 50% 54%; }
/* O quinto degrau entrou com a foto nova do Ludus Training (24/08). Os quatro
   acima ficam entre 34% e 54% porque nas outras fotos a cena está no meio do
   quadro. Nesta ela está no alto: o que a foto tem de argumento é a tela de
   frequência cardíaca na parede, e a 34% ela já sai cortada pela borda. */
.lx-photo--crown img { object-position: 50% 22%; }

.lx-bento__cell {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 260px;
  padding: var(--sp-6);
  border: 1px solid var(--line);        /* separa uma célula da outra */
  border-radius: var(--radius-md);
  overflow: hidden;
  color: var(--ink);
  isolation: isolate;
  transition: border-color var(--dur-state) var(--ease);
}
.lx-bento__cell .lx-photo { position: absolute; inset: 0; z-index: 0; border-radius: inherit; }
.lx-bento__cell > * { position: relative; z-index: 3; }

/* No hover a foto recupera a cor e avança um pouco. A célula ganha o contorno
   vermelho. É feedback, não enfeite: mostra qual das quatro está selecionada. */
.lx-bento__cell:hover { border-color: color-mix(in srgb, var(--accent-rule) 62%, transparent); }
.lx-bento__cell:hover img,
.lx-bento__cell:focus-visible img {
  filter: grayscale(0.08) saturate(1.06) contrast(1.1) brightness(0.94);
  transform: scale(1.035);
}
.lx-bento__cell:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }

.lx-bento__name { font-family: var(--font-display); font-weight: 600; font-size: var(--t-h3); margin: 0 0 var(--sp-2); color: var(--ink); }
.lx-bento__desc { font-size: var(--t-sm); color: var(--ink-soft); margin: 0; max-width: 40ch; }

/* O filete cresce no hover. Micro-interação, mesma linguagem dos momentos. */
.lx-bento__rule { display: block; width: 40px; height: var(--rule); background: var(--accent-rule); margin-bottom: var(--sp-4); transform-origin: left center; transition: transform var(--dur-state) var(--ease-out); }
.lx-bento__cell:hover .lx-bento__rule { transform: scaleX(2); }

/* --------------------------------------------------------------------------
   5. O MÉTODO — momento 2
   Sem imagem, de propósito. Vem depois de quatro seções de fotografia: a
   quebra é o descanso, e é onde o argumento técnico precisa de silêncio.
   -------------------------------------------------------------------------- */

.lx-method { padding-block: var(--sec-base); }

.lx-method__grid { display: grid; gap: var(--sp-12); }
@media (min-width: 940px) {
  .lx-method__grid { grid-template-columns: 5fr 7fr; gap: var(--sp-16); align-items: start; }
}

.lx-method__aside h2 { max-width: 12ch; margin-bottom: var(--sp-6); }
.lx-method__aside p { font-size: var(--t-sm); color: var(--ink-soft); }

.lx-method__list { list-style: none; margin: 0; padding: 0; position: relative; padding-left: 44px; }
.lx-method__rail { position: absolute; left: 6px; top: 0; bottom: 0; width: var(--rule); background: var(--line); }
.lx-method__line {
  position: absolute; left: 6px; top: 0; height: 100%; width: var(--rule);
  background: var(--accent-rule);
  transform: scaleY(var(--lx-progress, 1));
  transform-origin: top center;
}
.lx-method__list li {
  position: relative;
  margin: 0;
  max-width: none;
  padding-block: var(--sp-6);
  border-bottom: 1px solid var(--line);
  font-size: var(--t-lead);
  line-height: 1.4;
  color: var(--ink-faint);
  transition: color var(--dur-state) var(--ease);
}
.lx-method__list li:last-child { border-bottom: 0; }
.lx-method__list li.is-lit { color: var(--ink); }
.lx-method__list li::before {
  content: "";
  position: absolute;
  left: -44px; top: calc(var(--sp-6) + 0.5em);
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--bg); border: var(--rule) solid var(--line);
  transition: border-color var(--dur-state) var(--ease), background-color var(--dur-state) var(--ease);
}
.lx-method__list li.is-lit::before { border-color: var(--accent-rule); background: var(--accent-rule); }

/* --------------------------------------------------------------------------
   6. QUEM CONDUZ
   Retrato sangrando pela esquerda, credenciais em lista densa. Família
   diferente do split da seção anterior: aqui a informação é tabular.
   -------------------------------------------------------------------------- */

/* A EMENDA COM O BLOCO DE AGENDAR E UM DEGRADE, NAO UM FILETE
   O .lx-book tem fundo --bg-sunken e esta secao tem o --bg normal, com um
   filete de 1px entre os dois. Eram tres arestas no mesmo lugar: troca de
   fundo, linha e troca de assunto. Lidas juntas, cortavam a pagina em vez de
   emendar, e o cliente marcou exatamente esse ponto.

   Agora o proprio --bg-sunken escorre para dentro desta secao e se dissolve no
   --bg dela. A altura acompanha a largura da tela porque num monitor largo um
   degrade de 80px vira listra; a faixa precisa ser alta o bastante para o olho
   nao achar onde ela comeca.

   O ::before fica DEPOIS do fluxo na ordem de pintura, entao o conteudo precisa
   subir junto: dai o z-index no container. Sem ele, o topo da ficha do coach
   ficaria por baixo do vidro. */
.lx-coach {
  padding-block: var(--sec-base);
  position: relative;
  isolation: isolate;
}
.lx-coach::before {
  content: "";
  position: absolute;
  inset: 0 0 auto;
  height: clamp(90px, 11vw, 180px);
  background: linear-gradient(to bottom, var(--bg-sunken), transparent);
  pointer-events: none;
  z-index: 0;
}
.lx-coach > .lx-container { position: relative; z-index: 1; }

.lx-coach__grid { display: grid; gap: var(--sp-8); }
@media (min-width: 940px) {
  .lx-coach__grid { grid-template-columns: 5fr 7fr; gap: var(--sp-16); align-items: start; }
}

/* A MOLDURA DO COACH — canto chanfrado

   Chapa de armadura e bossa de escudo. Retangular, que é o que o resto do site
   é, com os quatro cantos cortados a 45 graus em vez de arredondados.

   Não é só gosto: F45, Burn, HOTWORX e Anytime arredondam tudo, e a internet
   inteira junto. Cortar o canto lê como metal e ninguém no quarteirão faz.

   Estrutura em três camadas, e a razão de existirem três:
     mount    carrega o plinto, porque o clip-path da moldura recortaria ele
     frame    o fundo vermelho aparecendo pelos 2px de padding é o traço
     photo    o mesmo chanfro, 2px menor, para os cortes ficarem concêntricos

   O chanfro é a única exceção ao sistema de canto do site. Fica em um lugar
   só, de propósito: repetido em cinco lugares viraria tema, e a peça perde o
   peso de ser a única. */

.lx-coach__mount { position: relative; margin: 0 0 var(--sp-8); }

/* O plinto, e o segundo degrau. Base de pedra passa da coluna e é escalonada. */
.lx-coach__mount::after {
  content: "";
  position: absolute;
  left: 50%; bottom: -10px;
  transform: translateX(-50%);
  width: calc(100% + var(--sp-8));
  height: var(--rule);
  background: var(--accent-rule);
}
.lx-coach__mount::before {
  content: "";
  position: absolute;
  left: 50%; bottom: -18px;
  transform: translateX(-50%);
  width: 58%;
  height: 1px;
  background: var(--line-strong);
}

.lx-coach__frame {
  --chamfer: 20px;
  padding: 2px;                    /* o traço */
  background: var(--accent-rule);
  clip-path: polygon(
    var(--chamfer) 0,
    calc(100% - var(--chamfer)) 0,
    100% var(--chamfer),
    100% calc(100% - var(--chamfer)),
    calc(100% - var(--chamfer)) 100%,
    var(--chamfer) 100%,
    0 calc(100% - var(--chamfer)),
    0 var(--chamfer)
  );
}

.lx-coach__photo {
  --chamfer: 18px;                 /* 20 menos os 2px do traço */
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--bg-sunken);
  clip-path: polygon(
    var(--chamfer) 0,
    calc(100% - var(--chamfer)) 0,
    100% var(--chamfer),
    100% calc(100% - var(--chamfer)),
    calc(100% - var(--chamfer)) 100%,
    var(--chamfer) 100%,
    0 calc(100% - var(--chamfer)),
    0 var(--chamfer)
  );
}
.lx-coach__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 26%;
  filter: saturate(0.84) contrast(1.08);
}

@media (max-width: 940px) {
  /* Em coluna única, um retrato 4:5 na largura toda ocupa mais de meia tela e
     empurra as credenciais para fora da primeira visada. O limite deixa a
     moldura como peça, não como banner. */
  .lx-coach__mount { max-width: 360px; }
}
@media (max-width: 520px) {
  .lx-coach__frame { --chamfer: 14px; }
  .lx-coach__photo { --chamfer: 11px; }
}

/* Nome, cargo e a linha de posicionamento. */
.lx-coach__name { margin-bottom: var(--sp-2); }
.lx-coach__role {
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--ink-faint);
  margin: 0 0 var(--sp-6);
}
.lx-coach__line {
  font-family: var(--font-display);
  font-size: var(--t-lead);
  line-height: 1.45;
  color: var(--ink);
  max-width: 44ch;
  margin-bottom: var(--sp-8);
}

/* AS CREDENCIAIS
   Lista de definição de verdade, em duas colunas: rótulo à esquerda numa
   coluna de largura fixa, valores à direita. Filete fino separando grupo.

   O <dl> cru do navegador põe o dt em cima e indenta o dd em 40px, que foi
   exatamente o que apareceu quando estas regras sumiram. Sem a grade, a
   informação mais densa da página vira recuo de documento do Word. */
.lx-creds { margin: 0; }

.lx-creds > div {
  display: grid;
  gap: var(--sp-2) var(--sp-6);
  padding-block: var(--sp-4);
  border-bottom: 1px solid var(--line);
}
.lx-creds > div:first-child { border-top: 1px solid var(--line); }

@media (min-width: 620px) {
  .lx-creds > div { grid-template-columns: 14ch minmax(0, 1fr); align-items: baseline; }

  /* CADA dd NA COLUNA 2, E ISSO CONSERTA UM DEFEITO QUE ESTAVA NO AR
     A linha e uma grade de duas colunas e os filhos entram na ordem: o dt pega
     a coluna 1, o primeiro dd pega a 2, e o SEGUNDO dd volta para a 1, embaixo
     do rotulo. Com um dd por grupo ninguem via. O grupo "Postgraduate" tinha
     tres desde sempre e ja saia torto; so apareceu em 28/08, quando o curriculo
     novo juntou tres mestrados dentro de "Degrees" e a captura mostrou o
     segundo deles ocupando a coluna do rotulo.

     O `dd + dd { margin-top }` logo abaixo sempre assumiu que eles estavam
     empilhados na mesma coluna. Agora estao. */
  .lx-creds dd { grid-column: 2; }
}

.lx-creds dt {
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--ink-faint);
  line-height: 1.6;
}
.lx-creds dd {
  margin: 0;
  font-size: var(--t-sm);
  line-height: 1.55;
  color: var(--ink);
  max-width: 52ch;
}
/* Vários dd sob o mesmo dt: cada um vira uma linha, separada por respiro e
   não por bullet. Bullet aqui pesaria mais que a informação. */
.lx-creds dd + dd { margin-top: var(--sp-3); }

/* --------------------------------------------------------------------------
   7. PREÇO
   Tabela de verdade, com números tabulares. Quatro cards com sombra seria a
   escolha padrão, e esconderia a comparação que a pessoa veio fazer.
   Filete só embaixo de cada linha: nunca em cima e embaixo das duas.
   -------------------------------------------------------------------------- */

.lx-pricing { padding-block: var(--sec-base); border-top: 1px solid var(--line); }
/* Título e apoio empilhados. Título grande à esquerda com um parágrafo pequeno
   flutuando no canto superior direito é um dos tiques mais reconhecíveis de
   layout gerado, e aqui ainda jogava fora a melhor frase da seção. */
.lx-pricing__head { margin-bottom: var(--sp-8); }
.lx-pricing__head h2 { max-width: 16ch; margin-bottom: var(--sp-4); }
.lx-pricing__head p { max-width: 46ch; }

/* A TABELA DE PRECO SAIU DAQUI EM 21/08
   Ela mostrava o preco e nao dava o que fazer com ele. Virou os mesmos
   cartoes da /testimonials: .lx-plan-grid, em ludus-page.css secao 3, com o
   markup em assets/html/block-plan-grid.html, que passou a ser o unico lugar
   do projeto onde os precos existem.

   Saiu junto o .lx-plans inteiro, o .lx-price e o @media de 640px que
   remontava a tabela em duas colunas no celular. Se algum dia a /membership
   pedir comparacao lado a lado, e outro componente: tem mais colunas e um
   trabalho diferente. */

/* O que vem junto: uma faixa, não a mesma lista repetida em cada cartão. Desde
   26/08 vale para os quatro planos de adulto, não para o Kids. Ver P27. */
.lx-included { margin-top: var(--sp-8); padding-top: var(--sp-6); border-top: var(--rule) solid var(--accent-rule); display: grid; gap: var(--sp-4) var(--sp-8); }
/* Tres colunas desde 31/08: eram quatro itens ate o nutrition app sair do
   escopo. Com `repeat(4, 1fr)` e tres itens, a quarta coluna fica vazia e a
   faixa desalinha do filete vermelho que a abre. */
@media (min-width: 720px) { .lx-included { grid-template-columns: repeat(3, 1fr); } }
.lx-included p { margin: 0; font-size: var(--t-sm); color: var(--ink); max-width: none; }
.lx-included span { display: block; font-size: var(--t-xs); color: var(--ink-faint); margin-top: 2px; }

/* A RUDIS mudou de arquivo em 21/08: a /membership passou a usar o mesmo
   bloco. Vive em ludus-page.css, secao 4. */

/* --------------------------------------------------------------------------
   8. MARCAR A AULA
   Mudou de arquivo. E o bloco B3 do sitemap, global, e a /testimonials passou
   a usar o mesmo formulario. Vive agora em ludus-page.css, secao 2.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   9. MOVIMENTO REDUZIDO
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  /* O `.lx-hero__media.lx-hero__media { display: none }` saiu em 02/09, junto com o vídeo do
     hero. Ele existia porque vídeo em loop É movimento e quem pede movimento
     reduzido não deve recebê-lo. Uma foto parada não é movimento, e esconder a
     única imagem acima da dobra puniria justamente quem pediu menos estímulo.

     De quebra some a armadilha que estava registrada: `--force-prefers-reduced-
     motion` no Chrome headless disparava esta regra e a captura do hero saía
     preta, parecendo layout quebrado. A captura.py continua sem a flag, mas
     agora por escolha e não por necessidade. */
  .lx-js .lx-spine__answer { opacity: 1; transform: none; }
  .lx-method__list li { color: var(--ink); }
  .lx-bento__cell:hover img { transform: none; }
}

/* --------------------------------------------------------------------------
   10. AJUSTES DE MARCA NO RODAPÉ
   No cabeçalho o símbolo divide 72px com a navegação. No rodapé ele tem espaço
   e é o único elemento de marca da coluna, então cresce.
   -------------------------------------------------------------------------- */

.lx-footer__col .lx-brand__mark { height: 56px; }
.lx-footer__col .lx-brand { align-items: center; gap: var(--sp-4); }


/* --------------------------------------------------------------------------
   11. AJUSTES DE 21/08
   -------------------------------------------------------------------------- */

/* O bento mostrava quatro programas e não dizia o que fazer com eles.
   Com dois botões (24/08) a linha virou fila: mesmo gap e mesma quebra do
   .lx-hero__cta, que é o outro par de CTA da página. O max-width existe porque
   a regra de base dá --measure a todo <p>, e aqui o <p> não carrega texto,
   carrega dois botões: com a medida de leitura o segundo quebraria sozinho
   muito antes de faltar espaço. */
.lx-programs__more {
  margin-top: var(--sec-tight);
  max-width: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
}
/* Mesmo corte do hero: em coluna estreita, botão de meia largura ao lado de
   botão de largura inteira lê como erro, então os dois ocupam a linha. */
@media (max-width: 560px) {
  .lx-programs__more .lx-btn { flex: 1 1 100%; }
}

/* A Rudis trocou de lugar com o bloco de marcar. Fecha a página: depois de o
   visitante já ter o caminho para agendar, o último parágrafo é o que a marca
   significa, e não mais uma oferta. */
.lx-rudis { padding-block: var(--sec-base); border-top: 1px solid var(--line); }
.lx-rudis .lx-milestone { margin-top: 0; }


/* ===== ludus-testimonials.css ===== */
/* ==========================================================================
   LUDUS ACTIUS — TESTIMONIALS
   Onda 1, item 5. Template T5 do sitemap.
   Depende de ludus-tokens.css, ludus-base.css e ludus-page.css.

   A SUPERFÍCIE, E POR QUE ELA NÃO É A DO SITEMAP INTEIRA
   -----------------------------------------------------
   O 01-Sitemap.md marca esta página como profunda. Ela abre profunda e
   continua marcada assim, mas o corpo é claro, e a razão é uma regra que o
   próprio sistema já tinha escrito:

     "corpo de texto longo em fundo escuro é a interface menos inclusiva
      do quarteirão"                                    01-Sitemap.md, §1

   Esta é a página com mais texto corrido do site: quatro depoimentos de 60 a
   110 palavras cada, e um deles é de uma mulher de 66 anos em reabilitação de
   coluna, que é literalmente a leitora que a regra protege. Deixar os quatro
   no escuro seria escolher a estética contra a pessoa que o depoimento cita.

   O corte é um só, e é o mesmo movimento da home: profunda enquanto a coisa
   impressiona, clara quando ela precisa ser lida. Aqui ele ainda ganha um
   sentido que não é decoração:

     a dúvida vive no escuro  ->  a prova acontece na luz

   Nenhuma alternância de duas em duas seções. Um corte, como composição.

   O MOVIMENTO
   -----------
   Nenhum efeito novo. Esta página reusa o MOMENTO 1 do ludus-motion.js, a
   espinha, sem uma linha de JS a mais: mesmo [data-lx-spine], mesmos
   [data-lx-spine-item]. O que muda é a escala, porque aqui cada item é uma
   história inteira e não uma linha. O orçamento de movimento do site continua
   sendo dois momentos.

   PENDÊNCIAS NESTE ARQUIVO
   ------------------------
   P05  os depoimentos em vídeo. O slot existe, tem altura reservada e está
        em .la-hold: invisível em produção, visível no modo revisão.
   P19  as idades são de 2020 e hoje estão seis anos atrasadas.
   ========================================================================== */


/* --------------------------------------------------------------------------
   O INDICE DOS QUATRO NOMES TINHA ~55 LINHAS AQUI, E SAIU EM 28/08
   .lx-roster e os filhos __rule, __name e __meta desenhavam a fileira de quatro
   pessoas que abria a pagina. O bloco saiu do markup porque repetia o que a
   primeira linha de cada depoimento ja diz.

   Se voltar a fazer falta, o que vale recuperar e o gesto do hover: o filete
   vermelho de cada nome esticava com scaleX(2.4), e era o unico lugar do site
   onde o filete reagia ao ponteiro. A regra de movimento reduzido que o
   desligava tambem saiu.
   -------------------------------------------------------------------------- */

/* --------------------------------------------------------------------------
   2. AS QUATRO HISTÓRIAS

   Geometria do trilho em variável local: o recuo aqui é maior que o da home
   porque o marcador é um algarismo romano de até três caracteres, e não um
   ponto de 14px. Declaradas na regra, não nos tokens, porque não existem
   fora deste componente.
   -------------------------------------------------------------------------- */

.lx-stories {
  padding-block: var(--sec-tall);
  --story-rail: 15px;   /* centro do trilho, a partir da borda do item */
  --story-gap:  52px;   /* onde o conteúdo começa */
}

/* O trilho e a lista são irmãos, não pai e filho: <span> solto dentro de um
   <ol> é markup inválido, e um <ol> que também é a moldura do trilho obriga
   o rail a herdar o padding da lista. */
.lx-stories__track { position: relative; }
.lx-stories__list { list-style: none; margin: 0; padding: 0; }

/* Trilho apagado, e por cima dele a linha vermelha que o scroll desenha.
   Mesmo mecanismo do .lx-spine__line da home: o --lx-progress é escrito pelo
   ludus-motion.js na seção, e o CSS só o consome. */
.lx-stories__rail,
.lx-stories__line {
  position: absolute;
  top: 0;
  left: calc(var(--story-rail) - var(--rule) / 2);
  width: var(--rule);
}
.lx-stories__rail { bottom: 0; background: var(--line); }
.lx-stories__line {
  height: 100%;
  background: var(--accent-rule);
  transform: scaleY(var(--lx-progress, 1));
  transform-origin: top center;
}

.lx-story {
  position: relative;
  max-width: none;
  padding-left: var(--story-gap);
  padding-bottom: var(--sec-tall);
  scroll-margin-top: 96px;   /* o cabeçalho é sticky e tem 72px */
}
.lx-story:last-child { padding-bottom: 0; }

/* O algarismo romano. A marca é inscricional e o cabeçalho já assina MMXIV;
   numerar as histórias assim é a mesma língua, não um enfeite. O ponto de
   14px da home vira algarismo aqui porque a página é um registro, e registro
   se numera. Decorativo para leitor de tela: a ordem já vem do <ol>. */
.lx-story__mark {
  position: absolute;
  left: 0;
  top: 0;
  width: calc(var(--story-rail) * 2);
  padding-block: var(--sp-2);
  background: var(--bg);
  font-family: var(--font-display);
  font-size: var(--t-sm);
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.08em;
  text-align: center;
  color: var(--ink-faint);
  transition: color var(--dur-state) var(--ease);
}
.lx-story.is-resolved .lx-story__mark { color: var(--accent); }

/* A objeção. Mesmo componente da home, uma escala acima: aqui ela é a
   manchete da história, lá era um item de lista. */
.lx-story__objection {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(1.45rem, 2.55vw, 2.60rem);
  line-height: 1.22;
  color: var(--ink-faint);
  margin: 0;
  max-width: 20ch;
  transition: color var(--dur-state) var(--ease);
}

/* O risco da objeção é .lx-strike, do ludus-base.css: o mesmo componente
   que a espinha da home usa. Nada dele mora aqui. */

/* O corpo entra depois de a objeção ser riscada. Sem JS ele já nasce aqui. */
.lx-story__body { margin-top: var(--sp-8); display: grid; gap: var(--sp-8); }
.lx-js .lx-story__body {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity var(--dur-enter) var(--ease-out), transform var(--dur-enter) var(--ease-out);
  transition-delay: 180ms;
}
.lx-story.is-resolved .lx-story__body { opacity: 1; transform: none; }

@media (min-width: 900px) {
  .lx-story__body { grid-template-columns: 232px minmax(0, 1fr); gap: var(--sp-16); align-items: start; }
}


/* --------------------------------------------------------------------------
   3. QUEM FALA — a coluna de identidade
   -------------------------------------------------------------------------- */

/* Em coluna estreita a identidade vem antes do depoimento, que é a ordem
   natural de leitura: quem fala, depois o que disse. A partir de 900px o
   grid do .lx-story__body põe as duas colunas lado a lado e a ordem visual
   passa a ser a mesma da do DOM. */
.lx-story__who { max-width: 42ch; }

.lx-story__name {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: 600;
  line-height: 1.2;
  color: var(--ink);
  margin: 0;
}

.lx-story__meta { margin: var(--sp-2) 0 0; font-size: var(--t-sm); color: var(--ink-soft); }

/* A data do depoimento. Existe porque as idades são de 2020 e sem ela a
   página afirmaria, em 2026, que o Gabriel tem 15 anos. Datar é mais honesto
   que atualizar por conta própria, e ainda soma: depoimento com data é
   registro, depoimento sem data é slogan. Ver P19. */
.lx-story__when {
  margin: var(--sp-4) 0 0;
  font-family: var(--font-body);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* O resultado, tratado como credencial e não como frase de efeito. Mesmo
   desenho do .lx-creds da home, de propósito: o que o Diogo prova sobre si
   e o que os alunos provam sobre ele são a mesma classe de evidência. */
.lx-story__proof { margin: var(--sp-6) 0 0; padding-top: var(--sp-4); border-top: 1px solid var(--line); }
.lx-story__proof dt {
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: var(--sp-2);
}
.lx-story__proof dd {
  margin: 0;
  font-size: var(--t-sm);
  line-height: 1.45;
  color: var(--ink);
  max-width: 26ch;
}
.lx-story__proof dd + dd { margin-top: var(--sp-2); }

/* Slot do vídeo. Fica em .la-hold: em produção não existe, no modo revisão
   aparece atenuado para o cliente ver o que está reservado esperando ele.
   Quando P05 e E3 fecharem, o miolo desta figure vira <video> hospedado ou
   embed, e só o miolo muda. */
.lx-story__media {
  margin: 0 0 var(--sp-6);
  aspect-ratio: 4 / 5;
  display: grid;
  place-items: center;
  background: var(--bg-sunken);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  color: var(--ink-faint);
  font-size: var(--t-xs);
  text-align: center;
  padding: var(--sp-4);
}
/* O .la-hold do modo revisão devolve o display para o padrão do elemento, e
   <figure> volta a ser block, o que desmonta a centralização acima. Aqui o
   grid é reposto com especificidade suficiente para ganhar dele. */
body.la-review .lx-story__media.la-hold { display: grid; }


/* --------------------------------------------------------------------------
   4. O DEPOIMENTO

   Texto de leitura, e é o que a página existe para entregar. Nada anima aqui.
   -------------------------------------------------------------------------- */

.lx-story__quote {
  margin: 0;
  padding: 0;
  border-left: 0;                 /* o base.css põe um filete vermelho à
                                     esquerda de todo blockquote; aqui ele
                                     brigaria com o trilho da espinha, que já
                                     ocupa essa margem */
  font-family: var(--font-display);
  font-size: var(--t-lead);
  line-height: 1.62;
  color: var(--ink);
  position: relative;
}
.lx-story__quote p { max-width: 62ch; }

/* Abaixo de 900px as duas colunas empilham, e o depoimento cai logo depois da
   lista de resultados sem nenhum sinal de que a voz mudou: até ali quem fala
   é o site, dali em diante é a pessoa. O filete marca a troca, e é o elemento
   que o site já usa para isso em todo lugar. */
@media (max-width: 899px) {
  .lx-story__quote::before {
    content: "";
    display: block;
    width: 40px;
    height: var(--rule);
    background: var(--accent-rule);
    margin-bottom: var(--sp-6);
  }
}

/* Aspas penduradas na margem, sem empurrar a primeira linha. Só a partir do
   ponto em que existe margem para pendurar: em coluna estreita ela sairia
   para fora do container. */
@media (min-width: 1100px) {
  .lx-story__quote::before {
    content: "\201C";
    position: absolute;
    left: -0.62em;
    top: -0.16em;
    font-size: 2.6em;
    line-height: 1;
    color: var(--accent);
    opacity: .30;
    pointer-events: none;
  }
}


/* --------------------------------------------------------------------------
   5. A AMPLITUDE — a ponte antes do fechamento

   Uma seção curta. Depois de quatro histórias longas o leitor precisa de um
   respiro antes do formulário, e este é o lugar onde o argumento emocional
   vira decisão: quatro pessoas diferentes, uma aula só.
   -------------------------------------------------------------------------- */

.lx-range { padding-block: var(--sec-base); border-top: 1px solid var(--line); }
.lx-range__grid { display: grid; gap: var(--sp-8); }
@media (min-width: 900px) { .lx-range__grid { grid-template-columns: 1fr 1fr; gap: var(--sp-16); align-items: start; } }
.lx-range h2 { max-width: 18ch; }
.lx-range p { color: var(--ink-soft); }


/* --------------------------------------------------------------------------
   6. MOVIMENTO REDUZIDO
   Estado final, não estado inicial congelado.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .lx-js .lx-story__body { opacity: 1; transform: none; }
}

/* ==========================================================================
   OS DEPOIMENTOS EM VÍDEO
   Seis retratos 9:16, filmados no celular, num carrossel que vale em toda
   largura. A justificativa de não virar grade está no markup, em
   block/testimonials.html.

   SUPERFÍCIE PROFUNDA, E NÃO POR CAPRICHO
   A seção nasce colada na abertura, que já é escura, então não há troca de
   superfície nova. E vídeo pede fundo escuro: a moldura clara em volta de seis
   retângulos de vídeo faria a página piscar a cada passada do carrossel.
   ========================================================================== */

/* SEM FILETE NO TOPO, DESDE 28/08
   Ele separava esta seção da abertura. Com o título e a chamada removidos, as
   duas viraram um bloco escuro só: a abertura apresenta, os vídeos são o que
   ela apresenta. Linha no meio partiria uma coisa que agora é única.

   O respiro de cima também encolhe: sem título para ancorar, --sec-base abriria
   um vazio grande entre a chamada da abertura e o primeiro rosto. */
.lx-films { padding-block: var(--sec-tight) var(--sec-base); }

/* .lx-films__head saiu junto com o título e a chamada. Se voltar a existir um
   cabeçalho aqui, ele precisa dizer algo que a abertura não diga. */

.lx-films__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: var(--sp-6);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
  /* A mesma espiada dissolvida dos outros carrosséis. Aqui ela importa mais:
     rosto humano cortado pela borda puxa o olho mais que texto cortado. */
  -webkit-mask-image: var(--mask-peek);
  mask-image: var(--mask-peek);
}
.lx-films__list::-webkit-scrollbar { display: none; }

.lx-film {
  margin: 0;
  max-width: none;
  /* 74vw no telefone deixa o próximo espiar; 300px acima disso é o ponto em que
     um retrato 9:16 fica com 533px de altura, que é o teto do que cabe sem a
     seção virar uma parede. */
  flex: 0 0 min(74vw, 300px);
  min-width: 0;
  scroll-snap-align: start;
}

/* O filete vermelho antes do nome. É o mesmo elemento que abre cada cartão de
   plano e cada célula do bento: aqui ele amarra o vídeo ao resto do site. */
.lx-film__rule {
  display: block;
  width: 28px;
  height: var(--rule);
  background: var(--accent-rule);
  margin-bottom: var(--sp-4);
}

.lx-film__name {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: 600;
  line-height: 1.2;
  color: var(--ink);
  margin: 0 0 var(--sp-4);
}

/* A MOLDURA
   Passe-partout: uma faixa de fundo elevado em volta do vídeo, com borda fina.
   Não é sombra e não é canto chanfrado. Sombra aqui seria o efeito genérico que
   o projeto evita, e o chanfro do coach cortaria os controles nativos do
   player, que ficam no canto inferior. */
/* A moldura destes videos e a .lx-frame do ludus-base.css, a mesma que emoldura
   as fotos de programa da /training. */

.lx-film__video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 9 / 16;
  border-radius: var(--radius-sm);
  background: var(--bg-sunken);
  /* object-fit porque o poster e o vídeo têm a mesma proporção, mas o Gloria
     Correa é 360x638 e não 720x1280: sem isso ele ganharia barra preta. */
  object-fit: cover;
}


/* ===== ludus-membership.css ===== */
/* ==========================================================================
   LUDUS ACTIUS — MEMBERSHIP
   Onda 1, item 4. Template T4 do sitemap.
   Depende de ludus-tokens.css, ludus-base.css e ludus-page.css.

   O QUE ESTA PÁGINA É, DEPOIS QUE O E2 FECHOU
   -------------------------------------------
   A venda acontece fora do site, numa plataforma externa. Isso muda o que a
   página tem de fazer: ela não é checkout, é a ponte. O trabalho dela é levar
   a pessoa a um de dois lugares, nesta ordem de preferência:

     1. marcar o tour e a aula grátis   <- converte mais, e o cliente confirma
     2. escolher o plano na plataforma  <- para quem já decidiu

   O tour vem primeiro por decisão do cliente, e a razão é operacional, não
   estética: quem entra no estúdio e faz uma aula fecha muito mais do que quem
   compra de fora. A página inteira está montada para empurrar para lá.

   A ORDEM DAS SEÇÕES, E POR QUE ELA É ESSA
   ----------------------------------------
     1  o que acontece antes de pagar     tour, aula, plano. Nessa ordem
     2  o preço                            publicado, sem pedir e-mail, e com
                                           o destaque do tour colado nele
     3  powerlifting                       o que NÃO é plano, dito na hora
     4  a semana                           a grade, B6
     5  o que vem junto                    cada vantagem explicada
     6  as perguntas                       as objeções, nomeadas
     7  marcar a visita                    o B3, com o tour dentro

   O powerlifting fica em 3, e não depois da grade, onde ficava até 21/08:
   ali ele era invisível. Quem rolava a grade inteira já tinha decidido, e
   quem não rolava nunca descobria que powerlifting existe. Tudo que é oferta
   fica junto da oferta.

   Preço ANTES das objeções, não depois. Esconder preço até o fim é o que os
   concorrentes de Bloomingdale fazem, e é justamente o que a home ataca. Quem
   chega aqui quer saber quanto custa; responder rápido compra o direito de
   falar mais.

   E as objeções vêm DEPOIS do preço porque é ali que elas nascem. Antes do
   número, elas são abstratas.

   PENDÊNCIAS NESTE ARQUIVO
   ------------------------
   P20  o link da plataforma de venda. Enquanto não vier, os botões de plano
        apontam para o bloco de visita, que é a próxima melhor ação.
   P21  as perguntas operacionais do FAQ que dependem do Diogo. Estão no
        markup em .la-hold: não existem em produção, aparecem no modo revisão.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. O CAMINHO ATÉ O PRIMEIRO PAGAMENTO

   Três passos, e o terceiro é onde a página admite que a venda é fora daqui.
   Admitir isso em voz alta, no meio do argumento, custa menos que deixar a
   pessoa descobrir sozinha no clique.

   Movimento: reusa o MOMENTO 2 do ludus-motion.js, o mesmo dos seis pontos do
   método na home. Mesmos [data-lx-method] e [data-lx-method-item], nenhuma
   linha de JS nova. Três passos numerados são uma sequência de verdade, então
   a numeração aqui é informação e não enfeite.
   -------------------------------------------------------------------------- */

.lx-path { padding-block: var(--sec-base); }

.lx-path__head { margin-bottom: var(--sec-tight); }
.lx-path__head h2 { max-width: 22ch; margin-bottom: var(--sp-4); }

.lx-path__list {
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
  display: grid;
  gap: var(--sp-12);
}
@media (min-width: 940px) {
  .lx-path__list { grid-template-columns: repeat(3, 1fr); gap: var(--sp-12); }
}

.lx-path__step {
  position: relative;   /* contexto do filete abaixo, declarado e não herdado */
  margin: 0;
  max-width: none;
  padding-top: var(--sp-6);
  border-top: 1px solid var(--line);
}

/* O filete de cada passo cresce quando o passo acende. É o mesmo desenho do
   resto do site, e aqui ele marca progresso por cima do divisor apagado. */
.lx-path__step::before {
  content: "";
  display: block;
  position: absolute;
  width: 0;
  height: var(--rule);
  margin-top: calc(-1 * var(--sp-6) - var(--rule) / 2);
  background: var(--accent-rule);
  transition: width var(--dur-enter) var(--ease-out);
}
.lx-path__step.is-lit::before { width: 56px; }

.lx-path__n {
  display: block;
  font-family: var(--font-body);
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: var(--sp-4);
  transition: color var(--dur-state) var(--ease);
}
.lx-path__step.is-lit .lx-path__n { color: var(--accent); }

.lx-path__t {
  display: block;
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: 600;
  line-height: 1.2;
  color: var(--ink);
  margin-bottom: var(--sp-3);
}

/* DUAS LINHAS RESERVADAS, DESDE 31/08
   O passo tres virou "Now, you are ready to start your journey!" e passou a
   ocupar duas linhas enquanto "Tour" e "Free trial" ocupam uma. Como cada passo
   e uma celula independente da grade, o paragrafo do terceiro descia sozinho e
   os tres deixavam de comecar na mesma altura.

   Piso e nao altura fixa: um titulo de tres linhas continua crescendo, e o que
   se perde e so o alinhamento que ja nao existiria de qualquer jeito. Vale
   apenas onde os tres estao lado a lado; empilhados no telefone nao ha o que
   alinhar, e a reserva viraria buraco embaixo de cada titulo curto. */
@media (min-width: 940px) {
  .lx-path__t { min-height: calc(var(--t-h3) * 1.2 * 2); }
}

.lx-path__d { font-size: var(--t-sm); color: var(--ink-soft); max-width: 42ch; }

/* A linha que fecha o caminho. Fica solta embaixo dos três, e é a frase que
   derruba a objeção mais cara da página: ninguém assina nada no dia. */
.lx-path__seal {
  margin-top: var(--sec-tight);
  padding-top: var(--sp-6);
  border-top: var(--rule) solid var(--accent-rule);
  font-family: var(--font-display);
  font-size: var(--t-lead);
  line-height: 1.45;
  color: var(--ink);
  max-width: 52ch;
}


/* --------------------------------------------------------------------------
   2. O PREÇO
   A grade vem do block-plan-grid.html, que é global. Aqui só a moldura.
   -------------------------------------------------------------------------- */

.lx-price-sec { padding-block: var(--sec-base); border-top: 1px solid var(--line); background: var(--bg-sunken); }
.lx-price-sec__head { margin-bottom: var(--sp-12); }
.lx-price-sec__head h2 { max-width: 24ch; margin-bottom: var(--sp-4); }

.lx-price-sec__note { margin: var(--sp-8) 0 0; font-size: var(--t-sm); color: var(--ink-soft); max-width: 64ch; }


/* --------------------------------------------------------------------------
   4. AS PERGUNTAS

   <details> nativo. Sem JS, sem biblioteca de acordeão, e o Ctrl+F do
   navegador encontra o texto fechado nos navegadores atuais. Cada pergunta é
   uma objeção real de quem está com o cartão na mão.
   -------------------------------------------------------------------------- */

.lx-faq { padding-block: var(--sec-base); border-top: 1px solid var(--line); }
.lx-faq__head { margin-bottom: var(--sp-12); }
.lx-faq__head h2 { max-width: 20ch; }

/* Empilhado, o FAQ ocupa uns 60% da largura e deixa o resto vazio, que é o
   mesmo defeito que a espinha da home tinha. Título de um lado, perguntas do
   outro. A coluna do título é a menor: ela carrega cinco palavras e a das
   perguntas carrega a página. */
/* Empilhado, a medida de leitura é o que segura a largura da pergunta. */
.lx-faq__list { max-width: 74ch; }

@media (min-width: 940px) {
  .lx-faq__grid { display: grid; grid-template-columns: minmax(0, 0.72fr) minmax(0, 1.6fr); gap: var(--sp-16); align-items: start; }
  .lx-faq__head { margin-bottom: 0; }
  /* Em duas colunas quem limita é a coluna, e o teto de 74ch acima passaria a
     deixar sobra dentro dela. */
  .lx-faq__list { max-width: none; }
}

.lx-q { border-top: 1px solid var(--line); }
.lx-q:last-child { border-bottom: 1px solid var(--line); }

.lx-q summary {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-6);
  min-height: var(--tap);
  padding-block: var(--sp-4);
  cursor: pointer;
  font-family: var(--font-display);
  font-size: var(--t-lead);
  font-weight: 600;
  line-height: 1.35;
  color: var(--ink);
  list-style: none;
}
.lx-q summary::-webkit-details-marker { display: none; }
.lx-q summary:hover { color: var(--accent); }
.lx-q summary:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }

/* O sinal é o filete outra vez: uma barra que ganha a cruz quando fechada, e
   perde a vertical quando aberta. Nada de seta girando, que é o gesto que
   todo acordeão do nicho usa. */
.lx-q__sign {
  position: relative;
  flex: none;
  width: 14px;
  height: 14px;
  align-self: center;
}
.lx-q__sign::before,
.lx-q__sign::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: calc(50% - var(--rule) / 2);
  height: var(--rule);
  background: var(--accent-rule);
  transition: transform var(--dur-state) var(--ease);
}
.lx-q__sign::after { transform: rotate(90deg); }
.lx-q[open] .lx-q__sign::after { transform: rotate(0deg); }

.lx-q__a { padding: 0 0 var(--sp-6); }
.lx-q__a p { font-size: var(--t-sm); color: var(--ink-soft); max-width: 66ch; }
.lx-q__a p + p { margin-top: 0; }

/* Pergunta que espera resposta do Diogo. Em produção não existe; no modo
   revisão aparece atenuada, para ele ver exatamente o que falta responder. */
body.la-review .lx-q.la-hold { display: block; }


/* --------------------------------------------------------------------------
   5. MOVIMENTO REDUZIDO
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .lx-path__step::before { width: 56px; }
  .lx-path__n { color: var(--accent); }
}


/* --------------------------------------------------------------------------
   6. A SALA, EM TRÊS FOTOS

   Fica dentro da seção do caminho, logo depois dos três passos e antes da
   frase que fecha. É o pagamento visual do passo um: a página acabou de
   dizer "venha fazer um tour" e mostra o que existe para ver.

   Assimétrica de propósito. Três fotos do mesmo tamanho em fila viram
   catálogo; a primeira é a mais larga porque é a que orienta, mostra a
   entrada e a mesa onde a pessoa vai chegar.

   Sem a graduação pesada da home. Lá as fotos vivem sobre carvão e precisam
   ser puxadas para o escuro; aqui a superfície é clara e a foto real de uma
   sala fluorescente pode ser o que é. Uma dessaturação leve costura com o
   resto do sistema sem mentir sobre o espaço.
   -------------------------------------------------------------------------- */

.lx-shots {
  list-style: none;
  margin: var(--sec-tight) 0 0;
  padding: 0;
  display: grid;
  gap: var(--sp-4);
}
/* Mesma grade dos três passos acima: três colunas iguais e o MESMO gap.
   Antes eram 1.35fr/1fr/1fr com gap de 16px contra 48px do texto, e as
   colunas não batiam com nada: cada foto começava num ponto diferente do
   parágrafo que ela ilustra. Alinhamento de coluna é o que faz a faixa ler
   como parte do bloco e não como uma fileira solta embaixo dele.

   Quadradas pelo mesmo motivo: três recortes de proporções diferentes
   brigam entre si, e o quadrado é a única proporção que não pede hierarquia. */
@media (min-width: 940px) {
  .lx-shots { grid-template-columns: repeat(3, 1fr); gap: var(--sp-12); }
}

/* Abaixo de 940 a faixa deita e passa sozinha. Eram tres fotos quadradas
   empilhadas, 984px de rolagem para ilustrar tres paragrafos que somam 657.
   Deitada, ocupa a altura de uma. */
@media (max-width: 939px) {
  .lx-shots {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
  }
  .lx-shots::-webkit-scrollbar { display: none; }
  .lx-shots > li {
    flex: 0 0 86%;
    min-width: 0;
    scroll-snap-align: start;
  }
}

.lx-shot { margin: 0; max-width: none; }

.lx-shot img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-md);
  background: var(--bg-sunken);
  filter: saturate(0.86) contrast(1.06);
}
.lx-shot--entrance img { object-position: 10% 52%; }   /* recorta na balança */
.lx-shot--racks    img { object-position: 50% 56%; }
.lx-shot--rowers   img { object-position: 54% 46%; }

@media (min-width: 940px) {
  .lx-shot img { aspect-ratio: 1 / 1; height: auto; }
}

.lx-shot figcaption {
  margin-top: var(--sp-3);
  font-size: var(--t-xs);
  color: var(--ink-faint);
  max-width: 34ch;
}


/* --------------------------------------------------------------------------
   8. A SEMANA
   Moldura da grade. A grade em si é o B6, em ludus-page.css seção 7.
   -------------------------------------------------------------------------- */

.lx-week-sec { padding-block: var(--sec-base); border-top: 1px solid var(--line); }
.lx-week-sec__head { margin-bottom: var(--sp-12); }
.lx-week-sec__head h2 { max-width: 20ch; margin-bottom: var(--sp-4); }
.lx-week-sec__note { margin: var(--sp-8) 0 0; font-size: var(--t-sm); color: var(--ink-soft); max-width: 62ch; }


/* --------------------------------------------------------------------------
   O POWERLIFTING TINHA SECAO PROPRIA AQUI, E ELA SAIU EM 28/08
   Eram ~55 linhas: .lx-pl, __panel, __photo, __col, __body e __cta, mais o
   painel de fundo afundado que separava a secao dos cartoes de plano sem
   trocar de superficie.

   O que ela dizia mora agora em dois lugares que ja existiam: a faixa deitada
   do powerlifting na grade de preco, que carrega os dois pacotes e a frase
   "sold in credits, and not included in any plan", e a grade da semana, que
   marca as duas aulas com o selo "Credits" e da os horarios.

   Se voltar a fazer falta, o desenho a recuperar e o painel: fundo --bg-sunken
   com borda, sem trocar de superficie. Era o jeito de separar comercialmente
   sem cortar a pagina em dois mundos.
   -------------------------------------------------------------------------- */

/* O destaque do tour saiu daqui em 21/08. Ele mandava o visitante para o
   bloco de marcar, três seções abaixo; agora o bloco de marcar é que subiu
   para este ponto, e um intermediário a menos é sempre melhor que um
   intermediário bem feito. */


/* O ritmo comprimido saiu daqui em 21/08. Ele valia só para esta página
   enquanto era exceção; quando as três passaram a usar o mesmo valor, deixou
   de ser exceção e desceu para o :root do ludus-tokens.css, que é onde mora
   o sistema. Três de três não é variação, é o padrão. */


/* ===== ludus-training.css ===== */
/* ==========================================================================
   LUDUS ACTIUS — TRAINING
   Onda 2. Uma página, cinco programas, rolando.

   UM COMPONENTE SÓ, REPETIDO CINCO VEZES
   --------------------------------------
   Cada programa é o mesmo bloco: filete, nome, linha curta, texto e foto. Nada
   de um desenho por programa. Cinco desenhos diferentes numa página de lista é
   o que faz parecer que cada seção foi feita num dia diferente, e obriga a
   inventar hierarquia entre coisas que são irmãs.

   O que dá ritmo é a foto trocar de lado, e só isso. Não há troca de superfície
   entre os programas: a página tem um corte só, no fim da abertura, como a
   /membership.
   ========================================================================== */

.lx-program { padding-block: var(--sec-base); border-top: 1px solid var(--line); }

/* TRÊS FILHOS, E NÃO DOIS, POR CAUSA DO CELULAR
   A pedido do cliente em 28/08 a foto passou a entrar entre a linha de resumo
   e a prosa, e não depois de tudo. No telefone a seção é uma coluna, então a
   única forma de intercalar é o texto ser dois elementos com a foto no meio:
   __head leva filete, nome, dias e resumo; __body leva a prosa e o botão.

   No desktop as duas metades voltam a ser uma coluna só. Quem faz isso é a
   grade nomeada abaixo, e não `order`, que só reordena e não junta. */
.lx-program__grid { display: grid; gap: var(--sp-12); }

@media (min-width: 940px) {
  /* AS DUAS LINHAS 1fr SÃO O TRUQUE, E ELAS NÃO SÃO DECORATIVAS
     Com `head` e `body` em linhas auto e a foto esticada sobre elas, a sobra
     de altura quando a foto é mais alta que o texto (o Kettlebell, que está
     sem texto até a P29 chegar) seria distribuída ENTRE as duas linhas de
     texto, e abriria um buraco exatamente onde o parágrafo tem que continuar
     o resumo. As duas linhas vazias comem essa sobra por fora, acima e
     abaixo, e o par de texto fica centrado contra a foto sem se separar. */
  .lx-program__grid {
    grid-template-columns: 6fr 5fr;
    grid-template-areas:
      ".    photo"
      "head photo"
      "body photo"
      ".    photo";
    grid-template-rows: 1fr auto auto 1fr;
    column-gap: var(--sp-16);
    row-gap: var(--sp-8);
  }
  .lx-program__head  { grid-area: head; }
  .lx-program__body  { grid-area: body; }
  .lx-program__photo { grid-area: photo; align-self: center; }

  /* A foto troca de lado nos pares. Só aqui: abaixo de 940 a página é uma
     coluna e a ordem do DOM já é a certa. */
  .lx-program--flip .lx-program__grid {
    grid-template-columns: 5fr 6fr;
    grid-template-areas:
      "photo .   "
      "photo head"
      "photo body"
      "photo .   ";
  }
}

/* --------------------------------------------------------------------------
   O ÍNDICE DOS CINCO
   Esta página engoliu quatro URLs. O que se perdeu junto foi conseguir ver os
   cinco programas de uma vez, que era o serviço que uma página de hub prestava:
   quem chega sem saber o nome do que procura hoje precisa rolar 5600px para
   descobrir que existe Kettlebell.

   Cinco links e nada mais. Sem números, sem ícone, sem cartão: a lista não é
   uma sequência a percorrer, é um cardápio de onde se escolhe um. Numerar de 01
   a 05 diria "siga a ordem", que é mentira.
   -------------------------------------------------------------------------- */

.lx-jump {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-8);
  margin-top: var(--sp-8);
}

.lx-jump a {
  font-family: var(--font-body);
  font-size: var(--t-sm);
  color: var(--ink-soft);
  text-decoration: none;
  padding-bottom: var(--sp-1);
  /* A borda nasce transparente e não some no hover: se ela aparecesse do nada,
     cada link empurraria os vizinhos 2px para baixo ao passar o mouse. */
  border-bottom: var(--rule) solid transparent;
  transition: color .16s ease, border-color .16s ease;
}
.lx-jump a:hover { color: var(--ink); border-bottom-color: var(--accent-rule); }

@media (prefers-reduced-motion: reduce) { .lx-jump a { transition: none; } }

/* --------------------------------------------------------------------------
   QUANDO O PROGRAMA RODA
   O dado que faltava em cada bloco. Os cinco tinham a mesma forma, lead, prosa
   e botão, e nenhum respondia a pergunta que decide se a pessoa entra: cabe na
   minha semana? A resposta já estava na página, presa na grade lá embaixo.

   Aqui em cima ela também quebra a igualdade entre os blocos: Kettlebell diz
   "Tuesday" e o Training Concept diz quatro dias, e essa diferença de tamanho
   é honesta, é o tamanho real de cada programa na semana.
   -------------------------------------------------------------------------- */

.lx-program__when { margin: 0 0 var(--sp-4); }

/* O filete é o .lx-rule--short do ludus-base.css, que já existe e já tem a
   medida. Criar um .lx-program__rule aqui seria um segundo filete com as mesmas
   propriedades e outro nome, e daí em diante mudar a cor do vermelho estrutural
   passaria a exigir lembrar dos dois. Só o respiro embaixo é local, porque
   depende do bloco em que ele está. */
.lx-program__head .lx-rule,
.lx-events__head .lx-rule,
.lx-open .lx-rule { margin-bottom: var(--sp-6); }

.lx-program__head h2 { max-width: 16ch; margin-bottom: var(--sp-4); }
/* Sem margem embaixo: o resumo é o último elemento da cabeça, e quem abre o
   espaço até a foto no celular e até a prosa no desktop é o gap da grade. Com
   os dois, o respiro contava em dobro. */
.lx-program__head .lx-lead { margin-bottom: 0; }
.lx-program__body p + p { margin-top: var(--sp-6); }
.lx-program__body > :first-child { margin-top: 0; }

/* O BOTAO DE CADA PROGRAMA
   Contorno, e nao o vermelho cheio. A acao vermelha desta pagina e uma so, a de
   marcar a aula gratis no bloco do meio, e ela so continua sendo a mais forte
   enquanto for a unica daquele peso. Quatro botoes vermelhos descendo a lista
   roubariam o lugar dela e nao venderiam nenhum plano a mais: quem chega em
   Kids ja sabe que quer Kids, e o que ele precisa e do caminho, nao de grito.

   Cada rotulo nomeia o que ha do outro lado, e nao a acao. "See the credit
   packs" e "See the Kids plan" chegam no mesmo lugar que "See the plans", mas
   dizem qual pedaco da grade responde aquele programa. */
.lx-program__cta { margin-top: var(--sp-8); }

/* Depois da letra miuda o respiro e menor: aquele bloco ja abriu com borda e
   espaco proprios, e repetir a medida cheia abriria um buraco no meio de duas
   coisas que sao a mesma resposta. */
.lx-program__fine + .lx-program__cta { margin-top: var(--sp-6); }

.lx-program__fine {
  margin-top: var(--sp-8);
  padding-top: var(--sp-6);
  border-top: 1px solid var(--line);
  font-size: var(--t-sm);
  color: var(--ink-soft);
}

/* PROPORÇÃO FORÇADA, E NÃO É CAPRICHO
   Quatro fotos são 1600x900 e a do powerlifting é 633x1024, retrato. Sem
   proporção fixa, a linha do powerlifting ficaria com o dobro da altura das
   outras e a página perderia o ritmo que a alternância cria. O cover recorta;
   o object-position sobe um pouco porque em foto de academia o assunto quase
   sempre está acima do centro geométrico. */
/* A moldura é a .lx-frame do ludus-base.css, a mesma dos vídeos da
   /testimonials. Aqui só cai o raio da imagem: quem carrega o raio maior passou
   a ser a moldura, e uma imagem com o mesmo raio da borda que a envolve deixa
   um crescente de fundo visível em cada canto. */
.lx-program__photo { margin: 0; }
.lx-program__photo img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: 50% 42%;
  border-radius: var(--radius-sm);
  background: var(--bg-sunken);
}

/* --------------------------------------------------------------------------
   EVENTOS
   Lista e não parágrafo: são quatro coisas nomeadas, e quem lê está procurando
   qual é qual. Parágrafo corrido obrigaria a ler os quatro para achar um.
   -------------------------------------------------------------------------- */

.lx-events { padding-block: var(--sec-base); border-top: 1px solid var(--line); }
.lx-events__head { margin-bottom: var(--sp-12); }
.lx-events__head h2 { max-width: 16ch; margin-bottom: var(--sp-4); }

.lx-events__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--sp-8);
}
@media (min-width: 760px) {
  .lx-events__list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-12) var(--sp-16); }
}

.lx-event {
  margin: 0;
  max-width: none;
  padding-top: var(--sp-6);
  border-top: 1px solid var(--line);
}

.lx-event__name {
  font-family: var(--font-display);
  font-size: var(--t-h3);
  font-weight: 600;
  line-height: 1.2;
  color: var(--ink);
  margin: 0 0 var(--sp-3);
}

/* --------------------------------------------------------------------------
   A ABERTURA
   Era a faixa da inclusão, que ficava no fim da página. Em 28/08 subiu para
   antes dos programas e ganhou por cima a frase que estava presa dentro do
   Training Concept.

   Alinhada com o resto da página. Quem segura a medida do texto é o max-width
   dos parágrafos, e não um container mais estreito: recuar a caixa faria a
   primeira coisa do lado claro nascer fora da margem do H1 logo acima.

   Sem borda em cima, ao contrário de todas as outras seções daqui: esta é a
   primeira do lado claro, e quem separa ela da abertura escura é a troca de
   superfície. Um filete cinza sobre a emenda preto-e-claro só sujaria a
   emenda.
   -------------------------------------------------------------------------- */

.lx-open { padding-block: var(--sec-base); }
.lx-open__call,
.lx-open p { max-width: 58ch; }
/* Mesmo respiro do botão de programa, para os seis lerem como a mesma
   família de controle apesar de um ser cheio e cinco serem de contorno. */
.lx-open__cta { margin-top: var(--sp-8); }
.lx-open h2 { margin-bottom: var(--sp-4); }

/* Mesmo corpo de uma lead, mas em tinta cheia, e é essa a diferença: a lead
   logo abaixo é cinza porque apoia um título, e esta frase não apoia nada, ela
   é a primeira coisa que a página afirma. O respiro embaixo é largo para ela
   não colar no filete do bloco da inclusão. */
.lx-open__call {
  font-size: var(--t-lead);
  line-height: 1.5;
  color: var(--ink);
  margin: 0 0 var(--sp-12);
}


/* --------------------------------------------------------------------------
   O PERSONAL 1-1, DESDE 31/08

   A secao reusa .lx-program inteiro: mesma grade, mesma moldura de foto, mesmo
   botao de contorno. O que ela tem de proprio sao duas coisas — a lista das
   seis entregas e a pergunta que fecha.
   -------------------------------------------------------------------------- */

/* Seis itens curtos, e por isso duas colunas assim que houver largura: em uma
   coluna eles viram uma torre estreita ao lado de um paragrafo largo, e o olho
   le a torre como menu. O filete de cada linha e o mesmo divisor dos valores da
   /about, para as duas listas do site lerem como a mesma familia. */
.lx-one__list {
  list-style: none;
  margin: 0 0 var(--sp-8);
  padding: 0;
  display: grid;
  gap: 0;
}
@media (min-width: 620px) { .lx-one__list { grid-template-columns: repeat(2, 1fr); column-gap: var(--sp-8); } }

.lx-one__list li {
  margin: 0;
  max-width: none;
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--line);
  font-size: var(--t-sm);
  color: var(--ink-soft);
}

/* A pergunta do cliente fecha a secao e leva ao botao. Ela e afirmacao de voz
   da marca, nao corpo de texto, e por isso tem o peso do lead sem o tamanho
   dele: maior que o paragrafo acima, menor que o H2. */
.lx-one__ask {
  font-family: var(--font-display);
  font-size: var(--t-lead);
  font-weight: 600;
  line-height: 1.3;
  color: var(--ink);
  margin-top: var(--sp-6);
}


/* ===== ludus-about.css ===== */
/* ==========================================================================
   LUDUS ACTIUS — ABOUT E LEGAL
   Duas páginas num arquivo só, e não dois arquivos, porque a /privacy-policy
   tem quatro regras: um carimbo de data, uma coluna de texto e o espaçamento
   entre as seções dela. Um arquivo de CSS para isso seria mais linha de
   cabeçalho do que de regra.

   O QUE ESTA PÁGINA REUSA, E É QUASE TUDO
   ---------------------------------------
   A abertura com imagem é a `.lx-pagehead--media` da /membership. A moldura das
   fotos é a `.lx-frame` do base. Os filetes são `.lx-rule--short`. O bloco de
   marcar é o global. O que sobra de novo aqui são cinco componentes, e os cinco
   existem porque o conteúdo deles não aparece em nenhum outro lugar do site:
   as cinco promessas, a missão, os nove valores, a tira de fotos do estúdio e o
   cartão do treinador.
   ========================================================================== */


/* --------------------------------------------------------------------------
   QUEM SOMOS

   O NOME É lx-why E NÃO lx-story, E A PRIMEIRA VERSÃO ERROU ISSO
   `.lx-story` já existe: é das quatro histórias da /testimonials, e lá ela
   nasce com opacity 0 esperando a entrada que o observador de rolagem dispara.
   Aqui esse observador não olha para esta seção, então o bloco ficou invisível
   e a página abriu com metade do "quem somos" em branco.

   Nenhuma das oito auditorias pega isso: a classe EXISTE e tem regra, ela só
   tem dono em outro lugar. Prefixo por página é o que evita, e este arquivo usa
   lx-why, lx-claims, lx-mission, lx-values, lx-place, lx-whois e lx-legal, que
   não aparecem em nenhum outro CSS do projeto.

   Texto à esquerda, as cinco promessas à direita. Duas colunas e não uma,
   porque as promessas não continuam o texto: elas são a mesma coisa dita em
   outro registro, e empilhadas viravam um sexto parágrafo que ninguém lê.
   -------------------------------------------------------------------------- */

.lx-why { padding-block: var(--sec-base); }

.lx-why__grid { display: grid; gap: var(--sp-12); }
@media (min-width: 940px) {
  .lx-why__grid {
    grid-template-columns: 1.15fr 1fr;
    gap: var(--sp-16);
    align-items: center;
  }
}

.lx-why__body .lx-rule { margin-bottom: var(--sp-6); }
.lx-why__body h2 { max-width: 16ch; margin-bottom: var(--sp-4); }
.lx-why__body .lx-lead { margin-bottom: var(--sp-8); }
.lx-why__body p + p { margin-top: var(--sp-6); }

/* A foto é retrato de nascença, 473x822, então nada de aspect-ratio: forçar 4/3
   aqui recortaria dois terços dela. O teto de altura existe para ela não
   esticar a seção quando a coluna de texto for curta. */
.lx-why__photo { margin: 0; }
.lx-why__photo img {
  width: 100%;
  max-height: 620px;
  object-fit: cover;
  object-position: 50% 30%;
  border-radius: var(--radius-sm);
  background: var(--bg-sunken);
}

/* AS CINCO PROMESSAS, EM FAIXA
   Desceram para a largura inteira em 29/08. Em coluna estreita ao lado do texto
   elas liam como legenda; em faixa, as cinco têm o mesmo peso, que é o que elas
   são: cinco afirmações independentes, nenhuma mais importante.

   O filete vermelho em cima de cada uma, e não entre elas. Entre, ele separava
   itens de uma pilha; em cima, ele abre cada coluna do mesmo jeito e é o que faz
   as cinco lerem como um conjunto e não como uma lista que sobrou. */
.lx-claims {
  list-style: none;
  margin: var(--sp-16) 0 0;
  padding: 0;
  display: grid;
  gap: var(--sp-8);
}
@media (min-width: 640px)  { .lx-claims { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .lx-claims { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--sp-6); } }

/* Os dois botões. Flex com wrap porque abaixo de 380px eles não cabem lado a
   lado, e empilhados eles continuam sendo dois caminhos e não um botão largo
   com um apêndice. */
.lx-why__cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  margin-top: var(--sp-12);
}

.lx-claims li {
  margin: 0;
  max-width: none;
  padding-top: var(--sp-4);
  border-top: var(--rule) solid var(--accent-rule);
  font-family: var(--font-display);
  font-size: var(--t-lead);
  line-height: 1.3;
  color: var(--ink);
}


/* --------------------------------------------------------------------------
   A MISSÃO
   Uma frase na tela inteira. A citação usa a serifada em corpo grande porque é
   a única declaração institucional do site: em corpo de leitura ela passaria
   como mais um parágrafo, e o ponto dela é justamente parar a rolagem.

   Sem aspas desenhadas em CSS. O blockquote já tem as aspas do texto, e uma
   aspa gigante de enfeite atrás é o clichê que faz uma citação parecer slide de
   apresentação.
   -------------------------------------------------------------------------- */

.lx-mission { padding-block: var(--sec-base); }
.lx-mission .lx-label { margin-bottom: var(--sp-6); }

.lx-mission__quote {
  margin: 0;
  padding-left: var(--sp-6);
  border-left: var(--rule) solid var(--accent-rule);
}
.lx-mission__quote p {
  margin: 0;
  max-width: 30ch;
  font-family: var(--font-display);
  font-size: var(--t-h2);
  line-height: var(--lh-title);
  letter-spacing: var(--tr-title);
  color: var(--ink);
}


/* --------------------------------------------------------------------------
   OS VALORES
   Lista numerada de verdade, com <ol>, e o número aparece. Aqui ele é
   informação e não enfeite: são NOVE, o cliente os conta como nove, e sem o
   número a lista vira um monte de frases motivacionais empilhadas. O número diz
   que existe uma lista fechada, e que esta é ela.
   -------------------------------------------------------------------------- */

.lx-values { padding-block: var(--sec-base); border-top: 1px solid var(--line); }
.lx-values__head { margin-bottom: var(--sp-12); }
.lx-values__head .lx-rule { margin-bottom: var(--sp-6); }
.lx-values__head h2 { margin-bottom: var(--sp-4); }

/* A ORDEM DO DOM É A DO CELULAR: foto, depois a lista.
   No desktop as áreas nomeadas devolvem a foto para a direita. `order` não
   serviria: aqui as duas colunas têm alturas muito diferentes, e area deixa a
   foto grudar no topo da própria coluna sem arrastar a lista. */
.lx-values__grid { display: grid; gap: var(--sp-12); }
@media (min-width: 940px) {
  .lx-values__grid {
    grid-template-columns: 1fr 1fr;
    grid-template-areas: "lista foto";
    gap: var(--sp-16);
    align-items: start;
  }
  .lx-values__list  { grid-area: lista; }
  .lx-values__photo { grid-area: foto; }
}

.lx-values__list {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: valor;
}
.lx-values__list li {
  counter-increment: valor;
  margin: 0;
  max-width: none;
  display: grid;
  grid-template-columns: 2.25rem 1fr;
  align-items: baseline;
  padding-block: var(--sp-3);
  border-bottom: 1px solid var(--line);
  font-family: var(--font-display);
  font-size: var(--t-h3);
  line-height: 1.25;
  color: var(--ink);
}
.lx-values__list li:first-child { border-top: 1px solid var(--line); }

/* O número em tabular para as duas colunas de dígito ficarem no mesmo eixo, e
   em corpo pequeno para ele contar sem competir com a frase. */
.lx-values__list li::before {
  content: counter(valor, decimal-leading-zero);
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: var(--tr-label);
  color: var(--accent);
}

.lx-values__photo { margin: 0; }
.lx-values__photo img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  object-position: 50% 42%;
  border-radius: var(--radius-sm);
  background: var(--bg-sunken);
}
/* No desktop a foto acompanha a lista em vez de nascer colada no topo: a lista
   tem nove linhas e a foto tem uma altura só. */
@media (min-width: 940px) { .lx-values__photo { position: sticky; top: var(--sp-16); } }


/* --------------------------------------------------------------------------
   O ESTÚDIO
   Três fotos em fileira, com legenda. A legenda existe porque foto de academia
   sem legenda é decoração: dizer "o telão é onde seu batimento aparece" é o que
   transforma um equipamento numa informação sobre a aula.
   -------------------------------------------------------------------------- */

.lx-place { padding-block: var(--sec-base); border-top: 1px solid var(--line); }
.lx-place__head { margin-bottom: var(--sp-12); }
.lx-place__head .lx-rule { margin-bottom: var(--sp-6); }
.lx-place__head h2 { margin-bottom: var(--sp-4); }

.lx-place__strip { list-style: none; margin: 0; padding: 0; }
.lx-place__strip > li { margin: 0; max-width: none; min-width: 0; }

@media (min-width: 760px) {
  .lx-place__strip {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--sp-8);
  }
}

/* Abaixo de 760 a faixa deita e passa sozinha. O 86% deixa a próxima espiar,
   que é o sinal de que há mais de uma, e a máscara desmancha os últimos 64px
   para a que espia não parecer cortada a régua. É o mesmo desenho das outras
   faixas do site. */
@media (max-width: 759px) {
  .lx-place__strip {
    display: flex;
    gap: var(--sp-4);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    -webkit-mask-image: var(--mask-peek);
    mask-image: var(--mask-peek);
  }
  .lx-place__strip::-webkit-scrollbar { display: none; }
  .lx-place__strip > li {
    flex: 0 0 86%;
    scroll-snap-align: start;
  }
}

.lx-place__shot { margin: 0; }
.lx-place__shot img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--radius-sm);
  background: var(--bg-sunken);
}
.lx-place__shot figcaption {
  margin-top: var(--sp-3);
  font-size: var(--t-sm);
  color: var(--ink-faint);
}


/* --------------------------------------------------------------------------
   O TREINADOR
   Foto em retrato 4/5, que é a proporção do arquivo, então nada é recortado. A
   moldura do plinto da home não vem junto de propósito: lá o Diogo é o
   argumento da seção inteira e aqui ele é um cartão que aponta para lá.
   -------------------------------------------------------------------------- */

.lx-whois { padding-block: var(--sec-base); border-top: 1px solid var(--line); }

.lx-whois__grid { display: grid; gap: var(--sp-12); }
@media (min-width: 760px) {
  .lx-whois__grid {
    grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
    gap: var(--sp-16);
    /* Topo, e não centro. Com a ficha completa aqui desde 29/08, a coluna da
       direita ficou duas vezes mais alta que a foto, e centrada a foto boiava
       no meio de um vão. Alinhada em cima ela começa junto com o nome, que é
       como se lê um perfil. */
    align-items: start;
  }
}

.lx-whois__photo { margin: 0; }
.lx-whois__photo img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  border-radius: var(--radius-sm);
  background: var(--bg-sunken);
}

.lx-whois__body .lx-rule { margin-bottom: var(--sp-6); }
.lx-whois__body h2 { margin-bottom: var(--sp-2); }
.lx-whois__role { margin: 0 0 var(--sp-6); }
.lx-whois__body .lx-lead { margin-bottom: var(--sp-6); }
.lx-whois__body p + p { margin-top: var(--sp-4); }
/* A ficha é a mesma da home, e a regra dela vive no ludus-home.css. Aqui só o
   respiro acima, porque lá ela vem depois de outro elemento. */
.lx-whois__body .lx-creds { margin-top: var(--sp-8); }


/* ==========================================================================
   A PÁGINA LEGAL
   Uma coluna, medida de leitura, e nada mais. É a única página do site sem
   imagem, sem grade e sem carrossel, e isso é deliberado: documento jurídico
   que tenta ser bonito atrapalha quem está procurando uma frase específica.
   ========================================================================== */

.lx-legal { padding-block: var(--sec-base); }

/* ALINHADO À ESQUERDA, E NÃO NUM CONTAINER ESTREITO CENTRADO
   O container--narrow centraliza a coluna, e o H1 da abertura logo acima não é
   centrado: o texto começava 190px à direita da manchete e o olho lia isso como
   erro de alinhamento, não como coluna de leitura. Quem segura a medida é o
   max-width do documento. É o mesmo reparo que a abertura da /training levou. */
.lx-legal__stamp,
.lx-legal__doc { max-width: 68ch; }

.lx-legal__stamp {
  margin: 0 0 var(--sp-12);
  padding-bottom: var(--sp-6);
  border-bottom: 1px solid var(--line);
  font-size: var(--t-sm);
  color: var(--ink-faint);
}

/* O vão entre seções é grande de propósito: quem lê política de privacidade
   quase sempre está caçando um assunto, e o vão é o que deixa o olho pular de
   título em título sem ler o corpo. */
.lx-legal__doc > section + section { margin-top: var(--sp-12); }
.lx-legal__doc h2 { margin-bottom: var(--sp-4); }
.lx-legal__doc p + p { margin-top: var(--sp-4); }


/* ===== ludus-review.css ===== */
/* ==========================================================================
   LUDUS ACTIUS — MODO REVISÃO
   Acende toda informação que ainda depende de resposta do Diogo.

   COMO USAR
   ---------
   No markup, envolver o valor provisório:

     <span class="la-pend" data-pend="P01">$129</span>

   Para ver todas acesas, adicionar a classe no <body>:

     document.body.classList.add('la-review')

   Ou abrir qualquer página com ?review=1 na URL — o ludus-motion.js liga
   sozinho. Abre a página, tira print, manda pro Diogo.

   Em produção, sem a classe, o .la-pend é completamente invisível: não muda
   layout, não muda cor, não deixa rastro.
   ========================================================================== */

/* Fora do modo revisão, o marcador não existe visualmente. */
.la-pend {
  /* deliberadamente vazio: o marcador é semântico, não visual */
}

/* -------------------------------------------------------------------------- */

body.la-review .la-pend {
  position: relative;
  outline: 2px dashed var(--red-500, #d8383c);
  outline-offset: 2px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--red-500, #d8383c) 12%, transparent);
}

body.la-review .la-pend::after {
  content: attr(data-pend);
  position: absolute;
  top: -0.55em;
  right: -0.35em;
  transform: translate(100%, -50%);
  z-index: 9999;
  padding: 1px 5px;
  background: var(--red-700, #c02428);
  color: #ffffff;
  font-family: "IBM Plex Mono", ui-monospace, Consolas, monospace;
  font-size: 10px;
  font-weight: 600;
  line-height: 1.5;
  letter-spacing: .04em;
  border-radius: 2px;
  white-space: nowrap;
  pointer-events: none;
}

/* Bloco inteiro pendente, não só um valor. */
body.la-review .la-pend--block {
  display: block;
  padding: var(--sp-4, 16px);
}

/* Conteúdo que está oculto esperando resposta (selo de prêmio, bloco do app).
   Em produção fica display:none; em revisão aparece atenuado, para lembrar
   que existe e está esperando. */
.la-hold { display: none; }

body.la-review .la-hold {
  display: revert;
  opacity: .45;
  outline: 2px dotted var(--red-500, #d8383c);
  outline-offset: 4px;
}

/* Barra fixa de aviso, para não esquecer que o modo está ligado. */
body.la-review::before {
  content: "MODO REVISÃO — os blocos marcados dependem de resposta do cliente";
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: 99999;
  padding: 8px 16px;
  background: var(--red-700, #c02428);
  color: #ffffff;
  font-family: "Archivo", Arial, sans-serif;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  text-align: center;
  pointer-events: none;
}

@media print {
  body.la-review::before { position: static; }
}
