/* ═══════════════════════════════════════════════════════════════════
   SITE SHELL — boutique de luxo
   Codado à mão. Sem framework, sem tema, sem template de mercado.
   Tudo que muda entre marcas vive nas variáveis de :root, injetadas
   pelo rebrand a partir do config. O resto é estrutura fixa.
   ═══════════════════════════════════════════════════════════════════ */

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

/* ═══════════════════════════════════════════════════════════════════
   SISTEMA — tokens INVARIANTES de marca.
   Colar no topo de system/site-shell/assets/site.css, logo depois do
   reset (linha 8) e ANTES de body{} (linha 13).

   POR QUE AQUI e não no rebrand.mjs: o bloco :root inline do
   rebrand.mjs:407-419 carrega o que MUDA entre clientes (paper, ink,
   accent, fontes, gutter). Nada abaixo muda entre clientes — ou é
   literal invariante, ou é color-mix() derivado de --ink/--accent, e
   nesse caso se recalcula sozinho para cada marca. Manter os dois
   blocos separados é o que impede o sistema de ser duplicado por
   cliente. Cascata: o <style> inline vem depois do <link> do site.css,
   mas são propriedades diferentes — não há conflito.
   ═══════════════════════════════════════════════════════════════════ */

:root {

  /* ─── ESCALA TIPOGRÁFICA ────────────────────────────────────────
     Dez degraus, razão ~1,25, ancorada no corpo de 16px.
     TODO font-size do arquivo tem de sair desta lista.

     Hoje: 35 tamanhos renderizados, 44 declarados em 103 declarações.
     A faixa 17,0–20,8px sozinha guarda 9 tamanhos com saltos de +1,5%
     a +4,3%; 17,0 e 17,3px são o mesmo corpo para o olho.
     Bringhurst §3.1: a escala é um conjunto FECHADO herdado das
     fundições, não um contínuo. Limiar perceptivo entre dois níveis
     de corpo: 15–20%. Aqui o passo mínimo é 23%.                     */

  --t-11:  11px;  /* ÚNICO tamanho de rótulo em CAIXA ALTA.
                     Fica fora da razão 1,25 de propósito: caixa alta
                     com tracking ≥0.14em lê ~15% maior que minúscula
                     no mesmo corpo (Bringhurst §3.2.2), então 11 caps
                     ocupa o mesmo degrau ÓPTICO que 13 minúsculo.
                     Absorve 8,5 · 10 · 10,5 · 11,5 · 12 · 12,5 —
                     293 nós de texto medidos em 8 páginas.           */
  --t-13:  13px;  /* legenda, crédito, nota, meta. Minúscula pequena.
                     Absorve 13,5 (12 nós).                           */
  --t-16:  16px;  /* CORPO. Base da escala. Absorve 14 · 14,5 · 14,8 ·
                     15 — 178 nós que hoje são prosa abaixo do corpo,
                     em quatro tamanhos que ninguém consegue
                     distinguir (14,5→14,8 = +2,1%).                  */
  --t-20:  20px;  /* lede, citação em grade, título de item de lista */
  --t-25:  25px;  /* título de cartão, pergunta de FAQ, h3 de bloco  */
  --t-31:  31px;  /* título de bloco secundário, h2 rebaixado        */
  --t-39:  39px;  /* statement, h2 em mobile                         */
  --t-49:  49px;  /* h1 de ficha, h1 em tablet                       */
  --t-61:  61px;  /* h2 de seção, desktop                            */
  --t-76:  76px;  /* h1 de página, desktop                           */

  /* ─── PARES FLUIDOS ─────────────────────────────────────────────
     Mínimo e máximo são SEMPRE degraus da lista acima, e a inclinação
     vw é dividida na mesma razão — é isso que trava a proporção.

     Hoje a razão H1:H2 desliza com a janela: 1,200 @390 · 1,281 @768 ·
     1,280 @1024 · 1,353 @1440 (medido). Variação de 12,8% na distância
     entre os dois níveis mais altos do site — o leitor recebe uma
     hierarquia diferente em cada dispositivo (Müller-Brockmann: o
     sistema tem de ser invariante sob mudança de formato).
     Com os valores abaixo: 1,258 @390 · 1,280 @768 · 1,280 @1024 ·
     1,246 @1440 — variação de 2,7%.                                  */

  --t-h1:   clamp(39px, 6.4vw, 76px);
  --t-h2:   clamp(31px, 5.0vw, 61px);
  --t-h3:   clamp(25px, 2.6vw, 31px);
  --t-lede: clamp(17px, 1.55vw, 20px);
  /* ATENÇÃO à lede: a 390px ela rende 17px contra corpo de 16px = +6%,
     abaixo do limiar de 15%. Não adianta aumentar — não há largura.
     A distinção no mobile é paga por OUTRO canal, na cor:
     .lede { color: var(--ink) } (16,7:1) contra p { color: var(--ink-soft) }
     (6,8:1). Ver item correspondente na Onda 1.                      */

  /* ─── PESOS ─────────────────────────────────────────────────────
     Três, e cada um aparece mais de uma vez por página — que é a
     condição para o leitor aprender o código (Bringhurst §3.2).
     O peso 600 aparece hoje 9 vezes em 822 nós: exatamente uma por
     página, e sempre no mesmo elemento (o aviso de compliance).      */
  --w-light:  300;  /* .display */
  --w-book:   400;  /* corpo, títulos serifados */
  --w-medium: 500;  /* rótulo em caixa alta, ênfase */

  /* ─── ESCALA DE ESPAÇO ──────────────────────────────────────────
     Vocabulário fechado, base 4. Valor novo sai desta lista ou não
     entra no arquivo.

     Hoje: 39 valores positivos distintos em 318 ocorrências, só 25%
     múltiplos de 4 e 12% de 8. Entre 8px e 111px, os 31 pares
     adjacentes têm razão abaixo de 1,25 — 12 e 13px não comunicam
     hierarquias diferentes, comunicam falta de decisão.
     Deslocamento máximo ao mapear os 39 valores nesta lista: 4px.    */

  --s-4:   4px;   /* ajuste óptico, gap de ícone            */
  --s-8:   8px;   /* interno apertado                       */
  --s-12: 12px;   /* absorve 9 · 10 · 11 · 13 · 14          */
  --s-16: 16px;   /* absorve 15 · 17 · 17,6 · 18            */
  --s-20: 20px;
  --s-24: 24px;   /* absorve 22 · 26                        */
  --s-32: 32px;   /* absorve 30 · 34 · 34,56                */
  --s-40: 40px;   /* absorve 37,44 · 38                     */
  --s-48: 48px;   /* absorve 46                             */
  --s-64: 64px;   /* absorve 57,6 · 60 · 63,36              */
  --wrap-max: 1240px;

  /* NÃO existe token de ritmo de seção aqui, de propósito. Medido em
     8 páginas: só 2 paddings de seção existem no site inteiro —
     100,8px (.pad-sm, 34 usos) e 158,4px (.pad, 13 usos), mais um
     único 111px que é o .hero-inner limpando a nav fixa. O ritmo
     vertical JÁ está disciplinado e é fluido (clamp). Ver "não mudar". */

  /* ─── MEDIDA (comprimento de linha) ─────────────────────────────
     Em `em`, nunca em `ch`. A unidade ch é o avanço do glifo '0', que
     no Inter é 39% mais largo que a média de prosa inglesa real
     (0,6309em contra 0,4528em). Os 20 limites em ch do arquivo estão
     todos inflados: .step p declara 62ch e mede 83 caracteres;
     .credit p declara 78ch e mede 96 (medido por Range.getClientRects).

     Os valores abaixo foram testados por injeção no browser a 1440px:
     30em rende 64–67 caracteres em .intro-grid p e 63–66 em
     .door-body p. Alvo 66 (Bringhurst §2.1.2: 45–75, 66 ideal).      */

  --measure:       30em;  /* prosa corrida — 66 caracteres medidos */
  --measure-wide:  34em;  /* lede de abertura — ~75               */
  --measure-tight: 22em;  /* citação em display, rodapé — ~48     */

  /* ─── NÍVEIS DE TEXTO SOBRE SUPERFÍCIE CHAPADA --ink ────────────
     Três níveis. Hoje são 13 alfas de branco, com 6 dos 12 intervalos
     abaixo de ΔE 3 (limiar de discriminação para texto em tela):
     .72 contra .70 = ΔE 1,69, um uso cada.
     Apple HIG define 4 rótulos, Material 3 define 2, Radix Colors
     define 2. Treze é ruído de autoria.
     Contraste medido nos DOIS clientes (charmi #1C1712 / ami #17120F). */

  --on-ink:   #FFFFFF;                /* 17,79:1 charmi · 18,59:1 ami */
  --on-ink-2: rgba(255,255,255,.82);  /* 12,14:1 · 12,57:1            */
  --on-ink-3: rgba(255,255,255,.62);  /*  7,42:1 ·  7,58:1            */

  /* Superfície FOTOGRÁFICA é outro problema: o fundo varia dentro do
     próprio elemento e o text-shadow já existente faz parte do
     cálculo. Par próprio, não reaproveitar os três acima.            */
  --on-photo:   rgba(255,255,255,.94);
  --on-photo-2: rgba(255,255,255,.82);

  /* ─── RÉGUA vs FRONTEIRA ────────────────────────────────────────
     A distinção que o sistema não faz hoje. WCAG 2.2 SC 1.4.11 isenta
     decoração e exige 3:1 do que identifica um componente ou o seu
     limite.

     --line (.12 = 1,28:1) e --line-strong (.26 = 1,76:1) continuam
     válidos como RÉGUA — separador entre blocos, moldura de cartão
     que já tem hover em três canais. Ficam como estão.

     O que NÃO é régua: o único limite de um campo de formulário
     (.field input não tem caixa, só border-bottom a 1,76:1), a borda
     completa de um botão, e o sublinhado que declara um link clicável
     em rodapé escuro — o próprio comentário do site.css:514 admite
     por escrito que ali "o sublinhado é o que declara clicável", e
     esse sublinhado mede 2,18:1.                                     */

  --line-ui: color-mix(in srgb, var(--ink) 47%, transparent);
             /* 3,06:1 sobre --paper e 3,01:1 sobre --paper-warm na
                charmi; 3,12:1 e 3,07:1 na ami. Derivado de --ink via
                color-mix, então acompanha a marca — NÃO escrever
                rgba(28,23,18,.47), que é a tinta da charmi.          */

  --rule-on-ink: rgba(255,255,255,.34);
             /* 3,12:1 sobre --ink nos dois clientes. Só para os DOIS
                usos funcionais: text-decoration-color de .foot-facts a
                e border-bottom de .credit a.                         */

  /* ─── OURO ──────────────────────────────────────────────────────
     Seis color-mix() anônimos hoje geram cinco ouros sobre fundo
     escuro que chegam ao navegador como color(srgb 0.733882 ...) —
     sem nome, invisíveis em auditoria. ΔE entre vizinhos: 5,31 · 1,31
     · 1,31 · 0,65 · 1,94. Quatro dos cinco intervalos abaixo de ΔE 2:
     é a mesma cor escrita de quatro maneiras. E três deles
     (.proof .kicker, .hero .kicker, .acclaim .kicker) são exatamente
     o mesmo papel.                                                   */

  --accent-on-ink: color-mix(in srgb, var(--accent) 68%, #fff);
             /* 7,45:1 sobre --ink na charmi · 8,05:1 na ami          */

  /* ─── MOVIMENTO ─────────────────────────────────────────────────
     Um gesto, uma magnitude. Hoje o zoom de hover de imagem tem 7
     valores (1.02 ×1, 1.04 ×2, 1.05 ×4, 1.06 ×2, 1.07 ×1, 1.08 ×1,
     1.1 ×1). Num ladrilho de 402px, 1,04 contra 1,06 é crescer 16px
     contra 24px — indistinguível. Mas 1,02 contra 1,1 é 5× no mesmo
     gesto, e essa o leitor lê como descuido.
     Vinte durações declaradas, várias em duas grafias (.4s e 0.4s),
     o que prova que não há fonte única.
     A CURVA, essa, já é única nos 20 usos — e fica.                  */

  --zoom:   1.05;
  --d-fast:  300ms;  /* cor, borda, sublinhado          */
  --d-base:  500ms;  /* transform, opacity              */
  --d-slow: 1200ms;  /* zoom de imagem, reveal ao rolar */
  --ease:   cubic-bezier(.2,.7,.2,1);

  /* ─── ESPACEJAMENTO ─────────────────────────────────────────────
     Quatro níveis. Havia 17 valores em 42 declarações, com trios como
     0,12em / 0,13em / 0,14em — abaixo de 0,04em o olho não separa dois
     rótulos, e o que sobra é ruído de autoria.
     Bringhurst §3.2.2: versalete pede abertura; minúscula em corpo de
     leitura, quase nenhuma; display, negativa — e o -0,015em do
     .display já cobre esse caso e fica onde está.                    */
  /* ─── ENTRELINHA ────────────────────────────────────────────────
     Cinco níveis. Havia 16 declarados, com o trio 1,65 / 1,68 / 1,7 —
     diferenças de 1,2% e 1,8%, que não existem para o olho.
     Bringhurst §2.2.5: a entrelinha acompanha a MEDIDA. Linha longa
     pede mais respiro; título curto em corpo grande pede menos.
     O corpo (1,7) fica no body e é herdado — não se repete aqui.     */
  --lh-1:    1;      /* numeral, display muito grande        */
  --lh-tight:1.15;   /* display                              */
  --lh-head: 1.3;    /* título de bloco                      */
  --lh-snug: 1.5;    /* lista, bloco denso, legenda          */
  --lh-body: 1.7;    /* corpo — igual ao herdado do body     */

  --ls-s: 0.05em;   /* minúscula com leve abertura            */
  --ls-m: 0.14em;   /* rótulo em versalete — o caso comum     */
  --ls-l: 0.20em;   /* rótulo isolado, chamada curta          */
  --ls-x: 0.30em;   /* assinatura, marca, versalete diminuto  */
}

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
html, body { max-width: 100%; overflow-x: clip; }

body {
  font-family: var(--font-body);
  background: var(--paper);
  color: var(--ink);
  line-height: var(--lh-body);
  font-size: var(--t-16);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;

  /* ─── ALGARISMO ALINHADO, GLOBAL ────────────────────────────────
     A Cormorant Garamond entrega algarismo de ESTILO ANTIGO por
     padrão. Medido no próprio subset auto-hospedado (upem 1000):
     0/1/2/4 sobem a ~400, o 6 vai a 661, o 8 a 574, e 3/5/7/9 descem
     a −275 abaixo da linha de base. Num dado numérico — "4.8", "416",
     "50" — isso não lê como estilo, lê como desalinhamento: metade
     dos algarismos afunda e o 6 e o 8 saltam.

     A feature `lnum` EXISTE nos quatro subsets de Cormorant deste
     projeto (verificado no GSUB), e substitui cada algarismo pela
     variante .lf, todas assentes na linha de base e todas com a
     mesma altura (~636). É por isso que a correção funciona sem
     trocar nenhum ficheiro de fonte.

     Por que aqui e não em oito seletores: o `.display` sozinho já
     cobre toda a titulação dos três sites, portanto escopar não
     reduziria o alcance do render — só multiplicaria as declarações
     e deixaria de fora qualquer bloco novo. Herdando do body, um
     número novo nasce certo.

     Alcance real: SÓ a Cormorant muda. A Inter já desenha algarismo
     alinhado por padrão e o seu subset não traz `lnum`, então as
     duas linhas são inertes no corpo de texto.

     Três blocos abaixo (.hero-proof b, .price-row, .src-score b) já
     traziam este par isolado. Ficam onde estão: repetem o valor
     herdado, não o contradizem, e documentam a intenção localmente.

     29 jul: isto entrou GLOBAL e mediu regressão na charmi e na ami (os
     "01/02/03" dos pilares alargaram 1px, e um h1 de ficha passou a
     quebrar noutra linha). Algarismo de estilo antigo em dado numérico é
     erro tipográfico, e a correção vale para os três sites, mas quem já
     está no ar não muda sem decisão do membro. Virou variável: o default
     é o comportamento de sempre, e só quem declarar `type.numerals` no
     config recebe o alinhamento.                                        */
  font-variant-numeric: var(--numerals, normal);
  font-feature-settings: var(--numerals-feat, normal);
}


img { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: none; cursor: pointer; }
/* O atalho `font` dos controlos de formulário arrasta consigo
   font-variant-numeric e font-feature-settings, e o agente do
   utilizador já os põe no valor inicial antes desta folha correr.
   Repor DEPOIS da linha acima, senão um número dentro de botão ou
   campo escapa à herança do body e volta ao estilo antigo. */
button, input, select, textarea {
  font-variant-numeric: var(--numerals, normal);
  font-feature-settings: var(--numerals-feat, normal);
}

/* Seleção: o dourado como fundo entregava 3,71:1 na charmi e 3,41:1 na ami —
   texto selecionado ficava MENOS legível que o não selecionado, que é o oposto
   do que a seleção existe para fazer. A tinta da marca leva a 16,7:1. */
::selection { background: var(--ink); color: var(--paper); }

/* Foco em dois anéis: o dourado sozinho tem 3,71:1 contra o papel e some
   sobre fotografia, que é justo onde o teclado mais precisa dele. O anel
   externo de tinta garante o limite em qualquer fundo. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  box-shadow: 0 0 0 5px var(--paper), 0 0 0 6px var(--ink);
}

/* ─── tipografia ─────────────────────────────────────────────── */

.display {
  font-family: var(--font-display);
  /* impede a palavra órfã na última linha; sem isto os títulos de duas
     linhas quebram 6-1 em algumas larguras. */
  text-wrap: balance;
  font-weight: var(--w-light);
  line-height: var(--lh-tight);
  letter-spacing: -0.015em;
}
/* Os três níveis saem da escala. Antes cada um trazia o seu próprio clamp,
   e a razão entre H1 e H2 deslizava com a janela — 1,200 a 390px contra
   1,353 a 1440px, ou seja, o leitor recebia uma hierarquia diferente em
   cada aparelho. Ancorando mínimo e máximo em degraus e dividindo a
   inclinação na mesma razão, a distância entre os níveis fica estável. */
h1.display { font-size: var(--t-h1); }
h2.display { font-size: var(--t-h2); }
h3.display { font-size: var(--t-h3); }

.kicker {
  font-size: var(--t-11);
  letter-spacing: var(--ls-x);
  text-transform: uppercase;
  color: var(--accent-text, var(--accent));
  font-weight: var(--w-medium);
}

/* A lede se distingue do corpo por DOIS canais, não um. No desktop o corpo
   dela é maior (20px contra 16px); no celular não há largura para isso —
   rende 17px contra 16px, diferença de 6% que ninguém enxerga. Ali a
   distinção é paga na cor: tinta cheia (16,7:1) contra o corpo em ink-soft
   (6,8:1). Hierarquia que depende de um canal só some quando esse canal
   fica sem espaço. A entrelinha de 1,68 sai: fica a 1,7 herdada do body,
   de que estava a 1,2% — diferença que não existe para o olho. */
.lede { font-size: var(--t-lede); color: var(--ink); }

/* Titulo de secao secundaria: h2 semantico com corpo de subsecao. Existe
   para que o nivel do documento e o peso visual nao precisem concordar —
   o leitor de tela recebe a hierarquia certa, o olho recebe a proporcao certa. */
.h-sec { font-size: var(--t-h3); margin-bottom: var(--s-16); }
p { color: var(--ink-soft); }
p + p { margin-top: 1.1em; }
em { font-family: var(--font-display); font-style: italic; color: var(--ink); }

/* ─── grid ───────────────────────────────────────────────────── */

.wrap { width: min(var(--wrap-max), 100% - 2 * var(--gutter)); margin-inline: auto; }
.wrap-narrow { width: min(780px, 100% - 2 * var(--gutter)); margin-inline: auto; }
section { position: relative; }
.pad { padding-block: clamp(80px, 11vw, 168px); }
.pad-sm { padding-block: clamp(56px, 7vw, 104px); }

/* ─── aviso de conceito não solicitado (gate de compliance) ──── */

.concept-bar {
  position: relative; z-index: 200;
  background: var(--ink); color: var(--paper);
  font-size: var(--t-11); letter-spacing: var(--ls-s);
  padding: 9px var(--gutter); text-align: center;
  line-height: var(--lh-snug);
}
.concept-bar strong { font-weight: var(--w-medium); }
.concept-bar span { opacity: 0.62; }

/* ─── navegação ──────────────────────────────────────────────── */

.nav {
  position: sticky; top: 0; z-index: 150;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-24);
  padding-block: var(--s-20);
  /* Alinha a nav ao mesmo eixo do conteúdo. Com padding fixo a logo
     descolava do H1 conforme a tela crescia — 42px a 1440, 276px a 1920.
     max() mantém o gutter nas telas estreitas e trava na grade nas largas. */
  padding-inline: max(var(--gutter), (100% - var(--wrap-max)) / 2);
  /* 82% é o valor de sempre e continua a ser o default. O problema medido:
     sobre as faixas `--ink` que passam por trás da barra, o composto dá
     rgb(210,205,199) e os rótulos de 11px em caixa alta caem para 3,36:1,
     contra os 4,5:1 que esse corpo exige. A 96% o composto é rgb(242,238,231)
     e a mesma tinta mede 4,58:1. Como é variável com fallback, quem não a
     declara recebe exatamente o pixel de antes. */
  background: color-mix(in srgb, var(--paper) var(--nav-veil, 82%), transparent);
  backdrop-filter: saturate(1.4) blur(14px);
  -webkit-backdrop-filter: saturate(1.4) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--d-base), padding var(--d-base), background var(--d-base), backdrop-filter var(--d-base);
}
.nav.is-stuck { border-bottom-color: var(--line); padding-block: var(--s-12); }

