/* ==========================================================================
   CARD EXPANSÍVEL EM TELA CHEIA — prefixo exp-
   Trilho horizontal de cards retrato. No clique, o card vira um overlay de
   tela cheia; o conteúdo entra depois que a caixa termina de crescer.

   O crescimento é FLIP: o overlay JÁ nasce do tamanho final (position:fixed
   inset:0) e recebe um transform inverso que o encolhe até o retângulo do
   card. Animar de volta ao transform identidade é o efeito inteiro — e o
   navegador compõe isso na GPU, coisa que top/left/width/height (o que o
   original animava) não permitem.

   O script escreve só cinco variáveis — --exp-tx, --exp-ty, --exp-sx,
   --exp-sy e --exp-r. Quem monta transform e border-radius é este arquivo.
   É o mesmo contrato de canal do midia/galeria-pasta: mudando a fórmula
   aqui, o script continua valendo.

   Tokens: --accent --bg --dark-rgb --display --ease --fg --fg-2 --fg-muted
           --light --max --pad --radius-media --radius-pill --rule --rule-2
   Primitivas do core em uso: .wrap .sec-pad .sec-head .eyebrow .sec-title
           .sec-lead .glass .pill .btn .btn-primary .grain
   ========================================================================== */

/* --dur do core é .9s: certo para entrada de seção, lento demais para uma
   caixa que cresce sob o dedo. As durações de interação são locais e ficam
   aqui, à mão de quem for ajustar. A curva continua sendo a do projeto. */
.exp{
  --exp-dur:.52s;        /* crescimento e recolhimento da caixa */
  --exp-fade:.34s;       /* entrada do conteúdo, depois da caixa */
  --exp-card-w:clamp(200px,24vw,300px);
  --exp-gap:16px;
  --exp-z:500;
  /* Borda da coluna reproduzida fora do .wrap: é o que alinha a primeira
     foto do trilho com o título da seção sem que o trilho entre na coluna
     (contrato §4 — quem precisa sangrar sai do .wrap, não ganha margem
     negativa). Lê os mesmos --max e --pad, então acompanha o tema. */
  --exp-gutter:calc(max(0px,(100% - var(--max)) / 2) + var(--pad));
  position:relative;
  margin-top:clamp(34px,5vh,56px);
}

/* Só o ajuste de largura: o resto vem da primitiva .sec-head do core. */
.exp-head{--head-max:680px}
.exp-head .eyebrow,
.exp-head .sec-title,
.exp-head .sec-lead{margin-inline:auto}

/* ---------------------------------------------------------------- trilho */
/* A barra de rolagem do sistema fica escondida de propósito: em fundo
   escuro ela corta a composição. Em troca, o .exp-rail abaixo devolve a
   informação de quanto ainda falta — esconder sem repor seria esconder. */
.exp-track{
  display:flex;
  gap:var(--exp-gap);
  overflow-x:auto;
  overflow-y:hidden;
  overscroll-behavior-inline:contain;
  padding-inline:var(--exp-gutter);
  /* respiro para o anel de foco do card não ser cortado pelo scrollport */
  padding-block:8px;
  scroll-padding-inline:var(--exp-gutter);
  scrollbar-width:none;
  -ms-overflow-style:none;
  margin:0;
}
.exp-track::-webkit-scrollbar{display:none}

.exp-item{flex:0 0 var(--exp-card-w)}

/* ---------------------------------------------------------------- card */
/* <button> de verdade, não <div> clicável: foco, Enter e Espaço vêm de
   graça, e o aria-haspopup="dialog" avisa que o clique abre um diálogo. */
.exp-card{
  position:relative;display:block;width:100%;aspect-ratio:3/4;
  padding:0;margin:0;background:none;text-align:left;
  color:inherit;font-size:inherit;
  border:1px solid var(--rule);
  border-radius:var(--radius-media);
  overflow:hidden;
  transition:border-color .4s var(--ease);
}
.exp-card:hover{border-color:var(--rule-2)}

.exp-card-img{
  position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;
  filter:grayscale(.25);
  transition:filter .6s var(--ease),transform .6s var(--ease);
}
.exp-card:hover .exp-card-img,
.exp-card:focus-visible .exp-card-img{filter:grayscale(0);transform:scale(1.06)}

/* Texto DENTRO da foto, ancorado embaixo, com véu em gradiente mais blur
   mascarado (contrato §6). Véu em caixa reta lê chapado; a máscara é o que
   dissolve a borda de cima do desfoque. */
