/*
 * RofSom App — folha única.
 *
 * Sem framework e sem build: o CSS é servido como está, e quem for mexer daqui
 * a dois anos abre um arquivo e entende. O peso disso é conhecido (não há
 * árvore de dependência para atualizar) e o ganho é direto — a página abre no
 * 3G do interior, que é onde metade do público está.
 *
 * Escuro por padrão porque o uso é noturno: fã no meio do show, artista no
 * camarim. Tela clara nesse contexto queima os olhos e denuncia o celular na
 * plateia.
 *
 * O alvo de toque é 44 px, e não os 32 px confortáveis no mouse: quem clica
 * está em pé, com uma mão só, muitas vezes segurando outra coisa.
 */

/* ───────────────────────────── Poppins ─────────────────────────────
 *
 * Hospedada aqui, não no Google Fonts: a CSP só libera `'self'` e — o que pesa
 * mais — uma fonte de terceiro é um DNS, um TLS e um servidor a mais entre o fã
 * e a página, no 3G onde a página precisa abrir.
 *
 * Quatro pesos, e só. O `latin-ext` fica junto por correção (nome próprio com
 * grafia estrangeira acontece), mas o português vive todo no `latin`: na
 * prática o celular baixa ~31 kB, não os 64 kB da pasta.
 *
 * `swap`: o texto aparece de cara na fonte do sistema e troca quando a Poppins
 * chega. O contrário — segurar o texto esperando a fonte — é tela em branco em
 * cima de quem tem a internet pior.
 */
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fontes/poppins-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fontes/poppins-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fontes/poppins-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fontes/poppins-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fontes/poppins-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fontes/poppins-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fontes/poppins-700-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Poppins';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fontes/poppins-700-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
  --fundo: #0b0b0f;
  --fundo-2: #15151c;
  --fundo-3: #1e1e28;
  --borda: #2a2a36;
  --texto: #f4f4f8;
  --texto-2: #c8c8d4;
  --texto-3: #8a8a9c;

  /* ── A bandeira de Pernambuco, inteira ─────────────────────────────
   *
   * A identidade da casa é a do estado. Não é enfeite — é a primeira coisa que
   * diz de onde a plataforma é, para um público que se reconhece nisso antes de
   * ler qualquer texto.
   *
   * **A paleta agora tem as cinco cores da bandeira** (15/08/2026). Faltava o
   * verde, e a falta não era um detalhe: o elemento mais reconhecível da
   * bandeira de Pernambuco é o **arco-íris de vermelho, amarelo e verde** no
   * campo azul, com o sol amarelo, a estrela branca e a cruz vermelha no campo
   * branco de baixo. Uma paleta com azul, vermelho e amarelo lembrava a
   * bandeira; com o verde, ela **é** a bandeira — e o arco-íris pode aparecer
   * como arco-íris (ver `.fio-pe`), que é o que faz o pernambucano reconhecer
   * a casa de relance.
   *
   * Cada cor tem papel fixo, e é o papel que impede a tela de virar bandeirola:
   *
   * - **azul** — o caminho alternativo (filtrar, buscar) e o número em
   *   destaque. É o campo maior da bandeira e é a cor institucional do estado,
   *   a mesma régua dos portais do Governo de Pernambuco.
   * - **vermelho** — a ação. É ele que vira botão principal e a marca da casa.
   * - **amarelo (o sol)** — atenção e distinção (o selo de fundador).
   * - **verde (o arco-íris)** — confirmação: o que deu certo, o que está no ar.
   * - **branco** — a paz da bandeira e o respiro da tela.
   *
   * Os tons saem da bandeira ajustados para tela escura: o azul oficial é
   * escuro demais para virar botão sobre fundo quase preto e o verde-bandeira
   * some. O que se mantém é a relação entre as cores, que é o que faz alguém
   * reconhecer de onde elas vêm.
   */
  --pe-azul: #1a4fbd;
  --pe-azul-clara: #4d80e4;
  --pe-azul-escura: #0f3184;
  --pe-vermelho: #c8102e;
  --pe-vermelho-clara: #ef4d63;
  --pe-vermelho-escura: #8c0a20;
  /* O sol da bandeira. Entra como destaque, nunca como fundo de texto longo. */
  --pe-amarelo: #f5c518;
  --pe-amarelo-escura: #b98f00;
  /* A terceira faixa do arco-íris — a que faltava. */
  --pe-verde: #1f9d55;
  --pe-verde-clara: #34c77b;
  --pe-verde-escura: #14713c;
  --pe-branco: #ffffff;
  /*
   * O branco **do fio da bandeira** é um token à parte, e o motivo apareceu na
   * primeira foto de tela no tema claro: sobre fundo branco, o trecho branco do
   * fio some e a faixa parece quebrada no meio. No escuro ele é branco puro; no
   * claro vira um cinza-claro que ainda lê como "o branco da bandeira" e
   * continua desenhando a faixa inteira.
   */
  --pe-fio-branco: var(--pe-branco);

  /* O vermelho da bandeira é a cor de ação: é ele que vira botão principal. */
  --marca: var(--pe-vermelho);
  --marca-clara: var(--pe-vermelho-clara);
  --marca-escura: var(--pe-vermelho-escura);
  /* A cor do texto por cima da cor da marca. Vira preto sozinha quando o
     artista escolhe uma cor clara para a página dele (ver core/cores.js). */
  --texto-na-marca: #fff;
  /* A assinatura da casa. NÃO entra na paleta do artista: o vermelho da RofSom
     no canto é o que diz ao fã em que plataforma ele está, e é a única marca
     que a página do artista não engole. */
  --marca-casa: var(--pe-vermelho);
  /* O verde do arco-íris é o "deu certo" — antes era um verde qualquer, de
     fora da bandeira, e ele aparece em selo, aviso e confirmação o dia inteiro:
     era a cor mais vista da casa que não era de Pernambuco. */
  --ok: var(--pe-verde);
  /* O amarelo do sol também é o tom de atenção — uma cor a menos na tela. */
  --atencao: var(--pe-amarelo);
  /*
   * ── O roxo, e por que ele **não** se chama `--pe-roxo` (05/09/2026) ───────
   *
   * O prefixo `--pe-` quer dizer bandeira de Pernambuco, e roxo não está lá.
   * Ele entra a pedido do dono da casa para um papel que nenhuma cor da
   * bandeira consegue segurar sem mentir: **esperando decisão de gente**.
   *
   * Isso era amarelo, junto com "fora do ar" e "rascunho" — e as duas coisas
   * não são a mesma. Amarelo é *"olha isto, pode estar errado"*; "em análise" é
   * *"está certo, falta alguém decidir"*. Quem varre a tela procurando o que
   * fazer precisa distinguir o problema da fila.
   *
   * Fica de fora da paleta do artista, como o azul de estado: a fila é da casa,
   * não da página de ninguém.
   */
  --roxo: #7c3aed;
  --roxo-clara: #c9b3fb;
  --roxo-escura: #5b21b6;
  --erro: #ef4444;
  --aovivo: #ef4444;

  /*
   * ── Os tons de sentido quando viram **texto** (05/09/2026) ────────────────
   *
   * `--ok`, `--atencao` e `--erro` são cores de **fundo cheio** — botão, ponto,
   * borda. Selo e recado usam a mesma cor de outro jeito: fundo translúcido com
   * o texto na própria cor, e aí a cor do fundo e a do texto têm de andar
   * juntas **e mudar com o tema**.
   *
   * ⚠️ Elas estavam escritas direto na regra, com o tom claro do tema escuro, e
   * não havia nada para o tema claro. O relato de 05/09/2026 é literal: *"na
   * página de Últimos cadastros tem pill de ativo que está com fundo verde
   * claro e letra verde claro, não dá para ver direito"* — verde-claro sobre
   * verde-claro sobre branco. Valia para os quatro selos, para o erro de campo
   * de formulário e para as regras de senha: 64 lugares nas telas.
   *
   * Como token, cada tema diz o seu par uma vez e todos os 64 acertam juntos.
   */
  --ok-fundo: rgba(31, 157, 85, 0.18);
  --ok-texto: #86efac;
  --atencao-fundo: rgba(245, 197, 24, 0.18);
  --atencao-texto: #f8dc72;
  --erro-fundo: rgba(239, 68, 68, 0.16);
  --erro-texto: #fca5a5;
  /* O azul da bandeira como informação: "no ar", "publicado", "em análise" —
     estado que não é acerto nem alarme, e que hoje saía em cinza. */
  --info-fundo: rgba(26, 79, 189, 0.26);
  --info-texto: #a9c4f5;
  /* O roxo da espera: "em análise", "aguardando aprovação", "pendente". */
  --analise-fundo: rgba(124, 58, 237, 0.26);
  --analise-texto: var(--roxo-clara);
  --marca-fundo: rgba(200, 16, 46, 0.18);

  --raio: 14px;
  --raio-p: 9px;
  --sombra: 0 10px 30px rgba(0, 0, 0, 0.35);
  /* O cabeçalho é translúcido; a cor precisa acompanhar o tema da página do
     artista, senão fica uma faixa escura em cima de uma página clara. */
  --fundo-topo: rgba(11, 11, 15, 0.92);

  /* A página ocupa a largura toda da tela — inclusive no painel e no admin. O
     que sobra de conforto de leitura vem da respiração lateral, que cresce com
     a tela em vez de uma caixa centralizada de largura fixa: na telona do
     escritório o admin vê a tabela inteira sem rolagem, e no celular a coluna
     útil não perde 36 px para margem. */
  --largura: 100%;
  --respiro: clamp(12px, 2.2vw, 40px);

  --toque: 44px;
}

* { box-sizing: border-box; }

/*
 * `hidden` tem que esconder — sempre.
 *
 * O navegador aplica `display: none` ao atributo `hidden` com a força de uma
 * regra de elemento; qualquer `.classe { display: flex }` desta folha ganha
 * dela. Foi o que aconteceu com o convite de instalar: ele nasce `hidden`, mas
 * `.aviso { display: flex }` o mostrava assim mesmo — e o × "não funcionava",
 * porque o JavaScript remarcava um `hidden` que a folha já estava ignorando.
 *
 * O `!important` é o remédio certo aqui, e não um atalho: esconder é a única
 * coisa que `hidden` faz, e nada nesta folha tem motivo para discordar.
 */
[hidden] { display: none !important; }

/* Avisa o navegador que a casa é escura: com isto o player de áudio nativo, o
   menu de `select` e a barra de rolagem vêm na versão escura, em vez de abrir
   um retângulo branco no meio da tela. */
:root { color-scheme: dark; }

/* ───────────────────────── Tema claro (opcional) ─────────────────────────
 *
 * O escuro continua sendo o padrão, e o motivo não mudou: o uso é noturno —
 * fã no meio do show, artista no camarim. Mas tela escura no sol do meio-dia
 * é ilegível, e quem administra o painel passa a tarde nele.
 *
 * Então é **opção**, guardada no aparelho (`public/js/tema.js`) e aplicada
 * pelo atributo `data-tema` no `<html>`. Só as variáveis mudam: nenhuma regra
 * abaixo precisa saber que existe um segundo tema, e é isso que impede o
 * claro de virar uma segunda folha de estilo para manter em dobro.
 *
 * As cores da bandeira **não** mudam de valor — mudam de papel: no claro,
 * texto sobre azul precisa do tom escuro, senão o link some no branco.
 */
:root[data-tema='claro'] {
  color-scheme: light;

  --fundo: #f7f7fb;
  --fundo-2: #ffffff;
  --fundo-3: #ececf3;
  --borda: #d8d8e2;
  --texto: #14141c;
  --texto-2: #3f3f52;
  --texto-3: #6b6b80;

  /* Sobre branco, o tom claro do vermelho não tem contraste para texto: o
     botão continua com o vermelho cheio, e o que era "clara" vira o escuro. */
  --marca-clara: var(--pe-vermelho-escura);
  --pe-azul-clara: var(--pe-azul-escura);
  --pe-fio-branco: #cfd6e2;

  --sombra: 0 10px 30px rgba(20, 20, 28, 0.10);
  --fundo-topo: rgba(255, 255, 255, 0.92);

  /*
   * O outro lado do par de sentido. Sobre branco o tom claro simplesmente some,
   * então o fundo fica **mais** leve e o texto vai para o tom escuro da mesma
   * cor — a leitura muda, a cor não.
   *
   * ⚠️ O amarelo é o único que não usa o token da bandeira: mesmo o
   * `--pe-amarelo-escura` (#b98f00) sobre o amarelo pálido dá cerca de 3,3:1, e
   * o selo é 11 px em caixa alta com espaçamento — o tamanho em que 3,3 não se
   * lê. O tom aqui é escurecido até passar de 6:1. Amarelo é a cor mais difícil
   * de virar texto, e fingir que não é seria repetir o defeito de origem.
   */
  --ok-fundo: rgba(31, 157, 85, 0.14);
  --ok-texto: var(--pe-verde-escura);
  --atencao-fundo: rgba(245, 197, 24, 0.22);
  --atencao-texto: #6b5000;
  --erro-fundo: rgba(200, 16, 46, 0.12);
  --erro-texto: var(--pe-vermelho-escura);
  --info-fundo: rgba(26, 79, 189, 0.12);
  --info-texto: var(--pe-azul-escura);
  --analise-fundo: rgba(124, 58, 237, 0.13);
  --analise-texto: var(--roxo-escura);
  --marca-fundo: rgba(200, 16, 46, 0.12);
}

/* ── O escuro é o padrão, e o sistema não vota (23/08/2026) ────────────────
 *
 * Aqui havia um `@media (prefers-color-scheme: light)` que virava a casa
 * inteira no claro para quem nunca tinha escolhido nada — e a maioria nunca
 * escolhe. Na prática o padrão da casa era o do aparelho, e como celular sai da
 * loja no claro, quem abria a RofSom pela primeira vez no celular via a casa
 * clara: outra identidade, outro contraste, e o botão de tema aparentemente
 * "invertido" (o desenho é feito para o escuro, e é nele que a bandeira e o
 * vermelho da marca funcionam).
 *
 * Agora **claro é escolha, e só escolha** — o `[data-tema='claro']` acima. Quem
 * quiser o claro aperta o botão uma vez e o aparelho lembra; quem não apertar
 * nada tem a casa como ela foi desenhada. De quebra some a cópia da paleta:
 * eram duas listas iguais de variáveis para manter em dobro.
 */

/* O botão de trocar: discreto, no cabeçalho e no rodapé. */
.tema-botao {
  background: transparent;
  border: 1px solid var(--borda);
  color: var(--texto-2);
  border-radius: var(--raio-p);
  min-height: 36px;
  padding: 6px 12px;
  font: inherit;
  font-size: 14px;
  cursor: pointer;
}
.tema-botao:hover { background: var(--fundo-2); }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--fundo);
  color: var(--texto);
  font: 400 16px/1.6 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }
a { color: var(--marca-clara); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4 { line-height: 1.25; margin: 0 0 12px; font-weight: 600; letter-spacing: -0.01em; }
h1 { font-size: clamp(28px, 5vw, 44px); }
h2 { font-size: clamp(22px, 3.5vw, 30px); }
h3 { font-size: 19px; }
strong, b { font-weight: 600; }
p { margin: 0 0 14px; }

.miudo { color: var(--texto-3); font-size: 13px; margin: 0; }
.olho { color: var(--marca-clara); font-weight: 600; text-transform: uppercase; letter-spacing: 0.12em; font-size: 12px; margin: 0 0 8px; }
.chamada { color: var(--texto-2); font-size: 18px; }
.centro { text-align: center; }
.estreita { max-width: 640px; margin-inline: auto; }

/* O link que só aparece para quem navega por teclado. */
.pular { position: absolute; left: -9999px; }
.pular:focus { left: 12px; top: 12px; z-index: 99; background: var(--marca); color: var(--texto-na-marca); padding: 10px 16px; border-radius: var(--raio-p); }

:focus-visible { outline: 3px solid var(--pe-azul-clara); outline-offset: 2px; }

/* ───────────────────────────── Estrutura ───────────────────────────── */

.faixa { width: var(--largura); margin-inline: auto; padding-inline: var(--respiro); }

.topo {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--fundo-topo);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--borda);
}

/*
 * O fio da bandeira, colado no alto de toda tela.
 *
 * **Ele virou a bandeira inteira** (15/08/2026). Era azul-branco-vermelho, o
 * que lembrava meia dúzia de bandeiras do mundo; agora é a leitura da de
 * Pernambuco de cima para baixo — o **campo azul**, o **arco-íris de vermelho,
 * amarelo e verde**, o **branco** de baixo e a **cruz vermelha**. O arco-íris é
 * o que ninguém confunde: é o elemento que faz o pernambucano reconhecer a
 * bandeira de longe, e agora ele está em toda tela da casa.
 *
 * Fica no cabeçalho, que é da casa, e usa `--pe-*` em vez de `--marca` de
 * propósito: na página do artista a paleta é dele e o resto da tela muda de
 * cor, mas o fio permanece — é a assinatura do estado, pela mesma razão que
 * `--marca-casa` não entra na paleta do artista.
 *
 * 3 px: reconhecível de relance, invisível como ruído. Some na impressão junto
 * com o resto do cabeçalho.
 */
.topo::before,
.fio-pe {
  content: '';
  display: block;
  height: 3px;
  background: linear-gradient(
    to right,
    var(--pe-azul) 0 30%,
    var(--pe-vermelho) 30% 42%,
    var(--pe-amarelo) 42% 54%,
    var(--pe-verde) 54% 66%,
    var(--pe-fio-branco) 66% 88%,
    var(--pe-vermelho) 88% 100%
  );
}
/* Duas linhas: navegação em cima, rádio da casa embaixo. O cabeçalho ficou mais
   alto de propósito — ele deixou de ser só um menu e passou a ser o painel da
   emissora, que acompanha o visitante por todas as telas. */
.topo-linha { display: flex; align-items: center; gap: 18px; min-height: 68px; flex-wrap: wrap; }

/*
 * O cabeçalho do painel, do admin e da vitrine da produtora (15/08/2026).
 *
 * Aqui é **uma linha só** — não há a faixa da rádio embaixo —, e por isso ele
 * usava `.faixa` pelada em vez de `.topo-linha`. Só que `.faixa` é um bloco
 * comum: sem `display:flex`, a marca e as ações empilhavam **coladas**, sem
 * respiro vertical nenhum, com os botões encostados no fio da bandeira e no
 * conteúdo da tela. A régua do celular já tentava consertar por cima
 * (`.topo .faixa { gap: … }`), mas `gap` em bloco não faz nada — o que faltava
 * era a regra de base.
 *
 * A marca empurra as ações para a direita (`margin-right: auto`) em vez de as
 * ações se puxarem para lá: assim a linha continua certa quando o nome de quem
 * está logado quebra para baixo em tela estreita.
 */
.topo-painel .faixa {
  display: flex;
  align-items: center;
  gap: 10px 18px;
  min-height: 64px;
  padding-block: 12px;
  flex-wrap: wrap;
}
.topo-painel .marca { margin-right: auto; }
/* Quem está logado é informação, não ação: fica antes dos botões, separado
   deles por um respiro maior que o que separa botão de botão. */
.topo-painel .acoes { gap: 8px; }
.topo-painel .acoes .miudo { margin-right: 6px; white-space: nowrap; }

/* Fio de carregamento da troca de tela (ver `navegacao.js`): fica colado na
   borda de baixo do cabeçalho e não empurra nada. */