/* Sobre o hero a barra some e a navegacao fica deitada na foto. O gradiente
   raso e o unico apoio: sem ele o texto branco morre num hero claro. */
.nav.over-hero {
  background: transparent;
  backdrop-filter: none; -webkit-backdrop-filter: none;
  border-bottom-color: transparent;
}
.nav.over-hero .nav-links a, .nav.over-hero .brandmark { color: #fff; }
.nav.over-hero .brandmark small, .nav.over-hero .nav-links a { text-shadow: 0 1px 8px rgba(0,0,0,.5); }
.nav.over-hero .brandmark small { color: var(--on-photo-2); }
.nav.over-hero .nav-links a::after { background: #fff; }
.nav.over-hero .nav-toggle i { background: #fff; }
/* ─── A LOGO SOBRE FUNDO ESCURO: DUAS SUPERFÍCIES, NÃO UMA ───────
   `brightness(0) invert(1)` achata a imagem inteira em branco puro.
   É exatamente o que uma logo de lettering PRETO precisa (a da
   Charmi), e continua a ser o valor por omissão nas duas.

   Mas achatar é destrutivo: uma logo cujo lettering JÁ É a cor da
   marca — o dourado da Dulhan — deixa de ser a marca dela e passa a
   ser a mesma mancha branca de qualquer outra. Daí as duas variáveis.

   E são DUAS porque os dois fundos são problemas diferentes, o que se
   mede. Medido sobre o hero real da Dulhan, na faixa onde a logo
   assenta, com os véus deste build já compostos por cima:

     rodapé (--ink, fundo CHAPADO e conhecido)
       dourado da logo, sem filtro nenhum ....... 3,97:1 a 6,47:1
     hero em desktop (véu vertical + véu lateral)
       dourado .................................. 3,14:1 a 6,05:1
     hero em telemóvel (só o véu vertical)
       dourado .................................. 1,26:1 a 4,40:1
       branco ................................... 3,20:1 a 11,22:1

   No rodapé o fundo é uma cor que o config escolheu: o dourado é
   seguro e o achatamento só destrói informação. No hero o fundo é
   FOTOGRAFIA, e no telemóvel as frestas de céu entre as árvores
   levam o dourado a 1,26:1 — a marca desaparece. O branco aguenta,
   e o `drop-shadow` que esta regra carrega foi desenhado para ele.

   Por isso `--logo-on-dark` (rodapé) e `--logo-on-photo` (hero) são
   separadas: um config pode soltar a cor no fundo chapado sem a
   soltar por cima de uma foto que não controla.

   O valor de cada uma é o FILTRO INTEIRO, não uma peça dele:
   `filter: none drop-shadow(...)` é sintaxe inválida e o navegador
   deitaria fora a declaração completa. Com o var a cobrir tudo, um
   config escreve `brightness(1.2)` — ou qualquer composição — sem
   nunca produzir valor inválido. */
.nav.over-hero .brand-logo { filter: var(--logo-on-photo, brightness(0) invert(1)) drop-shadow(0 1px 9px rgba(0,0,0,.62)); }

.brandmark {
  font-family: var(--font-display);
  font-size: var(--t-20);
  letter-spacing: var(--ls-m);
  text-transform: uppercase;
  font-weight: var(--w-book);
  white-space: nowrap;
}
/* A logo do cliente entra no lugar do nome. Um ficheiro so, com alfa: a
   versao para fundo escuro sai de um filtro, entao nao ha dois arquivos
   pra dessincronizar. Qual filtro depende da logo, e quem decide e o
   config via `--logo-on-dark` — ver a nota em `.nav.over-hero`. */
.brandmark.has-logo { line-height: 0; }
.brand-logo { display: block; width: auto; height: clamp(30px, 3.4vw, 42px); transition: filter var(--d-base); }
.nav.is-stuck .brand-logo { height: clamp(26px, 2.8vw, 34px); transition: filter var(--d-base), height var(--d-base); }
.foot .brand-logo { height: 46px; filter: var(--logo-on-dark, brightness(0) invert(1)); }
.brandmark.has-logo small { margin-top: var(--s-8); line-height: var(--lh-tight); }

.brandmark small {
  display: block;
  font-family: var(--font-body);
  font-size: var(--t-11); letter-spacing: var(--ls-x);
  color: var(--accent-text, var(--accent)); margin-top: 3px; text-transform: uppercase;
}

.nav-links { display: flex; gap: clamp(18px, 2.4vw, 38px); align-items: center; }
.nav-links a {
  font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase;
  color: var(--ink-soft); position: relative; padding-block: var(--s-4);
  transition: color var(--d-fast);
}
.nav-links a::after {
  content: ""; position: absolute; left: 0; bottom: 0;
  width: 100%; height: 1px; background: var(--accent);
  transform: scaleX(0); transform-origin: right; transition: transform var(--d-base) cubic-bezier(.2,.7,.2,1);
}
.nav-links a:hover { color: var(--ink); }
.nav-links a:hover::after, .nav-links a[aria-current="page"]::after { transform: scaleX(1); transform-origin: left; }
.nav-links a[aria-current="page"] { color: var(--ink); }

.nav-toggle { display: none; width: 26px; height: 16px; position: relative; }
.nav-toggle i { position: absolute; left: 0; width: 100%; height: 1px; background: var(--ink); transition: transform var(--d-base), opacity var(--d-fast); }
.nav-toggle i:nth-child(1) { top: 0; }
.nav-toggle i:nth-child(2) { top: 7.5px; }
.nav-toggle i:nth-child(3) { top: 15px; }
body.nav-open .nav-toggle i:nth-child(1) { transform: translateY(7.5px) rotate(45deg); }
body.nav-open .nav-toggle i:nth-child(2) { opacity: 0; }
body.nav-open .nav-toggle i:nth-child(3) { transform: translateY(-7.5px) rotate(-45deg); }

/* ─── botões ─────────────────────────────────────────────────── */

.btn {
  display: inline-flex; align-items: center; gap: var(--s-12);
  font-size: var(--t-11); letter-spacing: var(--ls-l); text-transform: uppercase;
  padding: var(--s-16) var(--s-32); border: 1px solid var(--ink);
  position: relative; overflow: hidden; isolation: isolate;
  transition: color var(--d-base);
}
.btn::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--ink); transform: translateY(101%);
  transition: transform var(--d-base) cubic-bezier(.2,.7,.2,1);
}
.btn:hover { color: var(--paper); }
.btn:hover::before { transform: translateY(0); }
.btn-solid { background: var(--ink); color: var(--paper); border-color: var(--ink); }
.btn-solid::before { background: var(--accent); }
.btn-solid:hover { color: var(--paper); }
.btn-ghost { border-color: var(--line-ui); }   /* a borda é o próprio botão: fronteira, não régua */
.btn .arw { transition: transform var(--d-base) cubic-bezier(.2,.7,.2,1); }
.btn:hover .arw { transform: translateX(5px); }

/* ─── hero ───────────────────────────────────────────────────── */

.hero { position: relative; min-height: min(calc(100svh - var(--bar-h, 44px)), 960px); display: grid; align-items: end; overflow: hidden; }
/* Com a barra transparente o hero precisa comecar ATRAS dela, senao a nav fica
   deitada num vazio claro em vez da foto. Sobe pela altura da nav e devolve
   o mesmo tanto em respiro interno. --nav-h vem do JS; o fallback cobre o no-JS. */
body.has-hero .hero { margin-top: calc(-1 * var(--nav-h, 84px)); min-height: min(calc(100svh - var(--bar-h, 44px)), 960px); }
body.has-hero .hero-inner { padding-top: calc(var(--nav-h, 84px) + 10px); }
.hero-media { position: absolute; inset: 0; z-index: 0; background: var(--art-fallback); }
/* Apoio da navegacao branca. Vive no hero, nao na nav, pra poder desvanecer
   alem da altura dela sem deixar corte na foto. */
.hero-media::before {
  content: ""; position: absolute; inset: 0 0 auto; z-index: 1;
  height: calc(var(--nav-h, 84px) + 90px);
  background: linear-gradient(to bottom, rgba(0,0,0,.46), rgba(0,0,0,.22) 46%, rgba(0,0,0,0));
  pointer-events: none;
}
.hero-media::after {
  content: ""; position: absolute; inset: 0;
  background: var(--hero-veil, linear-gradient(180deg,
    rgba(28,17,10,.54) 0%, rgba(40,25,14,.18) 22%,
    rgba(20,13,8,.62) 58%, rgba(20,13,8,.90) 100%));
}
/* Em tela larga o texto vive só na coluna esquerda. Um véu lateral segura a
   leitura ali e deixa o véu vertical mais leve, então o bordado do vestido
   volta a aparecer à direita em vez de morrer sob a mesma sombra. */
@media (min-width: 861px) {
  .hero-media::after {
    background:
      linear-gradient(90deg, rgba(18,12,8,.52) 0%, rgba(18,12,8,.22) 34%, rgba(18,12,8,0) 58%),
      var(--hero-veil-wide, linear-gradient(180deg,
        rgba(28,17,10,.50) 0%, rgba(40,25,14,.12) 26%,
        rgba(20,13,8,.44) 66%, rgba(20,13,8,.82) 100%));
  }
}
/* O vídeo do hero. Entra por cima da foto, com uma transição longa para não
   piscar: quem já leu o título não deve ver a imagem trocar debaixo dele.
   O véu e o gradiente da nav vivem em ::before/::after e precisam continuar
   por cima — daí o z-index deles subir. */
.hero-media .hero-vid {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 34%;
  opacity: 0; transition: opacity 1.1s ease; z-index: 0; pointer-events: none;
}
/* O arquivo servido abaixo de 861px já é vertical (540x960), recortado na
   origem em torno do rosto de cada plano. Sem isso o cover cortava as laterais
   de um quadro 16:9 e sobrava o centro geométrico, que quase nunca é a noiva. */
@media (max-width: 860px) { .hero-media .hero-vid { object-position: 50% 50%; } }
.hero-media .hero-vid.pronto { opacity: 1; }
.hero-media::before, .hero-media::after { z-index: 2; }

.hero-media img, .hero-media .fallback {
  width: 100%; height: 100%; object-fit: cover; object-position: var(--hero-focus, 50% 42%);
  transform: scale(var(--zoom)); animation: driftIn 16s ease-out forwards;
}
.hero-media .fallback { background: var(--art-fallback); }
@keyframes driftIn { to { transform: scale(1); } }

.hero-inner { position: relative; z-index: 2; padding-block: clamp(32px, 4.5vw, 60px); color: #fff; }
/* Reforço de leitura só onde a medição mostrou que falta, e só no tamanho em
   que falta. Medindo o fundo real sob cada linha (com o texto oculto, senão o
   branco do próprio glifo entra na conta e falseia tudo), o hero passa em todos
   os itens EXCETO a lede no celular: 4,4:1 contra os 4,5:1 que 16,8px exige.
   Em tela larga o véu lateral do .hero-media já entrega 11:1 e qualquer camada
   extra só apagaria o bordado à toa — por isso isto vive dentro de um
   max-width. A dose é a mínima que resolve, não a que dá folga bonita. */
@media (max-width: 860px) {
  .hero-inner::before {
    content: ""; position: absolute; z-index: -1;
    inset: -6% -12% -10% -12%;
    background: linear-gradient(180deg,
      rgba(14,9,6,0) 0%, rgba(14,9,6,.14) 38%,
      rgba(14,9,6,.30) 68%, rgba(14,9,6,.40) 100%);
    pointer-events: none;
  }
}
/* O kicker do hero herda o accent clareado, que tem teto de 5,16:1 mesmo contra
   preto puro. Num hero de foto CLARA ele não alcança 4,5:1, e subir o véu até
   compensar deixa o quarto superior opaco: paga-se a acessibilidade com a
   fotografia. Duas variáveis resolvem sem esse custo, e sem tocar em quem já
   está no ar: `--hero-kicker` troca o tom, `--hero-kicker-shadow` acrescenta o
   mesmo reforço que a h1 logo abaixo já carrega. Ambas caem no valor de sempre
   quando o config não as declara, então Charmi e Ami saem idênticas.
   A medição que motivou isto seguiu o método descrito acima: fundo real sob a
   linha, com o texto oculto. */
.hero .kicker {
  color: var(--hero-kicker, color-mix(in srgb, var(--accent) 70%, #fff));
  text-shadow: var(--hero-kicker-shadow, none);
}
.hero h1 {
  /* 16ch resolve para 236px dentro de uma coluna de 335px no iPhone SE: 29%
     da largura disponível jogados fora, e o título quebra em 7 linhas que
     empurram os dois botões 37px abaixo da dobra. A variável deixa o config
     abrir a medida onde a manchete é longa; sem ela, os 16ch de sempre. */
  color: #fff; margin: 0 0 var(--s-20); max-width: var(--hero-h1-measure, 16ch);
  text-shadow: 0 1px 2px rgba(10,6,4,.5), 0 2px 28px rgba(10,6,4,.4);
}
.hero .lede { color: var(--on-photo); max-width: var(--measure-tight); text-shadow: 0 1px 2px rgba(10,6,4,.45); }
.hero-cta { display: flex; flex-wrap: wrap; gap: var(--s-16); margin-top: var(--s-24); }
/* A prova mais forte da casa vinha em 12px depois dos botões, lida como nota
   de rodapé. Sobe para antes do pedido e ganha corpo: o número na serifada lê
   como nota, o nome próprio lê como credencial. */
.hero-proof {
  list-style: none; display: flex; flex-wrap: wrap; gap: var(--s-12) var(--s-32);
  margin-top: var(--s-24); padding-top: var(--s-20); max-width: var(--measure-tight);
  border-top: 1px solid rgba(255,255,255,.28);
}
.hero-proof li { display: flex; align-items: baseline; gap: var(--s-8); flex-wrap: wrap; }
.hero-proof b {
  font-family: var(--font-display); font-weight: var(--w-book); font-size: var(--t-25); line-height: var(--lh-1);
  color: #fff; letter-spacing: var(--ls-s);
  /* sem isto a Cormorant entrega algarismo de estilo antigo e o 4.9 desalinha */
  font-variant-numeric: lining-nums; font-feature-settings: "lnum" 1;
  text-shadow: 0 1px 2px rgba(10,6,4,.5);
}
.hero-proof .hp-lead, .hero-proof .hp-after {
  font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase;
  color: var(--on-photo-2); text-shadow: 0 1px 2px rgba(10,6,4,.45);
}
.hero-proof li:nth-child(2) b { font-size: var(--t-16); }
@media (max-width: 860px) { .hero-proof { gap: var(--s-8) var(--s-24); margin-top: var(--s-20); } }
.hero .btn { border-color: rgba(255,255,255,.5); color: #fff; }
.hero .btn::before { background: #fff; }
.hero .btn:hover { color: var(--ink); }
.hero .btn-solid { background: #fff; color: var(--ink); border-color: #fff; }
.hero .btn-solid::before { background: var(--accent); }
.hero .btn-solid:hover { color: #fff; }

.scroll-hint {
  position: absolute; z-index: 2; bottom: 26px; right: var(--gutter);
  writing-mode: vertical-rl; font-size: var(--t-11); letter-spacing: var(--ls-x);
  text-transform: uppercase; color: var(--on-photo-2);
  display: flex; align-items: center; gap: var(--s-12);
}
.scroll-hint::after { content: ""; width: 1px; height: 54px; background: linear-gradient(rgba(255,255,255,.7), transparent); }

/* Hero editorial da Dulhan: marca central, campanha no terço inferior e uma
   régua de descoberta junto à base. O guard no body impede que a composição
   se espalhe para páginas internas ou para os outros conceitos. */
.editorial-hero .hero-media::after {
  background: linear-gradient(180deg, rgba(12,10,8,.42) 0%, rgba(12,10,8,.06) 38%, rgba(12,10,8,.28) 62%, rgba(12,10,8,.72) 100%);
}
.hero--editorial .hero-inner {
  width: 100%; text-align: center;
  padding-bottom: clamp(142px, 17vh, 190px);
}
.hero--editorial h1 { max-width: 18ch; margin-inline: auto; }
.hero--editorial .hero-cta { justify-content: center; }
.hero--editorial .hero-cta .btn-solid {
  min-width: 220px; background: rgba(32,26,21,.30);
  border-color: rgba(255,255,255,.44); color: #fff;
  backdrop-filter: blur(14px) saturate(1.25);
  -webkit-backdrop-filter: blur(14px) saturate(1.25);
  box-shadow: 0 10px 34px rgba(0,0,0,.16);
  transform: translateZ(0);
  will-change: backdrop-filter;
}
.hero--editorial .hero-cta .btn-solid::before { background: rgba(255,255,255,.92); }
.hero--editorial .hero-cta .btn-solid:hover { color: var(--ink); border-color: rgba(255,255,255,.7); }
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hero--editorial .hero-cta .btn-solid { background: rgba(20,16,13,.72); }
}
.hero--editorial .scroll-hint { display: none; }
.hero-editorial-nav {
  position: absolute; z-index: 3; left: max(var(--gutter), (100% - var(--wrap-max)) / 2);
  right: max(var(--gutter), (100% - var(--wrap-max)) / 2); bottom: clamp(26px, 4vh, 48px);
  display: grid; grid-template-columns: repeat(3, 1fr); align-items: end;
}
.hero-editorial-nav a {
  color: rgba(255,255,255,.84); font-size: var(--t-11); letter-spacing: var(--ls-l);
  text-transform: uppercase; text-decoration: none; text-shadow: 0 1px 8px rgba(0,0,0,.5);
}
.hero-editorial-nav a:nth-child(2) { text-align: center; }
.hero-editorial-nav a:nth-child(3) { text-align: right; }
.hero-editorial-nav a span { margin-right: var(--s-8); color: rgba(255,255,255,.55); }
.hero-editorial-nav a:hover { color: #fff; }
@media (min-width: 861px) {
  .editorial-hero .nav .brandmark { position: absolute; left: 50%; transform: translateX(-50%); }
  .editorial-hero .nav .nav-links { width: 100%; }
  .editorial-hero .nav .nav-links a:nth-child(3) { margin-left: auto; }
}
@media (max-width: 700px) {
  .hero--editorial .hero-inner { padding-bottom: clamp(72px, 12vh, 110px); }
  .hero-editorial-nav { display: none; }
  .hero--editorial .hero-cta .btn-solid { min-width: 0; }
}

/* tela baixa: o hero encolhe pra o CTA nunca cair abaixo da dobra */
@media (max-height: 820px) {
  /* Encolher aqui é função, não enfeite: em tela baixa o CTA cairia abaixo
     da dobra. Mas encolher para um valor inventado quebrava a escala em
     todo aparelho de altura curta. Descer um DEGRAU resolve as duas coisas
     — o hero cabe e a razão entre os níveis continua a mesma. */
  h1.display { font-size: var(--t-h2); }
  .hero { min-height: min(72svh, 620px); }
  .hero-inner { padding-block: clamp(24px, 3vw, 40px); }
  .hero .lede { font-size: var(--t-16); }
}

/* ── cabeçalho de página secundária, com foto de fundo ───────────────
   Reusa TODA a mecânica do `.hero` (véu, contraste do kicker, troca de nav
   pra transparente, `has-hero`/margin-top) só trocando a altura: o `.hero`
   principal é o momento de entrada do site (quase a tela inteira), as
   páginas internas (atelier/collection/lookbook/contact) pedem uma faixa
   mais curta, o bastante pra dar clima sem empurrar o corpo da página.
   Sem CTA, sem kicker obrigatório, sem scroll-hint — o `subHeroBlock` do
   rebrand.mjs só emite `.hero-media` + h1/lede dentro de `.hero-inner`.
   `.hero--sub` é classe ADICIONAL a `.hero` (nunca sozinha), então herda
   veio/contraste/nav de graça e só sobrescreve a altura. Configs que não
   declaram `headerImage` na página nunca recebem esta classe — Charmi e
   Ami, que não declaram, saem com o cabeçalho de sempre (texto puro,
   sem foto), byte a byte iguais.

   ESPECIFICIDADE, corrigido na auditoria de 31 jul 2026 (ALTA-03). A regra
   simples `.hero--sub { min-height: ... }` (0,1,0) NUNCA vencia
   `body.has-hero .hero` (l.528, especificidade 0,2,1) — ficava
   silenciosamente inerte, e as 4 páginas internas saíam com a MESMA altura
   do hero da home (até 960px, quando o alvo era ~460px). Isto NÃO é
   duplicação a "limpar": as duas regras abaixo têm que repetir o
   `body.has-hero .hero` do seletor de origem pra ganhar 1 combinador a mais
   (0,3,1) e vencer de verdade. Testado por injeção pós-fix: minHeight cai
   pra 307/388/429px em 375/390/430, e o botão de agendamento da contact.html
   sobe pra dentro da dobra nos 7 viewports testados. */
body.has-hero .hero.hero--sub { min-height: min(58svh, 640px); }

/* O primeiro bloco visual de Collection e About não usa `.pad-sm`: ele tinha
   apenas padding inferior e, por isso, começava no mesmo pixel em que o hero
   terminava. O respiro pertence à transição entre as duas seções, não à foto. */
.hero--sub + main > section:first-child:not(.pad):not(.pad-sm):not(.lookbook-tools) {
  padding-top: clamp(36px, 6vw, 88px);
}
@media (max-width: 860px) {
  body.has-hero .hero.hero--sub { min-height: min(46svh, 460px); }
  /* ALTA-02, mesma auditoria: a pílula flutuante (.cta-float, fixed bottom:18px,
     altura 48px) pousa sobre a última linha da lede em qualquer telefone comum —
     medido em 7 larguras (320 a 430px), cada uma perdendo pelo menos uma palavra
     em alguma das 4 páginas internas (ex.: "before you even set [off]" cortado
     na contact.html). 48px de pílula + 18px de posição + 10px de folga = 76px.
     Escopado em `.hero--sub` só: o hero da home não tem esse problema (kicker +
     h1 + lede + 2 botões já dão altura de sobra) e não deve ganhar respiro extra
     sem necessidade. Testado por injeção: zero sobreposição em 8 viewports x 4
     páginas, folga mínima de 39,5px no pior caso. */
  body.has-hero .hero--sub .hero-inner { padding-bottom: 76px; }
}

/* ─── revelação no scroll ────────────────────────────────────── */

.reveal { opacity: 0; transform: translateY(26px); transition: opacity 0.9s cubic-bezier(.2,.7,.2,1), transform 0.9s cubic-bezier(.2,.7,.2,1); }
.reveal.in { opacity: 1; transform: none; }
.reveal[data-d="1"] { transition-delay: 0.1s; }
.reveal[data-d="2"] { transition-delay: 0.2s; }
.reveal[data-d="3"] { transition-delay: 0.3s; }
.reveal[data-d="4"] { transition-delay: 0.4s; }

.line-mask { display: block; overflow: hidden; }
.line-mask > span { display: block; transform: translateY(105%); transition: transform 1s cubic-bezier(.2,.7,.2,1); }
.in .line-mask > span, .line-mask.in > span { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .reveal, .line-mask > span { opacity: 1 !important; transform: none !important; transition: none !important; }
  .hero-media img, .hero-media .fallback { animation: none; transform: none; }
  html { scroll-behavior: auto; }
  /* O painel de navegação era o único movimento grande que sobrava: 757px em
     0,55s para quem pediu explicitamente menos movimento. */
  .nav-links { transition: none; }
}

/* ─── introdução editorial ───────────────────────────────────── */

.intro-grid { display: grid; grid-template-columns: 1fr 1.25fr; gap: clamp(36px, 6vw, 96px); align-items: start; }
/* O texto acompanha o centro da tela enquanto a fotografia rola.
   Antes quem grudava era a COLUNA DA IMAGEM, e como a imagem é alta ela nunca
   chegava a grudar de fato — o efeito não existia. Invertido: a imagem rola
   livre e o texto, que é curto, fica parado no meio do campo de visão.
   `top: 50%` mais `translate` de metade da própria altura centraliza sem
   depender de saber essa altura. Só a partir de 861px: abaixo disso as colunas
   viram empilhamento e não há o que acompanhar. */
.intro-grid .col-label { position: static; }
@media (min-width: 861px) {
  /* A célula ESTICA e o miolo dela é que gruda. Sem isso a célula do grid tem a
     altura do próprio texto, e um elemento não tem onde deslizar dentro de um
     espaço do tamanho dele — foi por isso que a primeira tentativa não pegou. */
  .intro-say { align-self: stretch; }
  /* top em % num sticky mede o CONTAINER, não a tela — foi por isso que a
     coluna continuava rolando junto. Em vh ele mede a janela, que é o que
     queremos: o texto para no meio do campo de visão. */
  /* Centraliza pelo TOP, não por translate: translate cria contexto de
     posicionamento próprio e desliga o sticky — verificado, com translate
     o bloco rolava junto; sem ele gruda. O desconto de 11em é metade da
     altura típica deste bloco, e como ele acompanha o corpo, acompanha
     também quem aumenta a fonte no navegador. */
  .intro-say-in { position: sticky; top: calc(50vh - 11em); }
}
@media (prefers-reduced-motion: reduce) {
  .intro-say-in { position: static; translate: none; }
}
.intro-media { position: relative; overflow: hidden; aspect-ratio: 4 / 5; background: var(--art-fallback); margin-top: var(--s-24); }
.intro-media img { width: 100%; height: 100%; object-fit: cover; }
.intro-media figcaption {
  position: absolute; left: 0; bottom: 0; background: var(--paper);
  padding: var(--s-12) var(--s-16); font-size: var(--t-11); letter-spacing: var(--ls-l); text-transform: uppercase; color: var(--ink-soft);
}
h2.statement, .statement { font-family: var(--font-display); font-size: var(--t-h3); line-height: var(--lh-head); font-weight: var(--w-light); color: var(--ink); margin: 0; }
.statement + p { margin-top: var(--s-24); }

.rule { height: 1px; background: var(--line); border: 0; margin-block: 0; }

/* ─── pilares ────────────────────────────────────────────────── */

.pillars { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--line); border-block: 1px solid var(--line); }
.pillar { background: var(--paper); padding: clamp(30px, 3.4vw, 46px); transition: background var(--d-base); }
.pillar:hover { background: var(--paper-warm); }
.pillar .n { font-family: var(--font-display); font-size: var(--t-13); color: var(--accent-text, var(--accent)); letter-spacing: var(--ls-l); }
.pillar h3 { font-family: var(--font-display); font-size: var(--t-25); font-weight: var(--w-book); margin: var(--s-16) 0 var(--s-12); line-height: var(--lh-head); }
.pillar p { font-size: var(--t-16); }

/* ─── bloco imagem + texto ───────────────────────────────────── */

.split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(32px, 5vw, 84px); align-items: center; }
.split.rev .split-media { order: 2; }
.split-media { position: relative; overflow: hidden; aspect-ratio: 4 / 5; background: var(--art-fallback); }
html.has-js .split-media img, html.has-js .card img, html.has-js .shot img { opacity: 0; transition: opacity .8s ease, transform var(--d-slow) cubic-bezier(.2,.7,.2,1); }
html.has-js .split-media img[data-loaded], html.has-js .card img[data-loaded], html.has-js .shot img[data-loaded] { opacity: 1; }
.split-media img { width: 100%; height: 100%; object-fit: cover; object-position: var(--media-focus, 50% 50%); transform: scale(var(--zoom)); transition: transform var(--d-slow) cubic-bezier(.2,.7,.2,1); }
.split-media:hover img { transform: scale(var(--zoom)); }
.split-media .tag {
  position: absolute; left: 0; bottom: 0; background: var(--paper);
  padding: var(--s-12) var(--s-20); font-size: var(--t-11); letter-spacing: var(--ls-l); text-transform: uppercase;
}

/* About editorial: a narrativa começa na imagem e no gesto fundador, depois
   respira em três marcos antes de entrar na experiência da visita. */
.about-story { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); gap: clamp(38px, 8vw, 132px); align-items: center; }
.about-story-media .split-media { aspect-ratio: 4 / 5; }
.about-story-copy { max-width: 43rem; }
.about-story-copy .kicker,
.about-story-copy .display,
.about-values-head .kicker,
.about-values-head .display { text-align: center; margin-inline: auto; }
.about-story-copy .display { max-width: 22ch; margin-top: 14px; margin-bottom: 30px; }
.about-story-copy > p:not(.kicker) { max-width: 40ch; color: var(--ink-soft); }
.about-story-copy > p + p { margin-top: 18px; }
.about-proof-band { border-block: 1px solid var(--line); background: var(--paper-warm); }
.about-proof-grid { display: grid; grid-template-columns: repeat(3, 1fr); }
.about-proof-item { display: grid; gap: 8px; padding: clamp(26px, 4vw, 48px) clamp(18px, 3vw, 46px); text-align: center; }
.about-proof-item + .about-proof-item { border-left: 1px solid var(--line); }
.about-proof-number { font-family: var(--font-display); font-size: clamp(40px, 5vw, 66px); line-height: .9; font-weight: var(--w-book); }
.about-proof-label { color: var(--ink-soft); font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase; }
.about-values-head { display: grid; grid-template-columns: .7fr 1.3fr; gap: 32px; align-items: end; margin-bottom: clamp(28px, 5vw, 56px); }
.about-values-head .display { max-width: 24ch; margin: 0; }
.about-values-grid { display: grid; grid-template-columns: repeat(3, 1fr); border-top: 1px solid var(--line); }
.about-value { padding: 22px clamp(16px, 2.5vw, 32px) 0 0; }
.about-value + .about-value { padding-left: clamp(16px, 2.5vw, 32px); border-left: 1px solid var(--line); }
.about-value-no { color: var(--accent-text, var(--accent)); font-size: var(--t-11); letter-spacing: var(--ls-m); }
.about-value h3 { margin-top: 36px; font-family: var(--font-display); font-size: var(--t-25); font-weight: var(--w-book); }
.about-value p { margin-top: 12px; max-width: 30ch; color: var(--ink-soft); }

/* ─── linhagem: duas gerações (bloco opcional) ─────────────── */

.lineage { text-align: center; }
.lineage .kicker { display: block; margin-bottom: var(--s-20); }
.lineage h2 { margin-bottom: var(--s-32); }
.lineage-pair {
  display: flex; align-items: flex-start; justify-content: center;
  gap: clamp(20px, 5vw, 76px); margin: var(--s-40) 0 var(--s-32);
}
.lineage-person { display: grid; justify-items: center; gap: var(--s-12); max-width: 200px; }
.lineage-person img {
  width: clamp(88px, 10vw, 132px); height: clamp(88px, 10vw, 132px);
  border-radius: 50%; object-fit: cover;
  filter: grayscale(0.88) contrast(1.04) sepia(0.12);
  border: 1px solid var(--line-strong);
}
.lineage-person .nm { font-family: var(--font-display); font-size: var(--t-20); line-height: var(--lh-tight); }
.lineage-person .rl { font-size: var(--t-11); letter-spacing: var(--ls-l); text-transform: uppercase; color: var(--accent-text, var(--accent)); }
.lineage-person .pl { font-size: var(--t-11); color: var(--ink-soft); line-height: var(--lh-snug); }
.lineage-rule { align-self: center; width: clamp(28px, 6vw, 90px); height: 1px; background: var(--line-strong); margin-top: var(--s-64); }
.lineage p.lede { margin-inline: auto; max-width: var(--measure); }

@media (max-width: 560px) {
  .lineage-pair { gap: var(--s-20); }
  .lineage-rule { display: none; }
}

/* ─── jornada bespoke ────────────────────────────────────────── */

.journey-title { max-width: none; font-size: clamp(28px, 5vw, 56px); }
.journey-title-line { display: block; white-space: nowrap; }

/* A sequência é a espinha do serviço dela, mas era desenhada com border-top
   por linha, que é vocabulário de tabela: a ordem só se lia pelos numerais, e
   os numerais estavam em --line-strong (1,75:1, quase invisíveis). Agora cada
   etapa desenha o próprio segmento de régua, do seu nó até o nó seguinte, e a
   régua termina na última em vez de sangrar. */
.journey { counter-reset: step; display: grid; gap: 0; }
.step {
  counter-increment: step; position: relative;
  display: grid; grid-template-columns: 62px 1fr; gap: clamp(16px, 2vw, 30px);
  padding-block: clamp(22px, 2.6vw, 34px);
  align-items: start;
}
/* o segmento: desce do nó desta etapa até o nó da próxima */
.step::after {
  content: ""; position: absolute; left: 5px; top: calc(clamp(22px, 2.6vw, 34px) + 12px);
  width: 1px; height: 100%; z-index: 0;
  background: color-mix(in srgb, var(--accent-text, var(--accent)) 34%, transparent);
}
.step:last-child::after { display: none; }
/* o nó */
.step::before {
  content: counter(step, decimal-leading-zero);
  position: relative; z-index: 1;
  padding-left: var(--s-24);
  font-family: var(--font-display); font-size: var(--t-h3);
  color: var(--accent-text, var(--accent)); line-height: var(--lh-1); transition: color 0.6s;
}
.step > div { position: relative; z-index: 1; }
.journey .step .no {
  position: absolute; left: 0; top: calc(clamp(22px, 2.6vw, 34px) + 5px);
  width: 11px; height: 11px; border-radius: 50%; z-index: 2;
  background: var(--paper); border: 1px solid var(--accent-text, var(--accent));
}
.journey .step:hover .no { background: var(--accent-text, var(--accent)); }
.step h3 { font-family: var(--font-display); font-size: var(--t-25); font-weight: var(--w-book); margin-bottom: var(--s-8); }
.step p { font-size: var(--t-16); max-width: var(--measure); }

/* Variante editorial: a ordem continua clara pelos numerais, mas deixa de
   depender de linha, nó ou posicionamento absoluto. O quinto card fecha a
   sequência em largura inteira, como conclusão, sem parecer uma lacuna. */
.journey--cards {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(12px, 1.6vw, 24px);
}
.journey--cards .step {
  display: block; min-height: clamp(230px, 22vw, 300px);
  padding: clamp(26px, 3.4vw, 46px);
  background: var(--paper-warm); border: 1px solid var(--line);
}
.journey--cards .step:nth-child(even) { background: var(--paper); }
.journey--cards .step:last-child:nth-child(odd) { grid-column: 1 / -1; min-height: 0; }
.journey--cards .step::after, .journey--cards .no { display: none; }
.journey--cards .step::before {
  display: block; position: static; padding: 0; margin-bottom: clamp(34px, 5vw, 70px);
  font-size: var(--t-h2); color: var(--accent-text, var(--accent));
}
.journey--cards .step:last-child::before { margin-bottom: var(--s-24); }
.journey--cards .step h3 { max-width: 18ch; font-size: var(--t-h3); }
.journey--cards .step p { margin-top: var(--s-12); color: var(--ink-soft); }
@media (max-width: 700px) {
  .journey--cards { grid-template-columns: 1fr; }
  .journey--cards .step, .journey--cards .step:last-child:nth-child(odd) { grid-column: auto; min-height: 0; }
  .journey--cards .step::before { margin-bottom: var(--s-32); }
}

/* ─── FAQ editorial ─────────────────────────────────────────────
   Perguntas não usam a timeline de processo. A lista compacta devolve ritmo
   à página e permite abrir só a resposta necessária. */
.faq-section > .display { margin: 14px 0 clamp(28px, 4vw, 48px); max-width: 19ch; }
.faq-list { border-top: 1px solid var(--line-strong); }
.faq-item { border-bottom: 1px solid var(--line-strong); }
.faq-item summary {
  min-height: 76px; display: grid; grid-template-columns: 1fr 24px;
  gap: var(--s-24); align-items: center; padding: var(--s-20) 0;
  list-style: none; cursor: pointer; color: var(--ink);
  font-family: var(--font-display); font-size: var(--t-25);
  font-weight: var(--w-book); line-height: var(--lh-head);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary svg {
  width: 22px; height: 22px; fill: none; stroke: var(--accent-text, var(--accent));
  stroke-width: 1.5; stroke-linecap: round;
  transition: transform var(--d-base) var(--ease);
}
.faq-item[open] summary svg { transform: rotate(45deg); }
.faq-item summary:hover { color: var(--accent-text, var(--accent)); }
.faq-item summary:focus-visible { outline: 2px solid var(--ink); outline-offset: 6px; }
.faq-answer { padding: 0 clamp(42px, 6vw, 76px) var(--s-24) 0; }
.faq-answer p { max-width: var(--measure); color: var(--ink-soft); }
@media (max-width: 640px) {
  .faq-section > .display { max-width: 14ch; }
  .faq-item summary { min-height: 68px; gap: var(--s-16); font-size: var(--t-20); }
  .faq-answer { padding-right: var(--s-16); }
}

/* ─── galeria / lookbook ─────────────────────────────────────── */

.celebrations { background: var(--paper-warm); }
.celebrations > .wrap > .kicker { text-align: center; }
.celebrations .display { max-width: 24ch; margin: 14px auto clamp(30px, 5vw, 58px); text-align: center; }
.celebration-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(12px, 1.6vw, 24px); }
.celebration-card { color: inherit; text-decoration: none; }
.celebration-media { aspect-ratio: 4 / 5; overflow: hidden; background: var(--art-fallback); }
.celebration-media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--d-slow) cubic-bezier(.2,.7,.2,1); }
.celebration-card:hover .celebration-media img { transform: scale(var(--zoom)); }
.celebration-card h3 { margin-top: var(--s-16); font-family: var(--font-display); font-size: var(--t-25); font-weight: var(--w-book); }
.celebration-card p { margin-top: var(--s-8); color: var(--ink-soft); font-size: var(--t-13); }
.celebration-link { display: inline-block; margin-top: var(--s-12); font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase; }
.lookbook-tools { padding-top: clamp(30px, 5vw, 64px); padding-bottom: var(--s-24); }
.filter-row { display: flex; flex-wrap: wrap; gap: var(--s-8); margin-top: var(--s-16); }
.filter-btn { border: 1px solid var(--line-strong); border-radius: 999px; background: transparent; color: var(--ink); padding: 10px 16px; font: inherit; font-size: var(--t-13); cursor: pointer; transition: background var(--d-fast), color var(--d-fast), border-color var(--d-fast); }
.filter-btn:hover, .filter-btn.is-active { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.filter-btn:focus-visible { outline: 2px solid var(--accent-text, var(--accent)); outline-offset: 3px; }
.shortlist-status { margin-top: var(--s-16); color: var(--ink-soft); font-size: var(--t-13); }

.gallery { display: grid; grid-template-columns: repeat(12, 1fr); column-gap: clamp(10px, 1.2vw, 20px); row-gap: clamp(22px, 2.8vw, 42px); }
.shot { position: relative; overflow: hidden; background: var(--art-fallback); cursor: zoom-in; transition: opacity var(--d-base), transform var(--d-base); }
.shot.is-filtered { display: none; }
.shot img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--d-slow) cubic-bezier(.2,.7,.2,1), filter 0.7s; }
.shot:hover img { transform: scale(var(--zoom)); }
.shot figcaption {
  position: absolute; inset: auto 0 0 0; padding: var(--s-24) var(--s-20) var(--s-16);
  background: linear-gradient(transparent, rgba(0,0,0,.72));
  color: #fff; font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase;
  opacity: 0; transform: translateY(8px); transition: opacity var(--d-base), transform var(--d-base);
}
.shot:hover figcaption { opacity: 1; transform: none; }
.shot figcaption small { display: block; margin-top: 5px; color: rgba(255,255,255,.78); font-size: 10px; letter-spacing: .05em; text-transform: none; }
.save-look { position: absolute; z-index: 3; top: 14px; right: 14px; width: 42px; height: 42px; display: grid; place-items: center; border: 1px solid rgba(255,255,255,.55); border-radius: 50%; background: rgba(18,16,14,.42); color: #fff; cursor: pointer; backdrop-filter: blur(8px); }
.save-look svg { width: 20px; height: 20px; fill: transparent; stroke: currentColor; stroke-width: 1.7; transition: fill var(--d-fast), color var(--d-fast); }
.save-look:hover, .save-look:focus-visible { background: var(--paper); color: var(--ink); }
.save-look:focus-visible { outline: 2px solid var(--paper); outline-offset: 3px; }
.save-look.is-saved { background: var(--paper); color: var(--accent-text, var(--accent)); }
.save-look.is-saved svg { fill: currentColor; }
.shot.tall  { grid-column: span 5; aspect-ratio: 4 / 5.4; }
.shot.wide  { grid-column: span 7; aspect-ratio: 7 / 5.4; }
.shot.third { grid-column: span 4; aspect-ratio: 4 / 5; }
.shot.half  { grid-column: span 6; aspect-ratio: 6 / 5; }
.shot.full  { grid-column: span 12; aspect-ratio: 16 / 7; }

/* O Lookbook usa uma grade de descoberta uniforme. Cada peça ocupa o mesmo
   cartão vertical para que o recorte não crie saltos de ritmo entre imagens. */
.lookbook-gallery .shot,
.lookbook-gallery .shot.tall,
.lookbook-gallery .shot.wide,
.lookbook-gallery .shot.third,
.lookbook-gallery .shot.half,
.lookbook-gallery .shot.full {
  grid-column: span 4;
  aspect-ratio: 4 / 5;
}

@media (hover: none) {
  .shot figcaption { opacity: 1; transform: none; }
  .pillar:hover { background: var(--paper); }
  /* `.step` é <article>, não é link nem sanfona. Pintar o ponto no hover
     promete um clique que não existe — e em iOS o hover fica colado depois do
     toque, então o ponto acende e não apaga mais. */
  .journey .step:hover .no { background: var(--paper); }
}

@media (max-width: 860px) {
  .celebration-grid { display: flex; overflow-x: auto; gap: var(--s-12); margin-right: calc(var(--gutter) * -1); padding-right: var(--gutter); scroll-snap-type: x mandatory; scrollbar-width: none; }
  .celebration-grid::-webkit-scrollbar { display: none; }
  .celebration-card { flex: 0 0 min(78vw, 310px); scroll-snap-align: start; }
  .filter-row { flex-wrap: nowrap; overflow-x: auto; margin-right: calc(var(--gutter) * -1); padding: 2px var(--gutter) 5px 2px; scrollbar-width: none; }
  .filter-row::-webkit-scrollbar { display: none; }
  .filter-btn { flex: none; }
  .lookbook-gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .lookbook-gallery .shot,
  .lookbook-gallery .shot.tall,
  .lookbook-gallery .shot.wide,
  .lookbook-gallery .shot.third,
  .lookbook-gallery .shot.half,
  .lookbook-gallery .shot.full { grid-column: span 1; }
  .about-story { grid-template-columns: 1fr; gap: 42px; }
  .about-story-copy .display { max-width: 22ch; }
  .about-proof-grid { grid-template-columns: 1fr; }
  .about-proof-item { grid-template-columns: 76px 1fr; align-items: center; text-align: left; gap: 18px; }
  .about-proof-item + .about-proof-item { border-left: 0; border-top: 1px solid var(--line); }
  .about-values-head { grid-template-columns: 1fr; gap: 18px; }
  .about-values-grid { grid-template-columns: 1fr; }
  .about-value, .about-value + .about-value { padding: 22px 0 26px; border-left: 0; }
  .about-value + .about-value { border-top: 1px solid var(--line); }
}

@media (max-width: 520px) {
  .lookbook-gallery { grid-template-columns: 1fr; }
}

/* lightbox */
.lb { position: fixed; inset: 0; z-index: 300; background: rgba(12,10,9,.94); display: grid; place-items: center; padding: 5vmin; opacity: 0; pointer-events: none; transition: opacity var(--d-base); }
.lb.open { opacity: 1; pointer-events: auto; }
.lb img { max-width: 100%; max-height: 90svh; object-fit: contain; }
/* ─── prova / depoimento ─────────────────────────────────────── */

.proof { background: var(--ink); color: var(--paper); }
.proof .kicker { color: var(--accent-on-ink); }
.proof blockquote { font-family: var(--font-display); font-size: var(--t-h2); font-weight: var(--w-light); line-height: var(--lh-head); max-width: 24ch; }
.proof cite { display: block; margin-top: var(--s-24); font-family: var(--font-body); font-style: normal; font-size: var(--t-11); letter-spacing: var(--ls-l); text-transform: uppercase; color: var(--on-ink-3); }
.proof-grid { display: grid; grid-template-columns: 1.3fr 1fr; gap: clamp(32px, 5vw, 80px); align-items: center; }
.stat-row { display: grid; gap: var(--s-24); }
.stat .n { font-family: var(--font-display); font-size: var(--t-h2); line-height: var(--lh-1); color: #fff; }
.stat .l { font-size: var(--t-11); letter-spacing: var(--ls-l); text-transform: uppercase; color: var(--on-ink-3); margin-top: var(--s-8); }
.proof--trust { background: var(--paper); color: var(--ink); padding-block: clamp(58px, 8vw, 108px); }
.proof--trust .proof-grid { grid-template-columns: 1fr; gap: clamp(38px, 5vw, 62px); align-items: center; }
.proof--trust .proof-grid > div:first-child { text-align: center; }
.proof--trust .kicker { color: var(--accent-text, var(--accent)); }
.proof--trust .lede { max-width: 27ch; margin-inline: auto; color: var(--ink) !important; font-family: var(--font-display); font-size: var(--t-h3); font-weight: var(--w-light); line-height: var(--lh-head); }
.proof--trust .stat-row { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0; max-width: 920px; width: 100%; margin-inline: auto; border-block: 1px solid var(--line); }
.proof--trust .stat { min-width: 0; padding: clamp(22px, 2.8vw, 34px) clamp(14px, 3vw, 40px); text-align: center; }
.proof--trust .stat + .stat { border-left: 1px solid var(--line); }
.proof--trust .stat .n { color: var(--ink); }
.proof--trust .stat:first-child .n { display: flex; align-items: center; justify-content: center; gap: clamp(7px, .8vw, 11px); }
.rating-star { width: .72em; height: .72em; flex: none; fill: var(--accent); }
.proof--trust .stat .l { margin-top: var(--s-8); color: var(--ink-soft); }
@media (max-width: 560px) {
  .proof--trust .proof-grid { gap: 34px; }
  .proof--trust .stat-row { grid-template-columns: 1fr; }
  .proof--trust .stat { padding: 20px var(--s-16); }
  .proof--trust .stat + .stat { border-top: 1px solid var(--line); border-left: 0; }
  .proof--trust .stat .n { font-size: clamp(32px, 10vw, 42px); }
  .proof--trust .stat .l { font-size: 10px; letter-spacing: .16em; }
}

/* ─── coleções ───────────────────────────────────────────────── */

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(272px, 1fr)); gap: clamp(16px, 2vw, 30px); }
.card { position: relative; overflow: hidden; background: var(--art-fallback); aspect-ratio: 3 / 4; display: grid; align-items: end; }
.card img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform var(--d-slow) cubic-bezier(.2,.7,.2,1); }
.card:hover img { transform: scale(var(--zoom)); }
.card::after { content: ""; position: absolute; inset: 0;
  background: linear-gradient(transparent 26%, rgba(0,0,0,.30) 47%, rgba(0,0,0,.62) 68%, rgba(0,0,0,.84)); }
.card-body { position: relative; z-index: 2; padding: clamp(20px, 2.4vw, 30px); color: #fff; }
.card-body h3, .card-body .card-h { font-family: var(--font-display); font-size: var(--t-25); font-weight: var(--w-book); }
.card-body p { color: var(--on-ink-2); font-size: var(--t-13); margin-top: var(--s-8); }
.card-body .price { display: inline-block; margin-top: var(--s-12); font-size: var(--t-11); letter-spacing: var(--ls-l); text-transform: uppercase; color: color-mix(in srgb, var(--accent) 65%, #fff); }

/* ─── captura / formulário ───────────────────────────────────── */

.enquiry { background: var(--paper-warm); padding-block: clamp(56px, 8vw, 112px); }
.enquiry-title-line { display: block; }
/* `stretch` é o default de sempre. Onde a coluna de texto é curta (bloco sem
   formulário) ela enche 570 de 792px e deixa 222px de marfim numa ponta só;
   `center` reparte o vazio nas duas. Variável para não mexer em quem está no ar. */
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(28px, 4vw, 72px); align-items: var(--form-grid-align, stretch); }
/* A coluna da imagem, no lugar que o bloco de captação deixou vazio.
   Ela acompanha a altura do formulário e é cortada pelo centro — assim a
   seção fecha nas duas pontas em vez de terminar em meia largura de papel.
   Some abaixo de 861px: no celular a coluna vira empilhamento, e uma foto
   grande antes do formulário só empurra o campo para longe. */
.enquiry-media { display: none; }
/* 30 jul: a regra acima existe porque uma foto grande ANTES de um formulario
   empurra o primeiro campo para fora da tela no celular. Isso continua certo
   para quem tem formulario. Mas um bloco `form:false` nao tem campo nenhum,
   tem dois botoes — e no telemovel ele fecha uma corrida de quatro blocos de
   texto seguidos (garantia, FAQ, captacao, rodape: 3.919px de rolagem sem
   uma unica imagem). Ali a foto e o unico respiro visual do fim da pagina.
   Charmi e Ami tem formulario, nao recebem a classe, e nao mudam.          */
@media (max-width: 860px) {
  .enquiry--cta .enquiry-media { display: block; margin-bottom: var(--s-32); border-radius: var(--r-md); overflow: hidden; }
  .enquiry--cta .enquiry-media img { width: 100%; height: 46vw; max-height: 300px; object-fit: cover; object-position: 50% 30%; }
}
@media (min-width: 861px) {
  .enquiry-media { display: block; align-self: stretch; overflow: hidden; }
  .enquiry-media img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 30%; }
}
.form-grid > div:first-child { align-self: start; }
/* O card e bem mais curto que o formulario: sem sticky ele deixa meia coluna vazia.
   A coluna estica pra linha inteira e o card gruda dentro dela. */
@media (min-width: 861px) { .magnet-col { position: sticky; top: 120px; } }
.field { margin-bottom: var(--s-20); }
.field label { display: block; font-size: var(--t-11); letter-spacing: var(--ls-l); text-transform: uppercase; color: var(--ink-soft); margin-bottom: var(--s-8); }
/* O campo não tem caixa: este traço é o ÚNICO limite dele. Régua entre blocos
   é decoração e a WCAG isenta; a fronteira de um controle, não — SC 1.4.11
   pede 3:1, e --line-strong entrega 1,76:1. --line-ui é derivado de --ink por
   color-mix, então acompanha a marca em vez de congelar a tinta de um cliente. */
.field input, .field select, .field textarea {
  width: 100%; font: inherit; font-size: var(--t-16); color: var(--ink);
  background: transparent; border: 0; border-bottom: 1px solid var(--line-ui);
  padding: var(--s-12) 2px; transition: border-color var(--d-base) var(--ease);
}
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-bottom-color: var(--accent); }
.field textarea { resize: vertical; min-height: 92px; }
.form-note { font-size: var(--t-13); color: var(--ink-soft); margin-top: var(--s-16); }
.form-status { min-height: 1.4em; margin-top: var(--s-16); font-size: var(--t-13); color: var(--ink); }
.consent-field { display: flex; align-items: flex-start; gap: var(--s-12); margin: var(--s-20) 0; font-size: var(--t-13); line-height: var(--lh-body); color: var(--ink-soft); }
.consent-field input { flex: 0 0 auto; width: 18px; height: 18px; margin-top: 2px; accent-color: var(--accent-text, var(--accent)); }
.consent-field a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }

