/* ============================================================
   MUSIMEE · PADRÕES DA LANDING  ·  v2.1
   ------------------------------------------------------------
   Classes prontas para os padrões que se repetem na camada
   expressiva. Importe DEPOIS de tokens.css:

     <link rel="stylesheet" href="tokens/tokens.css">
     <link rel="stylesheet" href="tokens/patterns.css">

   Tudo aqui saiu de problema real medido em produção. Os números
   de véu vêm de docs/texto-sobre-foto.md e não são chute.
   ============================================================ */

/* ══ 1. TEXTO SOBRE FOTO ═════════════════════════════════════
   Tokens de texto para superfície fotográfica escurecida.
   Aplique .on-photo no container que tem a foto de fundo.       */
.on-photo {
  --m-text:        var(--m-paper);   /* título              */
  --m-text-body:   #DDD8CE;          /* corpo               */
  --m-text-muted:  #C6C0B6;          /* eyebrow, legenda    */
  --m-text-faint:  #A9A49A;          /* apagado             */
  --m-accent-text: var(--m-signal-400);  /* 400, nao 500 —
       o 500 fica no limite sobre foto escurecida */
  color: var(--m-text-body);
}

/* Véus calculados. NUNCA edite os stops sem remedir — ver
   docs/texto-sobre-foto.md, secao "O procedimento". */

/* texto embaixo (mobile): rampa vertical */
.scrim-v::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg,
    rgba(25,23,20,.04)  0%,
    rgba(25,23,20,.06) 20%,
    rgba(25,23,20,.76) 27%,
    rgba(25,23,20,.84) 100%);
}

/* texto à esquerda (desktop): PLATÔ horizontal.
   Rampa linear nao serve: enfraquece no meio do proprio texto. */
.scrim-h::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(90deg,
      rgba(25,23,20,.76)  0%,
      rgba(25,23,20,.76) 56%,
      rgba(25,23,20,0)   72%),
    linear-gradient(180deg,
      rgba(25,23,20,.06)  0%,
      rgba(25,23,20,.06) 55%,
      rgba(25,23,20,.22) 100%);
}

/* legenda no rodapé de um card */
.scrim-card::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg,
    rgba(25,23,20,.06)  0%, rgba(25,23,20,0)   34%,
    rgba(25,23,20,.72) 74%, rgba(25,23,20,.88) 100%);
}

/* ══ 2. FOTO DE FUNDO DE SEÇÃO ═══════════════════════════════ */
.photo-bg { position: absolute; inset: 0; z-index: 0; }
.photo-bg picture { display: block; width: 100%; height: 100%; }
.photo-bg img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* costura a foto na paleta quente do resto da pagina */
  filter: saturate(.86) contrast(1.02);
}

/* ══ 3. RECORTE COM ALFA ═════════════════════════════════════
   drop-shadow segue o contorno; box-shadow desenharia o
   retangulo invisivel e entregaria o truque.                    */
.cutout {
  filter:
    drop-shadow(0 18px 26px rgba(43,41,38,.14))
    drop-shadow(0 2px 3px rgba(43,41,38,.10))
    saturate(.78) sepia(.05) contrast(1.02);
}

/* ══ 4. FAIXA DE CHIPS QUE ROLA ══════════════════════════════
   7 chips em 360px viram 3 linhas e 156px. Assim viram 44px.    */
.chipbar { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--m-3); }
@media (max-width: 600px) {
  .chipbar {
    flex-wrap: nowrap; justify-content: flex-start;
    overflow-x: auto; scroll-snap-type: x proximity;
    scrollbar-width: none; -ms-overflow-style: none;
    padding-inline: var(--m-gutter);
    margin-inline: calc(var(--m-gutter) * -1);
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
            mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
  }
  .chipbar::-webkit-scrollbar { display: none; }
  .chipbar > * { flex: 0 0 auto; scroll-snap-align: start; }
}

/* ══ 5. GRADE DE CARDS ═══════════════════════════════════════
   auto-fit sozinho vira UMA coluna no mobile e o 1fr estica o
   card para a largura toda. Trave 2 colunas.                    */
.cardgrid {
  display: grid; gap: clamp(12px, 2vw, 24px);
  grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr));
}
@media (max-width: 600px) {
  .cardgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--m-3); }
}

/* ══ 6. LISTA EXPANSÍVEL ═════════════════════════════════════
   [hidden] perde para qualquer display do autor — a regra
   precisa ser explicita E mais especifica.                      */
.expandable { display: flex; flex-wrap: wrap; gap: var(--m-2); list-style: none; margin: 0; padding: 0; }
.expandable[hidden] { display: none; }

/* ══ 7. TEXTO ANIMADO ════════════════════════════════════════
   Altura reservada: sem isso o bloco pula a cada troca e o texto
   sai da faixa onde o contraste foi medido.                     */