.exp-card-info{
  position:absolute;left:0;right:0;bottom:0;z-index:1;
  display:flex;flex-direction:column;gap:7px;
  padding:66px clamp(14px,1.6vw,22px) clamp(15px,1.7vw,24px);
  background:linear-gradient(to top,
    rgba(var(--dark-rgb),.92) 0%,
    rgba(var(--dark-rgb),.5) 46%,
    transparent 100%);
  backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
  mask-image:linear-gradient(to top,#000 0%,rgba(0,0,0,.9) 44%,transparent 100%);
  -webkit-mask-image:linear-gradient(to top,#000 0%,rgba(0,0,0,.9) 44%,transparent 100%);
}
.exp-card-cat{
  font-size:10.5px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--accent);
}
/* Único ponto do componente que não lê --fg: o véu é --dark-rgb em qualquer
   escopo, então o texto sobre ele tem de ser claro em qualquer escopo. */
.exp-card-title{
  font-family:var(--display);font-weight:700;
  font-size:clamp(16px,1.7vw,22px);letter-spacing:-.025em;line-height:1.14;
  color:var(--light);
}

/* Bolinha de dica no canto. Usa a primitiva .glass do core — borda tênue,
   brilho radial e desfoque já resolvidos lá. As transições do .glass são
   repetidas aqui de propósito, para esta regra não depender da ordem de
   carregamento das folhas (contrato §6.4). */
.exp-card-hint{
  position:absolute;top:13px;right:13px;z-index:2;
  width:34px;height:34px;border-radius:var(--radius-pill);
  display:grid;place-items:center;color:var(--light);
  opacity:0;transform:scale(.8) translateY(-4px);
  transition:opacity .3s var(--ease),transform .3s var(--ease),
             background .45s,border-color .45s;
}
.exp-card:hover .exp-card-hint,
.exp-card:focus-visible .exp-card-hint{opacity:1;transform:none}

/* ---------------------------------------------------------------- barra */
/* --exp-thumb (largura visível / largura total) e --exp-shift (deslocamento
   já resolvido, de 0 a 1) chegam do script. Aparece só quando o trilho
   realmente transborda. */
.exp-rail{
  --exp-thumb:1;--exp-shift:0;
  position:relative;height:2px;
  background:var(--rule);border-radius:var(--radius-pill);
  margin-top:clamp(22px,3.4vh,34px);
  opacity:0;transition:opacity .4s var(--ease);
}
.exp.is-scrollable .exp-rail{opacity:1}
.exp-rail-thumb{
  position:absolute;top:0;bottom:0;
  left:calc(var(--exp-shift) * 100%);
  width:calc(var(--exp-thumb) * 100%);
  background:var(--accent);border-radius:inherit;
}

/* ==========================================================================
   OVERLAY — o card virando tela
   ========================================================================== */

/* O overlay é sempre do tamanho final. O estado inicial é um transform
   inverso escrito pelo script: translate até o canto do card, scale até o
   tamanho do card. Animar até o transform identidade É a expansão.

   O raio precisa da divisão pela escala: um border-radius de 16px dentro de
   uma caixa escalada em .22 sairia com 16 * .22 = 3.5px na tela. Dividindo
   antes, o card começa com o raio exato que tinha, e termina em zero.

   O raio inicial não é constante: o script lê o border-radius do próprio
   card, que é --radius-media. Em tema flat (--radius-media:0) não há raio
   nenhum para animar e o crescimento sai reto — como deve. */
.exp-overlay{
  --exp-tx:0px;--exp-ty:0px;--exp-sx:1;--exp-sy:1;--exp-r:0px;
  position:fixed;inset:0;z-index:var(--exp-z);
  background:var(--bg);
  overflow:hidden;
  transform-origin:0 0;
  transform:translate(var(--exp-tx),var(--exp-ty)) scale(var(--exp-sx),var(--exp-sy));
  border-radius:calc(var(--exp-r) / var(--exp-sx)) / calc(var(--exp-r) / var(--exp-sy));
  transition:transform var(--exp-dur) var(--ease),
             border-radius var(--exp-dur) var(--ease);
}
/* [hidden] é retirado pelo script antes de medir. Existe para o estado
   fechado: sem ele o CTA e o botão de fechar entram na ordem de tabulação
   de uma página que não tem diálogo nenhum aberto. */
.exp-overlay[hidden]{display:none}
.exp-overlay:not([hidden]){will-change:transform}
/* Janela de medição: o script tira o [hidden] para poder medir a caixa e
   só então a encolhe até o card. Sem desligar a transição nesse intervalo,
   o overlay apareceria em tela cheia e a animação rodaria ao contrário. */
.exp-overlay.is-measuring{transition:none}

.exp-close{
  position:absolute;z-index:2;
  top:clamp(16px,2.4vw,26px);right:clamp(16px,2.4vw,26px);
  width:44px;height:44px;padding:0;
  border-radius:var(--radius-pill);
  display:grid;place-items:center;color:var(--fg);
  opacity:0;transform:scale(.9);
  transition:opacity .3s var(--ease),transform .3s var(--ease),
             background .45s,border-color .45s;
}
.exp-overlay.is-shown .exp-close{opacity:1;transform:none;transition-delay:.06s}

.exp-content{
  position:absolute;inset:0;
  display:grid;grid-template-columns:1fr 1fr;
  opacity:0;
  transition:opacity var(--exp-fade) var(--ease);
}
.exp-overlay.is-shown .exp-content{opacity:1}

.exp-media{position:relative;overflow:hidden;margin:0}
.exp-media-img{
  width:100%;height:100%;object-fit:cover;
  transform:scale(1.05);
  transition:transform 1.1s var(--ease);
}
.exp-overlay.is-shown .exp-media-img{transform:none}

.exp-detail{
  display:flex;flex-direction:column;justify-content:center;
  padding:clamp(36px,6vw,72px) var(--pad);
  overflow-y:auto;
}

/* Nada entra seco (contrato §5): o texto sobe com blur indo a zero, um
   tempo depois da imagem. O blur mora aqui, e não no .exp-content inteiro,
   porque desfocar a foto de tela cheia custa caro e não acrescenta nada. */
.exp-detail-body{
  opacity:0;filter:blur(12px);transform:translateY(16px);
  transition:opacity var(--exp-fade) var(--ease),
             filter calc(var(--exp-fade) + .2s) var(--ease),
             transform var(--exp-fade) var(--ease);
}
.exp-overlay.is-shown .exp-detail-body{
  opacity:1;filter:blur(0);transform:none;transition-delay:.1s;
}

/* A primitiva .eyebrow é inline-flex; aqui ela precisa ocupar a própria
   linha para a margem de baixo valer. Só o display muda — traço, tracking
   e cor continuam sendo os do core. */
.exp-cat{display:flex;width:fit-content;margin-bottom:16px}
.exp-title{
  font-family:var(--display);font-weight:700;
  font-size:clamp(28px,3.6vw,50px);letter-spacing:-.035em;line-height:1.02;
  color:var(--fg);max-width:16ch;
}
.exp-desc{
  color:var(--fg-2);line-height:1.72;max-width:44ch;margin-top:22px;
}
.exp-tags{display:flex;flex-wrap:wrap;gap:8px;margin-top:30px}
.exp-cta{margin-top:34px;align-self:flex-start}

/* [hidden] entra pelo script quando o slot do card vem vazio. Precisa ser
   dito onde o componente declarou um display: a regra do agente do usuário
   perde para qualquer regra de autor, e o slot vazio continuaria ocupando
   espaço — no caso do .exp-cat, com o traço do olho e nada depois dele. */
.exp-cat[hidden],
.exp-tags[hidden]{display:none}

/* ---------------------------------------------------------------- movimento reduzido */
/* Quem pediu menos movimento não vê o FLIP: o script pula a medição e o
   overlay simplesmente aparece inteiro. As durações caem para quase zero em
   vez de virarem "none" — assim o transitionend continua disparando e o
   encadeamento do script segue funcionando por um caminho só. */
@media(prefers-reduced-motion:reduce){
  .exp-overlay,.exp-content,.exp-detail-body,.exp-close,
  .exp-media-img,.exp-card,.exp-card-img,.exp-card-hint,.exp-rail{
    transition-duration:.01ms;transition-delay:0s;
  }
  .exp-card:hover .exp-card-img,
  .exp-card:focus-visible .exp-card-img{transform:none}
  .exp-media-img{transform:none}
  .exp-detail-body{filter:none;transform:none}
}

/* ---------------------------------------------------------------- mobile */
/* Duas colunas de 50% em tela estreita dão 180px para a foto e 180px para um
   parágrafo de 45 palavras: ilegível dos dois lados. Vira empilhado, com a
   foto em faixa e o texto rolando embaixo. Era o que faltava no original —
   o grid-template-columns:1fr 1fr valia até em telefone. */
@media(max-width:900px){
  .exp-content{
    grid-template-columns:1fr;
    grid-template-rows:minmax(0,34vh) minmax(0,1fr);
  }
  .exp-title{font-size:clamp(26px,6.4vw,38px);max-width:none}
  .exp-desc{max-width:none;margin-top:18px}
  .exp-detail{padding:clamp(26px,6vw,40px) var(--pad)}
  .exp-tags{margin-top:22px}
  .exp-cta{margin-top:26px}
}

@media(max-width:560px){
  .exp{--exp-card-w:clamp(180px,62vw,240px);--exp-gap:12px}
  .exp-close{width:40px;height:40px;top:14px;right:14px}
  .exp-content{grid-template-rows:minmax(0,30vh) minmax(0,1fr)}
  .exp-card-hint{width:30px;height:30px;top:11px;right:11px}
}

/* Telefone deitado: 30vh de foto não sobra texto nenhum. A foto sai e a
   coluna de texto fica com a tela inteira. */
@media(max-height:520px) and (orientation:landscape){
  .exp-content{grid-template-columns:1fr;grid-template-rows:1fr}
  .exp-media{display:none}
}