.magnet { border: 1px solid var(--line-strong); padding: clamp(24px, 3vw, 38px); background: var(--paper); }
.magnet h3 { font-family: var(--font-display); font-size: var(--t-25); font-weight: var(--w-book); margin-bottom: var(--s-12); }
.magnet p { font-size: var(--t-16); }
.magnet form { display: flex; gap: var(--s-12); margin-top: var(--s-20); flex-wrap: wrap; }
.magnet input { flex: 1 1 190px; border: 0; border-bottom: 1px solid var(--line-ui); background: transparent; font: inherit; font-size: var(--t-16); color: var(--ink); padding: var(--s-12) 2px; }
.magnet input:focus { outline: none; border-bottom-color: var(--accent); }

/* ─── faixa de visita: onde, quando, como falar ─────────────── */

/* ─── whatsapp flutuante ─────────────────────────────────────── */

.wa-float {
  position: fixed; right: 18px; bottom: 18px; z-index: 180;
  width: 52px; height: 52px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--ink); color: var(--paper);
  border: 1px solid rgba(255,255,255,.22);
  transition: transform var(--d-fast) cubic-bezier(.2,.7,.2,1);
}
.wa-float:hover { transform: translateY(-3px); }
.wa-float svg { width: 24px; height: 24px; }

/* ─── rodapé ─────────────────────────────────────────────────── */