.carga { position: absolute; left: 0; right: 0; bottom: -2px; height: 2px; overflow: hidden; }
.carga::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, var(--pe-azul), var(--pe-vermelho), var(--pe-amarelo), var(--pe-verde), transparent);
  animation: carga 900ms linear infinite;
}
@keyframes carga { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

/* Âncora não pode nascer escondida atrás do cabeçalho grudado no topo. */
html { scroll-padding-top: 150px; }

.marca { display: flex; align-items: baseline; gap: 7px; text-decoration: none; }
.marca:hover { text-decoration: none; }
.marca-nome { font-weight: 700; font-size: 21px; color: var(--marca-casa); letter-spacing: -0.02em; }
.marca-sub { font-size: 12px; color: var(--texto-3); text-transform: uppercase; letter-spacing: 0.18em; }
/* A logo que o master enviou. Altura travada e largura automática: o cabeçalho
   não pode mudar de tamanho conforme a arte, senão trocar a logo entorta o
   menu inteiro. `width/height` no HTML só reservam o espaço enquanto carrega. */
.marca-logo { height: 34px; width: auto; max-width: 210px; display: block; }

/* O atalho de instalar, no cabeçalho. Mesmo tamanho do botão de tema: são
   vizinhos e dois pesos diferentes ali brigam pela atenção sem motivo. */
.instalar-atalho {
  display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; min-height: 0; padding: 0;
  background: var(--fundo-2); border: 1px solid var(--borda); border-radius: var(--raio-p);
  cursor: pointer;
}
.instalar-atalho:hover { border-color: var(--marca); }
.instalar-atalho img { border-radius: 6px; display: block; }
@media (max-width: 640px) { .marca-logo { height: 28px; max-width: 150px; } }

.menu { display: flex; gap: 4px; flex: 1; flex-wrap: wrap; }
.menu a { color: var(--texto-2); padding: 9px 12px; border-radius: var(--raio-p); font-weight: 500; font-size: 15px; }
.menu a:hover, .menu a.ativo { background: var(--fundo-2); color: var(--texto); text-decoration: none; }

/* ── O hambúrguer ──
 *
 * Ele **não existe no computador**: lá sobra largura e um menu escondido só
 * cobraria um clique a mais por navegação. Ele aparece na régua do celular, e
 * `.menu-extra` são os itens que só fazem sentido de dentro dele — na tela
 * grande eles ficariam empurrando a busca para fora da linha.
 *
 * Três traços desenhados em CSS, sem imagem e sem fonte de ícone: é o desenho
 * que todo mundo reconhece, e um arquivo a menos para carregar no 3G.
 */
.hamburguer { display: none; }
.menu-extra { display: none; }
.hamburguer span,
.hamburguer span::before,
.hamburguer span::after {
  display: block;
  width: 18px;
  height: 2px;
  border-radius: 2px;
  background: var(--texto-2);
  transition: transform 140ms ease, opacity 140ms ease;
}
.hamburguer span::before, .hamburguer span::after { content: ''; position: absolute; }
.hamburguer span::before { transform: translateY(-6px); }
.hamburguer span::after { transform: translateY(6px); }
/* Aberto, os traços viram um ×: o mesmo botão fecha, e o desenho diz isso. */
.hamburguer[aria-expanded='true'] span { background: transparent; }
.hamburguer[aria-expanded='true'] span::before { transform: rotate(45deg); }
.hamburguer[aria-expanded='true'] span::after { transform: rotate(-45deg); }
@media (prefers-reduced-motion: reduce) {
  .hamburguer span, .hamburguer span::before, .hamburguer span::after { transition: none; }
}

.acoes { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.acoes-centro { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }

.busca input {
  background: var(--fundo-2);
  border: 1px solid var(--borda);
  color: var(--texto);
  border-radius: 999px;
  padding: 9px 16px;
  min-width: 200px;
  font-size: 14px;
}

.secao { width: var(--largura); margin-inline: auto; padding: 42px var(--respiro); }
.secao + .secao { padding-top: 0; }
.secao-cabeca { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 20px; flex-wrap: wrap; }

/* ── Celular e tablet: cabeçalho e rodapé centrados (23/08/2026) ───────────
 *
 * No computador a linha é longa e o alinhamento à esquerda é o certo — o olho
 * varre da esquerda para a direita e cada bloco começa no mesmo eixo. Em tela
 * estreita isso deixa de valer: os blocos **quebram para baixo** e viram uma
 * pilha de larguras diferentes encostada num canto, com um vão irregular do
 * outro lado. Empilhado, o que alinha é o centro.
 *
 * A régua é 1024 px, e não os 720 px do resto da folha, porque o tablet cai
 * exatamente no meio: ele ainda mostra o menu inteiro na linha (o hambúrguer só
 * entra aos 720), mas já é estreito o bastante para o rodapé e as ações do topo
 * quebrarem. Era ali que o desalinhamento mais aparecia.
 *
 * O cabeçalho do painel e do admin fica de fora de propósito: lá a marca à
 * esquerda e o "quem está logado" à direita são a orientação da tela de
 * trabalho — centralizar tiraria a referência de quem passa o dia nela. */
@media (max-width: 1024px) {
  /* Quando os itens do topo quebram, a sobra se divide dos dois lados. */
  .topo-linha { justify-content: center; }
  .menu { justify-content: center; }

  .rodape .faixa { justify-items: center; text-align: center; }
  .rodape nav { justify-content: center; }
  /* O bloco da marca e o do copyright são texto corrido: centrar a caixa sem
     centrar o texto dentro dela deixaria o parágrafo torto dentro de um bloco
     certo — que é o mesmo defeito, um nível abaixo. */
  .rodape .faixa > div,
  .rodape .faixa > p { text-align: center; }
}

/* O mesmo fio do cabeçalho fecha a página embaixo: a bandeira emoldura. */
.rodape { border-top: 3px solid transparent; border-image: linear-gradient(to right, var(--pe-azul) 0 30%, var(--pe-vermelho) 30% 42%, var(--pe-amarelo) 42% 54%, var(--pe-verde) 54% 66%, var(--pe-fio-branco) 66% 88%, var(--pe-vermelho) 88% 100%) 1; margin-top: 60px; padding: 34px 0; background: var(--fundo-2); }
.rodape .faixa { display: grid; gap: 18px; }
.rodape nav { display: flex; gap: 16px; flex-wrap: wrap; }
.rodape nav a { color: var(--texto-2); font-size: 14px; }

/* ───────────────────────────── Botões ───────────────────────────── */

.botao {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--toque);
  padding: 11px 20px;
  border-radius: var(--raio-p);
  border: 1px solid transparent;
  background: var(--marca);
  color: var(--texto-na-marca);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
  transition: filter 0.15s, transform 0.05s;
}
.botao:hover { filter: brightness(1.1); text-decoration: none; }
.botao:active { transform: translateY(1px); }
.botao[disabled] { opacity: 0.5; cursor: not-allowed; }

.botao.fantasma { background: transparent; border-color: var(--borda); color: var(--texto); }
.botao.fantasma:hover { background: var(--fundo-2); }
/*
 * ⚠️ O botão de apagar usa o vermelho **escuro** da bandeira, e não o `--erro`
 * (05/09/2026). Medido: `#ef4444` com texto branco dá **3,76:1**, abaixo do
 * mínimo de 4,5 — e logo no botão que mais precisa ser lido antes de ser
 * apertado. O tom escuro dá 9,3:1 e ainda se distingue do botão comum, que é o
 * vermelho médio: ação destrutiva fica visivelmente mais grave que ação normal.
 * `--erro` continua servindo de borda, ponto e fundo translúcido, onde não há
 * texto branco em cima.
 */
.botao.perigo { background: var(--pe-vermelho-escura); }
.botao.sucesso { background: var(--ok); color: #04240f; }
.botao.pequeno { min-height: 36px; padding: 7px 14px; font-size: 14px; }
.botao.largo { width: 100%; }

/*
 * O azul da bandeira é a **segunda** ação da tela — "ver a agenda" ao lado de
 * "contratar", "conferir" ao lado de "pagar". Duas cores fortes disputando o
 * mesmo peso ensinam o olho a ignorar as duas; aqui o vermelho continua sendo o
 * que se aperta, e o azul é o caminho alternativo que não pode virar cinza.
 *
 * Não usa `--marca`: na página do artista a paleta é dele, e o azul do estado
 * some junto com o resto — como deve ser. Este é o azul da casa.
 */
.botao.estado { background: var(--pe-azul); color: #fff; }
/*
 * O hover é o `brightness(1.1)` de todo botão da casa, e não uma troca para o
 * azul claro. Medido: `#4d80e4` com texto branco dá **3,8:1** — o botão perdia
 * legibilidade justamente quando o ponteiro estava em cima dele. Clarear em
 * 10% mantém acima de 6:1 e funciona igual nos dois temas, sem uma segunda
 * declaração para cada um.
 */

/* O sol: chamada de atenção pontual (contador de vagas, selo de fundador). */
.botao.sol { background: var(--pe-amarelo); color: #2b2100; }

/* ───────────────────────────── Avisos ───────────────────────────── */

.aviso {
  margin: 14px var(--respiro);
  padding: 13px 18px;
  border-radius: var(--raio-p);
  display: flex;
  align-items: center;
  gap: 12px;
  justify-content: space-between;
  border: 1px solid var(--borda);
  background: var(--fundo-2);
  font-size: 15px;
}
.aviso-ok { border-color: rgba(34, 197, 94, 0.45); background: rgba(34, 197, 94, 0.12); }
/* O amarelo do sol da bandeira, o mesmo de `--atencao`. */
.aviso-atencao { border-color: rgba(245, 197, 24, 0.45); background: rgba(245, 197, 24, 0.12); }
.aviso-erro { border-color: rgba(239, 68, 68, 0.5); background: rgba(239, 68, 68, 0.12); }
.aviso-fixo { margin-inline: 0; border-radius: 0; }
.aviso .fechar { background: none; border: 0; color: inherit; font-size: 22px; cursor: pointer; line-height: 1; padding: 0 6px; }
/* O ícone do aplicativo dentro do convite: é o mesmo desenho que vai ficar na
   tela do celular, e reconhecê-lo é metade da decisão de instalar. */
.instalar-icone { border-radius: 10px; flex: none; }

.lista-erros { text-align: left; background: var(--fundo-2); border-radius: var(--raio-p); padding: 14px 18px 14px 34px; }

/* ───────────────────────────── Cartões ───────────────────────────── */

.cartao {
  background: var(--fundo-2);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 20px;
}
.cartao + .cartao { margin-top: 16px; }
/* O cartão que a pessoa acabou de escolher numa lista de opções — hoje, o
   artista confirmado na importação de discografia. */
.cartao.destacado { border-color: var(--marca); }

.grade { display: grid; gap: 16px; }
.grade-2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grade-3 { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
.grade-4 { grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); }

.cartao-artista {
  background: var(--fundo-2);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  overflow: hidden;
  display: block;
  color: inherit;
  transition: transform 0.15s, border-color 0.15s;
}
.cartao-artista:hover { transform: translateY(-3px); border-color: var(--marca); text-decoration: none; }
.cartao-artista .foto { aspect-ratio: 1; background: var(--fundo-3) center/cover; }
.cartao-artista .corpo { padding: 13px 15px 16px; }
.cartao-artista h3 { font-size: 16px; margin-bottom: 3px; }

.selo {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 4px 9px;
  border-radius: 999px;
  background: var(--fundo-3);
  color: var(--texto-2);
}
.selo.marca { background: var(--marca-fundo); color: var(--marca-clara); }

/* O selo de verificado é azul em qualquer página, inclusive nas que o artista
   pintou de outra cor: selo que muda de cor com o tema deixa de ser selo. O
   `vertical-align` alinha o desenho com a linha de base do nome ao lado. */
/* O selo sobe e encosta no nome (23/08/2026): com `-0.18em` ele descia abaixo da
   linha do texto e ficava parecendo um adesivo solto ao lado. Agora acompanha a
   altura das maiúsculas, que é onde o público espera vê-lo. */
.verificado { color: #1d9bf0; display: inline-block; vertical-align: 0.08em; margin-left: -0.08em; flex: none; }
/* Fundador é distinção da casa: leva o amarelo do sol da bandeira, e não a cor
   do artista — senão o selo mudaria de sentido de página para página. */
.selo.fundador { background: var(--atencao-fundo); color: var(--atencao-texto); border: 1px solid rgba(245, 197, 24, 0.35); }
.selo.ok { background: var(--ok-fundo); color: var(--ok-texto); }
.selo.atencao { background: var(--atencao-fundo); color: var(--atencao-texto); }
.selo.erro { background: var(--erro-fundo); color: var(--erro-texto); }
/* O azul de informação: estado que não é acerto nem alarme ("no ar"). Era
   cinza, que é a cor de "não importa" — e "no ar" importa. */
.selo.info { background: var(--info-fundo); color: var(--info-texto); }
/* O roxo da espera: "em análise", "aguardando aprovação". Era amarelo, junto
   com "fora do ar" — e problema e fila não são a mesma coisa. Medido: 7,38:1 no
   tema claro e 7,93:1 no escuro. */
.selo.analise { background: var(--analise-fundo); color: var(--analise-texto); }

/* A pulsação do AO VIVO: é o elemento que precisa ser visto de longe, com o
   celular na mão, no escuro de uma casa de show. */
.selo.aovivo { background: var(--aovivo); color: #fff; }
.selo.aovivo::before { content: ''; width: 7px; height: 7px; border-radius: 50%; background: #fff; animation: pulsa 1.4s infinite; }
@keyframes pulsa { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
@media (prefers-reduced-motion: reduce) { .selo.aovivo::before { animation: none; } }

/* ───────────────────────────── Formulários ───────────────────────────── */

.campo { margin-bottom: 16px; }
.campo label { display: block; font-weight: 500; font-size: 14px; margin-bottom: 6px; color: var(--texto-2); }
.campo .dica { color: var(--texto-3); font-size: 12.5px; margin-top: 5px; }
.campo .erro { color: var(--erro-texto); font-size: 13px; margin-top: 5px; }
.campo-grupo > .dica { color: var(--texto-3); font-size: 12.5px; margin: -2px 0 12px; }
/* A resposta que chega enquanto se digita (o CEP encontrado, o @ livre). Cor é
   reforço, nunca a informação sozinha: o texto sempre diz o que aconteceu. */
.dica-ok { color: var(--ok) !important; }
.dica-erro { color: var(--erro-texto) !important; }

/* Campo com endereço na frente: `rofsom.app.br/` e, do lado, o @ do artista.
   Mostrar o endereço inteiro montado é o que faz ele entender que está
   escolhendo a URL da própria página, não um apelido. */
.campo-prefixo { display: flex; align-items: stretch; border: 1px solid var(--borda); border-radius: var(--raio-p); background: var(--fundo-2); overflow: hidden; }
.campo-prefixo .prefixo { display: flex; align-items: center; padding: 0 4px 0 12px; color: var(--texto-3); font-size: 14px; white-space: nowrap; }
.campo-prefixo input { border: 0; background: transparent; border-radius: 0; flex: 1; min-width: 0; padding-left: 0; }
.campo-prefixo:focus-within { border-color: var(--marca); }

input[type=text], input[type=email], input[type=password], input[type=url], input[type=tel],
input[type=date], input[type=time], input[type=number], input[type=search], input[type=file], select, textarea {
  width: 100%;
  min-height: var(--toque);
  padding: 11px 14px;
  border-radius: var(--raio-p);
  border: 1px solid var(--borda);
  background: var(--fundo-3);
  color: var(--texto);
  font: inherit;
}
textarea { min-height: 120px; resize: vertical; }
input:focus, select:focus, textarea:focus { border-color: var(--marca); outline: none; }
input::placeholder, textarea::placeholder { color: var(--texto-3); }

.linha { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

.marcar { display: flex; align-items: flex-start; gap: 10px; padding: 9px 0; cursor: pointer; }
.marcar input { width: 20px; height: 20px; min-height: 0; margin-top: 2px; accent-color: var(--marca); }
.marcar span { font-size: 15px; color: var(--texto-2); }

fieldset { border: 1px solid var(--borda); border-radius: var(--raio-p); padding: 14px 16px; margin: 0 0 16px; }
legend { padding-inline: 8px; font-weight: 600; font-size: 14px; color: var(--texto-2); }

/* ───────────────────────────── Tabelas ───────────────────────────── */

.rolagem { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table { width: 100%; border-collapse: collapse; font-size: 14.5px; }
th, td { text-align: left; padding: 11px 12px; border-bottom: 1px solid var(--borda); vertical-align: middle; }
th { color: var(--texto-3); font-size: 12px; text-transform: uppercase; letter-spacing: 0.07em; font-weight: 600; }
tbody tr:hover { background: var(--fundo-2); }
/*
 * A coluna de ações (15/08/2026).
 *
 * Cada botão vem de um formulário `inline` próprio — é `POST`, não link —, e o
 * único espaço entre eles era o espaço em branco entre as tags. Com duas ações
 * passava; com "ver a página, ver o painel, editar dados, excluir, verificar,
 * destacar, suspender" a coluna virou uma parede de botões colados, que é onde
 * o clique erra o alvo. `flex` com `gap` dá o respiro, e a quebra em duas linhas
 * é melhor que o `nowrap` de antes, que esticava a tabela para fora da tela.
 */
td.acoes-tabela {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  white-space: normal;
}
/* O `style="display:inline"` está escrito na tela e ganharia da folha; aqui o
   `!important` é o que faz o formulário se comportar como item da linha. */
td.acoes-tabela form { display: inline-flex !important; align-items: center; gap: 6px; }

/* ───────────────────────────── Painel ───────────────────────────── */

.painel-corpo { display: grid; grid-template-columns: 232px 1fr; gap: 24px; width: var(--largura); margin-inline: auto; padding: 22px var(--respiro) 60px; align-items: start; }
/*
 * ── O menu gruda **abaixo** do cabeçalho, medido e não chutado (05/09/2026) ──
 *
 * Era `top: 82px`, um número escrito à mão que valia enquanto o cabeçalho
 * tivesse uma linha. Ele pode ter duas: `.topo-painel .faixa` é `flex-wrap:
 * wrap`, e no aplicativo instalado entram os três botões de navegação — aí a
 * faixa quebra, o cabeçalho passa dos 82 px e o menu gruda **dentro** dele.
 * Foi o relato: *"quando rolo a tela para baixo os ícones do menu ficam por
 * cima do header"*.
 *
 * `--altura-topo` é medida pelo `geral.js` a cada mudança de tamanho do
 * cabeçalho. O `82px` do `var()` continua aqui como rede: sem JavaScript o
 * menu volta ao que era, que é errado só quando o cabeçalho quebra.
 *
 * E `z-index: 1` explícito: o cabeçalho é 40 e o menu era `auto`, o que já
 * bastava — mas "já bastava" é o tipo de coisa que a próxima regra desfaz sem
 * ninguém notar. Escrito, a ordem de pintura para de ser sorte.
 */
.painel-menu {
  position: sticky;
  top: calc(var(--altura-topo, 78px) + 4px);
  z-index: 1;
  display: grid;
  gap: 3px;
}
.painel-menu a { display: flex; align-items: center; gap: 11px; padding: 11px 14px; border-radius: var(--raio-p); color: var(--texto-2); font-weight: 500; min-height: var(--toque); }
.painel-menu a:hover { background: var(--fundo-2); text-decoration: none; }
.painel-menu a.ativo { background: var(--marca); color: var(--texto-na-marca); }
/* Os ícones do menu são emoji desde 16/08/2026 (ver `rotas/painel/index.js`),
   e emoji não se apaga: o `opacity` que suavizava o símbolo geométrico deixava
   o desenho colorido sujo, inclusive sobre o vermelho da linha aberta. */
.painel-menu .icone { width: 20px; text-align: center; font-size: 15px; line-height: 1; }
/* O submenu da seção aberta: recuado, menor e com um fio à esquerda ligando os
   filhos ao pai — sem o fio, uma lista recuada parece uma lista quebrada. */
.painel-menu a.sub {
  margin-left: 14px;
  padding-block: 8px;
  font-size: 13.5px;
  border-left: 2px solid var(--borda);
  border-radius: 0 var(--raio-p) var(--raio-p) 0;
  min-height: 34px;
}
.painel-menu a.sub.ativo { background: var(--fundo-2); color: var(--texto); border-left-color: var(--marca); }
.painel-conteudo { min-width: 0; }

/* ── Voltar, avançar e atualizar dentro do aplicativo (05/09/2026) ────────
   Instalado, o app roda em `display: standalone` e **não tem barra do
   navegador** — de propósito, é o que o faz parecer aplicativo. Só que no admin
   isso deixa a equipe sem voltar e sem atualizar. Estes três botões existem no
   HTML sempre e **só aparecem em modo aplicativo**: no navegador seriam uma
   segunda barra de navegação em cima da que já existe.
   Trocar o `display` do manifesto resolveria para a equipe e estragaria para
   todo mundo — por isso a saída mora aqui e não lá. */
.app-nav { display: none; gap: 4px; }
@media (display-mode: standalone) { .app-nav { display: inline-flex; } }
@media (display-mode: fullscreen) { .app-nav { display: inline-flex; } }
.app-nav-botao {
  width: 30px;
  height: 30px;
  border: 1px solid var(--borda);
  border-radius: var(--raio-p);
  background: transparent;
  color: var(--texto-2);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}
.app-nav-botao:hover { background: var(--fundo-2); color: var(--texto); }

/* ── O menu que recolhe (05/09/2026) ──────────────────────────────────────
   São vinte e uma seções numa coluna de 232 px, e num notebook de 1366 px isso
   é um sexto da largura útil. Recolhido, o menu vira uma tira de ícones:
   continua navegável e devolve 170 px ao conteúdo. Quem guarda a escolha é
   `public/js/menu-recolher.js`, no atributo do `<html>` — e a guarda antes da
   primeira pintura, senão a coluna encolheria na cara de quem a recolheu. */
.menu-recolher {
  justify-self: end;
  width: 30px;
  height: 30px;
  margin-bottom: 2px;
  border: 1px solid var(--borda);
  border-radius: var(--raio-p);
  background: transparent;
  color: var(--texto-3);
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
}
.menu-recolher:hover { background: var(--fundo-2); color: var(--texto); }

@media (min-width: 861px) {
  /*
   * ── O menu rola por conta própria (05/09/2026) ────────────────────────────
   *
   * São vinte e uma seções mais os submenus da aberta, e isso passa da altura
   * da tela em notebook. Sendo `sticky`, o menu ficava preso: as últimas linhas
   * só apareciam quando a pessoa rolava **o conteúdo** até o fim, e numa tela
   * curta de conteúdo elas não apareciam nunca. Foi o relato: *"a página do
   * conteúdo só ajuda o menu quando eu rolo lá pra baixo"*.
   *
   * A altura vem da mesma medida do cabeçalho que a grude: o que sobra da tela
   * depois dele, menos um respiro embaixo para a última linha não encostar na
   * borda.
   *
   * `overscroll-behavior: contain` porque sem isso chegar ao fim do menu
   * continua rolando **a página** — o gesto vaza para trás e a pessoa perde o
   * lugar nos dois. É a mesma regra da letra da música e do seletor de emoji.
   */
  .painel-menu {
    max-height: calc(100vh - var(--altura-topo, 78px) - 28px);
    overflow-y: auto;
    overscroll-behavior: contain;
    /* Um fio de folga para a barra de rolagem não passar por cima do texto do
       item mais comprido ("Configurações", "Músicas do Suno"). */
    padding-right: 4px;
    scrollbar-width: thin;
  }

  [data-menu-recolhido] .painel-corpo { grid-template-columns: 62px 1fr; }
  [data-menu-recolhido] .painel-menu a { justify-content: center; padding-inline: 6px; gap: 0; }
  /* O rótulo sai e o ícone passa a nomear a seção sozinho — é por isso que o
     script põe um `title` em cada item ao recolher: sem ele, a tira de ícones
     vira adivinhação para quem não usa o admin todo dia. */
  [data-menu-recolhido] .painel-menu a span:not(.icone) { display: none; }
  /* O submenu não sobrevive ao recolhimento: o filho não tem ícone, e sem o
     rótulo ele seria uma linha vazia. Volta inteiro quando o menu abre. */
  [data-menu-recolhido] .painel-menu a.sub { display: none; }
  [data-menu-recolhido] .menu-recolher { justify-self: center; }
}

/* No celular o menu já é o do hambúrguer e a coluna não existe: o botão de
   recolher ali seria um controle que não controla nada. */
@media (max-width: 860px) { .menu-recolher { display: none; } }

@media (max-width: 860px) {
  .painel-corpo { grid-template-columns: 1fr; }
  /*
   * No celular o menu do painel fica **atrás do hambúrguer** (15/08/2026).
   *
   * Antes era uma barra rolável no topo — e treze seções em 360 px significam
   * que dez delas ficam fora da tela, num gesto que ainda briga com o "voltar"
   * do sistema. Fechado, o painel abre direto no conteúdo, que é o que o
   * artista veio ver; aberto, ele é uma lista de alvos grandes, um por linha.
   */
  .painel-hamburguer { display: flex; align-items: center; justify-content: center; position: relative;
    width: 38px; height: 38px; padding: 0; background: transparent; border: 1px solid var(--borda);
    border-radius: var(--raio-p); cursor: pointer; margin-bottom: 4px; }
  .painel-menu { position: static; grid-auto-flow: row; padding-bottom: 6px; }
  .painel-menu[data-fechado] { display: none; }
  .painel-menu a span:not(.icone) { font-size: 14px; }
}

.numeros { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.numero { background: var(--fundo-2); border: 1px solid var(--borda); border-radius: var(--raio); padding: 16px 18px; }
.numero .valor { font-size: 30px; font-weight: 600; letter-spacing: -0.02em; color: var(--pe-azul-clara); }
.numero .rotulo { color: var(--texto-3); font-size: 13px; }

/* ───────────────────────────── Player ───────────────────────────── */

/* `minmax(0, 1fr)` na coluna, e não o `auto` implícito (30/08/2026).
   Coluna `auto` de grade não encolhe abaixo do conteúdo mínimo dos itens — e o
   conteúdo mínimo daqui é o **nome da estação**, que é `nowrap` ("Rádio Banda
   Encaixe Perfeito" pede 211 px sozinho). Num celular de 360 px o cartão virava
   423 px: o play saía pela direita e a página inteira ganhava rolagem lateral.
   Com o mínimo em zero a linha encolhe, o nome corta com reticências (que é o
   que o `text-overflow` sempre esteve ali para fazer) e o play volta para
   dentro da tela. */
.player {
  background: linear-gradient(160deg, var(--fundo-2), var(--fundo-3));
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  padding: 18px;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 14px;
}
.player-topo { display: flex; align-items: center; gap: 14px; }
.player-capa { width: 62px; height: 62px; border-radius: 11px; background: var(--fundo-3) center/cover; flex: none; display: grid; place-items: center; font-size: 24px; }

/* ── As ondas do som (01/09/2026) ───────────────────────────────────────────
   Pedido do dono da casa: "está muito estático o player". Cinco barras que
   sobem e descem enquanto o som corre.

   **Não é a onda real.** Desenhar a onda de verdade pede a Web Audio API, que
   obriga a passar o áudio por dentro de um grafo — e um erro ali não deixa o
   enfeite feio, deixa a rádio muda. Enfeite não vale risco de silêncio.

   Cada barra tem **duração e atraso próprios**, e é isso que faz o conjunto
   parecer batida em vez de ventilador: com o mesmo tempo em todas, as cinco
   sobem juntas e o olho lê uma coisa só se mexendo.

   `currentColor` para a barra herdar a cor do contexto — no cartão da rádio e
   na linha da playlist o fundo é diferente, e uma cor fixa acertaria um e
   erraria o outro. */
.ondas { display: flex; align-items: flex-end; justify-content: center; gap: 3px; height: 26px; color: var(--marca); }
.ondas i {
  display: block;
  width: 3px;
  height: 22%;
  border-radius: 2px;
  background: currentColor;
  /* Parado, as cinco ficam baixas e iguais: é uma linha, que é o desenho certo
     para "não há som saindo daqui". */
  transition: height 0.25s ease;
  /* A animação já vem montada aqui e **desligada pelo nome**. É o que permite
     acendê-la lá embaixo mexendo só em `animation-name`: escrever o atalho
     `animation:` na regra do `tocando` reiniciaria duração e atraso para os
     valores dela, e as cinco barras subiriam juntas — foi o que aconteceu na
     primeira versão, e o resultado parecia ventilador, não batida. */
  animation: onda-som 900ms ease-in-out infinite;
  animation-name: none;
}

/* Cada barra no seu tempo. Os números são primos entre si de propósito: com
   durações que se dividem, o conjunto reencontra o mesmo desenho a cada poucos
   segundos e o olho percebe a repetição. */
.ondas i:nth-child(1) { animation-duration: 700ms; animation-delay: -200ms; }
.ondas i:nth-child(2) { animation-duration: 1100ms; animation-delay: -600ms; }
.ondas i:nth-child(3) { animation-duration: 620ms; animation-delay: -100ms; }
.ondas i:nth-child(4) { animation-duration: 980ms; animation-delay: -450ms; }
.ondas i:nth-child(5) { animation-duration: 780ms; animation-delay: -300ms; }

/* Só anda quando há som. `tocando` é a mesma classe que o resto da casa já usa
   para dizer "este é o áudio que está no ar" — inventar um segundo crachá para
   o enfeite criaria dois estados que um dia discordam.

   Só o **nome**: ver o comentário acima. */
.player.tocando .ondas i,
.playlist-item.tocando .ondas i { animation-name: onda-som; }

@keyframes onda-som {
  0%, 100% { height: 22%; }
  50% { height: 100%; }
}

/* Quem pediu menos movimento no sistema recebe a linha parada — a mesma regra
   do degradê da capa e da rolagem das âncoras. O player continua dizendo o que
   está no ar pelo botão e pela barra de progresso. */
@media (prefers-reduced-motion: reduce) {
  .player.tocando .ondas i,
  .playlist-item.tocando .ondas i { animation-name: none; }
}

/* Na linha da playlist ela é miúda: ali o assunto é o título da música, e um
   equalizador do tamanho do da rádio roubaria a linha inteira.

   E ela **só existe na faixa que está tocando**: cinco barras paradas em cada
   linha de uma lista de dez seriam cinquenta enfeites disputando a atenção com
   os títulos, que é o que a lista existe para mostrar. */
.playlist-item .ondas { display: none; height: 13px; gap: 2px; float: left; margin: 3px 7px 0 0; }
.playlist-item .ondas i { width: 2px; }
.playlist-item.tocando .ondas { display: flex; }
.player-info { min-width: 0; flex: 1; }
.player-info strong { display: block; font-size: 17px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.player-controles { display: flex; align-items: center; gap: 10px; }
.player-botao { width: 54px; height: 54px; border-radius: 50%; background: var(--marca); color: var(--texto-na-marca); border: 0; font-size: 21px; cursor: pointer; display: grid; place-items: center; }
.barra { height: 5px; background: var(--fundo-3); border-radius: 999px; overflow: hidden; }
.barra > div { height: 100%; background: var(--marca); width: 0; transition: width 1s linear; }
.player-lista { display: grid; gap: 7px; font-size: 14px; color: var(--texto-2); }

/* ── A letra do que está tocando, em sanfona (31/08/2026) ──────────────────
 *
 * Mesma cara da sanfona da playlist (`.playlist-letra`), com **uma** diferença
 * que vem do comportamento e não do gosto: aqui o painel tem teto de altura e
 * rola por dentro. Na playlist a letra é da faixa que o ouvinte escolheu e
 * fica onde ele a abriu; aqui ela fica aberta enquanto a programação troca
 * sozinha, e sem teto a página inteira daria um salto a cada música — a de
 * dois versos e a de quarenta empurrariam tudo que está embaixo do player para
 * lugares diferentes.
 *
 * `overscroll-behavior: contain` para o dedo que chega ao fim da letra no
 * celular não continuar rolando a página junto. */
.player-letra { border-top: 1px solid var(--borda); padding-top: 10px; }
.player-letra > summary {
  cursor: pointer; font-size: 12px; color: var(--texto-3);
  display: inline-flex; align-items: center; gap: 6px;
  list-style: none; user-select: none;
}
.player-letra > summary::-webkit-details-marker { display: none; }
.player-letra > summary::marker { content: ''; }
.player-letra > summary::before { content: '▸'; display: inline-block; transition: transform .15s ease; }
.player-letra[open] > summary::before { transform: rotate(90deg); }
.player-letra > summary:hover { color: var(--texto-2); }
.player-letra-corpo {
  margin-top: 8px; max-height: min(46vh, 320px);
  overflow-y: auto; overscroll-behavior: contain;
}
.player-letra-corpo > strong { display: block; font-size: 13px; margin-bottom: 4px; }
/* O crédito, entre o título e a letra: só o nome, sem link (ver
   `escreverArtista`, em `public/js/player.js`). */
.player-letra-artista { margin: 0 0 6px; }
/* `pre-line`: a quebra de linha que o artista digitou é o verso. */
.player-letra-texto { white-space: pre-line; font-size: 12.5px; line-height: 1.6; color: var(--texto-2); }
.player-letra-texto.sem-letra { color: var(--texto-3); font-style: italic; }
/* O player oficial da faixa de vídeo, fora da área visível.

   Rádio é som: o quadro não aparece para quem está ouvindo. Ele continua sendo
   **desenhado** em tamanho normal e apenas posicionado fora da tela — com
   `display:none`, `visibility:hidden` ou dimensão zero, navegador nenhum garante
   que o áudio continue tocando, e alguns descartam o quadro. Fora da tela, toca.

   `pointer-events:none` porque ninguém deve conseguir alcançá-lo por tabulação
   ou toque acidental; quem manda nele é o botão de play da rádio, pela API. */
.player-audio-yt {
  position: fixed; left: -10000px; top: 0;
  width: 320px; height: 180px;
  pointer-events: none; opacity: 0;
}
.player-audio-yt iframe { display: block; width: 100%; height: 100%; border: 0; }

/* ─────────────────── Calendário da agenda ─────────────────── */

/* Sete colunas fixas, sempre — calendário que reflui em três colunas no celular
   deixa de ser calendário. Em tela estreita as células encolhem e mostram só o
   número e um risco por show; o nome de quem toca fica na lista, logo abaixo. */
.calendario {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 4px;
  margin-top: 8px;
}
.calendario-cabeca {
  text-align: center;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--texto-3);
  font-weight: 600;
  padding-bottom: 4px;
}
.calendario-dia {
  min-height: 96px;
  padding: 6px;
  border: 1px solid var(--borda);
  border-radius: var(--raio-p);
  background: var(--fundo-2);
  display: flex;
  flex-direction: column;
  gap: 3px;
  overflow: hidden;
}
.calendario-dia.fora { opacity: 0.35; }
.calendario-dia.hoje { border-color: var(--marca); }
.calendario-dia.tem-show { background: var(--fundo-3); }
.calendario-numero { font-size: 12px; font-weight: 600; color: var(--texto-2); }
.calendario-dia.hoje .calendario-numero { color: var(--marca-clara); }
.calendario-show {
  display: block;
  font-size: 11.5px;
  line-height: 1.25;
  padding: 3px 5px;
  border-radius: 5px;
  background: var(--marca);
  color: var(--texto-na-marca);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.calendario-show:hover { text-decoration: none; filter: brightness(1.1); }
.calendario-ponto {
  display: inline-block;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  margin-right: 3px;
  vertical-align: middle;
}

/* ─────────────────── Lista para contratantes ─────────────────── */

.contratar-topo { display: flex; gap: 14px; align-items: flex-start; }
.contratar-foto {
  width: 78px;
  height: 78px;
  flex: none;
  border-radius: var(--raio-p);
  background: var(--fundo-3) center/cover;
}
.contratar-item .botao { flex: 1 1 auto; }

/* ─────────────────── Rádio da casa (dentro do cabeçalho) ─────────────────── */

/* Faixa fina, escura, dentro do cabeçalho: é a emissora tocando, não um card
   de conteúdo. Nome de música e de artista não aparecem de propósito — quem
   liga o rádio liga na estação, não numa faixa.
   A cor é sempre a da casa (`--marca-casa`), inclusive na página de um artista:
   quem está no ar ali é a RofSom, e pintar a estação com a cor do artista faria
   parecer que é a rádio dele. */
.geral { background: linear-gradient(180deg, var(--fundo-2), var(--fundo)); border-top: 1px solid var(--borda); }
/* Na página de um artista quem toca é a rádio dele: a faixa da casa sai da
   frente. A regra é de CSS, e não só de JavaScript, porque sem ela quem navega
   com script desligado veria as duas rádios na mesma tela — e a de cima seria a
   da casa, em cima da página de quem paga para estar aqui. O `radio-geral.js`
   faz a outra metade: além de sumir, ela cala. */
body[data-radio-casa="nao"] .geral { display: none; }
.geral-caixa { display: flex; align-items: center; gap: 16px; min-height: 58px; padding-block: 8px; flex-wrap: wrap; position: relative; }
.geral.tocando .geral-marca strong::after { content: ' • no ar'; color: var(--marca-casa); font-size: 12px; letter-spacing: 0.06em; }

/* O vídeo do YouTube da faixa da vez. Fica flutuando sob o cabeçalho em vez de
   empurrar a página: o player oficial precisa estar visível (é a condição para
   tocar aquele áudio), mas o conteúdo da tela não pode dançar por causa dele. */
.geral-video {
  position: fixed;
  right: 14px;
  top: 132px;
  width: min(320px, calc(100vw - 28px));
  z-index: 39;
  border-radius: var(--raio);
  overflow: hidden;
  box-shadow: 0 18px 40px rgba(0, 0, 0, 0.5);
}
.geral-video iframe { display: block; width: 100%; aspect-ratio: 16 / 9; height: auto; border: 0; }
.geral-botao {
  width: 48px;
  height: 48px;
  flex: none;
  border-radius: 50%;
  border: 0;
  background: var(--marca-casa);
  color: #fff;
  font-size: 18px;
  cursor: pointer;
  display: grid;
  place-items: center;
}
.geral-botao:hover { filter: brightness(1.1); }
.geral-marca { display: grid; line-height: 1.3; }
.geral-marca strong { font-size: 17px; letter-spacing: -0.01em; }
.geral-numeros { display: flex; gap: 18px; margin-left: auto; flex-wrap: wrap; font-size: 13px; color: var(--texto-2); }
.geral-numeros strong { color: var(--texto); }

/* O volume fica à direita, do tamanho de um controle de rádio de verdade —
   pequeno, mas com área de toque suficiente para o polegar. */
.geral-volume { display: flex; align-items: center; gap: 8px; }
.geral-mudo {
  background: none;
  border: 0;
  color: var(--texto-2);
  font-size: 17px;
  cursor: pointer;
  line-height: 1;
  padding: 6px;
  border-radius: var(--raio-p);
}
.geral-mudo:hover { background: var(--fundo-3); }
.geral-volume input[type='range'] {
  width: 110px;
  min-height: 0;
  padding: 0;
  border: 0;
  background: transparent;
  accent-color: var(--marca-casa);
  cursor: pointer;
}
.geral-barra { position: absolute; left: 0; right: 0; bottom: 0; height: 3px; border-radius: 0; }
.geral-barra > div { background: var(--marca-casa); }

/* ── A letra do que toca na estação da casa (31/08/2026) ───────────────────
 *
 * O gatilho é uma pastilha na própria barra; o painel **flutua**, e isso não é
 * enfeite: a barra mora no cabeçalho de todas as telas públicas, e um bloco de
 * texto abrindo dentro dela empurraria a página inteira para baixo a cada
 * abertura — e de novo a cada música, com a sanfona aberta.
 *
 * Ele é `absolute` pendurado em `.geral-caixa` (que já é `relative`) e não
 * `fixed` com um `top` escrito à mão: assim ele acompanha a barra em qualquer
 * altura de cabeçalho, e as três réguas de celular que encolhem o topo não
 * precisam lembrar de reposicioná-lo. `.topo` é `sticky` e não corta o que
 * transborda, então o painel aparece inteiro por cima da página.
 *
 * Abre à **esquerda** porque a direita é do quadro do vídeo (`.geral-video`):
 * com uma faixa de vídeo no ar e a letra aberta, um ficaria por cima do outro. */
.geral-letra > summary {
  cursor: pointer; font-size: 12px; color: var(--texto-2);
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--borda); border-radius: 999px; padding: 5px 10px;
  list-style: none; user-select: none; white-space: nowrap;
}
.geral-letra > summary::-webkit-details-marker { display: none; }
.geral-letra > summary::marker { content: ''; }
.geral-letra > summary::before { content: '▸'; display: inline-block; transition: transform .15s ease; }
.geral-letra[open] > summary::before { transform: rotate(90deg); }
.geral-letra > summary:hover { background: var(--fundo-3); color: var(--texto); }
.geral-letra-painel {
  position: absolute; left: 0; top: 100%; margin-top: 8px; z-index: 41;
  width: min(360px, calc(100vw - 32px));
  max-height: min(46vh, 340px); overflow-y: auto; overscroll-behavior: contain;
  background: var(--fundo-2); border: 1px solid var(--borda);
  border-radius: var(--raio); box-shadow: 0 18px 40px rgba(0, 0, 0, 0.5);
  padding: 12px 14px;
}
.geral-letra-painel > strong { display: block; font-size: 13px; margin-bottom: 6px; }
/* De quem é a música. Só o nome: a barra da casa cala quando alguém chega numa
   página de artista, então um link aqui interromperia a música que fez a pessoa
   perguntar de quem ela é. */
.geral-letra-artista { margin: -2px 0 8px; }

/* ── As letras no mídia kit (31/08/2026) ───────────────────────────────────
 *
 * Nascem **abertas** porque esta é a peça que se imprime: `details` fechado não
 * sai no papel. O `summary` vira uma linha de título com o crédito embaixo, sem
 * o triângulo padrão de cada navegador. */
.kit-letra > summary { cursor: pointer; list-style: none; display: block; }
.kit-letra > summary::-webkit-details-marker { display: none; }
.kit-letra > summary::marker { content: ''; }
.kit-letra > summary strong { display: block; }
.kit-letra > summary .miudo { display: block; margin-top: 2px; }
.kit-letra-corpo { margin-top: 12px; border-top: 1px solid var(--borda); padding-top: 12px; }
/* `pre-line`: a quebra de linha que o artista digitou é o verso. */
.kit-letra-texto { white-space: pre-line; line-height: 1.65; color: var(--texto-2); }
/* `pre-line`: a quebra de linha que o artista digitou é o verso. */
.geral-letra-texto { white-space: pre-line; font-size: 12.5px; line-height: 1.6; color: var(--texto-2); }
.geral-letra-texto.sem-letra { color: var(--texto-3); font-style: italic; }

/* No celular sobra o essencial: play, o nome da estação, o mudo. O texto de
   apoio e o cursor de volume saem — o botão de mudo resolve, e o volume do
   aparelho está do lado do polegar. */
@media (max-width: 640px) {
  .geral-caixa { gap: 10px; min-height: 52px; }
  .geral-marca .miudo { display: none; }
  .geral-marca strong { font-size: 15px; }
  .geral-volume input[type='range'] { display: none; }
  .geral-video { top: auto; bottom: 12px; right: 12px; width: min(240px, calc(100vw - 24px)); }
  /* A pastilha da letra encolhe como o resto da barra; o painel continua
     pendurado nela, então não há posição para reajustar aqui. */
  .geral-letra > summary { font-size: 11px; padding: 4px 8px; }
  .geral-letra-painel { max-height: min(52vh, 300px); }
  html { scroll-padding-top: 120px; }
}

/* ───────────────────────────── Página do artista ───────────────────────────── */

/* Sem `border-bottom`: a linha passava **atrás da foto do perfil**, que sobe
   por cima da capa, e cortava o círculo ao meio — o "achatado" que se via na
   tela. A separação entre a capa e o conteúdo já é feita pelo degradê do
   `::after`. */
/* ── A capa deixou de cortar o banner (29/08/2026) ───────────────────────────
   Ela era uma faixa de altura fixa (260 px) ocupando a largura toda: num
   monitor de 1400 px isso é uma proporção de 5,4 por 1, e **qualquer** banner
   entrava cortado em cima e embaixo. O artista mandava a arte inteira, via um
   pedaço dela na página e concluía, com razão, que alguma coisa estava errada.

   Agora a faixa tem a **mesma proporção do que a casa pede** (3 por 1, um
   banner de 1800 × 600), então a arte aparece completa.

   O teto existe para a capa não virar a página inteira em monitor largo, e ele
   subiu para **560 px** em 29/08/2026 — com 420 a conta não fechava justamente
   nos monitores mais comuns: 1440 px de viewport pedem 480 de altura e perdiam
   12% da arte; 1600 pedem 533 e perdiam 21%. Com 560, a arte aparece **inteira**
   até 1680 px de largura, e só acima disso volta a haver corte — pelo centro e
   de pouco. */
.capa {
  position: relative;
  aspect-ratio: 3 / 1;
  min-height: 150px;
  max-height: 560px;
  background: var(--fundo-2) center/cover;
}
/* Página sem capa é o estado do primeiro dia de todo mundo — e era o que saía
   pior: `background-image:url('')` faz o navegador pedir a própria página como
   imagem e o resultado é um buraco. Aqui o vazio vira um fundo com a cor que o
   artista escolheu, que é melhor que buraco e não custa nenhuma requisição. */
.capa.vazia {
  background: linear-gradient(135deg, var(--marca-escura) 0%, var(--fundo-2) 55%, var(--fundo) 100%);
}
/* O degradê que emenda a capa com o corpo da página. Ele existe para o topo do
   conteúdo não brigar com a arte — mas ele **come o pé do banner**, e quem
   passou uma tarde fazendo a arte quer vê-la limpa.

   Passando o mouse (ou o dedo, no toque longo), ele sai: a capa fica como o
   artista a desenhou. É só enfeite, então some sem pressa e volta sem pressa —
   e para quem pediu menos movimento no sistema, a troca é seca. */
.capa::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent, var(--fundo));
  opacity: 1;
}
.capa:hover::after,
.capa:focus-within::after { opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  .capa::after { transition: opacity 0.35s ease; }
}
/* Só a **foto** sobe para cima da capa; o nome e o resto ficam abaixo dela.
   Com o bloco inteiro subindo -90 px, o nome caía sobre a imagem — texto
   escuro em cima de capa clara, ilegível justamente na linha mais importante
   da página. */
.perfil-topo { position: relative; z-index: 1; width: var(--largura); margin: 0 auto; padding: 10px var(--respiro) 8px; display: flex; gap: 22px; align-items: flex-end; flex-wrap: wrap; }
.perfil-topo > .perfil-foto { margin-top: -80px; }
/* Página sem capa (o fã de quem ainda não subiu banner — ver `artista.ejs`):
   não há sobre o que pousar, então a foto não sobe. O respiro do topo entra no
   lugar dos 80 px que a subida consumia, senão a foto encostaria no cabeçalho. */
.perfil-topo.sem-capa { padding-top: 22px; }
.perfil-topo.sem-capa > .perfil-foto { margin-top: 0; }
/* Com o versículo, a coluna de dados fica ~90 px mais alta e a foto — colada no
   fim dela — descia para fora da capa (medido: de 21 px sobrepostos para 111 px
   abaixo). Ancorada no início, ela volta a pousar sobre o banner, ao lado do
   nome, e o cartão do versículo cresce para baixo sem empurrar nada. */
.perfil-topo.com-versiculo > .perfil-foto { align-self: flex-start; }
/* Redonda (15/08/2026), em todo tipo de expositor: é o formato que o público
   já lê como "foto de perfil" — a mesma do Instagram e do WhatsApp, que é onde
   ele acabou de ver esse artista. Quadrado com canto arredondado parecia
   miniatura de conteúdo, não pessoa. A capa continua retangular atrás dela. */
.perfil-foto { width: 156px; height: 156px; border-radius: 50%; border: 4px solid var(--fundo); background: var(--fundo-3) center/cover; flex: none; }
.perfil-dados { flex: 1; min-width: 240px; }
.perfil-dados h1 { margin-bottom: 6px; }

/* ── O versículo do dia, ao lado da foto (04/09/2026) ──────────────────────
   Um cartão estreito, e não uma faixa da largura da página: ele divide a linha
   com a foto de perfil e o nome, e alargá-lo faria a primeira coisa vista na
   página ser o versículo em vez do artista — que é o contrário do que a página
   existe para fazer. `max-width` em `ch` porque o limite aqui é de leitura, não
   de layout: passando de ~54 caracteres o olho perde a linha ao voltar.

   A barra lateral usa a cor que o próprio artista escolheu (`--marca`), então o
   cartão pertence à página dele e não parece um bloco da plataforma colado ali.

   O texto é `blockquote` de verdade e a referência é `figcaption`: para quem
   ouve a página num leitor de tela, a diferença entre "a palavra" e "de onde
   ela veio" é justamente o que o cartão quer transmitir. As aspas entram pelo
   CSS, e não no HTML, para não serem lidas em voz alta. */
.versiculo-do-dia { margin: 14px 0 0; padding: 10px 0 10px 14px; border-left: 3px solid var(--marca); max-width: 54ch; }
.versiculo-do-dia .olho { margin-bottom: 4px; }
.versiculo-do-dia blockquote { margin: 0; font-size: 16px; line-height: 1.55; color: var(--texto); font-style: italic; }
.versiculo-do-dia blockquote::before { content: '\201C'; }
.versiculo-do-dia blockquote::after { content: '\201D'; }
.versiculo-do-dia figcaption { margin-top: 5px; font-size: 13px; font-weight: 600; color: var(--texto-2); }

.abas { display: flex; gap: 6px; overflow-x: auto; border-bottom: 1px solid var(--borda); padding: 14px var(--respiro) 0; width: var(--largura); margin-inline: auto; }
/* ── Clicar numa aba tem de **mostrar** a seção ────────────────────────────
   O cabeçalho é fixo (`.topo` é `sticky`) e, na casca pública, ele tem duas
   linhas: o menu e a faixa da rádio. Um link de âncora leva a seção para o topo
   absoluto da tela — ou seja, para **debaixo** do cabeçalho: o título sumia e a
   pessoa caía no meio do conteúdo achando que a página tinha pulado errado.
   `scroll-margin-top` reserva a altura do cabeçalho no destino do salto. */
:root { --altura-topo: 140px; }
.secao, .abas, [id] { scroll-margin-top: var(--altura-topo); }
/* A rolagem é suave para o salto ser lido como movimento — e some para quem
   pediu menos animação no sistema, que é quem costuma passar mal com ela. */
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
/* Cabeçalho do celular: fio + linha da logo + linha dos controles + a faixa da
   rádio. É o recuo que as âncoras precisam para não parar debaixo dele. */
@media (max-width: 720px) { :root { --altura-topo: 148px; } }
.abas a { padding: 10px 15px; color: var(--texto-2); font-weight: 500; border-bottom: 3px solid transparent; white-space: nowrap; }
.abas a:hover, .abas a.ativo { color: var(--texto); border-bottom-color: var(--marca); text-decoration: none; }

.linha-tempo { display: grid; gap: 14px; border-left: 2px solid var(--borda); padding-left: 20px; margin-left: 8px; }
.linha-tempo article { position: relative; }
.linha-tempo article::before { content: ''; position: absolute; left: -27px; top: 8px; width: 11px; height: 11px; border-radius: 50%; background: var(--marca); }
.linha-tempo .ano { color: var(--marca-clara); font-weight: 600; font-size: 13px; }

.recado { background: var(--fundo-2); border: 1px solid var(--borda); border-radius: var(--raio); padding: 15px 17px; }
.recado .quem { font-weight: 600; font-size: 14px; }
.recado .resposta { margin-top: 10px; padding: 11px 13px; background: var(--fundo-3); border-left: 3px solid var(--marca); border-radius: 0 var(--raio-p) var(--raio-p) 0; font-size: 14px; }

/* Vídeo incorporado (YouTube, Instagram). A capa tem a proporção de tela e o
   quadro do Instagram cresce depois do clique, porque lá o embed é o post
   inteiro — legenda e botões incluídos. */
.video { margin: 0; display: grid; gap: 8px; }
.video-capa {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--fundo-3) center/cover;
  cursor: pointer;
  display: grid;
  place-items: center;
  padding: 0;
  overflow: hidden;
}
/* O véu escuro existe para o botão de play aparecer sobre qualquer imagem — mas
   0,28 apagava a arte do post, que é justamente o que o artista quer mostrar.
   Agora é um degradê discreto: escurece só onde o botão e o selo ficam. */
.video-capa::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(closest-side, rgba(0, 0, 0, 0.34), rgba(0, 0, 0, 0.06) 70%, transparent),
    linear-gradient(180deg, transparent 55%, rgba(0, 0, 0, 0.42));
}
.video-play {
  position: relative;
  width: 62px;
  height: 62px;
  border-radius: 50%;
  background: var(--marca);
  color: var(--texto-na-marca);
  display: grid;
  place-items: center;
  font-size: 22px;
  padding-left: 4px;
}
.video-selo { position: absolute; left: 10px; bottom: 10px; font-size: 12px; color: #fff; letter-spacing: 0.04em; }
.video iframe { width: 100%; aspect-ratio: 16 / 9; border: 0; border-radius: var(--raio); background: var(--fundo-3); }
.video.video-alto iframe { aspect-ratio: auto; height: 640px; }

/* Um player e a fila ao lado: clicar troca o vídeo no mesmo quadro e, quando
   ele acaba, o próximo entra sozinho. É o que faz o visitante ficar — e é o
   tempo de permanência que vira visualização na conta do artista. */
.video-conjunto { display: grid; grid-template-columns: minmax(0, 2fr) minmax(230px, 1fr); gap: 16px; align-items: start; }
/* A prévia muda que rodava na capa saiu em 23/08/2026 (com ela, as regras de
   `[data-previa]` e `.com-previa`). A capa voltou a ser a miniatura parada do
   próprio YouTube; o porquê está em `public/js/video.js`. */

.video-fila { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; max-height: 420px; overflow-y: auto; }
/* A linha da fila agora tem duas partes: o item (que troca o vídeo) e as setas
   (que movem a linha). As setas ficam fora do botão do item de propósito —
   dentro dele, o clique na seta trocaria o vídeo em vez de reordenar. */
.video-fila li { display: flex; align-items: center; gap: 6px; }
.video-fila li > .video-item { flex: 1 1 auto; min-width: 0; }
.video-fila-topo { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; flex-wrap: wrap; }
.video-fila-topo .marcar { margin: 0; gap: 6px; }
.video-item-ordem { display: grid; gap: 3px; flex: none; }
.video-item-ordem button {
  width: 26px; height: 20px; padding: 0; cursor: pointer;
  border: 1px solid var(--borda); border-radius: 6px;
  background: transparent; color: var(--texto-2); font-size: 11px; line-height: 1;
}
.video-item-ordem button:hover { background: var(--fundo-2); color: var(--texto); }
.video-item {
  display: flex;
  gap: 10px;
  align-items: center;
  width: 100%;
  text-align: left;
  padding: 6px;
  border: 1px solid transparent;
  border-radius: var(--raio-p);
  background: none;
  color: inherit;
  cursor: pointer;
}
.video-item:hover { background: var(--fundo-2); }
.video-item.ativo { background: var(--fundo-2); border-color: var(--marca); }
.video-item-capa {
  width: 74px;
  height: 44px;
  flex: none;
  border-radius: 6px;
  background: var(--fundo-3) center/cover;
  display: grid;
  place-items: center;
  font-size: 13px;
  color: #fff;
}
.video-item-texto { min-width: 0; display: grid; }
.video-item-texto strong { font-size: 13.5px; font-weight: 500; }

@media (max-width: 780px) {
  .video-conjunto { grid-template-columns: 1fr; }
  .video-fila { max-height: 260px; }
  .video.video-alto iframe { height: 560px; }
}

/* A parede de posts das redes. Formato de post (mais alto que largo) e não de
   tela: é o que o Instagram devolve, e capa 16/9 cortaria o conteúdo. Quando um
   post abre, ele cresce na própria célula — `align-items: start` impede que a
   linha inteira estique junto. */
.parede { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); align-items: start; }
/* O post que veio do feed automático do Instagram: o quadro mais os números que
   a Meta devolveu (curtidas, comentários, data). Sem `margin` própria — quem
   espaça é a grade da parede. */
.post-rede { margin: 0; }
.post-rede figcaption { margin-top: 6px; }
.parede .video-capa { aspect-ratio: 4 / 5; }
/* ── O post aparece inteiro ────────────────────────────────────────────────
   A capa usa `cover`, que preenche a moldura **cortando** o que não cabe. Numa
   parede de fotos de show isso é o certo. Num post do Instagram, não: a arte foi
   composta com margem, texto e assinatura nas bordas, e é exatamente isso que o
   `cover` come. As peças espelhadas aqui são 640×640 (quadradas) e 361×640
   (reel) dentro de uma moldura 4:5 — as duas saíam cortadas, e foi o que o
   cliente viu como "post cortado, sem aparecer por completo".

   `contain` mostra a peça inteira e deixa o que sobra como moldura escura, que
   é o que o Instagram faz no próprio feed com foto fora do formato dele. */
.parede .video-externo .video-capa { background-size: contain; background-color: #0b0b0b; }
.parede .video.video-alto iframe { height: 620px; }

/* ── O mapa da cena ─────────────────────────────────────────────────────────
   O quadro precisa de altura escrita: o Leaflet mede o elemento para montar os
   ladrilhos, e div sem altura devolve um mapa de zero pixel — que é a forma
   silenciosa de a tela não ter mapa nenhum. O balão do pino é branco de
   propósito, em qualquer tema: ele fica por cima da imagem do mapa, que é
   sempre clara. */
.mapa-quadro { height: 460px; border-radius: var(--raio); border: 1px solid var(--borda); background: var(--fundo-2); }
.mapa-balao ul { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 4px; max-height: 220px; overflow-y: auto; }
.mapa-balao a { font-weight: 600; }
.leaflet-popup-content-wrapper, .leaflet-popup-tip { background: #fff; color: #1a1a1a; }
.leaflet-popup-content .miudo { color: #5a5a5a; }
@media (max-width: 720px) { .mapa-quadro { height: 340px; } }

.galeria { display: grid; gap: 10px; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
.galeria a { display: block; aspect-ratio: 1; border-radius: var(--raio-p); overflow: hidden; background: var(--fundo-3) center/cover; }

.peca { background: var(--fundo-2); border: 1px solid var(--borda); border-radius: var(--raio); overflow: hidden; }
.peca .imagem { aspect-ratio: 4/3; background: var(--fundo-3) center/cover; }
.peca .corpo { padding: 12px 14px; }

/* ───────────────────────────── Figurinhas ─────────────────────────────
 *
 * O xadrez atrás da peça não é enfeite: figurinha é PNG recortado, e sobre o
 * fundo escuro da casa uma arte de traço escuro fica invisível — parece imagem
 * quebrada, que é o pior que uma vitrine pode parecer. O xadrez é a convenção
 * que todo editor de imagem usa para dizer "aqui não tem fundo", e ela já é
 * entendida por quem lida com arte.
 */
.figurinha-quadro {
  aspect-ratio: 1/1;
  display: flex; align-items: center; justify-content: center;
  padding: 10px; border-radius: var(--raio-p);
  background-color: #e9e9ef;
  background-image:
    linear-gradient(45deg, #cfcfda 25%, transparent 25%, transparent 75%, #cfcfda 75%),
    linear-gradient(45deg, #cfcfda 25%, transparent 25%, transparent 75%, #cfcfda 75%);
  background-size: 18px 18px;
  background-position: 0 0, 9px 9px;
}
.figurinha-quadro img { max-width: 100%; max-height: 100%; object-fit: contain; }

/* O ↓ no canto da foto que pode ser baixada. Um crachá, não um botão: o clique
 * na foto abre a foto; quem quer o arquivo em alta passa pela sala de imprensa,
 * onde o download é contado e a régua do artista vale. */
.galeria-baixar {
  position: absolute; right: 8px; bottom: 8px;
  background: rgba(0, 0, 0, 0.6); color: #fff;
  border-radius: 50%; width: 26px; height: 26px;
  display: flex; align-items: center; justify-content: center; font-size: 13px;
}
.galeria a { position: relative; }

/* ─────────────────── Playlist das músicas do artista ───────────────────
 *
 * Uma linha por música, e a linha inteira legível de relance: play, nome,
 * tempo, baixar. É a mesma anatomia de `.show` (a lista de agenda) de
 * propósito — quem já leu uma lista nesta casa lê esta sem aprender nada novo.
 *
 * `list-style: none` com `<ol>`: a numeração visível não ajuda (ninguém diz "a
 * faixa 7"), mas a ordem **semântica** importa para quem navega por leitor de
 * tela e para o próximo item que o tocador vai pegar.
 */

/* `minmax(0, 1fr)` pelo mesmo motivo do `.player`: coluna `auto` de grade não
 * encolhe abaixo do conteúdo mínimo, e o nome da música é `nowrap` — em telas
 * de 320 px a lista empurrava a página inteira para 360 e criava rolagem
 * lateral. Com o mínimo em zero, o nome corta com reticências como sempre quis. */
.playlist { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
.playlist-item {
  display: flex; gap: 14px; align-items: center; flex-wrap: wrap;
  background: var(--fundo-2); border: 1px solid var(--borda);
  border-radius: var(--raio); padding: 10px 14px;
}
/* A que está tocando se destaca pela borda, e não pelo fundo: fundo colorido
 * numa lista longa vira listra e cansa antes da décima música. */
.playlist-item.tocando { border-color: var(--marca); }
/* A faixa que entra é trazida de volta para a tela quando a troca de sanfona
   desloca a página — mas quem calcula o destino é o `public/js/playlist.js`, e
   **não** um `scroll-margin-top` aqui: o `html` já tem `scroll-padding-top`
   para as âncoras das abas, e os dois somariam (a linha parava a 268 px do topo
   numa tela de 780). Esta nota fica no lugar da regra para o próximo leitor não
   reintroduzi-la. */
.playlist-play {
  flex: none; width: 40px; height: 40px; border-radius: 50%;
  background: var(--marca); color: var(--texto-na-marca);
  border: 0; cursor: pointer; font-size: 14px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
}
.playlist-play:hover { background: var(--marca-escura); }
/* `min-width: 0` para o nome longo poder ser cortado em vez de empurrar o
 * tempo e o botão de baixar para fora da linha no celular. */
.playlist-nome { flex: 1; min-width: 0; }
.playlist-nome strong { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.playlist-nome p { margin: 2px 0 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.playlist-tempo { flex: none; font-variant-numeric: tabular-nums; }

/* ── Ouvir nas plataformas, ao lado de cada música (06/09/2026) ────────────
 *
 * Ícone sem palavra, e sem moldura de botão: numa lista de trinta e sete
 * faixas, a palavra "Spotify" repetida trinta e sete vezes vira textura, e uma
 * borda por ícone faria a linha da música parecer uma barra de ferramentas. A
 * cor da marca é o que o olho acha, e é ela que já vem do `parciais/icone-rede`.
 *
 * Fica levemente apagado no repouso e inteiro no toque/passagem do mouse: o
 * play da casa continua sendo o botão que salta na linha — quem chegou aqui
 * veio para ouvir, e só depois de gostar é que vai atrás do catálogo completo.
 *
 * A área de toque é maior que o desenho (padding de 4 px): 18 px de SVG é alvo
 * de dedo pequeno demais numa linha onde os vizinhos são baixar e a caixinha do
 * pacote — errar aqui é abrir uma aba que ninguém pediu. */
.playlist-plataformas { flex: none; display: flex; align-items: center; gap: 4px; }
.playlist-plataforma {
  display: flex; padding: 4px; border-radius: var(--raio-p);
  opacity: 0.75; transition: opacity 0.15s ease, background 0.15s ease;
}
.playlist-plataforma:hover,
.playlist-plataforma:focus-visible { opacity: 1; background: var(--fundo-3); }

/* ── A seleção para o pacote (31/08/2026) ──────────────────────────────────
 *
 * A caixinha é maior que a do navegador (`transform: scale`) porque ela é
 * alvo de dedo numa lista onde o vizinho de cima é um botão de tocar: errar o
 * alvo aqui é começar uma música que a pessoa não pediu. `accent-color` para
 * ela nascer na cor da casa em vez do azul do sistema. */
.playlist-marca { flex: none; width: 18px; height: 18px; accent-color: var(--marca); cursor: pointer; }
.playlist-lote { margin-top: 10px; align-items: center; }
.playlist-lote .marcar { margin: 0; }

/* ── "entrar como", no admin (31/08/2026) ──────────────────────────────────
 *
 * O único botão com nome escrito numa coluna de ícones. `⧉` não se adivinha, e
 * o `title` que o explicava só existe para quem tem mouse — no celular ele nunca
 * aparece. No estreito o rótulo some e sobra o ícone, senão a linha volta a ter
 * duas alturas, que foi o que tirou os rótulos dali em 15/08. */
.acao-entrar { display: inline-flex; align-items: center; gap: 6px; }
@media (max-width: 700px) {
  .acao-entrar .acao-rotulo { display: none; }
}

/* ── A letra, em sanfona (31/08/2026) ──────────────────────────────────────
 *
 * `flex-basis: 100%` com o `flex-wrap` do item: a letra é a **segunda linha** da
 * faixa, embaixo do play, do nome e do botão de baixar — e não uma coluna
 * espremida ao lado deles. Fechada, ela custa a altura de "Letra"; é assim que
 * uma lista de dez músicas continua sendo uma lista de dez linhas.
 *
 * O traço acima separa a letra da linha da música sem desenhar outra caixa:
 * caixa dentro de caixa, dez vezes na mesma página, vira grade de tabela. */
.playlist-letra { flex: 0 0 100%; border-top: 1px dashed var(--borda); padding-top: 8px; }
.playlist-letra > summary {
  cursor: pointer; font-size: 12px; color: var(--texto-3);
  display: inline-flex; align-items: center; gap: 6px;
  list-style: none; user-select: none;
}
/* O triângulo padrão do `details` some nos dois navegadores (o `::marker` do
 * Firefox e o `::-webkit-details-marker` do Safari) e volta como uma seta
 * nossa, que gira ao abrir — o padrão de cada um tem cor, tamanho e recuo
 * próprios, e a mesma lista ficaria diferente em cada aparelho. */
.playlist-letra > summary::-webkit-details-marker { display: none; }
.playlist-letra > summary::marker { content: ''; }
.playlist-letra > summary::before {
  content: '▸'; display: inline-block; transition: transform .15s ease;
}
.playlist-letra[open] > summary::before { transform: rotate(90deg); }
.playlist-letra > summary:hover { color: var(--texto-2); }
/* `pre-line`: a quebra de linha que o artista digitou **é** o verso. Sem isto o
 * navegador emenda a letra inteira num parágrafo só e o refrão desaparece no
 * meio dele. O texto sai menor que o da lista de propósito — ele acompanha o
 * som, não é o assunto da página. */
.playlist-letra-texto {
  white-space: pre-line; margin-top: 8px;
  font-size: 12.5px; line-height: 1.6; color: var(--texto-2);
}

/* ── A foto ao lado da letra, em duas colunas (04/09/2026) ──────────────────
 *
 * A imagem 9:16 da música já aparecia embaixo do player, mas ali ela sai da
 * vista assim que a pessoa abre a letra e começa a rolar. Ao lado do texto ela
 * acompanha a leitura — que é justamente quando a música está tocando.
 *
 * `grid` com coluna fixa para a foto e `minmax(0, 1fr)` para o texto: sem o
 * `minmax(0,...)` uma linha longa da letra empurra a coluna e estoura a grade,
 * porque o mínimo padrão de um item de grid é o tamanho do conteúdo, não zero.
 *
 * Só quando **há** foto (`.com-foto`): sem ela a letra ocupa a largura inteira,
 * em vez de deixar uma coluna vazia. */
.playlist-letra-corpo.com-foto {
  display: grid;
  grid-template-columns: 132px minmax(0, 1fr);
  gap: 14px;
  align-items: start;
  margin-top: 8px;
}
.playlist-letra-corpo.com-foto .playlist-letra-texto { margin-top: 0; }

/* `sticky`: a letra é longa e a foto é curta. Sem isto, ela rola para fora nos
 * primeiros versos e a coluna fica vazia pelo resto do texto — que é o oposto
 * de "a foto ao lado da letra". */
.playlist-letra-foto {
  width: 100%;
  aspect-ratio: 9 / 16;
  object-fit: cover;
  border-radius: 10px;
  display: block;
  position: sticky;
  top: 8px;
}

@media (max-width: 560px) {
  /* Duas colunas **também no celular**, a pedido do dono da casa. A foto encolhe
   * em vez de sair: 96 px ainda mostram o rosto, e o que sobra continua sendo
   * largura de leitura para a letra, que tem verso curto. */
  .playlist-letra-corpo.com-foto { grid-template-columns: 96px minmax(0, 1fr); gap: 10px; }
}

@media (max-width: 560px) {
  /* No celular o tempo sai: ele é a informação menos usada da linha, e é o que
   * estava espremendo o nome da música. */
  .playlist-tempo { display: none; }
  .playlist-item { padding: 10px; gap: 10px; }
  /* ── Os três ícones também no celular (06/09/2026) ─────────────────────
   * Decisão do dono da casa, e ela é sobre receita: a maior parte de quem abre
   * a página está no telefone, e esconder Deezer e Amazon ali seria esconder as
   * plataformas de quem não usa Spotify justamente na tela onde quase todo
   * mundo está.
   *
   * O preço está medido, não suposto: em 390 px o título perde cerca de sete
   * caracteres — "Quando Jesus Chega" fica "Quando Jesus C…". É o custo aceito,
   * e por isso o que sobra de largura vai todo para o nome: os ícones encostam
   * um no outro (`gap: 0`), o desenho cai para 16 px e a área de toque encolhe
   * para 3 px de folga — ainda 22 px de alvo, que é dedo. */
  .playlist-plataformas { gap: 0; }
  .playlist-plataforma { padding: 3px; }
  .playlist-plataforma .icone-rede { width: 16px; height: 16px; }
}

/* ───────────────────────────── Listas de show ───────────────────────────── */

.show { display: flex; gap: 16px; align-items: center; background: var(--fundo-2); border: 1px solid var(--borda); border-radius: var(--raio); padding: 14px 16px; }
.show .data { text-align: center; flex: none; width: 62px; }
.show .data .dia { font-size: 25px; font-weight: 600; line-height: 1; }
.show .data .mes { font-size: 11px; text-transform: uppercase; color: var(--texto-3); letter-spacing: 0.08em; }
.show .info { flex: 1; min-width: 0; }
.show .info strong { display: block; }

/* ───────────────────────────── Gráfico ───────────────────────────── */

/* Barras em CSS puro: a alternativa seria uma biblioteca de 90 kB para desenhar
   trinta retângulos que o artista olha por dez segundos. */
.grafico { display: flex; align-items: flex-end; gap: 3px; height: 130px; padding: 12px; background: var(--fundo-2); border: 1px solid var(--borda); border-radius: var(--raio); overflow-x: auto; }
.grafico .barra-dia { flex: 1; min-width: 7px; background: var(--marca); border-radius: 3px 3px 0 0; opacity: 0.85; }
.grafico .barra-dia:hover { opacity: 1; }

/* ───────────────────────────── Lojinha ───────────────────────────── */

/* A foto do produto é quadrada e `contain`, não `cover`: mockup de caneca e de
   camiseta tem sobra branca em volta, e recortar para preencher o quadro corta
   justamente a estampa — que é o Toy do artista, o motivo da compra. */
.loja-img { aspect-ratio: 1; background: var(--fundo-3) center/contain no-repeat; border-radius: var(--raio-p); }
.loja-img.alta { aspect-ratio: 4 / 3; }
.loja-toy { width: 120px; height: 120px; flex: none; background: var(--fundo-3) center/contain no-repeat; border-radius: var(--raio-p); }
/* Linha de item do carrinho e do pedido. */
.loja-linha { padding: 10px 0; border-bottom: 1px solid var(--borda); }
.loja-linha:last-of-type { border-bottom: 0; }

/* ───────────────────────────── Utilidades ───────────────────────────── */

.entre { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.empilha { display: grid; gap: 12px; }
.linha-acoes { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
/* Campo dentro de uma linha de ações é filtro, não formulário: acompanha o
   botão ao lado em vez de esticar pela largura toda da tela. */
.linha-acoes input, .linha-acoes select { width: auto; flex: 0 1 auto; min-width: 150px; }
.fita { display: flex; gap: 8px; flex-wrap: wrap; }
.limite-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.vazio { text-align: center; padding: 34px 18px; color: var(--texto-3); border: 1px dashed var(--borda); border-radius: var(--raio); }
/* O herói da landing: o gradiente vai do azul ao vermelho da bandeira, com o
   sol no meio. É a primeira tela que o artista vê, e é onde a identidade do
   estado precisa aparecer inteira — não só no fio de 3 px do cabeçalho. */
.destaque-caixa {
  background:
    linear-gradient(135deg, rgba(26,79,189,0.24), rgba(245,197,24,0.12) 38%, rgba(31,157,85,0.12) 62%, rgba(200,16,46,0.20));
  border: 1px solid rgba(200,16,46,0.40);
  border-radius: var(--raio);
  padding: 22px;
  position: relative;
  overflow: hidden;
}
/* O fio da bandeira também aqui, na borda de cima da caixa. */
.destaque-caixa::before {
  content: '';
  position: absolute;
  inset: 0 0 auto 0;
  height: 3px;
  background: linear-gradient(to right, var(--pe-azul) 0 30%, var(--pe-vermelho) 30% 42%, var(--pe-amarelo) 42% 54%, var(--pe-verde) 54% 66%, var(--pe-fio-branco) 66% 88%, var(--pe-vermelho) 88% 100%);
}
.copiavel { display: flex; gap: 8px; align-items: center; }
.copiavel input { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; }

/* ─────────────────── Blocos de texto para copiar ───────────────────
 *
 * O primo do `.copiavel` para texto de vinte linhas: prompt de imagem, legenda
 * de post. Campo de uma linha não serve aqui — quem copia precisa **ler antes**
 * (é ele que decide se a cena é essa), e um `<input>` com um parágrafo dentro
 * mostra oito palavras por vez.
 *
 * `white-space: pre-wrap` porque a quebra de linha é conteúdo: o prompt é lido
 * pela IA em blocos separados por linha em branco, e a legenda vai para o
 * Instagram exatamente como está aqui. Rolagem lateral fica no próprio bloco,
 * nunca na página. */
.prompt { border: 1px solid var(--borda); border-radius: var(--raio-p); overflow: hidden; margin-top: 12px; }
.prompt-barra {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 7px 8px 7px 12px; background: var(--fundo-3); border-bottom: 1px solid var(--borda);
}
.prompt pre {
  margin: 0; padding: 14px 12px; background: var(--fundo-2); color: var(--texto);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; line-height: 1.62;
  white-space: pre-wrap; overflow-x: auto;
}
/* A legenda não é código: ela é lida como o fã vai ler, na fonte do texto. O
   fio vermelho na lateral é o que separa, de relance, "o que a IA recebe" de
   "o que o seguidor recebe". */
.prompt-legenda pre {
  font-family: inherit; font-size: 14.5px; border-left: 3px solid var(--marca);
}

/* O QR de contato na página do artista. Fundo branco fixo: o código é lido por
   contraste, e um QR que acompanha o tema não escaneia no escuro. A imagem
   ganha respiro próprio porque a zona de silêncio faz parte do código. */
.qr-contato { margin-top: 4px; }
.qr-contato summary { cursor: pointer; font-size: 13px; color: var(--texto-3); padding: 6px 0; }
.qr-contato summary:hover { color: var(--texto); }
.qr-contato img {
  display: block; width: 100%; max-width: 220px; height: auto; margin: 8px auto 6px;
  background: #fff; padding: 10px; border-radius: var(--raio-p);
}

/* O mesmo QR no mídia kit, aberto e ao lado do texto: ali a peça é impressa, e
   `<details>` fechado não sai no papel. No celular vira uma coluna só. */
.qr-kit {
  display: flex; gap: 14px; align-items: center; flex-wrap: wrap;
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--borda);
}
.qr-kit img { flex: none; width: 150px; height: 150px; background: #fff; padding: 8px; border-radius: var(--raio-p); }
.qr-kit > div { flex: 1 1 240px; }
.qr-kit p { margin-top: 4px; }

/* O contato do dossiê: a tabela e o QR lado a lado, e um embaixo do outro no
   celular. `break-inside: avoid` porque esta folha é impressa — o código partido
   entre duas páginas não escaneia. */
.dossie-contato { display: flex; gap: 18px; align-items: flex-start; flex-wrap: wrap; }
.dossie-contato > .rolagem { flex: 1 1 320px; }
.dossie-qr { flex: none; margin: 0; text-align: center; max-width: 170px; break-inside: avoid; }
.dossie-qr img { width: 140px; height: 140px; background: #fff; padding: 8px; border-radius: var(--raio-p); }
.dossie-qr figcaption { margin-top: 6px; }

.lista-simples { margin: 8px 0 0; padding-left: 20px; }
.lista-simples li { margin-bottom: 4px; }

.regras-lista { margin: 12px 0 0; }
.regras-lista dt { font-weight: 600; margin-top: 12px; }
.regras-lista dd { margin: 3px 0 0; color: var(--texto-3); font-size: 13px; }

/* O layout limpo também vai de ponta a ponta. O que precisa de coluna estreita
   para ser lido — formulário de entrar, texto legal — já pede `.estreita`, que
   é decisão do conteúdo e não da moldura da página. */
.limpo main { width: var(--largura); margin-inline: auto; padding: 24px var(--respiro) 60px; }

/* ───────────────────────────── Celular ─────────────────────────────
 *
 * Aqui a régua muda: a tela do artista no camarim e a da equipe no ônibus têm
 * 360 px de largura útil, e a mesma tabela que cabe folgada no monitor vira
 * rolagem lateral às cegas. A saída é tipo miúdo e denso — 13 px de corpo,
 * 11 px de rótulo — com cada linha de tabela virando um cartão rotulado, em
 * vez de encolher tudo por igual e empurrar o resto para fora da tela.
 *
 * O que NÃO encolhe é o alvo de toque (--toque continua 44 px) nem o número
 * que o artista abre o painel para ver. Letra pequena é para o rótulo, a
 * data, o endereço — não para o botão nem para o dado.
 */
/*
 * A régua do celular.
 *
 * Denso de propósito. A tela do artista tem 360 px de largura e ele a usa em pé
 * no palco, entre uma música e outra: cada pixel gasto em respiro é uma linha
 * de conteúdo que desceu para baixo da dobra. O corpo cai para 13 px e os
 * títulos encolhem junto — encolher só o corpo quebra a hierarquia e a tela
 * vira um bloco cinza.
 *
 * **Dois pisos não se mexem, e não é preferência:**
 *
 * - **campo de formulário fica em 16 px.** Abaixo disso o iOS dá zoom sozinho
 *   ao focar, e o artista perde o enquadramento da tela no meio do cadastro.
 * - **`--toque` não desce de 40 px.** É o alvo do polegar; ganhar 4 px de altura
 *   ao custo de o botão errar o toque não é compactar, é piorar.
 */
@media (max-width: 720px) {
  /*
   * ── A régua do celular: letra miúda, respiro largo ──
   *
   * A revisão de 15/08/2026 mudou **só o espaço**, não o tamanho da letra. O
   * pedido era esse, e ele tem razão técnica: em 360 px de largura, fonte
   * pequena é o que faz caber a informação inteira (título de show, nome de
   * cidade, valor) sem quebrar em uma palavra por linha. O que estava errado
   * não era o tamanho — era a distância. Tudo encostado em tudo faz a tela
   * virar um bloco cinza, e o olho perde onde uma coisa acaba e a outra começa.
   *
   * Então: fontes como estavam (13 px de corpo, 11 px no miúdo), e o dobro de
   * ar entre os blocos. O espaço é o que separa; o tamanho é o que faz caber.
   */
  :root { --respiro: 14px; --raio: 10px; --raio-p: 7px; --toque: 40px; }

  body { font-size: 13px; line-height: 1.55; }
  h1 { font-size: 19px; margin-bottom: 10px; }
  h2 { font-size: 15.5px; margin-bottom: 10px; }
  h3 { font-size: 14px; margin-bottom: 7px; }
  p { margin-bottom: 11px; }
  .chamada { font-size: 14px; line-height: 1.6; }
  .miudo { font-size: 11px; line-height: 1.55; }
  .olho { font-size: 10px; letter-spacing: 0.09em; margin-bottom: 6px; }

  /*
   * Cabeçalho: marca, hambúrguer e ações numa linha só.
   *
   * **O menu virou hambúrguer em 15/08/2026**, revertendo a decisão de 14/08 —
   * e o que mudou foi o custo do lado de fora. A fita de rolagem lateral
   * mostrava que havia mais coisa, sim, mas cobrava a largura inteira de uma
   * terceira linha do cabeçalho e ainda deixava marca, busca, tema e botão de
   * entrar espremidos na primeira. Guardando os seis itens atrás de um toque, o
   * que fica na tela ganha o espaço que faltava — e some a rolagem horizontal,
   * que no celular sempre disputa com o gesto de voltar do sistema.
   *
   * O que motivava a decisão anterior continua de pé e continua atendido: a
   * rádio **não** foi para dentro do menu. Ela segue na segunda linha do
   * cabeçalho, visível e tocando, em todas as telas.
   */
  .topo .faixa { gap: 8px 10px; min-height: 48px; padding-block: 8px; }
  /* A faixa da rádio também é `.faixa` e mora dentro do cabeçalho: sem esta
     linha, a régua acima (escrita para a linha da navegação) vencia por
     especificidade e apagava o desenho próprio da rádio mais abaixo. */
  .topo .geral-caixa { gap: 9px; min-height: 52px; padding-block: 7px; }
  /* Sozinha na primeira linha, ela pode crescer: os 28 px que a régua de 640
     dava eram do tempo em que a logo dividia espaço com dois controles. */
  .marca-logo { height: 32px; max-width: 200px; }
  .marca-nome { font-size: 18px; }
  .marca-sub { font-size: 9px; letter-spacing: 0.12em; }

  .hamburguer {
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
    width: 38px;
    height: 38px;
    padding: 0;
    background: transparent;
    border: 1px solid var(--borda);
    border-radius: var(--raio-p);
    cursor: pointer;
  }

  /* Aberto, o menu é uma coluna que ocupa a largura toda embaixo do cabeçalho:
     alvo grande, um por linha, com respiro entre eles. É o formato que se toca
     andando — que é como este menu é usado. */
  .menu {
    order: 5;
    width: 100%;
    flex-direction: column;
    gap: 2px;
    overflow: visible;
    flex-wrap: nowrap;
    padding: 6px 0 2px;
    border-top: 1px solid var(--borda);
    margin-top: 4px;
  }
  .menu[data-fechado] { display: none; }
  .menu { align-items: stretch; text-align: center; }
  .menu a { font-size: 13px; padding: 10px 12px; border-radius: var(--raio-p); }
  .menu-extra { display: block; }
  /* ── O cabeçalho do celular, remontado (23/08/2026) ────────────────────
   *
   * Ele estava quebrado, e não por uma causa só — eram quatro coisas
   * disputando a mesma linha de 360 px:
   *
   * 1. **Voltar e avançar do aplicativo** (`.nav-pwa`) ocupavam dois alvos de
   *    40 px no canto mais disputado da tela, e ainda um `margin-right`
   *    somado ao `gap` da linha. São o item menos usado da barra e o que mais
   *    custava: encolhem.
   * 2. **O botão de tema** herdava `min-height: 36px` e `padding: 6px 12px` da
   *    regra de base e recebia aqui `width: 32px` — 24 px de recheio dentro de
   *    32 px de caixa, com 36 px de altura contra 32 pedidos. O emoji saía do
   *    lugar e a borda ficava torta. Era literalmente "o botão de tema
   *    quebrado". Agora é um ícone quadrado, sem recheio lateral.
   * 3. **A busca abria dentro de `.acoes`**, que é uma caixa encolhida à
   *    direita: o campo nascia com uns 150 px e o texto do placeholder não
   *    cabia. Com a busca aberta, as ações passam a valer a linha inteira.
   * 4. **Entrar + Sou artista + tema** não cabiam ao lado da marca e do
   *    hambúrguer, e caíam para uma segunda linha sem respiro nenhum. O
   *    `row-gap` dá a essa quebra o ar que ela precisa em vez de fingir que
   *    ela não acontece.
   */
  /*
   * ── A logo em cima, os controles todos na linha de baixo (23/08/2026) ──
   *
   * Duas linhas, e cada uma com um assunto:
   *
   *   ┌──────────────────────────────┐
   *   │             LOGO             │  ← quem é a casa
   *   │   ← →  ☰   ☀️  Entrar  …      │  ← o que dá para fazer
   *   └──────────────────────────────┘
   *
   * Antes a logo dividia a primeira linha com os botões de voltar/avançar do
   * aplicativo e com o hambúrguer: a coisa mais importante do cabeçalho ficava
   * espremida entre dois controles, e o alinhamento à esquerda ainda a colava
   * nos botões do PWA com um vão sobrando do outro lado.
   *
   * `order: -1` põe a marca na frente dos irmãos (que são `order: 0`; o menu e
   * a busca já eram 5 e 6) e `flex-basis: 100%` faz dela a linha inteira,
   * centrada — do tamanho que ela merece, sem competir com botão nenhum.
   *
   * Embaixo fica tudo o que é botão, num grupo centrado. Para isso as ações
   * **deixaram de ocupar a largura toda**: era o que as empurrava sozinhas para
   * uma terceira linha, com os botões de navegação numa linha e o de tema em
   * outra. A exceção é a busca aberta — ali `.acoes` volta a valer a linha
   * inteira, senão o campo nasce com uns 150 px espremidos à direita.
   */
  .topo-linha { justify-content: center; }
  .topo-linha .marca { order: -1; flex: 1 1 100%; justify-content: center; }
  .topo .acoes { gap: 6px; row-gap: 8px; justify-content: center; }
  .topo .acoes:has(.busca:not([data-fechado])) { flex: 1 1 100%; }
  .topo .acoes .miudo { width: 100%; text-align: center; }

  .nav-pwa { gap: 2px; margin-right: 2px; }
  .nav-pwa-botao { width: 32px; height: 32px; min-height: 32px; font-size: 18px; }
  /* No cabeçalho o botão é ação secundária ao lado da marca: ele pode ser mais
     baixo que o alvo geral sem prejuízo, porque nunca é o alvo principal da
     tela. Ainda assim fica em 32 px, acima do mínimo de acessibilidade. */
  .topo .acoes .botao.pequeno { min-height: 32px; padding: 4px 9px; font-size: 11.5px; }
  .topo .acoes .tema-botao {
    width: 34px; height: 34px; min-height: 34px;
    padding: 0; display: grid; place-items: center; font-size: 15px;
  }
  /*
   * A busca **entra no menu** no celular (15/08/2026).
   *
   * Com ela na linha de fora, o cabeçalho fechado ocupava três faixas antes de
   * a página começar: marca + hambúrguer, os botões, e a busca. Ninguém busca
   * antes de olhar — quem chega quer ver a casa. Dentro do menu ela continua a
   * um toque de distância e o topo volta a caber em duas linhas, com a rádio
   * (que é o que precisa estar sempre à mão) logo abaixo.
   */
  .busca { order: 6; flex: 1 1 100%; margin-top: 2px; }
  .busca[data-fechado] { display: none; }
  .busca input { width: 100%; min-width: 0; font-size: 16px; padding: 9px 12px; }

  /* O respiro entre seções é o que dá o ritmo da rolagem: sem ele, home,
     agenda e página de artista chegam como uma parede única de texto. */
  .secao { padding: 26px var(--respiro); }
  .secao-cabeca { margin-bottom: 16px; gap: 12px; }
  .rodape { margin-top: 34px; padding: 24px 0; }
  .rodape nav { gap: 10px 14px; }
  .rodape nav a { font-size: 11.5px; }

  .cartao { padding: 14px; }
  .cartao + .cartao { margin-top: 12px; }
  .grade { gap: 14px; }
  /* Dois cartões de artista por linha: um só por linha vira rolagem infinita
     e esconde o catálogo, que é o que a home existe para mostrar. */
  .grade-3, .grade-4 { grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .cartao-artista .corpo { padding: 10px 11px 12px; }
  .cartao-artista h3 { font-size: 13px; }
  .galeria { grid-template-columns: repeat(3, 1fr); gap: 7px; }

  /* Botão continua com letra pequena e ganha altura: o dedo acerta pela área,
     não pela fonte — e é a área que estava faltando. */
  .botao { font-size: 13px; padding: 11px 16px; }
  .botao.pequeno { font-size: 12px; padding: 7px 12px; min-height: 34px; }
  .fita { gap: 8px; }
  .acoes, .linha-acoes { gap: 10px; }
  .selo { font-size: 9.5px; padding: 3px 7px; }
  .empilha { gap: 12px; }

  .aviso { font-size: 12.5px; padding: 12px 13px; gap: 9px; align-items: flex-start; }

  .campo { margin-bottom: 16px; }
  .campo label { font-size: 12px; margin-bottom: 5px; }
  .campo .dica { font-size: 11px; margin-top: 6px; }
  .linha { gap: 14px; grid-template-columns: 1fr; }
  .campo-grupo, fieldset legend + .dica { margin-bottom: 14px; }
  input[type=text], input[type=email], input[type=password], input[type=url], input[type=tel],
  input[type=date], input[type=time], input[type=number], input[type=search], input[type=file], select, textarea {
    font-size: 16px; /* menos que isso e o iOS dá zoom sozinho no foco */
    padding: 8px 11px;
  }
  .marcar { padding: 9px 0; gap: 10px; }
  .marcar span { font-size: 12.5px; }
  fieldset { padding: 14px; }

  .numeros { gap: 10px; grid-template-columns: repeat(2, 1fr); }
  .numero { padding: 12px 13px; }
  .numero .valor { font-size: 19px; }
  .numero .rotulo { font-size: 10.5px; line-height: 1.4; }

  .painel-corpo { padding: 14px var(--respiro) 44px; gap: 16px; }
  /* A barra rolável do painel: o ícone carrega o reconhecimento e o texto
     confirma. Encolher os dois junto mantém a leitura — encolher só o texto
     deixaria um ícone grande com legenda de rodapé. */
  .painel-menu { gap: 2px; padding-bottom: 4px; }
  .painel-menu a { padding: 6px 9px; font-size: 12px; gap: 7px; min-height: 34px; }
  .painel-menu a span:not(.icone) { font-size: 11.5px; }
  .painel-menu .icone { width: 13px; }

  /* No celular a capa tem 120 px de altura e a foto, 88: com o cabeçalho subindo
     -60 e a foto outros -80, o círculo ficava **inteiro dentro da capa** e ainda
     começava acima dela — a arte que o artista mandou sumia atrás do rosto.
     Agora só o pé da foto encosta na capa (30/08/2026), como no Instagram: o
     bloco não sobe mais, e a foto morde 32 px da faixa. */
  .perfil-topo { margin-top: 0; gap: 11px; padding-top: 0; }
  .perfil-topo > .perfil-foto { margin-top: -32px; }
  .perfil-topo.sem-capa { padding-top: 14px; }
  .perfil-topo.sem-capa > .perfil-foto { margin-top: 0; }
  .perfil-foto { width: 88px; height: 88px; border-radius: 50%; border-width: 3px; }
  .perfil-dados { min-width: 100%; }
  /* No celular os dados descem para debaixo da foto e a largura é a da tela:
     o cartão perde o teto de leitura (a linha já é curta) e ganha um respiro
     menor, senão ele empurra as ações da página para fora da primeira dobra. */
  .versiculo-do-dia { margin-top: 10px; max-width: none; }
  .versiculo-do-dia blockquote { font-size: 15px; }
  /* No celular a proporção 3:1 já dá uma faixa baixa; o mínimo evita que ela
     suma em tela estreita — mas **preso a 120 px** ele fazia o contrário do que
     promete abaixo de 360 px: com `aspect-ratio`, uma altura mínima de 120
     obriga a largura a ser 360, e a capa passava a empurrar a página inteira
     para fora da tela num aparelho de 320 px. `min()` deixa o piso valer até
     onde ele cabe e devolve a conta para a proporção quando não cabe. */
  .capa { min-height: min(120px, 33.34vw); }
  .abas { padding-top: 10px; }
  .abas a { padding: 7px 10px; font-size: 12.5px; }

  /* A linha do show tem data, texto e ações. Em 360 px as três lado a lado
     espremem o título em uma palavra por linha — que é justamente o que a
     pessoa está procurando. Data e título dividem a primeira linha; selo e
     botões descem alinhados ao texto. */
  /* No celular a célula vira só o número e um risco por show: o nome de quem
     toca não cabe em 45 px e está logo abaixo, na lista. */
  .calendario { gap: 2px; }
  .calendario-dia { min-height: 52px; padding: 3px; gap: 2px; border-radius: 6px; }
  .calendario-numero { font-size: 10.5px; }
  .calendario-show { font-size: 0; padding: 0; height: 4px; border-radius: 2px; }
  .calendario-ponto { display: none; }
  .calendario-cabeca { font-size: 9.5px; letter-spacing: 0.04em; }

  .geral-caixa { gap: 9px; padding-block: 7px; }
  /* O play da rádio é o único alvo do cabeçalho que não encolhe abaixo de
     40 px: é o botão mais apertado da casa e o único que alguém procura com o
     celular na mão sem olhar. */
  .geral-botao { width: 40px; height: 40px; font-size: 15px; }
  .geral-marca strong { font-size: 14px; }
  .geral-marca .miudo { font-size: 10.5px; }
  .geral-numeros { gap: 8px; font-size: 11px; margin-left: auto; }
  /*
   * No celular fica **só o botão de mudo**, na mesma linha do play.
   *
   * A régua de 640 px já escondia o cursor de volume (o volume do aparelho está
   * do lado do polegar), mas esta regra, declarada depois na folha, o trazia de
   * volta e ainda dava a ele uma linha inteira — o resultado era uma faixa vazia
   * embaixo da rádio com um alto-falante solto. Ordem na folha é o que decide
   * quando duas réguas falam da mesma coisa.
   */
  .geral-volume { width: auto; margin-left: auto; }

  .show { padding: 9px 10px; gap: 10px; row-gap: 7px; flex-wrap: wrap; align-items: flex-start; }
  .show .data { width: 38px; padding-top: 2px; }
  .show .data .dia { font-size: 18px; }
  .show .info { flex: 1 1 0; }
  .show .fita { flex: 1 0 calc(100% - 48px); margin-left: 48px; }
  .player { padding: 11px; gap: 10px; }
  .player-capa { width: 44px; height: 44px; font-size: 18px; }
  .player-botao { width: 46px; height: 46px; font-size: 18px; }
  /* Duas linhas no celular, em vez das quatro coisas espremidas numa só
     (30/08/2026). Em 360 px, capa + nome + play + cursor de volume davam um
     cursor de 64 px (curto demais para o polegar) e o nome da estação cortado
     em "Rádio Banda …" — justamente o que o cartão existe para dizer.

     Em cima, a capa e o nome, com a largura inteira para ele. Embaixo, os dois
     controles juntos: o play do tamanho de sempre e o volume ocupando o resto.
     O cursor fica **ao lado do play**, e não solto acima da barra de progresso,
     onde duas linhas laranja empilhadas pareciam a mesma coisa duas vezes. */
  /* `:has(.player-volume)` porque a rádio da produtora usa o mesmo cartão **sem**
     cursor de volume: lá a segunda linha teria só o play, solto embaixo da capa.
     Onde o navegador não conhecer o `:has`, o cartão continua na linha única de
     sempre — que cabe na tela desde que a coluna da grade parou de esticar. */
  .player-topo:has(.player-volume) {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    column-gap: 12px;
    row-gap: 10px;
  }
  .player-topo:has(.player-volume) > .player-capa { grid-area: 1 / 1; }
  .player-topo:has(.player-volume) > .player-info { grid-area: 1 / 2; }
  .player-topo:has(.player-volume) > .player-controles { grid-area: 2 / 1; }
  .player-volume { grid-area: 2 / 2; }
  .player-volume input[type="range"] { flex: 1; width: auto; }
  /* No palco fixo, não: ali o cartão é uma barra ligada dentro do cabeçalho, e
     uma segunda linha empurraria o conteúdo da página para baixo em toda tela
     (é a altura que as âncoras descontam em `--altura-topo`). A barra fica com
     capa, nome e play, como sempre — o volume do aparelho está do lado do
     polegar, e o cursor volta assim que a pessoa abre a página do artista. */
  .palco-fixo .player .player-topo:has(.player-volume) { display: flex; }
  .palco-fixo .player .player-volume { display: none; }
  .player-info strong { font-size: 14px; }
  .player-lista { font-size: 12px; gap: 5px; }

  .destaque-caixa { padding: 12px; }
  .vazio { padding: 18px 12px; font-size: 12px; }
  .linha-tempo { padding-left: 13px; margin-left: 4px; gap: 10px; }
  .recado { padding: 11px 12px; }
  .recado .quem { font-size: 12.5px; }
  .recado .resposta { padding: 8px 10px; font-size: 12.5px; margin-top: 7px; }
}

/* ── Tabela que vira lista de cartões ──
 *
 * Tabela de 7 colunas em 360 px só existe em rolagem lateral, e rolagem
 * lateral esconde justamente a coluna de ações — é onde a equipe dá baixa numa
 * cobrança e o artista pausa uma faixa. Cada linha vira um cartão e cada
 * célula carrega o próprio rótulo (`data-col`), que é o cabeçalho que sumiu.
 * Só entram aqui as tabelas de trabalho: comprovante e relatório continuam
 * tabela de verdade, porque são documentos que o contratante imprime. */

@media (max-width: 720px) {
  .rolagem:has(.tabela-cartoes) { overflow-x: visible; }

  .tabela-cartoes, .tabela-cartoes tbody, .tabela-cartoes tr, .tabela-cartoes td { display: block; width: 100%; }
  .tabela-cartoes thead { display: none; }
  .tabela-cartoes { font-size: 12.5px; }

  .tabela-cartoes tr {
    background: var(--fundo-2);
    border: 1px solid var(--borda);
    border-radius: var(--raio-p);
    padding: 10px 12px;
    margin-bottom: 9px;
  }
  .tabela-cartoes tbody tr:hover { background: var(--fundo-2); }

  .tabela-cartoes td { border: 0; padding: 3px 0; }

  /* Recuo pendente em vez de duas colunas de grade: a célula costuma ter mais
     de um filho (dois selos, um parágrafo miúdo, um formulário), e em grade
     cada filho viraria uma célula própria — os selos desandavam em ziguezague.
     Assim o rótulo ocupa a margem da primeira linha e todo o resto do conteúdo
     flui normal, alinhado na mesma coluna. */
  .tabela-cartoes td[data-col] {
    display: block;
    padding-left: 84px;
    text-indent: -84px;
  }
  .tabela-cartoes td[data-col]::before {
    content: attr(data-col);
    display: inline-block;
    width: 76px;
    margin-right: 8px;
    text-indent: 0;
    vertical-align: top;
    color: var(--texto-3);
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    line-height: 1.9;
  }
  .tabela-cartoes td[data-col] > * { text-indent: 0; }
  /* A primeira célula é o nome da coisa: entra como título do cartão, sem
     rótulo e em corpo maior, para dar onde bater o olho. */
  .tabela-cartoes td:first-child { font-size: 13.5px; padding-bottom: 5px; }
  .tabela-cartoes td:first-child[data-col] { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .tabela-cartoes td:first-child[data-col]::before { display: none; }
  .tabela-cartoes td p.miudo { margin: 2px 0 0; }

  .tabela-cartoes td.acoes-tabela {
    white-space: normal;
    padding-left: 0;
    text-indent: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    align-items: center;
    margin-top: 7px;
    padding-top: 9px;
    border-top: 1px dashed var(--borda);
  }
  .tabela-cartoes td.acoes-tabela form { display: inline-flex !important; gap: 6px; align-items: center; flex-wrap: wrap; }
  .tabela-cartoes td.acoes-tabela input[type=text],
  .tabela-cartoes td.acoes-tabela input[type=number],
  .tabela-cartoes td.acoes-tabela select { width: auto; max-width: 160px; min-height: 34px; padding: 5px 9px; font-size: 13px; }
  .tabela-cartoes td.acoes-tabela details { display: block; width: 100%; }
  .tabela-cartoes td.acoes-tabela details form { margin-top: 6px; }
  .tabela-cartoes td:empty { display: none; }
}

/* As tabelas que continuam tabela só apertam o passo. */
@media (max-width: 720px) {
  table { font-size: 12.5px; }
  th, td { padding: 8px 8px; }
  th { font-size: 10.5px; }
}

/*
 * Celular pequeno (iPhone SE, Android de entrada — 360 px e abaixo).
 *
 * Aqui o problema deixa de ser densidade e passa a ser **caber**: dois cartões
 * de artista por linha ficam com 160 px cada, e o nome do artista quebra em
 * três linhas. Só o essencial encolhe mais — o resto herda a régua de cima.
 */
@media (max-width: 380px) {
  :root { --respiro: 8px; }

  body { font-size: 12.5px; }
  h1 { font-size: 17.5px; }
  h2 { font-size: 15px; }

  .marca-sub { display: none; } /* "Painel"/"Admin" ao lado da marca não cabe */
  .menu a { font-size: 11.5px; padding: 5px 7px; }
  .topo .acoes .botao.pequeno { font-size: 11px; padding: 4px 7px; }

  .cartao-artista h3 { font-size: 12px; }
  .numeros { gap: 6px; }
  .numero .valor { font-size: 17px; }
  .numero .rotulo { font-size: 10px; }
  .galeria { grid-template-columns: repeat(2, 1fr); }
}

@media print {
  /* O comprovante de veiculação e o relatório do evento são entregues
     impressos ou em PDF com frequência — o contratante nem sempre abre link. */
  body { background: #fff; color: #111; }
  .topo, .rodape, .painel-menu, .botao, .aviso { display: none !important; }
  .cartao, table { border-color: #ccc; }
  .painel-corpo { display: block; padding: 0; }
  /* Uma letra cortada ao meio pela quebra de página é uma letra que ninguém lê
     no papel. Elas já saem abertas do servidor, então aqui basta não deixar a
     folha partir cada uma delas. */
  .kit-letra { break-inside: avoid; }
}

/* ── O envio do acervo, com barra por arquivo (15/08/2026) ──
 *
 * A área de soltar é um `<label>` do input escondido: no computador ela aceita
 * arrastar, e no celular — onde arrastar arquivo não existe — ela é um alvo de
 * toque grande, que é o que faltava para o botão de escolher arquivo ser achado.
 */
.envio-solta {
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 22px 16px;
  margin-top: 10px;
  border: 2px dashed var(--borda);
  border-radius: var(--raio-p);
  background: var(--fundo-2);
  cursor: pointer;
  min-height: 96px;
}
.envio-solta:hover, .envio-solta.arrastando { border-color: var(--marca); background: var(--fundo-3); }

.envio-item { padding: 10px 12px; border: 1px solid var(--borda); border-radius: var(--raio-p); background: var(--fundo-2); }
.envio-nome { font-weight: 500; font-size: 14px; word-break: break-all; }
/* O trilho fica sempre visível: barra que só aparece quando começa a andar faz
   o primeiro segundo do envio parecer que nada aconteceu. */
.envio-trilho { height: 6px; margin-top: 8px; border-radius: 999px; background: var(--fundo-3); overflow: hidden; }
.envio-barra { height: 100%; width: 0; border-radius: 999px; background: var(--marca); transition: width 140ms linear; }
@media (prefers-reduced-motion: reduce) { .envio-barra { transition: none; } }

/* ── Ajuda de formulário: telefone, e-mail e o olho da senha (15/08/2026) ── */
.campo-recado.erro { color: var(--erro); }
input.invalido, input.invalido:focus { border-color: var(--erro); }

/* O olho fica **dentro** do campo, encostado na borda: fora dele, ou o campo
   encolhe (e a senha longa some da vista), ou o botão cai para a linha de
   baixo no celular, que é onde ele mais serve. */
.campo-senha { position: relative; display: block; }
.campo-senha input { width: 100%; padding-right: 46px; }
.olho-senha {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  width: 34px;
  height: 34px;
  min-height: 34px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 0;
  border-radius: var(--raio-p);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  opacity: 0.75;
}
.olho-senha:hover { opacity: 1; background: var(--fundo-3); }

/* ── Quebra de palavra comprida (15/08/2026) ──
 *
 * `rofsom.app.br/seunome` é uma palavra só para o navegador, e palavra sem
 * espaço **não quebra**: ela vazava do cartão e empurrava o layout inteiro. O
 * endereço da casa aparece escrito em dezenas de telas (é o produto), então a
 * regra é global, e não um remendo por cartão. */
h1, h2, h3, h4, p, li, dd, dt, summary, td, th, .selo, .miudo, .chamada {
  overflow-wrap: break-word;
  word-break: break-word;
}
code { overflow-wrap: anywhere; }
/* Bloco de comando para copiar — o `certbot` do domínio próprio, o alinhamento
   do bloco de programa. Rola por dentro em vez de esticar a tela: comando é uma
   linha longa por natureza, e quebrar no meio faz alguém copiar pela metade. */
pre.codigo {
  margin: 0;
  padding: 10px 12px;
  background: var(--fundo-3);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  font-size: 12.5px;
  line-height: 1.5;
  overflow-x: auto;
  white-space: pre;
}

/* ── A página de lançamento ──
 *
 * Ela é a única tela da casa que é **peça de venda**, e peça de venda se lê
 * centralizada: título no meio, texto de apoio embaixo, cartões de largura
 * igual. O resto do site continua alinhado à esquerda, que é o certo para tela
 * de trabalho — daí o escopo `.lancamento` em vez de mexer no geral.
 *
 * A largura de leitura vem daqui e não do `--largura` da casa: numa tela de
 * 27 polegadas, um parágrafo de venda ocupando 2.400 px não se lê. */
.lancamento .secao { max-width: 1180px; margin-inline: auto; }
.lancamento h1,
.lancamento h2,
.lancamento .olho,
.lancamento .chamada { text-align: center; }
.lancamento .chamada.estreita { margin-inline: auto; }
.lancamento .destaque-caixa { text-align: center; }

/* Cartão da landing: texto centralizado, altura igual na linha e o conteúdo
   distribuído — cartão curto ao lado de cartão longo desalinha a leitura. */
.lancamento .grade > .cartao {
  text-align: center;
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.lancamento .grade { align-items: stretch; }

/* O formulário é a ação da página: ele merece largura, e não a caixa estreita
   de 640 px que o deixava parecendo uma ilha no meio de uma tela larga. */
.lancamento .secao.estreita, .lancamento #formulario { max-width: 980px; }
/* Dentro do formulário, tudo volta a ser alinhado à esquerda: rótulo
   centralizado em cima de um campo que começa na margem esquerda é o jeito
   rápido de deixar um formulário difícil de preencher. */
.lancamento form, .lancamento form h2, .lancamento form .olho { text-align: left; }
.lancamento form .campo label { text-align: left; }

/* O realce da casa: vermelho da bandeira, para a frase que **vende** — usada
   com parcimônia, porque destaque em tudo é destaque em nada. */
.realce { color: var(--marca-clara); font-weight: 600; }

/* ── Documento legal (termos, privacidade) ──
 *
 * Coluna de leitura de verdade: texto jurídico de 100% de largura numa tela de
 * 27 polegadas não se lê, e a régua da casa é 100% de propósito (é tela de
 * trabalho). Aqui o limite é o comprimento de linha, não a tela.
 *
 * A numeração e o espaço entre seções também são conteúdo: quem procura "o que
 * acontece se eu cancelar" varre os títulos, não lê do começo. */
.legal { max-width: 860px; margin-inline: auto; }
.legal h2 { margin-top: 30px; padding-top: 14px; border-top: 1px solid var(--borda); }
.legal h2:first-of-type { border-top: 0; }
.legal p { margin-top: 10px; color: var(--texto-2); line-height: 1.7; }
.legal ul, .legal ol { margin: 10px 0 0 20px; color: var(--texto-2); line-height: 1.7; }
.legal li { margin-bottom: 6px; }
.legal .cartao p, .legal .cartao ul { color: var(--texto-2); }
.legal nav ol { margin-top: 8px; }
/* O índice não é leitura corrida: em duas colunas ele cabe numa olhada. */
@media (min-width: 720px) { .legal nav ol { columns: 2; column-gap: 28px; } }
.legal table { font-size: 13.5px; }
.legal td { vertical-align: top; }

/* Cartão que é link (o índice de Configurações, por exemplo).
 *
 * `.cartao` nasceu como `<div>` e não declarava `display` — virando `<a>`, ele
 * herdava `inline` e a caixa inteira desmontava: título, selo e texto viravam
 * uma linha corrida. É o tipo de defeito que só aparece no dia em que alguém
 * usa a classe num elemento diferente. */
a.cartao { display: block; color: inherit; text-decoration: none; }
a.cartao:hover { border-color: var(--marca); text-decoration: none; }
a.cartao h3 { color: var(--texto); }

/* ── Modal (`<dialog>`) e botões de ícone (15/08/2026) ── */
dialog.modal {
  width: min(760px, calc(100vw - 24px));
  max-height: calc(100vh - 48px);
  padding: 0;
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  background: var(--fundo-2);
  color: var(--texto);
  overflow: auto;
}
dialog.modal::backdrop { background: rgba(0, 0, 0, 0.62); backdrop-filter: blur(2px); }
.modal-topo {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 18px;
  background: var(--fundo-2);
  border-bottom: 1px solid var(--borda);
}
.modal-corpo { padding: 18px; }

/* ── A caixa de entrar da página do artista (01/09/2026) ────────────────────
   O `dialog.modal` da casa é largo (760 px) porque nasceu para formulário de
   catálogo, com quinze campos em duas colunas. Aqui são três campos e uma
   decisão: 460 px é a largura em que um formulário curto continua parecendo
   curto — esticado, ele dá a impressão de que falta coisa para preencher.

   Ela também não usa `.modal-topo`/`.modal-corpo`: aquele cabeçalho grudento
   existe para tabela que rola por dentro, e aqui não há o que rolar. */
dialog.modal-entrar { width: min(460px, calc(100vw - 24px)); padding: 20px; }
.modal-entrar .modal-fecha-linha { display: flex; justify-content: flex-end; margin: -6px -6px 2px 0; }
.modal-entrar .campo { margin-top: 12px; }
/* A caixa vem do navegador com um contorno de foco no primeiro elemento; o
   `<h3>` não é interativo e o contorno ali parece defeito. */
dialog.modal-entrar:focus { outline: none; }
.modal-fecha {
  width: 34px;
  height: 34px;
  min-height: 34px;
  padding: 0;
  border: 1px solid var(--borda);
  border-radius: var(--raio-p);
  background: transparent;
  color: var(--texto-2);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
}
.modal-fecha:hover { background: var(--fundo-3); color: var(--texto); }

/* Botão só com ícone: mesma altura de toque do botão de texto, largura de um
   quadrado. Ele **sempre** leva `aria-label` e `title` — ícone sem nome é
   adivinhação para quem usa leitor de tela e para quem usa o sistema uma vez
   por mês. */
.botao.icone {
  width: 34px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  line-height: 1;
}
.botao.pequeno.icone { min-height: 32px; }

/* ── Grade de cartões que se alinham (15/08/2026) ──
 *
 * Dois defeitos apareceram juntos numa tela larga: cartão com altura própria
 * (terminando em linhas diferentes, como se estivessem desalinhados) e coluna
 * estreita demais, sobrando faixa vazia dos dois lados numa tela de 1900 px.
 *
 * `align-items: stretch` na grade e `height: 100%` no cartão resolvem o
 * alinhamento; a largura mínima maior faz o cartão **crescer** em vez de a tela
 * caber mais um. Coluna de 220 px numa tela grande é texto com quatro palavras
 * por linha. */
.grade { align-items: stretch; }
.grade > .cartao, .grade > a.cartao { height: 100%; }
.grade-2 { grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }
.grade-3 { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
@media (max-width: 720px) {
  /* No celular a régua volta a ser a de antes: `minmax` grande vira uma coluna
     só, e uma coluna só de 340 px numa tela de 360 estoura a lateral. */
  .grade-2, .grade-3 { grid-template-columns: 1fr; }
}

/* Cartão dentro de grade nunca empurra a coluna: sem `min-width: 0`, um
   endereço comprido (ou um `<code>`) faz a coluna crescer além da fração e a
   linha inteira sai do alinhamento — é o defeito que parece "card quebrado". */
.grade > * { min-width: 0; }
.cartao > * { min-width: 0; max-width: 100%; }

/* ── O cabeçalho do cartão (15/08/2026) ──
 *
 * Título de um lado, selo do outro. Dois defeitos apareciam quando o selo era
 * comprido ("40% para o artista", "app não configurado"): ele empurrava o
 * título e, quando quebrava a linha, ficava centralizado verticalmente — o que
 * dava a impressão de cartões desalinhados entre si numa mesma linha da grade.
 *
 * `flex-start` alinha os dois pelo topo, o selo não quebra no meio de uma
 * palavra e o título tem prioridade de espaço. */
.cartao > .entre { align-items: flex-start; }
.cartao > .entre > h3,
.cartao > .entre > h4,
.cartao > .entre > div { flex: 1 1 220px; min-width: 0; }
/* ...menos o que tem tamanho próprio. A regra de cima é para texto que precisa
   quebrar; aplicada à foto de perfil (que é uma `div` com largura e altura
   fixas), ela esticava o círculo até virar um oval de 384×96 — foi como a
   "foto achatada" apareceu no painel, e só ali: na página pública a foto não
   mora dentro de um `.entre`. */
.cartao > .entre > .perfil-foto,
.cartao > .entre > .foto,
.cartao > .entre > img { flex: none; }
.cartao > .entre > .selo { flex: 0 0 auto; white-space: nowrap; }

/* Cartão de grade é uma coluna: cabeçalho em cima, texto no meio, ação no pé.
   Com isso os botões do fim ficam na mesma altura em toda a linha, mesmo com
   textos de tamanhos diferentes — que é o alinhamento que se vê. */
.grade > .cartao, .grade > a.cartao, .grade > form.cartao {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.grade > .cartao > .linha-acoes,
.grade > .cartao > form:last-child,
.grade > .cartao > .botao:last-child { margin-top: auto; }

/* ── O desalinhamento que estava em toda grade de cartões (15/08/2026) ──
 *
 * `.cartao + .cartao { margin-top: 16px }` existe para cartões **empilhados**,
 * um embaixo do outro. Dentro de uma grade ela continuava valendo — e como o
 * primeiro cartão da linha não tem irmão antes dele, ele ficava 16 px **acima**
 * de todos os outros. Era exatamente isso que se via: o primeiro cartão
 * "subindo" e o resto da linha desalinhado, em toda tela que usa grade.
 *
 * Na grade quem separa é o `gap`; a margem sobra e atrapalha. */
.grade > .cartao + .cartao,
.grade > a.cartao + a.cartao,
.grade > form.cartao + form.cartao { margin-top: 0; }

/* O título encolhe antes de empurrar o selo para a linha de baixo: com uma
   largura mínima fixa, um selo comprido ("40% para o artista") quebrava a linha
   e derrubava o texto do cartão inteiro alguns pixels. */
.cartao > .entre > h3,
.cartao > .entre > h4 { flex: 1 1 auto; }

/* ── Foto de produto no catálogo e na galeria (15/08/2026) ── */
.produto-linha { display: flex; gap: 12px; align-items: flex-start; }
.produto-capa {
  flex: 0 0 auto;
  width: 56px;
  height: 56px;
  border-radius: var(--raio-p);
  background: var(--fundo-3) center/cover no-repeat;
  border: 1px solid var(--borda);
}
.galeria-admin { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 10px; }
.galeria-item { position: relative; }
.galeria-foto {
  width: 92px;
  height: 92px;
  border-radius: var(--raio-p);
  background: var(--fundo-3) center/cover no-repeat;
  border: 1px solid var(--borda);
}
/* O apagar fica **sobre** a foto, no canto: em lista de miniaturas, um botão
   embaixo de cada uma dobra a altura da tira. */
.galeria-item form { position: absolute; top: 4px; right: 4px; }

/* ── A galeria do produto, do lado do fã ── */
.galeria-fa { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.galeria-mini {
  width: 68px;
  height: 68px;
  border-radius: var(--raio-p);
  background: var(--fundo-3) center/cover no-repeat;
  border: 2px solid var(--borda);
}
.galeria-mini.ativa { border-color: var(--marca); }
.galeria-mini:hover { border-color: var(--marca-clara); }

/* Tamanho como botão: no celular, escolher tamanho é a decisão mais rápida da
   compra, e uma lista suspensa custa dois toques a mais. O `radio` continua
   sendo o que vai no formulário — só a aparência muda. */
.escolha-variacao { display: flex; gap: 8px; flex-wrap: wrap; }
.variacao input { position: absolute; opacity: 0; width: 0; height: 0; }
.variacao span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 52px;
  min-height: var(--toque);
  padding: 0 14px;
  border: 1px solid var(--borda);
  border-radius: var(--raio-p);
  background: var(--fundo-2);
  cursor: pointer;
  font-weight: 600;
}
.variacao input:checked + span { border-color: var(--marca); background: var(--marca); color: var(--texto-na-marca); }
.variacao input:focus-visible + span { outline: 2px solid var(--pe-azul); outline-offset: 2px; }

/* ── Assistente de senha (public/js/senha.js) ──────────────────────────────
   A régua de senha endureceu em 15/08/2026, e régua dura sem ajuda produz
   "Show2026!" em todo mundo. O bloco abaixo é o que aparece embaixo de todo
   campo de senha nova: o botão que sugere uma pronta, o que mostra o que foi
   digitado e a lista do que ainda falta — verde no que já está, vermelho no
   que não. Sem JavaScript nada disso existe e o formulário segue igual. */
.senha-ajuda { margin-top: 8px; }
.senha-ajuda .fita { gap: 8px; }
.senha-regras { list-style: none; padding: 0; margin: 10px 0 0; display: flex; flex-wrap: wrap; gap: 6px 14px; }
.senha-regras li { position: relative; padding-left: 18px; color: var(--texto-3); }
.senha-regras li::before { content: '○'; position: absolute; left: 0; }
.senha-regras li.ok { color: var(--ok); }
.senha-regras li.ok::before { content: '✔'; }
.senha-regras li.falta { color: var(--erro-texto); }
.senha-regras li.falta::before { content: '✕'; }

/* ── Banner do RofSom Ads (parciais/anuncio.ejs) ───────────────────────────
   O espaço se adapta à peça, e não o contrário: a arte entra com a largura
   máxima que couber e mantém a proporção (`height:auto`), porque o anunciante
   manda 970×90 e o ouvinte abre em 360 px. `max-width` na medida declarada
   impede a peça pequena de ser esticada e virar borrão. */
.anuncio { margin: 22px auto; text-align: center; max-width: 100%; }
.anuncio-selo {
  font-size: 10px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--texto-3); margin: 0 0 6px;
}
.anuncio img { max-width: 100%; height: auto; border-radius: 10px; display: inline-block; }
.anuncio a:focus-visible { outline: 2px solid var(--pe-azul); outline-offset: 3px; }

/* ── O estúdio da estação (admin/radio-estudio) ────────────────────────────
   Os efeitos são uma grade de botões grandes o bastante para serem acertados
   sem olhar: quem está no ar tem o olho no texto que vai ler, não na tela. A
   cor vem do próprio efeito (a borda), e a tecla de atalho fica escrita no
   canto — no ar ninguém lembra qual era o terceiro da esquerda. */
.efeitos { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
.efeito {
  position: relative; min-height: 64px; padding: 12px 14px; text-align: left;
  background: var(--fundo-2); color: var(--texto); cursor: pointer;
  border: 1px solid var(--linha); border-left-width: 4px; border-radius: 10px;
  font-weight: 600; font-size: 14px; line-height: 1.3;
}
.efeito:hover { background: var(--fundo-3, var(--fundo-2)); transform: translateY(-1px); }
.efeito:active { transform: translateY(1px); }
.efeito:focus-visible { outline: 2px solid var(--pe-azul); outline-offset: 2px; }
.efeito-nome { display: block; }
.efeito-tecla {
  position: absolute; top: 8px; right: 10px; font-size: 10px; font-weight: 700;
  color: var(--texto-3); border: 1px solid var(--linha); border-radius: 4px; padding: 1px 5px;
}
@media (max-width: 640px) {
  .efeitos { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); }
  .efeito { min-height: 56px; font-size: 13px; }
}

/* ── A lista do estúdio (estilo ZaraRadio) ─────────────────────────────────
   Duas listas lado a lado: a biblioteca e o que vai ao ar. A linha no ar é
   marcada pela cor da marca e a "próxima" pelo amarelo do sol — as duas
   informações que o operador procura sem ler, com o olho de canto. */
.lista-estudio { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 6px; }
.item-estudio {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 10px; border: 1px solid var(--linha); border-radius: 8px;
  background: var(--fundo-2); font-size: 13.5px;
}
.item-estudio .item-texto { min-width: 0; }
.item-estudio .item-texto strong { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.item-estudio .item-texto span { font-size: 12px; }
.item-estudio.fora-do-ar { opacity: 0.72; border-style: dashed; }
.lista-ar .item-estudio { cursor: grab; }
.lista-ar .item-estudio.arrastando { opacity: 0.5; }
.lista-ar .item-estudio.alvo { border-color: var(--pe-azul); }
.lista-ar .item-estudio.no-ar { border-left: 4px solid var(--marca); background: rgba(200, 16, 46, 0.08); }
.lista-ar .item-estudio.proximo { border-left: 4px solid var(--pe-amarelo); }

/* ── Quem está logado, no cabeçalho (16/08/2026) ───────────────────────────
   Foto, @ e nome respondem sem clique a "estou logado como quem?" — a pergunta
   de quem volta num aparelho compartilhado, que no camarim é a diferença entre
   publicar na conta certa e na errada. No celular sobra só a foto: o nome
   comeria a linha inteira, e a foto já responde a pergunta. */
.topo-perfil {
  display: inline-flex; align-items: center; gap: 8px; text-decoration: none;
  color: var(--texto); padding: 4px 10px 4px 4px; border: 1px solid var(--linha);
  border-radius: 999px; background: var(--fundo-2); max-width: 220px;
}
.topo-perfil:hover { border-color: var(--marca); }
.topo-perfil:focus-visible { outline: 2px solid var(--pe-azul); outline-offset: 2px; }
.topo-avatar {
  width: 28px; height: 28px; border-radius: 50%; flex: 0 0 28px;
  background-size: cover; background-position: center; background-color: var(--fundo-3, var(--fundo));
}
.topo-quem { display: flex; flex-direction: column; line-height: 1.15; min-width: 0; }
.topo-quem strong { font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topo-quem .miudo { font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 860px) {
  .topo-perfil { padding: 3px; border-radius: 50%; max-width: none; }
  .topo-quem { display: none; }
}

/* ── Telas de exemplo desenhadas (16/08/2026) ──────────────────────────────
 *
 * Os "prints" da landing (`parciais/tela-modelo.ejs`). Não são imagens: são
 * caixas de HTML com o desenho de uma tela dentro — e essa escolha resolve
 * quatro coisas de uma vez. Acompanham o tema claro e o escuro sozinhas (usam
 * os mesmos tokens do resto da folha); não borram no celular; pesam o que pesa
 * um parágrafo, o que importa no 3G do interior, que é onde metade de quem lê
 * está; e não envelhecem em silêncio quando a página do artista mudar — uma
 * captura de tela envelhece e ninguém percebe.
 *
 * Tudo aqui é ilustração: o texto que interessa está na legenda, que é
 * conteúdo de verdade (`<figcaption>`) e chega a quem usa leitor de tela.
 */
.tm-grade {
  display: grid; gap: 22px;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
}
.tm { margin: 0; display: flex; flex-direction: column; gap: 10px; min-width: 0; }

/* A moldura. `--tm-cor` é a cor daquele expositor: na casa, a paleta da página
   é dele — e é isso que faz sete telas iguais parecerem sete páginas. */
.tm-quadro {
  --tm-cor: var(--marca);
  background: var(--fundo);
  border: 1px solid var(--borda);
  border-radius: var(--raio);
  overflow: hidden;
  box-shadow: var(--sombra);
  width: 100%;
}
.tm-celular {
  max-width: 250px; margin-inline: auto;
  border: 7px solid var(--fundo-3); border-radius: 24px;
}
.tm-janela { border-radius: 10px; }

.tm-barra-janela {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px; background: var(--fundo-3); border-bottom: 1px solid var(--borda);
}
.tm-bolinhas { display: inline-flex; gap: 4px; flex: none; }
.tm-bolinhas i { width: 7px; height: 7px; border-radius: 50%; background: var(--borda); }
.tm-barra-status {
  display: flex; justify-content: space-between;
  padding: 4px 12px; font-size: 9px; color: var(--texto-3); background: var(--fundo-2);
}
.tm-url {
  font-size: 9.5px; color: var(--texto-2); background: var(--fundo-2);
  border-radius: 999px; padding: 3px 9px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tm-url-celular { display: block; margin: 0 8px 4px; border: 1px solid var(--borda); }

.tm-tela { display: grid; gap: 7px; padding: 8px; font-size: 10.5px; line-height: 1.35; }
.tm-tela > * { min-width: 0; }
.tm-fraco { color: var(--texto-3); font-weight: 400; }

/* A casca da casa dentro do print: marca em cima e a rádio na segunda linha,
   que é onde ela mora de verdade em toda tela pública. */
.tm-topo {
  display: flex; align-items: center; justify-content: space-between;
  border-bottom: 2px solid var(--marca-casa); padding-bottom: 5px;
}
.tm-marca { font-weight: 700; color: var(--marca-casa); font-size: 11px; }
.tm-topo-menu { color: var(--texto-3); }
.tm-radio-topo {
  display: flex; align-items: center; gap: 6px;
  background: var(--fundo-2); border: 1px solid var(--borda); border-radius: 999px;
  padding: 3px 8px; color: var(--texto-2); font-size: 9.5px;
}
.tm-play {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; border-radius: 50%; flex: none;
  background: var(--marca-casa); color: #fff; font-size: 8px;
}
.tm-play-grande { width: 24px; height: 24px; font-size: 10px; background: var(--tm-cor); }

/* ── O painel, desenhado ───────────────────────────────────────────────────
 * A tela de quem entrou com login: menu das seções à esquerda, trabalho à
 * direita. O menu inteiro aparece porque ele **é** o argumento da tela — não é
 * uma página, é um sistema com dezoito seções. Numa tela estreita ficam só os
 * ícones: dezoito rótulos numa coluna de 60 px viram dezoito linhas quebradas,
 * e aí o menu passa a dizer o contrário do que devia. */
.tm-topo-painel { border-bottom-color: var(--borda); }
.tm-topo-painel .tm-marca em { font-style: normal; font-size: 8.5px; color: var(--texto-3); letter-spacing: 0.14em; text-transform: uppercase; }
.tm-topo-acoes { display: flex; gap: 4px; }
.tm-topo-acoes i {
  font-style: normal; font-size: 8px; color: var(--texto-2);
  border: 1px solid var(--borda); border-radius: 999px; padding: 2px 6px; white-space: nowrap;
}
.tm-painel { display: grid; grid-template-columns: 108px 1fr; gap: 8px; align-items: start; }
.tm-painel-menu { display: grid; gap: 1px; }
.tm-painel-menu span {
  display: flex; align-items: center; gap: 5px;
  font-size: 8.5px; color: var(--texto-2); padding: 3px 5px; border-radius: 5px;
}
.tm-painel-menu i { font-style: normal; width: 12px; text-align: center; font-size: 9px; line-height: 1; }
.tm-painel-menu em { font-style: normal; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-menu-ativo { background: var(--fundo-2); color: var(--texto); font-weight: 700; }
.tm-menu-ativo i { color: var(--marca); }
.tm-painel-corpo {
  display: grid; gap: 6px; min-width: 0;
  border-left: 1px solid var(--borda); padding-left: 8px;
}

.tm-cabeca { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.tm-cabeca > span { display: grid; min-width: 0; }
.tm-cabeca i { font-style: normal; font-size: 8px; color: var(--marca-clara); text-transform: uppercase; letter-spacing: 0.1em; }
.tm-cabeca strong { font-size: 12px; }
.tm-cabeca em { font-style: normal; font-size: 8.5px; color: var(--texto-3); }

.tm-capa {
  height: 46px; border-radius: var(--raio-p);
  background: linear-gradient(120deg, var(--tm-cor), var(--fundo-3) 78%);
  display: flex; align-items: flex-end; padding: 6px; color: #fff; font-size: 9px;
}

.tm-perfil { display: flex; gap: 8px; align-items: flex-start; margin-top: -18px; padding-left: 4px; }
.tm-avatar {
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  display: flex; align-items: center; justify-content: center; font-size: 15px;
  background: var(--fundo-3); border: 2px solid var(--fundo);
}
.tm-avatar-quadrado { border-radius: 8px; }
.tm-perfil-dados { padding-top: 16px; min-width: 0; }
.tm-nome { margin: 0; font-weight: 700; font-size: 12px; color: var(--texto); }
.tm-sub { margin: 0; font-size: 9.5px; color: var(--texto-2); }
.tm-selo-ok { color: var(--pe-azul-clara); }

.tm-selos { display: flex; flex-wrap: wrap; gap: 4px; }
.tm-etiqueta {
  font-size: 8.5px; font-weight: 600; letter-spacing: 0.04em;
  border: 1px solid var(--borda); border-radius: 999px; padding: 2px 7px; color: var(--texto-2);
}
.tm-etiqueta-vivo { background: var(--aovivo); border-color: var(--aovivo); color: #fff; }
.tm-etiqueta-ok { border-color: var(--ok); color: var(--ok); }

.tm-acoes { display: flex; flex-wrap: wrap; gap: 5px; }
.tm-botao {
  font-size: 9.5px; font-weight: 600; border-radius: 999px; padding: 4px 10px;
  border: 1px solid var(--borda); color: var(--texto-2); background: var(--fundo-2);
}
.tm-botao-marca { background: var(--tm-cor); border-color: var(--tm-cor); color: #fff; }
.tm-botao-estado { background: var(--pe-azul); border-color: var(--pe-azul); color: #fff; }

.tm-player {
  display: flex; align-items: center; gap: 7px;
  background: var(--fundo-2); border: 1px solid var(--borda); border-radius: var(--raio-p); padding: 6px 8px;
}
.tm-player-dados { display: grid; min-width: 0; }
.tm-player-dados strong { font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-player-dados span { font-size: 8.5px; color: var(--texto-3); }
.tm-onda { display: flex; align-items: flex-end; gap: 2px; margin-left: auto; height: 14px; }
.tm-onda i { width: 2px; background: var(--tm-cor); border-radius: 1px; }
.tm-onda i:nth-child(1) { height: 5px; }
.tm-onda i:nth-child(2) { height: 11px; }
.tm-onda i:nth-child(3) { height: 7px; }
.tm-onda i:nth-child(4) { height: 14px; }
.tm-onda i:nth-child(5) { height: 6px; }
.tm-onda i:nth-child(6) { height: 10px; }
.tm-onda i:nth-child(7) { height: 4px; }

.tm-titulo {
  margin: 3px 0 0; font-weight: 700; font-size: 10px; color: var(--texto);
  text-transform: uppercase; letter-spacing: 0.06em;
}
/* O complemento do título ("ver agenda", "8 artistas") fica fora da caixa
   alta: em maiúscula ele vira parte do título e a linha passa a ler
   "SHOWS VER AGENDA", que não é o que a tela mostra. */
.tm-titulo .tm-fraco { text-transform: none; letter-spacing: 0; font-size: 9px; }

.tm-lista { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.tm-lista li {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  background: var(--fundo-2); border: 1px solid var(--borda); border-radius: 8px; padding: 5px 7px;
}
.tm-lista-texto { display: grid; min-width: 0; }
.tm-lista-texto strong { font-size: 9.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tm-lista-texto span { font-size: 8.5px; color: var(--texto-3); }
.tm-lista-dir { font-size: 9px; color: var(--texto-2); font-weight: 600; flex: none; }

.tm-videos { display: grid; grid-template-columns: repeat(auto-fit, minmax(70px, 1fr)); gap: 5px; }
.tm-video {
  position: relative; display: flex; align-items: flex-end; height: 46px; padding: 4px;
  border-radius: 8px; background: linear-gradient(160deg, var(--fundo-3), var(--fundo-2));
  border: 1px solid var(--borda);
}
.tm-video em { font-size: 8px; font-style: normal; color: var(--texto-2); }
.tm-video-play {
  position: absolute; inset: 0; margin: auto; width: 18px; height: 18px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; font-style: normal; font-size: 8px;
  background: rgba(0, 0, 0, 0.55); color: #fff;
}

.tm-fotos { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
.tm-foto {
  height: 38px; border-radius: 6px; border: 1px solid var(--borda);
  /* Gradiente, e não uma cor chapada: no tema claro um quadrado cinza-claro
     sobre branco some, e a grade de fotos do mídia kit deixa de existir. */
  background: linear-gradient(150deg, var(--fundo-3), var(--borda));
}

.tm-cartoes { display: grid; grid-template-columns: repeat(auto-fill, minmax(66px, 1fr)); gap: 5px; }
.tm-cartao-mini {
  display: grid; justify-items: center; gap: 2px; text-align: center;
  background: var(--fundo-2); border: 1px solid var(--borda); border-radius: 8px; padding: 6px 4px;
}
.tm-cartao-mini strong { font-size: 8.5px; }
.tm-cartao-mini em { font-size: 8px; font-style: normal; color: var(--texto-3); }
.tm-avatar-mini {
  width: 22px; height: 22px; border-radius: 50%; background: var(--fundo-3);
  display: flex; align-items: center; justify-content: center; font-size: 11px; font-style: normal;
}

.tm-texto { margin: 0; font-size: 9.5px; color: var(--texto-2); }
.tm-linhas { display: grid; gap: 4px; }
.tm-linhas i { height: 5px; border-radius: 3px; background: var(--fundo-3); }
.tm-linhas i:last-child { width: 62%; }

.tm-campos { display: grid; gap: 5px; }
.tm-campo { display: grid; gap: 2px; }
.tm-campo em { font-size: 8.5px; font-style: normal; color: var(--texto-3); }
.tm-campo i {
  font-style: normal; font-size: 9.5px; color: var(--texto-2);
  background: var(--fundo-2); border: 1px solid var(--borda); border-radius: 6px; padding: 4px 7px;
}

.tm-marcar { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; font-size: 9.5px; color: var(--texto-2); }
.tm-marcar li { display: flex; align-items: center; gap: 6px; }
.tm-caixa {
  width: 12px; height: 12px; flex: none; border-radius: 3px; border: 1px solid var(--borda);
  display: flex; align-items: center; justify-content: center; font-size: 8px;
}
.tm-caixa-on { background: var(--ok); border-color: var(--ok); color: #04240f; }

.tm-push {
  display: grid; gap: 2px; background: var(--fundo-2); border: 1px solid var(--borda);
  border-radius: 10px; padding: 7px 9px;
}
.tm-push-app { display: flex; align-items: center; gap: 5px; font-size: 8.5px; color: var(--texto-3); }
.tm-push-app i { width: 10px; height: 10px; border-radius: 3px; background: var(--marca-casa); }
.tm-push strong { font-size: 10px; }
.tm-push-sub { font-size: 9px; color: var(--texto-2); }

.tm-busca {
  background: var(--fundo-2); border: 1px solid var(--borda); border-radius: 999px;
  padding: 6px 10px; font-size: 9.5px; color: var(--texto-2);
}
.tm-resultado { display: grid; gap: 1px; padding: 4px 2px; }
.tm-resultado-url { font-size: 8.5px; color: var(--ok); }
.tm-resultado strong { font-size: 10px; color: var(--pe-azul-clara); }
.tm-resultado span { font-size: 8.5px; color: var(--texto-3); }

.tm-conversa { display: grid; gap: 5px; }
.tm-balao {
  justify-self: start; max-width: 88%; font-size: 9.5px; color: var(--texto);
  background: var(--fundo-2); border: 1px solid var(--borda);
  border-radius: 10px 10px 10px 2px; padding: 5px 8px;
}
.tm-balao-eu {
  justify-self: end; border-radius: 10px 10px 2px 10px;
  background: rgba(31, 157, 85, 0.18); border-color: rgba(31, 157, 85, 0.4);
}

.tm-baixar {
  display: grid; gap: 4px; justify-items: start;
  background: var(--fundo-2); border: 1px dashed var(--borda); border-radius: 8px; padding: 8px;
}
.tm-baixar strong { font-size: 10px; }
.tm-baixar span:not(.tm-botao) { font-size: 8.5px; color: var(--texto-3); }

.tm-abas { display: flex; gap: 8px; font-size: 9px; color: var(--texto-3); border-bottom: 1px solid var(--borda); padding-bottom: 4px; }
.tm-aba-ativa { color: var(--tm-cor); font-weight: 700; }

.tm-numeros { display: grid; grid-template-columns: repeat(auto-fit, minmax(56px, 1fr)); gap: 5px; }
.tm-numero {
  display: grid; justify-items: center; background: var(--fundo-2);
  border: 1px solid var(--borda); border-radius: 8px; padding: 5px 3px;
}
.tm-numero strong { font-size: 12px; color: var(--pe-azul-clara); }
.tm-numero em { font-size: 8px; font-style: normal; color: var(--texto-3); text-align: center; }

.tm-aviso {
  margin: 0; font-size: 9px; color: var(--texto-2); background: var(--fundo-2);
  border-left: 3px solid var(--atencao); border-radius: 6px; padding: 5px 7px;
}

/* A legenda é o que a tela desenhada não consegue dizer sozinha — e é o que o
   leitor de tela recebe no lugar do desenho. */
.tm-legenda { display: grid; gap: 3px; font-size: 13px; color: var(--texto-2); }
.tm-legenda strong { color: var(--texto); }
.tm-legenda span { font-size: 12.5px; color: var(--texto-3); }
.tm-passo {
  justify-self: start; display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%; font-size: 12px; font-weight: 700;
  background: var(--marca); color: var(--texto-na-marca);
}

/* O fluxo: quadro, seta, quadro. No celular a seta vira ↓ — e a fila vira uma
   coluna, que é como a pessoa lê um passo a passo com o polegar. */
.tm-fluxo-titulo { margin: 26px 0 12px; }
/* A tela do painel é larga: ela mostra o menu e o trabalho lado a lado, que é
   como ele vai abrir na primeira vez. Espremida numa coluna da grade, viraria
   um borrão de letra pequena. */
.tm-largo { max-width: 900px; margin-inline: auto; }
.tm-fluxo { display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
.tm-fluxo .tm { flex: 1 1 220px; max-width: 300px; }
.tm-seta { align-self: center; color: var(--texto-3); font-size: 20px; padding-top: 40px; flex: none; }

@media (max-width: 760px) {
  /* Numa coluna só, o celular desenhado pode crescer: com 250 px no meio de
     uma tela de 360 sobra faixa vazia dos dois lados e a tela fica menor do
     que precisa ser para se ler o que está escrito nela. */
  .tm-celular { max-width: 300px; }
  /* Dezoito rótulos numa coluna estreita viram dezoito linhas quebradas — o
     menu passaria a dizer o contrário do que ele existe para dizer. Ficam os
     ícones, e a seção aberta continua marcada. */
  .tm-painel { grid-template-columns: 26px 1fr; gap: 5px; }
  .tm-painel-menu em { display: none; }
  .tm-painel-menu span { justify-content: center; padding: 3px 2px; }
  .tm-fluxo { flex-direction: column; align-items: stretch; }
  .tm-fluxo .tm { max-width: none; }
  .tm-seta { align-self: center; padding-top: 0; }
  .tm-seta::before { content: '↓'; }
  .tm-seta { font-size: 0; }
  .tm-seta::before { font-size: 20px; }
}

/* Documento do artista lido dentro da página (ver `parciais/documento.ejs`).
   A altura é fixa em proporção de folha: quadro de leitura curto demais faz o
   contratante desistir e sair para o Drive, que é o que se quer evitar. */
.documento-quadro { position: relative; width: 100%; aspect-ratio: 3 / 4; max-height: 70vh; border: 1px solid var(--borda); border-radius: 10px; overflow: hidden; background: var(--fundo-2); }
.documento-quadro iframe { display: block; width: 100%; height: 100%; border: 0; }
@media (min-width: 700px) { .documento-quadro { aspect-ratio: 4 / 3; } }

/* ── Primeiros passos do painel (23/08/2026) ──────────────────────────────
   O painel abria igual para quem tem página há um ano e para quem entrou hoje,
   e para o segundo era um mosaico de caixas zeradas. Esta lista é o contrário
   disso: uma coisa por linha, o feito marcado e **um** botão só — o do próximo
   passo. Cinco botões ao mesmo tempo é o que faz a pessoa fechar a aba. */
.passos { background: var(--fundo-2); border: 1px solid var(--borda); border-radius: var(--raio); padding: 16px; }
.passos-barra { height: 6px; border-radius: 999px; background: var(--fundo-3); margin: 12px 0 4px; overflow: hidden; }
.passos-barra span { display: block; height: 100%; background: var(--marca); border-radius: 999px; transition: width 0.3s; }
.passos-lista { list-style: none; margin: 8px 0 0; padding: 0; }
.passo {
  display: grid; grid-template-columns: 26px 1fr auto; align-items: center; gap: 12px;
  padding: 12px 4px; border-top: 1px solid var(--borda);
}
.passo:first-child { border-top: 0; }
.passo p { margin: 2px 0 0; }
.passo-marca {
  width: 22px; height: 22px; border-radius: 50%; border: 2px solid var(--borda);
  display: grid; place-items: center; font-size: 13px; font-weight: 700; color: var(--texto-3);
}
.passo.feito .passo-marca { background: var(--ok, #1f9d55); border-color: transparent; color: #fff; }
.passo.feito strong { color: var(--texto-3); text-decoration: line-through; text-decoration-thickness: 1px; }
.passo.feito p { display: none; }
/* O próximo passo é o único que ganha peso: é onde a pessoa deve olhar. */
.passo.agora { background: var(--fundo-3); border-radius: var(--raio-p); }
.passo.agora .passo-marca { border-color: var(--marca); color: var(--marca); }
@media (max-width: 560px) {
  .passo { grid-template-columns: 26px 1fr; }
  .passo > a, .passo > .botao { grid-column: 2; justify-self: start; }
}

/* ── As ações da página do artista (23/08/2026) ────────────────────────────
   Seguir, contratar, mídia kit e loja moravam numa coluna estreita dentro do
   cabeçalho, junto de um `<details>` que abria um QR de 220 px — cinco botões
   largos empilhados espremendo o nome e empurrando o resto da tela. Agora eles
   são uma barra de largura total logo abaixo do cabeçalho: em linha no
   computador, um embaixo do outro no celular, e o QR saiu daqui para a seção
   de contato, onde ele tem espaço para existir. */
.acoes-artista {
  width: var(--largura); margin-inline: auto; padding: 6px var(--respiro) 0;
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
}
/* Os botões da página do artista vestem a **cor dele**, não o cinza da casa: a
   paleta vem de `artistas.cor_marca` (ver `core/cores.js`, que injeta `--marca`
   nesta página). Fundo fantasma transparente fazia a página de todo mundo
   parecer a mesma — e a identidade que o expositor escolheu no painel não
   chegava até aqui. O contraste do texto vem de `--texto-na-marca`, calculado
   junto com a paleta, para a cor clara não virar texto branco em fundo claro. */
.acoes-artista .botao { flex: 1 1 220px; justify-content: center; text-align: center; }
.acoes-artista .botao.fantasma {
  background: color-mix(in srgb, var(--marca) 14%, transparent);
  border-color: color-mix(in srgb, var(--marca) 42%, transparent);
  color: var(--texto);
}
.acoes-artista .botao.fantasma:hover {
  background: color-mix(in srgb, var(--marca) 24%, transparent);
  border-color: var(--marca);
}
.acoes-artista .recado-previa { flex: 1 1 100%; margin: 0; }
@media (max-width: 560px) { .acoes-artista .botao { flex: 1 1 100%; } }

/* O contato ganhou seção própria, e o QR deixou de ser um detalhe espremido:
   ele fica ao lado do texto no computador e por baixo no celular. */
/* O bloco do QR tem a largura da imagem, e a legenda vive dentro dela: solta,
   ela se espalhava pela linha inteira, ficava maior que o próprio código e
   parecia desalinhada dele. No celular o bloco inteiro vai para o meio, embaixo
   dos botões. */

/* ── Voltar, avançar e atualizar do aplicativo instalado ───────────────────
   Só existem quando a casa abre como app (sem barra de navegador). No
   navegador comum eles não aparecem: repetir botão que a pessoa já tem ali em
   cima é gastar espaço da tela pequena com nada. */
/* Três caminhos para o mesmo lugar, porque um só não alcança todo mundo: a
   media query (o jeito certo, quando o aparelho respeita), o crachá que o
   JavaScript escreve no `<body>` (iPhone e atalhos que abrem em minimal-ui) e a
   tela pequena — no celular a barra do navegador some ao rolar, e ter o voltar
   à mão ajuda mesmo fora do app. No computador eles não aparecem: ali a barra
   está sempre lá, e repetir botão é gastar espaço com o que já existe. */
.nav-pwa { display: none; gap: 4px; align-items: center; margin-right: 6px; }
@media (display-mode: standalone), (display-mode: fullscreen), (display-mode: minimal-ui) {
  .nav-pwa { display: flex; }
}
body[data-app="sim"] .nav-pwa { display: flex; }
@media (max-width: 700px) { .nav-pwa { display: flex; } }
.nav-pwa-botao {
  width: var(--toque); height: var(--toque); min-height: var(--toque);
  display: grid; place-items: center; font-size: 22px; line-height: 1;
  background: var(--fundo-2); color: var(--texto); border: 1px solid var(--borda);
  border-radius: var(--raio-p); cursor: pointer; padding: 0;
}
.nav-pwa-botao:hover { background: var(--fundo-3); }
.nav-pwa-botao[disabled] { opacity: 0.5; cursor: default; }

/* O volume da rádio do artista: o único ajuste que uma rádio tem. Some em telas
   muito estreitas, onde o botão de play precisa de todo o espaço. */
.player-volume { display: flex; align-items: center; gap: 6px; }
.player-volume input[type="range"] { width: 92px; accent-color: var(--marca); }
@media (max-width: 420px) { .player-volume input[type="range"] { width: 64px; } }

/* O cartão de post do Instagram: mesmo desenho do quadro de vídeo, mas é um
   link — o embed deles passou a exigir sessão e virava um retângulo vazio. */
.video-externo .video-capa { display: grid; place-items: center; text-decoration: none; }
.video-externo .video-play { font-size: 26px; }

/* ── O vídeo que fica no canto (23/08/2026) ────────────────────────────────
   Ele nasceu no lugar da capa, dentro da página, e morria a cada rolagem ou
   navegação. Agora mora aqui: fixo, por cima de tudo, do tamanho de um quadro
   que dá para assistir sem tomar a tela — a pessoa continua lendo a agenda,
   abre a loja, muda de artista, e o vídeo segue. No celular ele ocupa a
   largura, porque um quadro pequeno num aparelho pequeno não se assiste. */
.video-flutuante {
  position: fixed; right: 16px; bottom: 16px; z-index: 60; width: min(380px, calc(100vw - 32px));
  background: var(--fundo-2); border: 1px solid var(--borda); border-radius: var(--raio);
  box-shadow: var(--sombra); overflow: hidden;
}
.video-flutuante-barra { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 8px 6px 12px; }
.video-flutuante-barra > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.video-flutuante-botao {
  width: 32px; height: 32px; display: grid; place-items: center; font-size: 18px; line-height: 1;
  background: var(--fundo-3); color: var(--texto); border: 1px solid var(--borda);
  border-radius: 8px; cursor: pointer; text-decoration: none;
}
.video-flutuante-quadro { position: relative; aspect-ratio: 16 / 9; background: #000; }
.video-flutuante-quadro iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.video-flutuante-recado { padding: 12px; margin: 0; font-size: 13px; color: var(--texto-2); }
@media (max-width: 560px) { .video-flutuante { right: 8px; left: 8px; bottom: 8px; width: auto; } }

/* ── A janela do post (23/08/2026) ─────────────────────────────────────────
   O Instagram não deixa mostrar o post embutido, e mandar o visitante para
   fora era perdê-lo no meio da página do artista. A janela mostra o que a casa
   tem — a foto de prévia em tamanho de gente, a legenda inteira — e deixa as
   saídas à mão. */
/* ── Voltar ao topo ────────────────────────────────────────────────────────
   No canto **esquerdo**: o direito é do vídeo flutuante, que no celular ocupa
   quase a largura toda. `z-index` acima dele, abaixo da janela do post — um
   botão de rolagem não tem o que fazer por cima de um diálogo aberto.
   `env(safe-area-inset-bottom)` porque no iPhone o rodapé do sistema comeria
   metade dele no aplicativo instalado. */
.ao-topo {
  position: fixed;
  left: 16px;
  bottom: calc(16px + env(safe-area-inset-bottom, 0px));
  z-index: 61;
  width: 46px; height: 46px;
  border-radius: 50%;
  border: 1px solid var(--borda);
  background: var(--fundo-2);
  color: var(--texto);
  font-size: 19px; line-height: 1;
  cursor: pointer;
  display: grid; place-items: center;
  box-shadow: var(--sombra);
}
.ao-topo:hover { background: var(--fundo-3); }
.ao-topo[hidden] { display: none; }

.post-modal { position: fixed; inset: 0; z-index: 80; display: grid; place-items: center; padding: 16px; }
.post-modal-fundo { position: absolute; inset: 0; background: rgba(0, 0, 0, 0.72); }
.post-modal-caixa {
  /* Largura maior: a janela é para **ver** o post, e 560 px deixavam a arte
     pequena numa tela de computador. */
  position: relative; z-index: 1; width: min(760px, 100%); max-height: 92vh; overflow: auto;
  background: var(--fundo-2); border: 1px solid var(--borda); border-radius: var(--raio); box-shadow: var(--sombra);
}
.post-modal-x {
  position: absolute; top: 8px; right: 8px; z-index: 2;
  width: 36px; height: 36px; border-radius: 50%; border: 0; cursor: pointer;
  background: rgba(0, 0, 0, 0.55); color: #fff; font-size: 16px; line-height: 1;
}
/* `contain` e não `cover`: a arte do post é o conteúdo, e cortar as bordas
   dela para preencher o quadrado é apagar justamente o que se veio ver. */
.post-modal-foto { width: 100%; aspect-ratio: 1; max-height: 62vh; background: #000 center/contain no-repeat; }
.post-modal-topo { gap: 10px; margin-bottom: 8px; }
.post-modal-corpo { padding: 16px; }
.post-modal-legenda { margin: 0 0 12px; color: var(--texto-2); font-size: 14px; overflow-wrap: anywhere; }
/* **A legenda não é mais dobrada** (23/08/2026).

   Ela nascia cortada em 6 linhas, com um botão para abrir. Só que legenda de
   Instagram é escrita em blocos, com linha em branco entre eles — e como as
   quebras são preservadas (`pre-wrap`), aquelas 6 linhas mal chegavam ao fim do
   primeiro parágrafo. O resultado na tela era **exatamente igual** ao defeito
   que o corte de 180 caracteres no banco já causava: o cliente olhou e disse
   que os posts continuavam cortados. Estava certo — o texto tinha chegado
   inteiro ao navegador e a folha de estilo o cortava de novo.

   Não é preciso dobrar nada: a janela já rola sozinha (`max-height: 92vh` com
   `overflow: auto` em `.post-modal-caixa`), que é o jeito de mostrar um texto
   longo sem escondê-lo. */
.post-modal-numeros { margin: 0 0 8px; }
/* O porquê de o vídeo abrir fora: fica junto do botão que leva para lá. */
.post-modal-aviso { margin: 0 0 10px; }
/* A foto abre o post — quem clica numa capa de reel quer assistir, e o quadro
   oficial do Instagram monta aqui dentro. Tocando, ela deixa de ser uma imagem
   de proporção fixa e passa a acompanhar o quadro: reel é vertical, e forçá-lo
   num quadrado cortaria justamente o vídeo. */
.post-modal-foto { cursor: pointer; position: relative; }
/* Com o quadro montado, a caixa deixa de ser um quadrado de imagem e passa a
   ser um palco: reel é vertical e post de feed é quase quadrado, e o player
   deles centraliza o que for dentro. O teto em pixel evita a moldura gigante
   num monitor alto. */
/* Com o quadro montado, a caixa ganha respiro. O `iframe` do Instagram é um
   cartão branco com cantos próprios; encostado na borda do modal ele fica
   grudado, sem moldura nenhuma entre um e outro. O mesmo respiro do corpo da
   janela (16 px) resolve.

   A altura medida vai no **`iframe`**, não aqui: com `box-sizing: border-box`,
   uma altura fixa no pai seria comida pelo `padding` e o post voltaria a
   aparecer cortado — pelos 28 px que a moldura acabou de ganhar. */
.post-modal-foto.tocando {
  aspect-ratio: auto; max-height: none; height: auto;
  padding: 16px; background: var(--fundo-3);
}
.post-modal-foto iframe {
  display: block; width: 100%; height: 620px; border: 0;
  border-radius: 10px; background: #fff;
  /* ── Uma aparição só, em vez de três ──────────────────────────────────
     Ao abrir, a janela mostrava a miniatura que a casa espelhou, depois o
     quadro do Instagram entrava por cima na altura padrão, e depois ele pulava
     para a altura medida. Três estados em menos de um segundo: parecia defeito.
     Agora o quadro nasce invisível e aparece pronto, e a mudança de altura é
     um movimento e não um salto. */
  opacity: 0;
  transition: opacity 0.2s ease, height 0.2s ease;
}
.post-modal-foto iframe.pronto { opacity: 1; }
/* A barra de ações: duas escritas e o resto em ícone. Eram seis botões de
   texto quebrando em três linhas no celular, todos com o mesmo peso — e aí
   nenhum era o principal. */
.post-modal-acoes { gap: 8px; align-items: center; }
.post-modal-acoes .botao { padding: 8px 12px; font-size: 13px; }
.post-modal-icone {
  width: 36px; height: 36px; flex: none;
  display: grid; place-items: center;
  border: 1px solid var(--borda); border-radius: 9px;
  background: transparent; color: var(--texto-2);
  font-size: 15px; line-height: 1; cursor: pointer; text-decoration: none;
}
.post-modal-icone:hover { background: var(--fundo-3); color: var(--texto); }
/* O paredão de hashtags do fim da legenda: continua na tela, porque é o que a
   pessoa escreveu, mas apagado — não é leitura, é indexação do Instagram. */
.post-modal-tags { font-size: 12px; opacity: 0.6; word-break: break-word; }
.post-modal-legenda p { margin: 0 0 10px; }
/* A menção é o crédito de quem trabalhou no post — precisa parecer clicável,
   sem virar um texto todo colorido: a legenda continua sendo leitura. */
.post-modal-legenda a { color: var(--marca); font-weight: 600; }
.post-modal-tags a { color: inherit; font-weight: 600; }
.post-modal-legenda p:last-child { margin-bottom: 0; }
/* O número da peça, só para o dono e a equipe: identificação de sistema, não
   conteúdo. Discreto de propósito — quem precisa dele sabe que ele está ali. */
.post-ref {
  margin: 6px 0 0; font-size: 11px; letter-spacing: 0.04em;
  color: var(--texto-2); opacity: 0.75;
}
/* O gatilho escrito na capa do post. Fica no rodapé da peça, sobre um degradê,
   para continuar legível em foto clara e em foto escura — a mesma peça serve a
   um cartaz branco e a uma foto de show à noite. */
.video-cta {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 22px 10px 8px;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.78), rgba(0, 0, 0, 0));
  color: #fff; font-size: 13px; font-weight: 600; text-align: left;
}
.video-capa:hover .video-cta,
.video-capa:focus-visible .video-cta { text-decoration: underline; }
.sem-rolagem { overflow: hidden; }

/* ── O palco fixo: a rádio do artista dentro do cabeçalho ──────────────────
   Ela começa dentro da página dele e, quando está tocando, muda-se para cá na
   primeira navegação — o cabeçalho é a única parte que a troca de tela não
   remonta. Aqui o player fica compacto: é um rádio ligado, não uma seção. */
.palco-fixo { border-top: 1px solid var(--borda); background: var(--fundo-2); }
.palco-fixo .player {
  width: var(--largura); margin-inline: auto; padding: 8px var(--respiro);
  border: 0; border-radius: 0; background: transparent;
}
.palco-fixo .player .barra,
.palco-fixo .player .entre { display: none; }
.palco-fixo .player .player-topo { margin: 0; }

/* ── O Top 10 da estação ───────────────────────────────────────────────────
   Uma lista, e não uma grade de cartões: quem lê um Top 10 lê de cima para
   baixo, e a ordem é a informação. O @ é desenhado como o que ele é — um
   endereço para clicar —, com a cor da marca e peso de link, porque é ele que
   quem divulga música veio buscar. O número da posição é grande de propósito:
   é o que faz a seção ser reconhecida de relance como um ranking. */
.top10 { list-style: none; margin: 0; padding: 0; counter-reset: none; }
.top10-linha {
  display: flex; align-items: center; gap: 14px;
  padding: 10px 14px;
  border: 1px solid var(--borda); border-radius: var(--raio);
  background: var(--fundo-2);
}
.top10-linha + .top10-linha { margin-top: 8px; }
.top10-posicao {
  flex: none; width: 34px; text-align: center;
  font-size: 22px; font-weight: 700; color: var(--texto-3);
  font-variant-numeric: tabular-nums;
}
/* Os três primeiros levam a cor da casa: pódio é a única hierarquia que um
   Top 10 promete, e ela precisa ser visível antes da leitura. */
.top10-linha:nth-child(-n + 3) .top10-posicao { color: var(--marca-clara); }
.top10-capa {
  flex: none; width: 46px; height: 46px; border-radius: var(--raio-p);
  background-size: cover; background-position: center;
  border: 1px solid var(--borda);
}
.top10-quem { min-width: 0; flex: 1; }
.top10-musica { display: block; font-size: 15px; }
.top10-autor {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
  margin-top: 2px; font-size: 13px;
}
.top10-autor > a { color: var(--texto-3); }
.top10-autor > a:hover { color: var(--texto-2); }
.top10-arroba { color: var(--marca-clara); font-weight: 600; }
.top10-arroba:hover { text-decoration: underline; }
.top10-vezes { flex: none; color: var(--texto-3); font-size: 12px; text-align: right; }
.top10-vezes strong { display: block; color: var(--texto); font-size: 16px; font-variant-numeric: tabular-nums; }

@media (max-width: 560px) {
  /* No celular a contagem de execuções desce para debaixo do nome: ela é a
     informação menos urgente da linha, e disputando largura com o @ ela
     espremia justamente o que a seção existe para mostrar. */
  .top10-linha { flex-wrap: wrap; gap: 10px; padding: 10px; }
  .top10-posicao { width: 26px; font-size: 18px; }
  .top10-capa { width: 40px; height: 40px; }
  .top10-quem { flex: 1 1 60%; }
  .top10-vezes { flex: 1 1 100%; text-align: left; padding-left: 36px; }
  .top10-vezes strong { display: inline; font-size: 13px; }
}

/* ── O Instagram oficial no alto da "Minha página" ─────────────────────────
   Uma faixa, não um cartão de estatística: o número é o que o artista vem
   buscar, mas o @ é o que confirma que ele está olhando a conta certa. Por
   isso os dois na mesma linha, com o número à direita, no peso de dado. */
.ig-topo { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.ig-topo-icone { font-size: 24px; line-height: 1; }
.ig-topo-quem { min-width: 0; flex: 1; }
.ig-topo-quem .miudo { margin: 2px 0 0; }
@media (max-width: 560px) { .ig-topo { gap: 10px; } }

/* ── Os ícones das plataformas ─────────────────────────────────────────────
   Cada um veste a cor da marca dele: numa fita de oito botões iguais, é a cor
   e a forma que o olho usa para achar o Spotify sem ler nada. As duas exceções
   são deliberadas — o preto do TikTok somiria no tema escuro, e link comum não
   tem marca para vestir; os dois herdam a cor do texto. */
.icone-rede { flex: none; display: block; }
.icone-instagram { color: #e4405f; }
.icone-youtube { color: #ff0000; }
.icone-spotify { color: #1db954; }
.icone-deezer { color: #a238ff; }
.icone-facebook { color: #1877f2; }
.icone-whatsapp { color: #25d366; }
.icone-soundcloud { color: #ff5500; }
.icone-applemusic { color: #fa243c; }
.icone-amazonmusic { color: #00a8e1; }
.icone-suamusica { color: #f5661e; }
.icone-palco_mp3 { color: #ff9000; }
.icone-tiktok,
.icone-site,
.icone-outro { color: var(--texto-2); }

.botao-rede { display: inline-flex; align-items: center; gap: 8px; }
/* O ícone não desbota junto com o botão fantasma: ele é a informação. */
.botao-rede .icone-rede { opacity: 1; }

/* A linha de um link salvo no painel: ícone, @ e endereço. */
.link-linha { display: flex; align-items: center; gap: 10px; }

/* ── Os @ do Instagram, debaixo do nome ────────────────────────────────────
   Fica entre o nome e a frase de efeito, que é onde o olho procura "onde eu
   sigo essa pessoa". Cada @ é uma pastilha clicável; o número de seguidores,
   quando existe, entra em peso de dado dentro dela — e a pastilha sem número
   não fica com um buraco, ela simplesmente termina no @. */
/* **Alinhado à esquerda, e miúdo.** Ele mora entre o nome e a frase de efeito,
   e ali tudo começa no mesmo eixo do `<h1>` — centrar só esta linha a fazia
   flutuar solta no meio do bloco. E é dado de contato, não manchete: pastilha
   grande competia com o nome do artista logo acima.

   `flex-start` está escrito, e não subentendido: a régua do celular centraliza
   cabeçalho e rodapé, e sem isto a herança pegaria esta linha junto. */
.arrobas { display: flex; flex-wrap: wrap; justify-content: flex-start; gap: 6px; margin: 6px 0 10px; }
.arroba {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 9px; border: 1px solid var(--borda); border-radius: 999px;
  background: var(--fundo-2); color: var(--texto-2); font-size: 12px;
}
.arroba:hover { border-color: var(--marca); color: var(--texto); text-decoration: none; }
.arroba strong { color: var(--texto); font-variant-numeric: tabular-nums; margin-left: 2px; }
.arroba .miudo { font-size: 10.5px; }
@media (max-width: 720px) {
  .arrobas { justify-content: flex-start; gap: 5px; }
  .arroba { font-size: 11px; padding: 3px 8px; gap: 5px; }
}

/* A fita das outras plataformas, logo abaixo do @ (06/09/2026).
   Mesma pastilha do @ — é a mesma informação, "onde me achar", e duas formas
   diferentes na mesma altura fariam parecer duas coisas. Sobe colada na linha
   de cima porque as duas são um bloco só; a margem de baixo é a que separa do
   nome artístico e da frase de efeito.
   O rótulo que o artista escreveu pode ser uma frase inteira: aqui ele termina
   em reticências, e o `title` guarda o texto inteiro. Esticar a pastilha seria
   deixar um link empurrar o cabeçalho da página. */
.redes-topo { margin-top: -4px; }
.redes-topo .arroba span {
  max-width: 15ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ig-topo-perfis { display: flex; flex-wrap: wrap; gap: 8px; }
.ig-topo-icone { display: flex; }
@media (max-width: 560px) { .ig-topo-perfis { flex: 1 1 100%; } }

/* A linha de um link no painel: o número de seguidores fica junto do link a que
   ele pertence — quem tem dois @ precisa ver qual número é de qual, e uma caixa
   solta no alto da página não sabe responder isso. */
.link-acoes { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.link-seguidores { display: flex; align-items: center; gap: 6px; }
.link-seguidores label { white-space: nowrap; }
.link-seguidores input {
  width: 92px; text-align: right; font-variant-numeric: tabular-nums;
  background: var(--fundo-3); border: 1px solid var(--borda); color: var(--texto);
  border-radius: var(--raio-p); padding: 5px 8px; font-size: 13px;
}
@media (max-width: 560px) {
  .link-acoes { width: 100%; justify-content: flex-end; }
  .link-seguidores input { width: 78px; }
}

/* A faixa do Instagram no alto de "Minha página": cabeça em cima, um perfil por
   linha embaixo. O campo do número mora **aqui**, e não só na lista de links lá
   embaixo: quem quer publicar o número procura onde o número aparece. */
.ig-topo { display: block; }
.ig-topo-cabeca { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 12px; }
.ig-topo-cabeca .ig-topo-quem { flex: 1; min-width: 0; }
.ig-topo-perfis { display: grid; gap: 8px; }
.ig-perfil { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ig-perfil-numero { display: inline-flex; align-items: baseline; gap: 6px; }
.ig-perfil-numero strong { font-size: 18px; font-variant-numeric: tabular-nums; }
@media (max-width: 560px) {
  .ig-perfil { gap: 8px; }
  .ig-perfil .link-seguidores { flex: 1 1 100%; }
}

/* Enquanto o número não foi respondido, o campo pergunta em voz alta: ele é a
   única origem do dado até o app da casa na Meta existir, e um rótulo de três
   letras ao lado de uma caixinha some no meio da tela. Respondido, encolhe. */
.link-seguidores.pedindo {
  border: 1px dashed var(--marca); border-radius: var(--raio-p);
  padding: 6px 10px; background: var(--fundo-3);
}
.link-seguidores.pedindo label strong { font-size: 13px; color: var(--texto); }

/* ── A caixinha do show (28/08/2026) ──────────────────────────────────────
   O QR do Pix na página do artista e o telão de tela cheia. Duas regras
   mandam no bloco todo: **o QR tem fundo branco fixo** (código é lido por
   contraste, e um QR que segue o tema não escaneia no escuro do show) e o
   telão é claro mesmo no tema escuro, porque a câmera de quem está a três
   metros agradece cada ponto de luz. */
.caixinha-bloco {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  align-items: center;
  margin-top: 14px;
}
.caixinha-qr {
  width: 200px;
  height: 200px;
  padding: 10px;
  background: #fff;
  border-radius: var(--raio-p);
  border: 1px solid var(--borda);
}
.caixinha-lado { flex: 1 1 260px; display: flex; flex-direction: column; gap: 10px; }
.caixinha-lado input { font-family: var(--mono, monospace); font-size: .8rem; }

/* O telão: uma coisa só na tela. */
.telao {
  min-height: 100vh;
  background: #f7f7f5;
  color: #121212;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  padding: 28px 20px 36px;
  text-align: center;
}
.telao-cabeca { display: flex; flex-direction: column; gap: 6px; }
.telao-olho {
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--pe-vermelho);
}
.telao-nome {
  margin: 0;
  font-size: clamp(1.8rem, 5vw, 3rem);
  line-height: 1.05;
  color: #121212;
}
.telao-recado { margin: 0; font-size: clamp(1rem, 2.4vw, 1.3rem); color: #3a3a3a; max-width: 30ch; }
.telao-qr {
  width: min(72vw, 62vh, 520px);
  height: auto;
  background: #fff;
  padding: 14px;
  border-radius: 12px;
  box-shadow: 0 10px 40px -24px rgba(0, 0, 0, .8);
}
.telao-pe { display: flex; flex-direction: column; gap: 4px; }
.telao-titular { margin: 0; font-size: 1.05rem; color: #121212; }
.telao-miudo { margin: 0; font-size: .9rem; color: #5a5a5a; }
.telao-link { font-size: .9rem; color: var(--pe-azul); text-decoration: none; }

/* A fila de trabalho da visão geral do master: uma linha por decisão que
   espera, com o botão que leva à tela onde ela é tomada. Sem cor de alarme —
   fila cheia é o normal de uma casa que funciona, não um erro. */
.lista-fila { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.lista-fila li { padding: 10px 0; border-top: 1px solid var(--borda); }
.lista-fila li:first-child { border-top: 0; }
.lista-fila .realce { font-size: 18px; margin-right: 4px; }

/* ── O título que se edita na própria linha ──────────────────────────────────
   O campo parece texto até receber o clique: sem moldura, sem fundo, na mesma
   fonte e no mesmo peso do resto da tabela. O botão de salvar só existe quando
   o campo está em foco (`:focus-within`), senão cada linha da lista carregaria
   um botão que ninguém vai apertar.

   Tudo em CSS porque a casa não permite script embutido — e porque o que não
   depende de JavaScript não quebra no celular de quem tem a internet pior. */
.titulo-inline { display: flex; align-items: center; gap: 6px; }
.titulo-inline input {
  flex: 1 1 auto;
  min-width: 0;
  font: inherit;
  font-weight: 600;
  color: inherit;
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--raio-p);
  padding: 4px 6px;
  margin: -4px -6px;
  cursor: text;
  text-overflow: ellipsis;
}
.titulo-inline input:hover { border-color: var(--borda); }
.titulo-inline input:focus {
  background: var(--fundo-3);
  border-color: var(--marca);
  outline: none;
  margin: 0;
  text-overflow: clip;
}
.titulo-inline button { display: none; flex: 0 0 auto; }
.titulo-inline:focus-within button { display: inline-flex; }

/* ── O sininho e a caixa de notificações ─────────────────────────────────────
   O sino é um link, não um menu: o cabeçalho só precisa dizer que há coisa
   esperando, e a lista mora na tela dela. A pastilha só existe quando há o que
   contar — sino com "0" pendurado ensina a ignorar o sino. */
.sino {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  font-size: 17px;
  text-decoration: none;
  border: 1px solid var(--borda);
}
.sino:hover { background: var(--fundo-3); }
.sino-conta {
  position: absolute;
  top: -4px;
  right: -4px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: 9px;
  background: var(--erro);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  display: grid;
  place-items: center;
}

.lista-notificacoes { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.lista-notificacoes li {
  background: var(--fundo-2);
  border: 1px solid var(--borda);
  border-left: 3px solid var(--marca);
  border-radius: var(--raio);
  padding: 12px 14px;
}
/* Lida perde o realce da borda e um pouco de peso — continua legível, deixa de
   chamar. Apagar seria perder o histórico, que é metade do valor da caixa. */
.lista-notificacoes li.lida { border-left-color: var(--borda); opacity: .62; }

/* A prévia da capa no painel: proporção do banner (8:3) e imagem **inteira**.
   `contain`, e não `cover`, porque aqui a pergunta é "foi esta imagem que eu
   mandei?" — na página ela é cortada pelo centro, e é a dica ao lado do campo
   que avisa isso. */
.previa-capa {
  width: 216px;
  max-width: 100%;
  aspect-ratio: 3 / 1;
  border-radius: 10px;
  border: 1px solid var(--borda);
  background: var(--fundo-3) center/contain no-repeat;
}

/* A linha para onde a página voltou depois de salvar: um realce de um segundo,
   que diz "é esta" sem a pessoa precisar procurar. Sem animação para quem pediu
   menos movimento no sistema. */
.tabela-cartoes tr:target { background: color-mix(in srgb, var(--marca) 12%, transparent); }
@media (prefers-reduced-motion: no-preference) {
  .tabela-cartoes tr:target { transition: background 1.2s ease-out 0.6s; }
}

/* Aleatório e repetir ligados: o botão deixa de ser fantasma (o JS troca a
   classe) e o `aria-pressed` conta a mesma coisa para o leitor de tela. */
.playlist-modo[aria-pressed='true'] { border-color: var(--marca); }