.typer { min-height: calc(1.55em * 2); }          /* 2 linhas: mobile */
@media (min-width: 900px) { .typer { min-height: 1.55em; } }
.typer__cur {
  display: inline-block; width: 2px; height: 1em; margin-left: 3px;
  vertical-align: -.12em; background: var(--m-signal-400);
  animation: typer-blink 1s steps(1) infinite;
}
@keyframes typer-blink { 0%,50% { opacity: 1 } 50.01%,100% { opacity: 0 } }
@media (prefers-reduced-motion: reduce) { .typer__cur { animation: none } }

/* ══ 8. DENSIDADE DE SEÇÃO ═══════════════════════════════════
   Padrao 160px nas duas pontas era o dobro do necessario em
   secao com card grande.                                        */
.sec-tight { padding-block: clamp(56px, 6vw, 96px); }
@media (max-width: 600px) { .sec-tight { padding-block: var(--m-10); } }

/* ══ 9. TEXTURA — teto de 0.06 ═══════════════════════════════
   Acima disso o grao suja o fundo inteiro de cinza.             */
.grain::after {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background-image: var(--m-grain);
  opacity: .05; mix-blend-mode: multiply;
}
.on-ink.grain::after { mix-blend-mode: screen; }

/* ── .scrim-panel ─────────────────────────────────────────────────────────
   Véu de painel-rodapé: o bloco opaco onde moram controles e legenda,
   colado na base de uma foto. Difere de .scrim-card (que é véu de legenda
   solta) por ser uma PRATELEIRA — entra forte e fica forte.

   Os stops garantem alfa >= .78 em qualquer ponto abaixo de 16% do painel.
   Esse é o piso para o qual a escala .on-photo foi calibrada, então dentro
   de um .scrim-panel valem os MESMOS tokens de texto do hero — sem cor
   local, sem exceção por foto.

   Medido no pior pixel das seis fotos da demo:
     duração (--m-text-muted, alfa .795)  5,41 : 1   pior caso
     letra   (--m-text,       alfa .886) 12,25 : 1
     próxima (--m-text-faint, alfa .905)  5,84 : 1
   Antes, com .68 em 16%, demo-homenagem dava 4,38 e reprovava.
   Trocou a foto? Remeça. Ver docs/texto-sobre-foto.md.            */
.scrim-panel {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
  background: linear-gradient(180deg,
    rgba(25, 23, 20, 0)   0%,
    rgba(25, 23, 20, .78) 16%,
    rgba(25, 23, 20, .88) 50%,
    rgba(25, 23, 20, .94) 100%);
}

/* ── .scrim-body ──────────────────────────────────────────────────────────
   Véu de CORPO INTEIRO: texto do topo à base da peça.

   Aqui não existe rampa — existe PLATÔ. Rampa enfraquece no meio do próprio
   texto: a primeira versão do card da demo usava .52 aos 38% e os versos
   sumiam sobre a parte clara da foto.

   O platô .74 só funciona junto com duas decisões de TEXTO. Escurecer mais
   não era a saída — texto mais claro custa zero na foto:

     versos em --m-text-faint  #A9A49A -> exigia alfa .845 (foto vira breu)
     versos em --m-text-body   #DDD8CE -> exige alfa .690
     acento a 16px  (alvo 4,5)         -> exigia alfa .816
     acento a 19px bold (AA-large 3,0) -> exige alfa .704

   Por isso, dentro de .scrim-body: corpo em `body`, nunca `faint`; e a linha
   de acento a >=18.66px em negrito. Medido no pior pixel de 6 fotos, no
   desktop e no mobile. Ver docs/texto-sobre-foto.md.                       */
.scrim-body::after {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg,
    rgba(25, 23, 20, .62)   0%,
    rgba(25, 23, 20, .74)   6%,
    rgba(25, 23, 20, .74)  93%,
    rgba(25, 23, 20, .88) 100%);
}

/* ── Texturas ─────────────────────────────────────────────────────────────
   CSS puro, de propósito: `repeating-gradient` não custa requisição nem
   data URI. Tráfego pago paga por cada KB — textura não pode ser imagem.

   Período de 4px, nunca 1px: em tela com DPR fracionário (1.25, 1.5) um
   padrão de 1px vira moiré e a página parece com defeito de renderização.

   Alfa no chão. Textura é para ser sentida, não vista — a mesma regra do
   `--m-grain` (teto .06). Se você consegue apontar a trama, está alta.     */

/* Trama de papel guardado — para as seções em Paper.
   A marca é memória de família; a superfície tem de parecer papel que
   alguém guardou, não tela de dashboard. */
.tex-linen {
  background-image:
    repeating-linear-gradient(0deg,
      rgba(43, 41, 38, .038) 0 1px, transparent 1px 5px),
    repeating-linear-gradient(90deg,
      rgba(43, 41, 38, .028) 0 1px, transparent 1px 5px);
}