.foot { background: var(--ink); color: var(--on-ink-3); }
.foot p { color: var(--on-ink-3); }
.foot a { color: var(--on-ink-3); transition: color var(--d-fast); }
.foot a:hover { color: #fff; }
.foot-legal { display: inline-flex; flex-wrap: wrap; gap: var(--s-16); }
.foot-legal a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }

/* ─── consentimento e páginas legais ───────────────────────────── */
.consent-banner {
  position: fixed; left: 50%; bottom: 18px; z-index: 260; transform: translateX(-50%);
  width: min(760px, calc(100% - 32px)); display: grid; grid-template-columns: 1fr auto;
  gap: var(--s-24); align-items: end; padding: clamp(20px, 3vw, 30px);
  background: var(--ink); color: var(--paper); border: 1px solid rgba(255,255,255,.22);
  box-shadow: 0 18px 60px rgba(0,0,0,.22);
}
.consent-banner[hidden] { display: none; }
.consent-copy .kicker { color: var(--accent-on-ink, #C9B082); margin-bottom: var(--s-8); }
.consent-copy h2 { font-family: var(--font-display); font-size: var(--t-25); font-weight: var(--w-book); margin-bottom: var(--s-8); }
.consent-copy p { color: var(--on-ink-2); font-size: var(--t-13); max-width: 52ch; }
.consent-links { display: flex; gap: var(--s-16); margin-top: var(--s-12); }
.consent-links a { color: var(--paper); text-decoration: underline; text-underline-offset: 3px; }
.consent-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: var(--s-12); }
.consent-banner .btn { white-space: nowrap; }
.consent-banner .btn:not(.btn-solid) { color: var(--paper); border-color: rgba(255,255,255,.38); }
.legal-page { max-width: 860px; }
.legal-page > .display { max-width: 16ch; margin: var(--s-16) 0 var(--s-20); }
.legal-sections { margin-top: clamp(44px, 7vw, 84px); border-top: 1px solid var(--line-strong); }
.legal-section { padding: clamp(24px, 3vw, 36px) 0; border-bottom: 1px solid var(--line); }
.legal-section h2 { font-family: var(--font-display); font-size: var(--t-25); font-weight: var(--w-book); margin-bottom: var(--s-12); }
.legal-section p { max-width: var(--measure); color: var(--ink-soft); }

/* Link em rodape escuro sem cor propria: o sublinhado e o que o declara clicavel. */

/* ─── responsivo ─────────────────────────────────────────────── */

@media (max-width: 900px) {
  .intro-grid, .split, .proof-grid, .form-grid { grid-template-columns: 1fr; }
  .intro-grid .col-label { position: static; }
  .split.rev .split-media { order: 0; }
  .pillars { grid-template-columns: 1fr; }
  
  .shot.tall, .shot.wide, .shot.third, .shot.half { grid-column: span 6; }
  .shot.full { grid-column: span 12; aspect-ratio: 4 / 3; }
}

@media (max-width: 860px) {
  /* backdrop-filter cria containing block e prende o menu fixed dentro da nav.
     No mobile a nav vira fundo sólido e o filtro sai. */
  .nav { background: var(--paper); backdrop-filter: none; -webkit-backdrop-filter: none; }
  body.nav-open .nav.over-hero { background: var(--paper); }
  body.nav-open .nav.over-hero .brandmark,
  body.nav-open .nav.over-hero .nav-links a { color: var(--ink); }
  /* A sombra existe para texto branco sobre foto. Com o painel aberto o
     fundo é marfim e a letra é tinta: a sombra vira borrão. */
  body.nav-open .nav.over-hero .nav-links a,
  body.nav-open .nav.over-hero .brandmark,
  body.nav-open .nav.over-hero .brandmark small { text-shadow: none; }
  /* O painel cobre a tela: a bolha não pode boiar por cima dele. */
  body.nav-open .wa-float { opacity: 0; pointer-events: none; }
  body.nav-open .nav.over-hero .nav-links a::after { background: var(--ink); }
  body.nav-open .nav.over-hero .brandmark small { color: var(--accent-text, var(--accent)); }
  body.nav-open .nav.over-hero .nav-toggle i { background: var(--ink); }
  body.nav-open .nav.over-hero .brand-logo { filter: none; }
  /* A declaração `margin: -var(--s-16) -var(--s-16)` vivia aqui e era letra
     morta: `-var(` não é CSS válido, o tokenizador descarta a linha inteira e
     o computado sempre foi 0px. Removida em vez de corrigida — corrigir faria
     a margem passar a valer e mudaria a caixa do botão em 160 páginas que já
     foram revistas com ela a zero. */
  .nav-toggle { display: block; padding: var(--s-16) var(--s-16); width: auto; height: auto; box-sizing: content-box; }
  .nav-toggle i { width: 26px; position: static; display: block; }
  /* Valor literal, não token: o espaço entre as barras do menu é desenho do
     ícone, não ritmo de layout. Já esteve corrompido aqui (uma substituição
     automática comeu o decimal e produziu 6.var(--s-4), que o navegador
     descarta — as três barras colavam e viravam uma linha só). */
  .nav-toggle i + i { margin-top: 6px; }
  body.nav-open .nav-toggle i:nth-child(1) { transform: translateY(7.5px) rotate(45deg); }
  body.nav-open .nav-toggle i:nth-child(3) { transform: translateY(-7.5px) rotate(-45deg); }
  /* O painel fixed e irmao do toggle dentro da .nav, entao o z-index dos dois
     e comparado no mesmo contexto: sem elevar o toggle, o painel aberto cobre
     o proprio botao de fechar e a marca. */
  .brandmark, .nav-toggle { position: relative; z-index: 160; }
  .nav-links {
    position: fixed; inset: 0; z-index: 140;
    background: var(--paper); flex-direction: column; justify-content: center;
    gap: var(--s-24); transform: translateY(-100%);
    /* `visibility: hidden` tira os cinco links do tab order enquanto o painel
       está fechado. Sem isto o teclado passeia por "Home, The four days, The
       shops, Lookbook, Book a visit" com o menu fechado e nada na tela — os
       links continuam `visibility: visible` a 757px acima da dobra. O atraso de
       0s na transição de visibilidade só na volta é o que mantém o painel
       visível durante os 0,55s da saída; o pixel não muda em momento nenhum. */
    visibility: hidden;
    transition: transform 0.55s cubic-bezier(.2,.7,.2,1), visibility 0s 0.55s;
    padding-top: var(--s-64);
  }
  body.nav-open .nav-links { transform: none; visibility: visible; transition: transform 0.55s cubic-bezier(.2,.7,.2,1), visibility 0s 0s; }
  .nav-links a { font-size: var(--t-16); letter-spacing: var(--ls-l); padding: var(--s-12) var(--s-20); }
  .concept-bar { font-size: var(--t-11); letter-spacing: var(--ls-s); padding: var(--s-8) var(--s-16); }
  .step { grid-template-columns: 1fr; gap: var(--s-8); }
  .step::before { font-size: 1.6rem; }
  
  .scroll-hint { display: none; }
  .shot.tall, .shot.wide, .shot.third, .shot.half { grid-column: span 12; aspect-ratio: 4 / 5; }
}

/* ═══════════════════════════════════════════════════════════════════
   Blocos novos: prova global, preço, linha de convidada, depoimentos
   ═══════════════════════════════════════════════════════════════════ */

/* ── Madame Tussauds: a credencial de fora da boutique ────────────── */
.acclaim { background: var(--ink); color: var(--on-ink-2); }
.acclaim .kicker { color: var(--accent-on-ink); }
.acclaim .display, .acclaim strong { color: #fff; }
.acclaim .lede { color: var(--on-ink-2); }
/* O cabecalho fica na coluna de texto; as pecas descem para a faixa. A esquerda
   a chamada, a direita a frase e a explicacao: duas colunas alinhadas por baixo. */
.acclaim-note {
  margin: var(--s-24) 0 0; max-width: var(--measure-tight);
  padding-top: var(--s-20); border-top: 1px solid rgba(255,255,255,.2);
  font-family: var(--font-display); font-weight: var(--w-light);
  font-size: var(--t-20); line-height: var(--lh-head);
  color: var(--on-ink); font-style: normal;
}

/* ── a faixa das figuras: uma peca por artista ─────────────────────
   Nao e um carrossel que troca slide sozinho. E uma faixa que rola de
   verdade: dedo no telefone, trackpad no desktop, e dois botoes para quem
   prefere clicar. O corte do ultimo cartao na borda direita e o que conta
   ao visitante que ha mais. Sem JS a faixa continua rolando e a lista
   continua legivel — so os controles somem. */

/* As cinco fotos são de naturezas diferentes: figura pronta, peça em
   construção, o artista com a própria estátua. Sem dizer o que se está
   vendo, a faixa parece um apanhado solto. */

.price-rows { border-top: 1px solid var(--line); }
.price-row {
  display: grid; grid-template-columns: 1.25fr auto 1fr; gap: var(--s-12) var(--s-24);
  padding: var(--s-20) 0; border-bottom: 1px solid var(--line); align-items: baseline;
}
.pr-line { font-family: var(--font-display); font-size: var(--t-16); color: var(--ink); }
.pr-range {
  font-family: var(--font-display); font-weight: var(--w-book);
  font-size: var(--t-h3); line-height: var(--lh-1); color: var(--ink);
  white-space: nowrap; font-variant-numeric: lining-nums; font-feature-settings: "lnum" 1;
}
.pr-body { font-size: var(--t-13); color: var(--ink-soft); }
.price-note { margin-top: var(--s-24); font-size: var(--t-13); color: var(--ink-soft); }
/* A saída para a linha de convidada. Fica DEPOIS da tabela e da nota, com
   régua acima, porque é outra pergunta — quem chega aqui procurando preço de
   noiva não deve tropeçar num número vinte vezes menor antes de ler o dela. */
.price-aside {
  margin-top: var(--s-24); padding-top: var(--s-20);
  border-top: 1px solid var(--line);
  font-size: var(--t-13); color: var(--ink-soft); max-width: var(--measure);
}
.price-aside a { color: var(--accent-text, var(--accent)); white-space: nowrap; }
.price-aside a:hover { color: var(--ink); }

/* ── Simply Charmi ─────────────────────────────────────────────────── */
.guest-lede { max-width: var(--measure); }
.guest-lede p + p { margin-top: var(--s-16); }
.occasions { list-style: none; display: flex; flex-wrap: wrap; gap: var(--s-8); margin-top: var(--s-24); }
.occasions li {
  font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase;
  padding: var(--s-8) var(--s-16); border: 1px solid var(--line); color: var(--ink-soft);
}
.guest-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(330px, 100%), 1fr)); gap: clamp(18px, 2.4vw, 34px); }
.guest-card { display: flex; flex-direction: column; }
/* A proporção do quadro acompanha a da foto (1000x1690). Com 3/4 o cover
   cortava 21% da altura e comia os pés — a peça inteira é justamente o que
   o site dela mostra, e numa peça pronta a barra da saia é argumento. */
.guest-shot { position: relative; overflow: hidden; aspect-ratio: 1000 / 1690; background: var(--art-fallback); }
.guest-shot img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 50%; transition: transform var(--d-slow) cubic-bezier(.2,.7,.2,1); }
.guest-card:hover .guest-shot img { transform: scale(var(--zoom)); }
.guest-body { display: grid; gap: var(--s-4); padding-top: var(--s-16); }
.guest-h { font-family: var(--font-display); font-size: var(--t-20); font-weight: var(--w-book); }
.guest-tag { font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase; color: var(--ink-soft); }
/* Voltou. Foi removida como regra morta porque nenhum build a usava — e não
   usava porque os itens da linha não tinham preço no config, não porque o
   preço não devesse aparecer. Agora as seis peças têm valor e ficha. */
.guest-cost { display: block; margin-top: var(--s-8); font-size: var(--t-13);
  color: var(--accent-text, var(--accent)); font-weight: var(--w-medium); }
/* O cartão virou <a>: precisa se comportar como alvo, não como texto. */
a.guest-card { display: block; color: inherit; }
a.guest-card:hover .guest-h { color: var(--accent-text, var(--accent)); }
.guest-foot { margin-top: var(--s-32); font-size: var(--t-13); color: var(--ink-soft);
  /* sem teto este bloco esticava até 153 caracteres por linha em tela larga:
     o olho perde o retorno e relê a mesma linha. */
  max-width: var(--measure); }