/* Ondas concêntricas — para a seção em Ink, onde se ouve.
   O som saindo do card e tomando a sala.

   O CENTRO tem de coincidir com o card, senao vira padrao decorativo
   aleatorio em vez de som saindo dali. Medido: centro do card fica a
   62,3% da secao no desktop e 67,0% no mobile — 64% serve os dois,
   porque banda suave perdoa 3% de desvio. Se o layout da secao mudar,
   remeça e ajuste --tex-y.

   BANDAS SUAVES, não fio de 2px. Fio fino desenha arame; banda com
   transição feathered lê como onda de luz. E, por ser suave, o pico de
   claridade fica menor — mexe menos no contraste do texto por cima.

   Alfa .055 no pico: aqui a regra do grão (teto .06) NÃO se aplica.
   Grão é ruído e some no fundo; isto é desenho e precisa ser visto.
   Em .030 ficava invisível — a textura existia e ninguém enxergava.

   Custo no contraste, medido sobre o pico da banda:
     h2      --m-text        12,10  (era 13,20)
     lede    --m-text-body    9,37  (era 10,21)
     eyebrow --m-text-muted   5,60  (era  6,10)
   Todos folgados. Ver docs/peso.md e docs/texto-sobre-foto.md.          */
.tex-rings {
  --tex-x: 50%;
  --tex-y: 64%;   /* centro do card, medido */
  background-image:
    repeating-radial-gradient(circle at var(--tex-x) var(--tex-y),
      rgba(240, 121, 59, 0)     0     38px,
      rgba(240, 121, 59, .055)  50px  58px,
      rgba(240, 121, 59, 0)     70px 104px);
}

/* As duas convivem com .grain — grão é ruído, textura é desenho.
   Juntas dão superfície; só o grão dá sujeira. */
@media (prefers-reduced-motion: reduce) {
  /* textura é estática, nada a desligar aqui — nota para quem for animar */
}

/* ── .lang · seletor de idioma ────────────────────────────────────────────
   O markup é injetado no build (um por idioma), então este CSS precisa
   existir mesmo quando o elemento não está na página de desenvolvimento.

   A BANDEIRA é enfeite reconhecível; quem identifica é o NOME DO IDIOMA no
   próprio idioma — é assim que alguém que não lê português acha a própria
   língua. Por isso o nome nunca é traduzido para o idioma da página.      */
.lang { position: relative; }

.lang__btn {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 44px; padding: 0 10px;
  background: transparent; border: 0; cursor: pointer;
  font-family: var(--m-font); font-size: 13px; font-weight: 500;
  letter-spacing: .04em; color: var(--m-text-body);
  border-radius: var(--m-r-pill);
  transition: color var(--m-t-fast), background var(--m-t-fast);
}
.lang__btn:hover { color: var(--m-text); background: var(--m-surface-alt); }
.lang__btn svg { transition: transform var(--m-t-fast); }
.lang__btn[aria-expanded="true"] svg { transform: rotate(180deg); }

/* SVG, não emoji: o Windows não traz glifo de bandeira e desenha o par de
   indicadores regionais como duas letras ("BR", "US"). Ver scripts/flags.mjs. */
.lang__fl {
  width: 18px; height: 12px; flex: 0 0 18px;
  border-radius: 2px; display: block;
  box-shadow: 0 0 0 1px rgba(43, 41, 38, .12) inset;
}

.lang__menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 60;
  min-width: 210px; padding: 6px;
  background: var(--m-surface); border: 1px solid var(--m-border);
  border-radius: var(--m-r-lg); box-shadow: var(--m-sh-lg);
  display: flex; flex-direction: column;
}
/* `hidden` perde para qualquer `display` do autor — a regra tem de ser
   mais específica que a do próprio componente. Já quebrou o menu mobile
   deste projeto uma vez (docs/armadilhas.md). */
.lang__menu[hidden] { display: none; }

.lang__op {
  display: flex; align-items: center; gap: 10px;
  min-height: 44px; padding: 0 12px;
  border-radius: var(--m-r-md);
  color: var(--m-text-body); text-decoration: none;
  font-size: 14px; white-space: nowrap;
}
.lang__op:hover { background: var(--m-surface-alt); color: var(--m-text); }
.lang__op.is-on { color: var(--m-accent-text); font-weight: 500; }
.lang__op.is-on::after {
  content: ''; margin-left: auto; width: 14px; height: 2px;
  border-radius: 2px; background: currentColor;
}

@media (max-width: 900px) {
  /* na nav estreita fica só a bandeira e o código; o nome vive no menu */
  .lang__btn { padding: 0 6px; }
  .lang__menu { right: -8px; }
}