/* ── depoimentos assinados ─────────────────────────────────────────── */
/* Carrossel infinito de avaliações.
   No celular a lista em coluna passava de 1.700px — seis depoimentos empilhados
   que ninguém lê até o fim. Um por vez, avançando sozinho a cada 5s.
   A trilha é scroll-snap nativo: sem JS ela continua rolando por dedo, e o JS
   só acrescenta o avanço automático e os pontos. Quem pede menos movimento no
   sistema não recebe avanço nenhum — a regra está no @media abaixo e no script. */
.voices {
  display: flex; gap: var(--s-24); list-style: none; margin: 0; padding: 0;
  overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.voices::-webkit-scrollbar { display: none; }
/* O retorno ao primeiro cartão em lista longa (>6). O script apaga a trilha,
   salta para o início com ela invisível e reacende. Os 260ms daqui e os do
   setTimeout em site.js são o mesmo número: mexer num pede mexer no outro.
   Em lista curta a classe nunca é aplicada e nada disto acontece. */
.voices { transition: opacity 0.26s var(--ease); }
.voices.rebobinando { opacity: 0; }
.voices .voice {
  flex: 0 0 100%; scroll-snap-align: center; min-width: 0;
  break-inside: auto; margin: 0;
}
@media (min-width: 861px) { .voices .voice { flex-basis: calc((100% - 2 * var(--s-24)) / 3); } }
/* Um ponto por avaliação. Com seis cabem numa linha em qualquer tela; com vinte
   cabem em 292px, mas o wrap está aqui para que a fila nunca force scroll
   horizontal na página numa tela estreita ou com fonte aumentada. */
.voices-dots { display: flex; flex-wrap: wrap; gap: var(--s-8); justify-content: center; margin-top: var(--s-24); }
.voices-dots button {
  width: 7px; height: 7px; padding: 0; border-radius: 50%;
  border: 1px solid var(--line-strong); background: transparent;
  transition: background var(--d-fast) var(--ease), border-color var(--d-fast) var(--ease);
}
.voices-dots button[aria-current="true"] {
  background: var(--accent-text, var(--accent)); border-color: var(--accent-text, var(--accent));
}
@media (prefers-reduced-motion: reduce) { .voices { scroll-behavior: auto; } }
.voice {
  break-inside: avoid; margin-bottom: clamp(26px, 3vw, 44px);
  padding-top: var(--s-20); border-top: 1px solid var(--line);
}
.voice blockquote { font-family: var(--font-display); font-size: var(--t-20); line-height: var(--lh-snug); color: var(--ink); }
.voice figcaption { margin-top: var(--s-16); font-size: var(--t-11); letter-spacing: var(--ls-l); text-transform: uppercase; color: var(--accent-text, var(--accent)); }
/* ── redes no rodapé ───────────────────────────────────────────────── */
/* Só os ícones. O nome da rede é legível na forma, e a contagem de
   seguidores num rodapé de ateliê é ruído. */

.social-icon {
  width: 20px; height: 20px;
  stroke: currentColor; fill: none; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
  color: var(--on-ink-3); transition: color var(--d-fast);
}
.foot-social a:hover .social-icon { color: #fff; }
.social-word { font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase; color: var(--on-ink-3); }

@media (max-width: 960px) {
  .voices { columns: 2; }
}
@media (max-width: 720px) {
  .voices { columns: 1; }
  .price-row { grid-template-columns: 1fr auto; }
  .pr-body { grid-column: 1 / -1; }
  .guest-strip { grid-template-columns: repeat(3, 1fr); gap: var(--s-8); }
}

/* ═══════════════════════════════════════════════════════════════════
   Estrutura: as duas portas, e a página de respostas
   ═══════════════════════════════════════════════════════════════════ */

/* ── a bifurcação, logo depois do hero ────────────────────────────── */
.fork { border-bottom: 1px solid var(--line); }
.fork-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(18px, 2.6vw, 40px); }
.door {
  display: grid; grid-template-rows: auto 1fr; background: var(--paper-warm);
  border: 1px solid var(--line); transition: border-color var(--d-base), transform var(--d-base) cubic-bezier(.2,.7,.2,1);
}
.door:hover { border-color: var(--accent-text, var(--accent)); transform: translateY(-3px); }
.door-media { position: relative; overflow: hidden; aspect-ratio: 4 / 3; background: var(--art-fallback); }
.door-media img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 16%; transition: transform var(--d-slow) cubic-bezier(.2,.7,.2,1); }
.door:hover .door-media img { transform: scale(var(--zoom)); }
.door-body { display: grid; align-content: start; gap: var(--s-12); padding: clamp(22px, 2.6vw, 34px); }
.door-eyebrow { font-size: var(--t-11); letter-spacing: var(--ls-l); text-transform: uppercase; color: var(--accent-text, var(--accent)); }
.door-h { font-family: var(--font-display); font-size: var(--t-h3); font-weight: var(--w-book); line-height: var(--lh-tight); }
.door-body p { font-size: var(--t-16); line-height: var(--lh-body); color: var(--ink-soft); }
.door-meta { font-size: var(--t-13); letter-spacing: var(--ls-s); color: var(--ink-soft); padding-top: var(--s-12); border-top: 1px solid var(--line); }
/* A única promessa de clique do cartão, e no dedo ela chega em tinta de corpo,
   11px, sem sublinhado: lê como legenda, não como ação. As duas variáveis
   deixam o config dar-lhe a cor e a régua que `.way-link` e `.voices-link` já
   usam; sem elas, o cartão de sempre. */
.door-cta {
  margin-top: var(--s-8); font-size: var(--t-11); letter-spacing: var(--ls-l);
  text-transform: uppercase; color: var(--door-cta-color, var(--ink));
  border-bottom: var(--door-cta-rule, 0) solid currentColor;
  padding-bottom: var(--door-cta-pad, 0); width: var(--door-cta-w, auto);
}
.door:hover .door-cta { color: var(--accent-text, var(--accent)); }
.door:hover .arw { transform: translateX(5px); }
/* cartão do contraste: reusa a grade da bifurcação, mas não é link — anula os
   dois efeitos que o .door:hover aplica (borda de destaque e subida de 3px) */
.door--static { cursor: default; }
.door--static:hover { border-color: var(--line); transform: none; }

/* ── filmes ───────────────────────────────────────────────────────── */
.film { display: grid; gap: var(--s-12); }
.film-shot { position: relative; overflow: hidden; aspect-ratio: 16 / 9; background: var(--ink); }
.film-shot img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.2s cubic-bezier(.2,.7,.2,1), opacity var(--d-base); }
.film:hover .film-shot img { transform: scale(var(--zoom)); opacity: .82; }
.film-blank { position: absolute; inset: 0; background: linear-gradient(140deg, #2a221b, #1c1712); }
.film-play {
  position: absolute; left: 12px; bottom: 11px; width: 38px; height: 38px; border-radius: 50%;
  background: rgba(0,0,0,.62); border: 1px solid rgba(255,255,255,.5);
  display: grid; place-items: center; transition: transform var(--d-fast), background var(--d-fast);
}
.film-play svg { width: 16px; height: 16px; fill: #fff; margin-left: 2px; }
.film:hover .film-play { transform: scale(var(--zoom)); background: rgba(0,0,0,.85); }
.film-dur {
  position: absolute; right: 9px; bottom: 9px; background: rgba(0,0,0,.72); color: #fff;
  padding: 3px var(--s-8); font-size: var(--t-11); letter-spacing: var(--ls-s);
}
.film-title { font-family: var(--font-display); font-size: var(--t-20); line-height: var(--lh-head); }
.film-cta { font-size: var(--t-11); letter-spacing: var(--ls-l); text-transform: uppercase; color: var(--accent-text, var(--accent)); }

.film-feature { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(18px, 2.6vw, 38px); }
.feature-body { margin-top: var(--s-12); font-size: var(--t-16); line-height: var(--lh-body); color: var(--ink-soft); }

/* ── perguntas e respostas ────────────────────────────────────────── */
.answers { background: var(--paper-warm); border-block: 1px solid var(--line); }
.qa-list { display: grid; gap: clamp(28px, 3.4vw, 52px); }
.qa {
  display: grid; grid-template-columns: 1fr 300px; gap: clamp(20px, 3vw, 48px);
  align-items: start; padding-bottom: clamp(28px, 3.4vw, 52px); border-bottom: 1px solid var(--line);
}
.qa:last-child { border-bottom: 0; padding-bottom: 0; }
.qa-q { font-family: var(--font-display); font-size: var(--t-25); font-weight: var(--w-book); margin-bottom: var(--s-12); }
.qa-text p { max-width: var(--measure); color: var(--ink-soft); }
.qa-film {
  display: inline-flex; align-items: center; gap: var(--s-8); margin-top: var(--s-16);
  font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase; color: var(--accent-text, var(--accent));
}
.qa-film svg { width: 15px; height: 15px; fill: currentColor; }
.qa-film:hover { color: var(--ink); }
.qa-shot { position: relative; overflow: hidden; aspect-ratio: 16 / 9; background: var(--ink); }
.qa-shot img { width: 100%; height: 100%; object-fit: cover; }

.interview { display: grid; grid-template-columns: 0.9fr 1.1fr; gap: clamp(24px, 3.4vw, 56px); align-items: center; }

@media (max-width: 900px) {
  .fork-grid { grid-template-columns: 1fr; }
  .film-feature { grid-template-columns: 1fr; gap: var(--s-32); }
  .qa { grid-template-columns: 1fr; }
  .qa-shot { order: -1; }
  .interview { grid-template-columns: 1fr; }
}

/* ═══════════════════════════════════════════════════════════════════
   Catálogo: linhas, grade e ficha de peça
   ═══════════════════════════════════════════════════════════════════ */

/* ── as cinco linhas, na página Bridal ────────────────────────────── */
.range-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: clamp(14px, 1.8vw, 24px); }
.range { display: grid; }
.range-shot { position: relative; overflow: hidden; aspect-ratio: 3 / 4; background: var(--art-fallback); }
.range-shot img { width: 100%; height: 100%; object-fit: cover; object-position: var(--shot-focus, 50% 12%); transition: transform var(--d-slow) cubic-bezier(.2,.7,.2,1); }
.range:hover .range-shot img { transform: scale(var(--zoom)); }
.range-body { padding: var(--s-16) 0 0; display: grid; gap: var(--s-4); }
.range-h { position: relative; padding-bottom: var(--s-8); }
.range-h::after {
  content: ""; position: absolute; left: 0; bottom: 0; width: 28px; height: 1px;
  background: var(--line-strong); transition: width var(--d-base) cubic-bezier(.2,.7,.2,1), background var(--d-base);
}
.range:hover .range-h::after { width: 100%; background: var(--accent-text, var(--accent)); }
.range-h { font-family: var(--font-display); font-size: var(--t-20); font-weight: var(--w-book); }
.range-meta { font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase; color: var(--accent-text, var(--accent)); }

/* ── grade de peças dentro de uma linha ───────────────────────────── */
.cat-count { font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase; color: var(--accent-text, var(--accent)); margin-top: var(--s-24); }
.cat-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--s-12) var(--s-12); }
@media (min-width: 720px)  { .cat-grid { grid-template-columns: repeat(3, 1fr); gap: clamp(14px, 1.8vw, 22px); } }
@media (min-width: 1040px) { .cat-grid { grid-template-columns: repeat(4, 1fr); gap: clamp(16px, 1.8vw, 26px); } }
.cat-item { display: grid; gap: var(--s-8); align-content: start; }
.cat-shot { position: relative; overflow: hidden; aspect-ratio: 3 / 4; background: var(--art-fallback); }
.cat-shot img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 18%; transition: transform var(--d-slow) cubic-bezier(.2,.7,.2,1); }
.cat-item:hover .cat-shot img { transform: scale(var(--zoom)); }
.cat-name { font-family: var(--font-display); font-size: var(--t-16); line-height: var(--lh-head); }
@media (max-width: 719px) { .cat-note { font-size: var(--t-11); letter-spacing: var(--ls-m); } }
.cat-note { font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase; color: var(--ink-soft); }

/* ── ficha da peça ────────────────────────────────────────────────── */
.piece-grid { display: grid; grid-template-columns: 1.25fr 0.75fr; gap: clamp(24px, 3.4vw, 56px); align-items: start; margin-top: var(--s-20); }
.piece-shots { display: grid; gap: var(--s-12); }
.piece-shots figure { position: relative; overflow: hidden; background: var(--art-fallback); }
.piece-shots img { width: 100%; height: auto; display: block; }
.piece-side { position: sticky; top: 120px; }
.piece-desc { color: var(--ink-soft); max-width: var(--measure-tight); }
.piece-facts { margin: var(--s-24) 0 var(--s-24); border-top: 1px solid var(--line); }
.piece-facts > div { display: flex; justify-content: space-between; gap: var(--s-20); padding: var(--s-12) 0; border-bottom: 1px solid var(--line); }
.piece-facts dt { font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase; color: var(--ink-soft); }
.piece-facts dd { font-size: var(--t-13); text-align: right; }
.piece-note { margin-top: var(--s-20); font-size: var(--t-13); line-height: var(--lh-body); color: var(--ink-soft); max-width: var(--measure-tight); }
.piece-nav {
  display: flex; justify-content: space-between; gap: var(--s-20); margin-top: clamp(44px, 5vw, 76px);
  padding-top: var(--s-24); border-top: 1px solid var(--line); font-size: var(--t-13);
}
.piece-nav a { color: var(--ink-soft); }
.piece-nav a:hover { color: var(--ink); }   /* dourado→dourado não muda nada em escala de cinza */

@media (max-width: 860px) {
  /* Ordem de loja: foto, nome, ficha, botão, texto. Quem abre uma peça quer
     ver a peça — o nome não diz nada que a imagem não diga primeiro.
     A galeria mostra a foto de capa e recolhe as demais atrás de um controle,
     para que a ficha e o botão continuem alcançáveis sem rolar quatro fotos. */
  .piece-grid { grid-template-columns: 1fr; }
  .piece-side { position: static; order: 1; }
  .piece-shots { order: -1; }
  .piece-shots figure:nth-child(n+2) { display: none; }
  .piece-shots.aberta figure:nth-child(n+2) { display: block; }
  .shots-mais {
    order: -1; margin-top: var(--s-12); align-self: start;
    min-height: 44px; padding: 0 var(--s-16);
    border: 1px solid var(--line-ui); background: transparent;
    font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase;
    color: var(--ink);
  }
  .piece-nav { font-size: var(--t-13); }
}

/* ── contato direto, ao lado do formulário ─────────────────────────
   A segunda coluna ficava com 538px de marfim vazio em 149 das 150
   páginas: o cartão de captura tem 363px e a coluna estica junto do
   formulário. Quem não quer preencher formulário agora tem para onde ir. */
.direct { margin-top: var(--s-24); padding-top: var(--s-24); border-top: 1px solid var(--line); }
.direct-h {
  font-family: var(--font-display); font-size: var(--t-20); font-weight: var(--w-book);
  margin-bottom: var(--s-16);
}
.direct ul { list-style: none; display: grid; gap: var(--s-12); }
.direct li { display: flex; align-items: flex-start; gap: var(--s-12); font-size: var(--t-16); line-height: var(--lh-snug); color: var(--ink-soft); }
.direct svg {
  width: 16px; height: 16px; flex-shrink: 0; margin-top: 3px;
  stroke: currentColor; fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
  color: var(--accent-text, var(--accent));
}
.direct a { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px;
  text-decoration-color: var(--line-strong); }
.direct a:hover { color: var(--accent-text, var(--accent)); text-decoration-color: currentColor; }

/* ── prova social: procedência à vista ─────────────────────────────
   A frase que dizia de onde vinham as avaliações estava em 13px no rodapé
   da seção. Agora a fonte é um selo no cabeçalho, cada avaliação carrega
   a nota e a data, e a seção termina no link do perfil público. */
.voices-head {
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: var(--s-24) var(--s-40); margin-bottom: var(--s-20);
}
.src-badge {
  display: inline-flex; align-items: center; gap: var(--s-12);
  padding: var(--s-12) var(--s-20); border: 1px solid var(--line); background: var(--paper-warm);
  transition: border-color var(--d-base);
}
.src-badge:hover { border-color: var(--accent-text, var(--accent)); }
.g-mark { width: 20px; height: 20px; flex-shrink: 0; }
.src-score { display: flex; align-items: baseline; gap: var(--s-8); }
.src-score b {
  font-family: var(--font-display); font-weight: var(--w-book); font-size: var(--t-25); line-height: var(--lh-1);
  font-variant-numeric: lining-nums; font-feature-settings: "lnum" 1; color: var(--ink);
}
.src-count { font-size: var(--t-13); letter-spacing: var(--ls-s); color: var(--ink-soft); }
.voices-note { max-width: var(--measure); font-size: var(--t-13); color: var(--ink-soft); margin-bottom: var(--s-32); }

.stars { display: inline-flex; gap: 2px; }
.stars svg { width: 13px; height: 13px; fill: var(--accent-text, var(--accent)); }
.src-score .stars svg { width: 11px; height: 11px; }
.voice .stars { margin-bottom: var(--s-12); }

.voice figcaption { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-4) var(--s-12); }
.voice-who { font-size: var(--t-11); letter-spacing: var(--ls-l); text-transform: uppercase; color: var(--accent-text, var(--accent)); }
.voice-when { font-size: var(--t-11); color: var(--ink-soft); }
.voices-link {
  display: inline-flex; align-items: center; gap: var(--s-8); margin-top: var(--s-8);
  font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase; color: var(--ink);
  border-bottom: 1px solid var(--line-strong); padding-bottom: var(--s-4);
}
.voices-link:hover { color: var(--accent-text, var(--accent)); border-bottom-color: currentColor; }

@media (max-width: 640px) {
  .voices-head { flex-direction: column; align-items: flex-start; gap: var(--s-20); }
  .src-badge { width: 100%; }
}

/* ── os três caminhos, antes do formulário ─────────────────────────
   O formulário era o portão único: 5 campos antes de qualquer conversa,
   com os canais reais espremidos numa coluna lateral. A ordem inverteu. */
.ways { background: var(--paper-warm); border-top: 1px solid var(--line); }
.way-grid { list-style: none; display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(24px, 3.4vw, 56px); }
.way { display: grid; align-content: start; gap: var(--s-12); }
.way-icon { display: block; }
.way-icon svg {
  width: 22px; height: 22px; stroke: currentColor; fill: none;
  stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round;
  color: var(--accent-text, var(--accent));
}
.way-h { font-family: var(--font-display); font-size: var(--t-20); font-weight: var(--w-book); margin-top: var(--s-4); }
.way p { font-size: var(--t-16); line-height: var(--lh-body); color: var(--ink-soft); max-width: var(--measure-tight); }
.way-link {
  display: inline-flex; align-items: center; gap: var(--s-8); margin-top: var(--s-8);
  font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase; color: var(--ink);
  border-bottom: 1px solid var(--line-strong); padding-bottom: var(--s-4); width: fit-content;
}
.way-link:hover { color: var(--accent-text, var(--accent)); border-bottom-color: currentColor; }
.way:hover .arw { transform: translateX(4px); }

@media (max-width: 860px) { .way-grid { grid-template-columns: 1fr; gap: var(--s-32); } }

@media (max-width: 640px) {
  .consent-banner { grid-template-columns: 1fr; gap: var(--s-16); bottom: 0; width: 100%; border-left: 0; border-right: 0; border-bottom: 0; }
  .consent-actions { justify-content: stretch; }
  .consent-actions .btn { flex: 1 1 160px; text-align: center; }
}

/* ── origem de cada afirmação ──────────────────────────────────────
   Cada figura aponta para o post dela que sustenta a frase. Ela abre,
   confere, e vê que nada foi inventado aqui. */

/* ── o padrão, reenquadrado ────────────────────────────────────────
   Antes eram cinco cartões com foto de figura de cera e nome de celebridade
   em manchete, o que lê como caça-fama. O sujeito passa a ser o ofício: duas
   fotos do trabalho e os nomes numa linha de crédito. */
.acclaim-grid {
  display: grid; grid-template-columns: 1fr 1.05fr;
  gap: clamp(30px, 4.4vw, 76px); align-items: start;
}
.acclaim-say .display { margin: var(--s-16) 0 var(--s-24); }
.acclaim-say .lede { color: var(--on-ink-2); max-width: var(--measure-tight); }

.work-pair { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(12px, 1.6vw, 22px); }
.work { display: grid; gap: var(--s-12); align-content: start; }
.work-shot { position: relative; overflow: hidden; aspect-ratio: 4 / 5; background: #241d16; }
.work-shot img { width: 100%; height: 100%; object-fit: cover; transition: transform 1.6s cubic-bezier(.2,.7,.2,1); }
.work:hover .work-shot img { transform: scale(var(--zoom)); }
.work figcaption {
  font-size: var(--t-13); line-height: var(--lh-snug); color: var(--on-ink-3);
  max-width: 26ch;
}
/* a segunda desce um pouco: duas fotos na mesma linha de base viram diagrama */
@media (min-width: 861px) { .work-pair .work:nth-child(2) { margin-top: clamp(28px, 4vw, 64px); } }

.credit {
  display: grid; grid-template-columns: auto 1fr; gap: var(--s-16) var(--s-24); align-items: baseline;
  margin-top: clamp(44px, 5vw, 84px); padding-top: var(--s-24);
  border-top: 1px solid rgba(255,255,255,.16);
}
.credit-label {
  font-size: var(--t-11); letter-spacing: var(--ls-l); text-transform: uppercase;
  color: var(--accent-on-ink); white-space: nowrap;
}
.credit p { font-size: var(--t-13); line-height: var(--lh-body); color: var(--on-ink-3); max-width: var(--measure); }
.credit a {
  color: var(--on-ink); border-bottom: 1px solid var(--rule-on-ink);
  padding-bottom: 2px; white-space: nowrap;
}
.credit a:hover { border-bottom-color: currentColor; }

@media (max-width: 860px) {
  .acclaim-grid { grid-template-columns: 1fr; }
  .credit { grid-template-columns: 1fr; gap: var(--s-12); }
}

/* ── rodapé em dois níveis ─────────────────────────────────────────
   Eram quatro colunas de alturas desiguais, uma faixa isolada para as redes
   e outra para a base: três réguas e dois vazios grandes. A marca e as redes
   passam a andar juntas; os dados viram uma lista de definição compacta. */
.foot-top {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.35fr);
  gap: clamp(34px, 5vw, 88px); align-items: start;
}
.foot-brand { display: grid; gap: var(--s-20); align-content: start; }
.foot .brandmark { color: #fff; }
.foot .brand-logo { height: 44px; filter: var(--logo-on-dark, brightness(0) invert(1)); }
.foot .brandmark small { color: var(--accent-on-ink); }
.foot-line { font-size: var(--t-16); line-height: var(--lh-body); color: var(--on-ink-3); max-width: var(--measure-tight); }

.foot-facts { display: grid; grid-template-columns: 1fr 1.1fr 1fr; gap: clamp(20px, 2.6vw, 40px); }
.foot-facts dt {
  font-size: var(--t-11); letter-spacing: var(--ls-l); text-transform: uppercase;
  color: var(--on-ink-3); margin-bottom: var(--s-12);
}
.foot-facts dd { font-size: var(--t-16); line-height: var(--lh-body); color: var(--on-ink-2); }
.foot-facts a {
  color: var(--on-ink-2);
  text-decoration: underline; text-decoration-thickness: 1px;
  text-underline-offset: 3px; text-decoration-color: var(--rule-on-ink);
}
.foot-facts a:hover { color: #fff; text-decoration-color: currentColor; }
.foot-facts .by-appt {
  display: inline-block; margin-top: var(--s-8);
  font-size: var(--t-13); color: var(--accent-on-ink);
}

.foot-social { display: flex; flex-wrap: wrap; gap: 2px var(--s-4); margin-left: -var(--s-8); }
.foot-social a { display: grid; place-items: center; width: 38px; height: 38px; }

.foot-base {
  display: flex; flex-wrap: wrap; gap: var(--s-12) var(--s-32); justify-content: space-between;
  margin-top: clamp(34px, 4vw, 58px); padding-top: var(--s-24);
  border-top: 1px solid rgba(255,255,255,.13);
  font-size: var(--t-13); color: var(--on-ink-3);
}

@media (max-width: 900px) {
  .foot-top { grid-template-columns: 1fr; gap: var(--s-40); }
  .foot-facts { grid-template-columns: 1fr 1fr; gap: var(--s-32); }
}
@media (max-width: 560px) { .foot-facts { grid-template-columns: 1fr; gap: var(--s-24); } }

/* ═══════════════════════════════════════════════════════════════════
   AUDITORIA DE 29 JUL 2026 — mobile, acessibilidade, ritmo, interação
   ═══════════════════════════════════════════════════════════════════

   Regra que governa este bloco inteiro: nada aqui pode mudar o pixel em
   repouso de quem já está no ar. Cada regra usa uma das três saídas —
   (a) variável com fallback no valor de hoje, (b) classe que só um config
   emite, (c) media query nova que não existia no arquivo. Onde uma regra
   toca seletor partilhado, ela é ou invisível (área de toque transparente,
   visibilidade de elemento já invisível) ou transitória (estado :active),
   e está identificada como tal no comentário. */

/* ── medida de linha: o teto que o arquivo declara e não aplica ──────
   O sistema tem `--measure` (30em, 66 caracteres medidos) e usa-o em 11
   seletores. Estes sete ficaram de fora, e a 1440px produzem 79 a 101
   caracteres por linha, contra os 75 do limite de Bringhurst. No celular
   nenhum deles passa de 42, então o defeito é exclusivamente de desktop —
   e por isso a correção é um max-width, que no celular não tem efeito.
   Variável com fallback `none`: quem não a declara sai como sempre. */
.form-note,
.intro-grid > div p,
.proof-grid > div p,
.enquiry .form-grid > div p,
.door-meta,
.wrap-narrow > p { max-width: var(--measure-prose, none); }
/* A lede tem teto próprio maior: é abertura, não prosa corrida. */
.lede { max-width: var(--measure-lede, none); }
.hero .lede { max-width: var(--measure-tight); }

/* ── a linha de endereço do hero ─────────────────────────────────────
   `.hero-trust` nunca teve regra nenhuma no arquivo: caía no `p { color:
   var(--ink-soft) }`, ou seja tinta suave de papel por cima de fotografia
   escura. Medido no build a 375px: 1,65:1, com o pior pixel a 1,32:1, numa
   linha que carrega a morada e o formato da visita. Com `--on-photo-2` o
   composto sobre o fundo real mede 6,55:1.
   Classe que só existe quando o config declara `hero.trust` sem
   `hero.proof` — nem Charmi nem Ami a emitem em página nenhuma. */
.hero .hero-trust {
  /* `--on-photo-2` (.82) já levava a linha de 1,65:1 para 6,88:1 na média do
     fundo real, mas o pior pixel amostrado ficava em 3,91:1. `--on-photo`
     (.94) fecha também esse: é o mesmo nível que a `.lede` logo acima usa. */
  color: var(--on-photo);
  font-size: var(--t-13);
  letter-spacing: var(--ls-s);
  max-width: var(--measure-tight);
  margin-top: var(--s-20);
  text-shadow: 0 1px 2px rgba(10,6,4,.45);
}

/* ── botão de fechar do lightbox ─────────────────────────────────────
   O site.js cria `<button class="lb-close">Close</button>` desde sempre e o
   CSS nunca teve uma linha para ele: herda `color: inherit` do reset de
   button, ou seja `--ink` quase preto sobre o fundo do lightbox. Medido:
   1,04:1 — invisível — e posicionado ACIMA da foto, porque o `.lb` é grid
   com `place-items: center` e dois filhos.
   Seletor partilhado com Charmi e Ami. O elemento não existe no HTML
   gerado (é criado em tempo de execução) e hoje está invisível nas três:
   isto corrige um defeito comum, não introduz um desvio. */
.lb-close {
  position: absolute;
  top: max(12px, env(safe-area-inset-top)); right: 12px;
  min-width: 44px; min-height: 44px;
  display: grid; place-items: center;
  color: #fff; font-size: var(--t-11); letter-spacing: var(--ls-m);
  text-transform: uppercase;
  background: rgba(0,0,0,.45); border: 1px solid rgba(255,255,255,.35);
  border-radius: 50%;
}
.lb-close:hover { background: rgba(0,0,0,.7); }
.lb-close svg, .lb-nav svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.lb-nav { position: absolute; z-index: 2; top: 50%; width: 48px; height: 48px; display: grid; place-items: center; transform: translateY(-50%); border: 1px solid rgba(255,255,255,.35); border-radius: 50%; background: rgba(0,0,0,.38); color: #fff; cursor: pointer; }
.lb-nav:hover, .lb-nav:focus-visible { background: rgba(0,0,0,.75); }
.lb-prev { left: max(12px, env(safe-area-inset-left)); }
.lb-next { right: max(12px, env(safe-area-inset-right)); }
.lb-count { position: absolute; bottom: max(12px, env(safe-area-inset-bottom)); left: 50%; transform: translateX(-50%); color: rgba(255,255,255,.78); font-size: var(--t-11); letter-spacing: var(--ls-l); }
@media (max-width: 640px) {
  .lb { padding: 64px 12px; }
  .lb-nav { top: auto; bottom: max(10px, env(safe-area-inset-bottom)); transform: none; }
  .lb-prev { left: 12px; }
  .lb-next { right: 12px; }
  .lb-count { bottom: calc(max(10px, env(safe-area-inset-bottom)) + 16px); }
}
/* Fechado, `opacity: 0` e `pointer-events: none` não tiram o botão da árvore
   de foco: havia um "Close" invisível e tabulável no fim de toda página com
   galeria. `visibility` tira. Zero efeito visual: o elemento já era invisível. */
.lb:not(.open) { visibility: hidden; }

/* ── pular para o conteúdo ───────────────────────────────────────────
   Invisível até receber foco. A classe só existe quando o config declara
   `skipLink`, portanto não entra no HTML de quem não a pediu. */
.skip { position: absolute; left: -9999px; top: 0; z-index: 400; }
.skip:focus {
  left: var(--gutter); top: var(--s-8);
  background: var(--ink); color: var(--paper);
  padding: var(--s-12) var(--s-20);
  font-size: var(--t-11); letter-spacing: var(--ls-l); text-transform: uppercase;
}
main:focus { outline: none; }

/* ── a bolha de reserva ──────────────────────────────────────────────
   Mesmo slot da bolha de WhatsApp, para o cliente que não tem WhatsApp
   confirmado. Classe emitida só por `contact.floatHref`. Leva palavra além
   do ícone porque um calendário sozinho não diz o que faz. */
.cta-float {
  width: auto; height: auto; border-radius: 999px;
  grid-auto-flow: column; align-items: center; gap: var(--s-8);
  padding: var(--s-12) var(--s-20);
  min-height: 48px;
  font-size: var(--t-11); letter-spacing: var(--ls-m); text-transform: uppercase;
  background: var(--ink); color: var(--paper);
  box-shadow: 0 6px 22px rgba(0,0,0,.22);
}
.cta-float svg { width: 18px; height: 18px; }
.cta-float:hover { background: var(--accent-text, var(--accent)); }
/* CORRIGIDO na auditoria de 31 jul 2026 (M2). Esta regra (que só define elevação) vem
   1.330+ linhas depois da `:focus-visible` de base (l.304, mesma especificidade),
   então vencia por ordem de cascata e apagava o anel duplo — sobrava só a sombra de
   6px, medida em 2,86-2,94:1 contra a foto em 3 de 5 posições de scroll (abaixo do
   mínimo de 3:1 pra indicador não-textual). Reafirmar os dois anéis aqui, na MESMA
   regra que decide a elevação, garante que a próxima edição deste bloco não separe
   os dois de novo. */
.cta-float:focus-visible {
  box-shadow: 0 0 0 5px var(--paper), 0 0 0 6px var(--ink), 0 6px 22px rgba(0,0,0,.22);
}
body.float-recuada .cta-float {
  opacity: 0;
  pointer-events: none;
  transform: translateY(8px);
  transition: opacity var(--d-fast), transform var(--d-fast);
}

/* ── cartão do contraste: forma que sobrevive ao dedo ────────────────
   `.door--static` e `a.door` são hoje idênticos ao pixel — mesma borda,
   mesmo fundo — e a única diferença é o cursor, que não existe no toque.
   Pior: os dois cartões MORTOS aparecem antes dos dois vivos, então quem
   toca aprende que o componente não clica. A classe `.door--static` não
   aparece em nenhuma página de Charmi nem de Ami (verificado por grep no
   dist das duas: 0 ocorrências), logo esta regra é provadamente inerte lá. */
.door--static { background: var(--paper); }

/* ── estado :active: o site inteiro não tinha nenhum ─────────────────
   Todo o vocabulário de resposta vivia em `:hover` — o preenchimento do
   botão, a subida do cartão, a seta que desliza — e nada disso dispara num
   dedo. Estado transitório: o pixel em repouso de Charmi e Ami não muda,
   e o gate de marcação não lê pseudo-classe. */
.btn:active { color: var(--paper); }
.btn:active::before { transform: translateY(0); }
.hero .btn:active { color: var(--ink); }
.hero .btn-solid:active { color: #fff; }
a.door:active { transform: translateY(-3px); border-color: var(--accent-text, var(--accent)); }
a.door:active .door-cta { color: var(--accent-text, var(--accent)); }
.way-link:active, .voices-link:active, .src-badge:active { border-bottom-color: currentColor; }
.nav-toggle:active i { opacity: .55; }
.voices-dots button:active { background: var(--accent-text, var(--accent)); }

/* ── alvos de toque ──────────────────────────────────────────────────
   Media query nova, e só toque. A caixa não muda: a área cresce por
   pseudo-elemento transparente, o que deixa a geometria de layout intacta
   (verificado por snapshot de ~2.000 caixas antes e depois). No desktop de
   Charmi e Ami nada disto sequer é avaliado. */
@media (pointer: coarse) {
  /* O azul de fábrica do Android sobre uma paleta marfim e ouro. */
  body { -webkit-tap-highlight-color: color-mix(in srgb, var(--ink) 12%, transparent); }

  /* Telefone do rodapé: 103x20px medidos, e é o segundo caminho de
     conversão da página inteira. */
  .foot-facts a { position: relative; }
  .foot-facts a::after {
    content: ""; position: absolute; left: 0; right: 0; top: 50%;
    height: 44px; transform: translateY(-50%);
  }
  /* "Read all 416 reviews": 176x24px, logo depois de vinte depoimentos. */
  .voices-link, .way-link { position: relative; }
  .voices-link::after, .way-link::after { content: ""; position: absolute; inset: -11px 0; }
  /* Ícone social: 38x38, faltam 6px em cada eixo. */
  .foot-social a { position: relative; }
  .foot-social a::after { content: ""; position: absolute; inset: -3px; }
}

/* ── setas do carrossel, em lista longa ───────────────────────────────
   Vinte pontos de 7x7px viravam duas linhas de bolinhas sem leitura nenhuma
   pra quem olha. Em lista longa, o controle passa a ser duas setas
   (anterior/próxima), a mesma glifo `.arw` já usada no resto do site pra
   paginação e links com seta — sem moldura, sem contagem visual de posição.
   Pausa por hover/foco/toque continua ativa (site.js); só o botão dedicado
   de pausa some, porque em lista longa o toque já assume controle manual.

   A classe `.voices-nav` é criada pelo site.js SÓ quando há mais de seis
   depoimentos. Charmi tem seis, Ami não tem carrossel: nenhuma das duas
   recebe a marcação, e os pontos delas continuam exatamente como estão. */
.voices-nav { display: flex; justify-content: center; align-items: center; gap: var(--s-32); margin-top: var(--s-24); }
.voices-nav-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0; border: none; background: transparent;
  font-size: var(--t-20); line-height: 1; color: var(--ink-soft); cursor: pointer;
  transition: color var(--d-fast) var(--ease);
}
.voices-nav-btn:hover, .voices-nav-btn:focus-visible { color: var(--accent-text, var(--accent)); }
.voices-nav-btn .arw { display: inline-block; transition: transform var(--d-base) cubic-bezier(.2,.7,.2,1); }
.voices-nav-btn:first-child:hover .arw { transform: translateX(-3px); }
.voices-nav-btn:last-child:hover .arw { transform: translateX(3px); }
.voices-pause svg { width: 17px; height: 17px; fill: currentColor; }
.voices-count {
  min-width: 4.6em; text-align: center; color: var(--ink-soft);
  font-size: var(--t-13); font-variant-numeric: tabular-nums;
}
@media (max-width: 860px) {
  .voices .voice { flex: 0 0 var(--voice-w-sm, 100%); }
  .voices-nav { gap: var(--s-16); }
}

/* ── mural de peças (home) ─────────────────────────────────────────
   A grade e a foto são as do lookbook (.gallery / .shot, l. 823-838).
   Só o cabeçalho, o respiro entre peças e o pé de CTA são desta seção.
   Nenhuma regra abaixo toca em .gallery fora de .piecewall, portanto o
   lookbook de Charmi e Ami sai igual. */
.piecewall-head { margin-bottom: clamp(24px, 3.4vw, 48px); }
.piecewall-head .kicker { display: block; margin-bottom: var(--s-16); }
.piecewall-head h2 { max-width: 42ch; }   /* o título é de uma linha: a medida só existe para o telemóvel não o esticar */
.piecewall .gallery { gap: clamp(14px, 1.8vw, 28px); }
.piecewall-foot { margin-top: clamp(24px, 3.4vw, 48px); }

@media (max-width: 860px) {
  /* Peça pequena em telemóvel não vende. Abaixo de 861px a grade já é de uma
     coluna em 4/5; a de largura cheia era a excepção, ficava em faixa 4/3 e
     encolhia o bordado a uma tira. Aqui ela volta a retrato como as outras. */
  .piecewall .shot.full { aspect-ratio: 4 / 5; }
}

/* A garantia era o unico bloco de peso da pagina sem nada para olhar, e no
   telemovel ela abria uma corrida de 3.324px de rolagem sem uma unica imagem
   (garantia + FAQ). Uma peca acabada logo abaixo da promessa fecha a frase:
   e isto que se esta a garantir. Guardada por `promise.image`, entao quem nao
   declara nao ganha figura nenhuma.                                          */
.promise-piece { margin: var(--s-40) auto 0; max-width: 980px; padding-inline: var(--gutter); }
.promise-piece img { width: 100%; height: 42vw; max-height: 380px; object-fit: cover; border-radius: var(--r-md); }
.promise-piece figcaption { margin-top: var(--s-12); font-size: var(--t-13); color: var(--ink-soft); text-align: center; }
@media (max-width: 860px) { .promise-piece img { height: 56vw; max-height: 300px; } }
