/* A faixa leva a cor do festival como a organização a definiu. Quem lhe dá
   borda é a régua roxa à esquerda — terceiro uso do mesmo gesto que ancora
   o wordmark na home e marca estado na lateral do card. Sem ela, um
   festival de cor clara (o Rock in Rio é #efece6) produziria uma faixa que
   some contra o papel.
   Os dois valores padrão valem para festival sem o campo cor: o build não
   publica estilo nenhum nesse caso. */
.faixa-festival {
  --faixa-cor: var(--papel);
  --faixa-tinta: var(--tinta);
  background: var(--faixa-cor);
  border-left: 8px solid var(--marca);
  /* e2 vertical em vez de e4: a meta é a grade aparecer sem rolagem na
     primeira tela, e o padding vertical da faixa é o que mais pesa nessa
     conta. Horizontal fica em e5 — a folga lateral não entra nessa conta
     e o teste de 500px (passo 7) cobre o excesso na horizontal. */
  padding: var(--e2) var(--e5);
}

.faixa-conteudo {
  display: flex;
  align-items: center;
  gap: var(--e4);
}

/* Altura fixa e limite absoluto no logo, pelo mesmo motivo do card da
   home: os dois logos têm proporções opostas — 451x293 e 340x384 — e
   porcentagem não resolve contra a altura da faixa. O logo ou estica a
   faixa ou vaza por cima do título. Isso já custou três tentativas lá. */
.faixa-logo {
  flex: 0 0 82px;
  height: 62px;
  display: grid;
  place-items: center;
}

.faixa-logo img {
  max-width: 100%;
  max-height: 58px;
  object-fit: contain;
  display: block;
}

/* min-width: 0 deixa o título encolher em vez de empurrar o botão de
   ingressos para fora da faixa num nome longo. */
.faixa-texto {
  flex: 1;
  min-width: 0;
}

.faixa-festival h1 {
  margin: 0;
  font-family: var(--fonte-display);
  font-size: var(--t-faixa);
  font-weight: 800;
  line-height: .95;
  letter-spacing: -.025em;
  text-transform: uppercase;
  color: var(--faixa-tinta);
  /* Piso, não afinação: nem todo nome de festival é curto. Sem isto, um
     nome longo (ou o próprio --t-faixa-compacta ainda não bastando) vaza
     para fora da coluna em vez de quebrar dentro dela. */
  overflow-wrap: break-word;
}

/* Navegação do site, em faixa própria acima da identidade do festival.
   Dentro da faixa o link tomava emprestada a tinta dela e ficava a 4px do
   <h1>, na mesma cor — que é o padrão tipográfico de linha de apoio, então
   o olho lia como categoria do título e não como controle. Fora dela, ele
   volta a usar o .voltar puro de base.css: some a regra escopada, some o
   acoplamento com --faixa-tinta e some o opacity, que só existiam para o
   link sobreviver sobre a cor do festival.

   A borda esquerda transparente tem a mesma espessura da régua roxa da
   faixa. É ela que alinha este texto com o conteúdo de lá — por
   construção, não por um padding calculado que sairia de sincronia se a
   régua mudasse de espessura. */
/* Fixa no topo: numa lista longa de celular, o controle deixa de depender
   de a pessoa estar no começo da página. Era esse o "escondido" de verdade
   — não o tamanho dele, mas ter que rolar de volta para achá-lo.
   O fundo precisa ser sólido: transparente, o conteúdo passaria por baixo
   dela ao rolar. z-index 4 a põe acima da programação e abaixo dos botões
   flutuantes (5) e do modal (10). */
.barra-nav {
  position: sticky;
  top: 0;
  z-index: 4;
  background: var(--papel);
  border-left: 8px solid transparent;
  border-bottom: 1px solid var(--linha);
  padding: var(--e2) var(--e5);
}

/* Escopado à barra: o .voltar de base.css continua servindo o 404, que
   carrega só base.css e não tem faixa nem barra. */
.barra-nav .voltar {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  padding: 7px var(--e3);
  border-radius: var(--raio-pilula);
  background: var(--marca-tenue);
  color: var(--marca);
  font-size: var(--t-rotulo);
  letter-spacing: .05em;
}

/* Invertido: fundo na cor do texto, texto na cor da faixa. Assim o botão
   fica legível nos dois extremos sem precisar de uma terceira cor.
   Escopado a .faixa-festival, não solto: var(--faixa-tinta) e
   var(--faixa-cor) só existem ali (são custom properties de
   .faixa-festival). Fora da faixa cairiam nos valores herdados/iniciais —
   fundo transparente, texto na cor herdada — um link sem estilo nenhum e
   sem aviso. Mesma gramática de .faixa-festival .voltar, acima. */
.faixa-festival .btn-ingressos {
  display: inline-block;
  flex-shrink: 0;
  margin: 0;
  padding: var(--e2) var(--e4);
  border-radius: var(--raio-chip);
  background: var(--faixa-tinta);
  color: var(--faixa-cor);
  font-family: var(--fonte-display);
  font-weight: 800;
  font-size: var(--t-rotulo);
  letter-spacing: .06em;
  text-transform: uppercase;
  text-decoration: none;
}

/* A borda transparente de 8px repete o recurso da .barra-nav: alinha este
   texto com o conteúdo da faixa, que a régua roxa empurra para a direita.
   Sem ela o bloco do topo tem três bordas esquerdas diferentes — 32px na
   faixa, 24px aqui e nas abas — e o desalinhamento aparece como um degrau
   logo abaixo do título. */
.festival-info {
  border-left: 8px solid transparent;
  padding: var(--e3) var(--e5);
  border-bottom: 1px solid var(--linha);
}

/* Caixa baixa e sem tracking, ao contrário do que era. Maiúscula espaçada
   é boa num rótulo de três palavras e péssima numa frase longa: "PARQUE
   PERMANENTE DE EXPOSIÇÕES DE RIBEIRÃO PRETO" era o texto mais difícil de
   ler da página, e é o menos importante dela.

   Data e local viram fatos separados, cada um com seu ícone. Como frase
   corrida com pontos médios, o olho tinha que ler tudo para achar
   "quando" ou "onde"; o ícone faz o trabalho de um rótulo sem ocupar
   linha própria. */
.festival-fatos {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e2) var(--e5);
  margin: 0;
  font-size: var(--t-atracao);
  color: var(--tinta-suave);
}

.fato {
  display: flex;
  align-items: center;
  gap: 7px;
}

.fato b {
  font-weight: 700;
  color: var(--tinta);
}

/* currentColor: o ícone acompanha a cor do texto ao lado sem precisar de
   uma regra por contexto. */
.icone {
  width: 14px;
  height: 14px;
  flex: 0 0 14px;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .7;
}

/* Estado do dado, não instrução — por isso selo e não frase. É o mesmo
   aviso que o card da home já mostra, agora com a mesma cara nos dois
   lugares. No Rock in Rio é a única coisa na página que explica por que
   não existe grade de horários. */
.selo-status {
  display: inline-flex;
  align-items: center;
  margin: var(--e2) 0 0;
  padding: 4px var(--e3);
  border-radius: var(--raio-pilula);
  background: var(--marca-tenue);
  color: var(--marca);
  font-size: var(--t-rotulo);
  font-weight: 800;
  letter-spacing: .05em;
  text-transform: uppercase;
}

/* Colada na programação, não na barra de informação: ela descreve a
   interação, e lá em cima se misturava com data e local, que respondem
   outra pergunta.

   É a única faixa do topo centralizada, e de propósito: as outras
   carregam identidade e fatos, que se lêem descendo por uma borda comum;
   esta é legenda de uma grade larga e simétrica, e no eixo dela pertence
   ao conjunto em vez de à coluna da esquerda.

   Por isso ela também NÃO leva a borda esquerda de 8px que alinha as
   demais: aqui ela não teria função e ainda empurraria o texto 4px para
   fora do eixo real da página. */
.dica-programacao {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  margin: 0;
  padding: var(--e2) var(--e5) 0;
  font-size: var(--t-rotulo);
  color: var(--tinta-tenue);
}

/* O aviso ocupa o lugar da programação, então respira como ela e fica no
   eixo, como a instrução que ele substitui. */
.aviso-lineup {
  margin: 0;
  padding: var(--e7) var(--e5);
  text-align: center;
  font-size: var(--t-corpo);
  color: var(--tinta-suave);
}

/* Estado de espera, não erro: a página de um festival anunciado era faixa,
   fatos e uma frase — duas linhas de conteúdo antes do rodapé. No celular
   isso é meia tela vazia. A contagem é o que dá a ela um motivo para
   existir antes de o line-up sair, e ela já é calculada pelo site. */
.aviso-vazio {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: var(--e7) var(--e4);
  border-left: 8px solid var(--marca);
  border-radius: var(--raio-card);
  background: var(--superficie);
  box-shadow: var(--sombra-repouso);
}

/* Vazio até o JavaScript preencher — e some por completo se ele falhar, em
   vez de deixar um buraco com rótulo. */
.aviso-contagem:empty { display: none; }

/* Container das duas linhas — o tamanho vive nos filhos, senão a unidade
   sairia no mesmo corpo do número. */
.aviso-contagem {
  display: flex;
  flex-direction: column;
  align-items: center;
  color: var(--marca);
}

.aviso-contagem-val {
  font-family: var(--fonte-display);
  font-size: var(--t-titulo);
  font-weight: 800;
  line-height: .85;
  letter-spacing: -.05em;
  /* Os dígitos mudam todo dia; sem largura tabular o bloco dança na virada
     de 99 para 100. */
  font-variant-numeric: tabular-nums;
}

.aviso-contagem-un {
  font-family: var(--fonte-display);
  font-size: var(--t-rotulo);
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
}

.aviso-vazio h2 {
  margin: var(--e4) 0 0;
  font-family: var(--fonte-display);
  font-size: var(--t-secao);
  font-weight: 800;
  letter-spacing: -.02em;
}

.aviso-vazio p {
  margin: var(--e1) 0 var(--e4);
  max-width: 32ch;
  font-size: var(--t-atracao);
  color: var(--tinta-suave);
}

.aviso-btn {
  padding: 10px var(--e4);
  border-radius: var(--raio-chip);
  background: var(--tinta);
  color: var(--papel);
  font-family: var(--fonte-display);
  font-weight: 800;
  font-size: var(--t-rotulo);
  letter-spacing: .06em;
  text-transform: uppercase;
  text-decoration: none;
}

.grade {
  display: grid;
  gap: var(--e3);
  overflow: auto;
  max-height: 80vh;
  padding: 0 var(--e5) var(--e5);
}

.grade-corner {
  position: sticky;
  top: 0;
  left: 0;
  background: var(--papel);
  z-index: 3;
}

.palco-header {
  position: sticky;
  top: 0;
  border-radius: var(--raio-card) var(--raio-card) 0 0;
  padding: var(--e3);
  min-height: 56px;
  text-align: center;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--e1);
}

.palco-nome {
  font-family: var(--fonte-display);
  font-weight: 800;
  font-size: var(--t-palco);
  letter-spacing: -.01em;
  line-height: 1.08;
  text-transform: uppercase;
}

.tempo-col {
  position: relative;
  position: sticky;
  left: 0;
  background: var(--papel);
  z-index: 1;
}

/* Chip na cor da marca, encostado na grade — é dele que a linha da hora
   parte. A cor nunca acompanha o palco: se acompanhasse, o roxo perderia o
   papel de âncora e a régua viraria mais uma coluna colorida. */
.tempo-marker {
  position: absolute;
  right: var(--e2);
  transform: translateY(-50%);
  background: var(--marca);
  color: var(--superficie);
  font-family: var(--fonte-display);
  font-weight: 800;
  font-size: var(--t-rotulo);
  letter-spacing: .02em;
  padding: 3px var(--e2);
  border-radius: var(--raio-chip);
}

/* A opacidade é baixa de propósito. Mais forte e a grade ganha cara de
   planilha, que é o oposto da direção escolhida. */
.palco-col {
  position: relative;
  border-radius: 0 0 var(--raio-card) var(--raio-card);
  background-image: repeating-linear-gradient(
    to bottom,
    rgba(27, 27, 26, .13) 0 1px,
    transparent 1px var(--altura-hora)
  );
}

.show-block {
  position: absolute;
  left: var(--e1);
  right: var(--e1);
  /* As duas laterais ficam reservadas desde sempre, transparentes. Se elas
     só nascessem junto com o estado, o card mudaria de largura ao ser
     marcado e a coluna inteira dançaria a cada clique. */
  border: 0;
  border-left: 4px solid transparent;
  border-right: 7px solid transparent;
  border-radius: var(--raio-card);
  background: var(--superficie);
  color: var(--tinta);
  font-size: var(--t-atracao);
  padding: 7px var(--e2);
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 70px;
  box-shadow: var(--sombra-repouso);
}

.show-horario {
  position: absolute;
  top: var(--e1);
  left: var(--e2);
  color: var(--tinta-tenue);
  font-weight: 700;
  font-size: var(--t-rotulo-menor);
  letter-spacing: .04em;
}

/* Aplicada via JS somente nos cards em que o nome da atração,
   centralizado, sobreporia o selo de horário. O selo continua fixo
   no canto superior esquerdo; o padding-top (calculado em JS) é que
   empurra o nome pra baixo do selo. */
.show-block.horario-sobreposto {
  flex-direction: column;
  justify-content: flex-start;
}

/* Tinta neutra, não a do palco: a coluna já diz de qual palco é. Duas
   coisas coloridas dizendo a mesma coisa é o canal duplo que esta reforma
   desfaz. */
.show-atracao {
  color: var(--tinta);
  font-weight: 600;
  font-size: var(--t-atracao);
  text-transform: uppercase;
  text-align: center;
  line-height: 1.2;
}

/* Selecionado: só a esquerda. */
.show-block.selecionado {
  border-left-color: var(--selecionado);
  background: var(--selecionado-fundo);
}

.show-block.selecionado::before {
  content: '✓';
  position: absolute;
  bottom: var(--e1);
  right: var(--e2);
  background: var(--selecionado);
  color: var(--superficie);
  font-size: var(--t-rotulo-menor);
  font-weight: 800;
  line-height: 1;
  padding: 3px 5px;
  border-radius: var(--raio-chip);
}

/* Conflito: os dois lados, e o fundo levemente rosado. Vale também quando
   o show está selecionado — os dois avisos convivem, o ✓ continua lá. */
.show-block.conflito,
.show-block.selecionado.conflito {
  border-left-color: var(--conflito);
  border-right-color: var(--conflito);
  background: var(--conflito-fundo);
}

.show-block.conflito::after {
  content: '⚠ CONFLITO';
  position: absolute;
  bottom: var(--e1);
  left: var(--e2);
  color: var(--conflito-tinta);
  font-size: var(--t-nota);
  font-weight: 800;
  letter-spacing: .05em;
  line-height: 1;
  white-space: nowrap;
}

.lista-shows {
  list-style: none;
  padding: 0;
  margin: 0;
}

/* Fixo na rolagem: a hora corrente gruda no topo enquanto se percorre o
   bloco dela. É o que substitui, no celular, a régua de tempo lateral que a
   grade tem no desktop — sem ela a lista não tem eixo nenhum, e a única
   forma de achar "o que toca às 20h" é ler cada linha. */
.lista-marco {
  position: sticky;
  top: 0;
  z-index: 2;
  margin: var(--e3) 0 var(--e2);
  padding: 3px var(--e2);
  background: var(--papel);
  border-bottom: 1px solid var(--linha);
  font-family: var(--fonte-display);
  font-size: var(--t-rotulo);
  font-weight: 800;
  letter-spacing: .12em;
  color: var(--tinta-tenue);
}

.lista-item {
  --cor-texto-palco: var(--tinta);
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--e2);
  padding: var(--e3) var(--e2);
  margin-bottom: var(--e1);
  border: 0;
  border-left: 4px solid transparent;
  border-right: 7px solid transparent;
  border-radius: var(--raio-card);
  background: var(--superficie);
  color: var(--tinta);
  cursor: pointer;
  box-shadow: var(--sombra-repouso);
}

.lista-item.selecionado {
  border-left-color: var(--selecionado);
  background: var(--selecionado-fundo);
}

/* Os dois avisos saem do fluxo e ancoram no rodapé do item, que já é
   position: relative.

   No flex eles não conseguiam dividir uma linha, e a razão é o
   .lista-atracao ter flex-basis zero: ele não consome espaço no cálculo de
   quebra, então sobram ~200px na primeira linha de um item de 326px. Um
   flex-basis pequeno o bastante para os dois caberem juntos TAMBÉM cabe lá
   em cima — foi o que aconteceu: o conflito subia para a direita da linha do
   show e o selecionado descia sozinho. E um flex-basis grande o bastante
   para forçar a quebra não deixa os dois juntos. Não existe valor que
   resolva os dois lados; fora do fluxo o problema desaparece.

   O padding-bottom é o que reserva a faixa para eles: sem ele o texto
   absoluto passaria por cima do nome da atração. */
.lista-item.conflito,
.lista-item.selecionado {
  padding-bottom: calc(var(--e3) + var(--e5));
}

.lista-item.conflito::before,
.lista-item.selecionado::after {
  position: absolute;
  bottom: var(--e3);
  font-size: var(--t-rotulo);
  font-weight: 800;
  letter-spacing: .02em;
}

/* O conflito fica à DIREITA e o selecionado à esquerda, não o contrário:
   na imagem exportada o conflito cai logo abaixo do chip do palco, que
   também é o canto direito, e a tela e a imagem contam a mesma história.
   Trocar os dois de lado aqui é o que mantém as duas consistentes. */
.lista-item.conflito::before {
  content: '⚠ Conflito de horário';
  right: var(--e2);
  color: var(--conflito-tinta);
}

.lista-item.selecionado::after {
  content: '✓ Selecionado';
  left: var(--e2);
  color: var(--selecionado);
}

/* Sozinho, cada um ocupa a faixa inteira e fica centralizado — é como o
   "Selecionado" sempre apareceu. Os dois extremos só valem quando há dois. */
.lista-item.conflito:not(.selecionado)::before,
.lista-item.selecionado:not(.conflito)::after {
  left: var(--e2);
  right: var(--e2);
  text-align: center;
}

.lista-item.conflito,
.lista-item.selecionado.conflito {
  border-left-color: var(--conflito);
  border-right-color: var(--conflito);
  background: var(--conflito-fundo);
}


/* Aqui não há coluna tonalizada para dizer o palco, então o selo em cor
   cheia é que carrega a identidade — e o nome do palco vai escrito dentro
   dele, que é o que satisfaz o aviso de contraste da paleta. */
.palco-badge {
  flex-shrink: 0;
  padding: 3px var(--e2);
  border-radius: var(--raio-chip);
  font-family: var(--fonte-display);
  font-size: var(--t-rotulo);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .01em;
}

.lista-horario {
  flex-shrink: 0;
  background: var(--marca);
  color: var(--superficie);
  font-family: var(--fonte-display);
  font-weight: 800;
  font-size: var(--t-rotulo);
  letter-spacing: .02em;
  padding: 3px var(--e2);
  border-radius: var(--raio-chip);
}

/* A tinta do palco vale sobre branco; o card da lista é branco, então ela
   pode ficar. É o único lugar da lista onde a cor do palco aparece como
   texto. */
.lista-atracao {
  flex-basis: 100%;
  text-align: center;
  margin-top: 2px;
  color: var(--cor-texto-palco);
  font-family: var(--fonte-display);
  font-weight: 800;
  font-size: var(--t-secao);
  text-transform: uppercase;
}

.app-content {
  padding: var(--e3);
  padding-bottom: 170px;
}

.acoes-flutuantes {
  position: fixed;
  bottom: 90px;
  right: 20px;
  display: flex;
  align-items: center;
  gap: 10px;
  z-index: 5;
}

.btn-flutuante {
  padding: var(--e3) var(--e5);
  border-radius: var(--raio-pilula);
  border: none;
  background: var(--marca);
  color: var(--superficie);
  font-family: var(--fonte-display);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .03em;
  font-size: var(--t-atracao);
  cursor: pointer;
  box-shadow: var(--sombra-flutuante);
}

.btn-flutuante:disabled {
  background: var(--desabilitado);
  color: var(--tinta-tenue);
  box-shadow: none;
  cursor: not-allowed;
}

/* A barra do Desfazer ocupa o lugar dos dois botões, com a mesma altura e a
   mesma elevação — trocar a elevação junto faria a barra parecer pular de
   plano no instante da troca. */
.desfazer {
  display: flex;
  align-items: center;
  gap: var(--e2);
  padding: var(--e3) var(--e3) var(--e3) var(--e4);
  border-radius: var(--raio-pilula);
  border: 1px solid var(--linha);
  background: var(--superficie);
  color: var(--tinta);
  font-size: var(--t-atracao);
  box-shadow: var(--sombra-flutuante);
}

/* Roxo e sublinhado: ele é a única saída de uma ação destrutiva e some em
   segundos. Sublinhado porque cor sozinha não distingue para quem não
   diferencia matiz — e aqui não há tempo de procurar. */
.btn-desfazer {
  border: 0;
  background: none;
  padding: var(--e1) var(--e2);
  color: var(--marca);
  font-family: var(--fonte-display);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .03em;
  font-size: var(--t-atracao);
  text-decoration: underline;
  cursor: pointer;
}

.btn-flutuante-secundario {
  padding: var(--e3) var(--e4);
  border-radius: var(--raio-pilula);
  border: 1px solid var(--linha);
  background: var(--superficie);
  color: var(--tinta);
  font-family: var(--fonte-display);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .03em;
  font-size: var(--t-atracao);
  cursor: pointer;
  box-shadow: var(--sombra-flutuante);
}

.btn-flutuante-secundario:disabled {
  border-color: var(--linha);
  color: var(--tinta-tenue);
  box-shadow: none;
  cursor: not-allowed;
}

.modal {
  position: fixed;
  inset: 0;
  background: rgba(27, 27, 26, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
}

.modal.hidden {
  display: none;
}

.modal-conteudo {
  background: var(--superficie);
  color: var(--tinta);
  border-radius: var(--raio-card);
  padding: var(--e5);
  max-width: 420px;
  width: 90%;
  max-height: 80vh;
  overflow-y: auto;
  position: relative;
  box-shadow: var(--sombra-flutuante);
}

.modal-conteudo h2 {
  margin: 0;
  text-align: center;
  font-family: var(--fonte-display);
  font-size: var(--t-secao);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: -.01em;
  color: var(--marca);
}

.btn-fechar {
  position: absolute;
  top: var(--e3);
  right: var(--e3);
  background: none;
  border: none;
  color: var(--tinta);
  font-size: var(--t-secao);
  cursor: pointer;
}

.modal-previa {
  max-height: 52vh;
  border: 1px solid var(--linha);
  border-radius: var(--raio-card);
  background: var(--papel);
  font-size: var(--t-rotulo);
  color: var(--tinta-suave);
  text-align: center;
}

/* Rola verticalmente: a programação pode ficar mais alta que a caixa, e é
   percorrendo que se confere que está tudo lá. O atributo sobrevive só
   porque main.js ainda escreve data-formato="programacao" no elemento —
   não há mais outro valor possível, mas o seletor não custa nada manter. */
.modal-previa[data-formato="programacao"] {
  overflow-y: auto;
}

.modal-previa[data-formato="programacao"] canvas {
  display: block;
  width: 100%;
  height: auto;
}

/* Abaixo de ~820px de altura de viewport, os 52vh de prévia mais o resto
   do conteúdo fixo (título, resumo, botões e o padding de .modal-conteudo)
   somam mais que os 80vh do teto do modal. Abaixo disso o botão "Baixar"
   cai para fora da área visível e só chega rolando. Reduzida a prévia
   para 34vh aqui, a mesma lógica cobre janela de desktop baixa, split
   screen e a maioria dos celulares em paisagem. Abaixo de ~500px ainda
   sobra rolagem — não há mais um teto rígido a defender aqui (a prévia
   só mostra a programação, que já rola por conta própria), então 34vh é
   só o ponto em que a caixa ainda mostra linha o bastante pra ser útil.

   820px e 500px vêm de antes desta rodada, quando a prévia também podia
   trocar para o story — que precisava do 9:16 inteiro visível, sem
   rolagem, pra não perder a única coisa que ele mostra — e o conteúdo
   fixo somava os chips de formato e o aviso de "não cabe num story".
   Tirar os dois só folgou a conta: os limiares de altura continuam
   seguros, só deixaram de ser os mais justos possíveis. Reapertá-los
   pede medir de novo num aparelho real, não aritmética. */
@media (max-height: 820px) {
  .modal-previa {
    max-height: 34vh;
  }
}

.modal-resumo {
  margin: var(--e2) 0 var(--e3);
  font-size: var(--t-rotulo);
  color: var(--tinta-suave);
}

.modal-botoes {
  display: flex;
  gap: var(--e3);
}

.btn-baixar {
  flex: 1;
  min-width: 0;
  padding: var(--e3);
  border-radius: var(--raio-chip);
  border: none;
  background: var(--marca);
  color: var(--superficie);
  font-family: var(--fonte-display);
  font-size: var(--t-corpo);
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .02em;
  cursor: pointer;
  overflow-wrap: break-word;
}

/* Aplicada ao botão que for secundário no momento — que muda conforme o
   navegador compartilhe arquivo ou não. Vem depois de .btn-baixar de
   propósito: as duas regras têm a mesma especificidade e disputam as
   mesmas três propriedades (background, color, border) no mesmo botão —
   sem vir por último aqui, .btn-secundario perderia a disputa e o botão
   "secundário" sairia idêntico ao primário. */
.btn-secundario {
  background: var(--superficie);
  color: var(--marca);
  border: 1px solid var(--marca);
}

.abas-dia {
  display: flex;
  gap: var(--e2);
  overflow-x: auto;
  /* Mesma borda transparente da .barra-nav e da .festival-info: as quatro
     faixas do topo compartilham uma borda esquerda só. */
  border-left: 8px solid transparent;
  padding: var(--e3) var(--e5);
  scrollbar-width: none;
}
.abas-dia::-webkit-scrollbar { display: none; }

/* Um `display` de autor derrota o [hidden] da folha do navegador, seja qual
   for a especificidade — então o container esvaziado continuaria ocupando
   seu padding. Num festival de um dia isso é espaço morto sob o cabeçalho,
   e a regra da spec é que ele não ganhe elemento nenhum a mais. */
.abas-dia[hidden],
.modal-chips[hidden],
.desfazer[hidden] { display: none; }

.aba-dia {
  flex: 0 0 auto;
  padding: 7px var(--e4);
  border: 1px solid var(--linha);
  border-radius: var(--raio-chip);
  background: var(--superficie);
  color: var(--tinta);
  font-family: var(--fonte-display);
  font-weight: 700;
  font-size: var(--t-atracao);
  cursor: pointer;
}
.aba-dia.ativa {
  border-color: var(--marca);
  background: var(--marca);
  color: var(--superficie);
}

.modal-chips { display: flex; flex-wrap: wrap; gap: var(--e2); margin-bottom: var(--e3); }

.chip {
  padding: var(--e1) var(--e3);
  border: 1px solid var(--linha);
  border-radius: var(--raio-chip);
  background: var(--superficie);
  color: var(--tinta);
  font-size: var(--t-rotulo);
  font-weight: 700;
  cursor: pointer;
}
.chip.ativo {
  border-color: var(--marca);
  background: var(--marca);
  color: var(--superficie);
}

.lineup {
  display: grid;
  gap: var(--e5);
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  /* Sem os botões flutuantes nesta página, não há o que folgar embaixo. E
     align-items: start impede que um palco com poucas atrações estique até
     a altura do vizinho, deixando um vazio dentro do card. */
  align-items: start;
  padding: 0 var(--e5) var(--e7);
}

.lineup-palco {
  overflow: hidden;
  border-radius: var(--raio-card);
  background: var(--superficie);
  box-shadow: var(--sombra-repouso);
}

.lineup-palco-nome {
  margin: 0;
  padding: var(--e3) var(--e4);
  font-family: var(--fonte-display);
  font-size: var(--t-palco);
  font-weight: 800;
  letter-spacing: -.01em;
  text-transform: uppercase;
}

.lineup-atracoes {
  margin: 0;
  padding: var(--e2) 0;
  list-style: none;
}

/* Card branco, então a tinta do palco vale aqui. O valor de reserva é dito e
   não herdado por acaso: sem palco ninguém define --cor-texto-palco, o var()
   fica inválido no cálculo, e color — que é herdada — cai na cor do pai. Sai
   o resultado certo por um caminho que ninguém escolheu, e que a próxima
   mudança de estrutura desfaz em silêncio. */
.lineup-atracoes li {
  padding: 10px var(--e4);
  color: var(--cor-texto-palco, var(--tinta));
  font-weight: 700;
  font-size: var(--t-corpo);
}

.lineup-atracoes li + li { border-top: 1px solid var(--linha); }

/* Sem palco não há um card por palco, e a grade de cards passa a trabalhar
   contra: um bloco só ocuparia uma coluna de 260px com espaço vazio ao lado,
   e os 20 nomes de um dia do Primavera virariam uma tira alta e estreita.
   O bloco toma a largura inteira e as atrações fluem em colunas. */
.lineup-sem-palco { grid-column: 1 / -1; }

.lineup-sem-palco .lineup-atracoes { columns: 200px; }

.lineup-sem-palco .lineup-atracoes li { break-inside: avoid; }

/* Sem régua entre itens, em qualquer número de colunas. `li + li` é ordem de
   DOM, não de coluna: em várias colunas o primeiro item de cada uma ganharia
   uma linha solta no topo, sugerindo uma separação que não existe. E como o
   número de colunas depende da largura da tela — no celular este bloco cai
   para uma só —, a régua apareceria e sumiria com o giro do aparelho. Um
   bloco que muda de anatomia conforme a viewport é pior que um sem régua. */
.lineup-sem-palco .lineup-atracoes li + li { border-top: 0; }

@media (min-width: 768px) {
  .lista-shows {
    display: none;
  }
}

@media (max-width: 767px) {
  .grade {
    display: none;
  }

  .btn-flutuante,
  .btn-flutuante-secundario {
    font-size: var(--t-rotulo-menor);
    padding: var(--e3) var(--e4);
    white-space: nowrap;
  }

  /* A faixa some da meta de altura no celular se nada aqui muda: a e5
     horizontal, os dois gaps de e4 e o logo de 82px inteiro são o que
     sobra do orçamento pro título (ver a aritmética no brief e no
     task-3-report). Encolher os três é o que devolve espaço suficiente
     pra "JOÃO ROCK 2026" e "ROCK IN RIO 2026" caberem numa linha a 390px
     — --t-faixa-compacta sozinho não bastaria. */
  .faixa-festival {
    padding: var(--e2) var(--e4);
  }

  /* Acompanha o padding horizontal da faixa: as duas se alinham na borda
     esquerda, e a barra não fica mais recuada que a identidade que ela
     encima. */
  .barra-nav {
    padding: var(--e2) var(--e4);
  }

  .dica-programacao {
    padding-left: var(--e4);
    padding-right: var(--e4);
  }

  .faixa-conteudo {
    gap: var(--e2);
  }

  .faixa-logo {
    flex-basis: 44px;
    height: 40px;
  }

  .faixa-logo img {
    max-height: 36px;
  }

  .faixa-festival h1 {
    font-size: var(--t-faixa-compacta);
  }

  /* Cinco bordas esquerdas viram uma. Medido a 390px antes desta correção:
     a lista ficava a 12px da borda, a dica a 16, a barra e a faixa a 24, a
     barra de informação e as abas a 32, e o line-up a 36 — mais estreito
     que a faixa que o encima, porque .lineup guardava o padding de desktop
     dentro de um .app-content que já tinha o seu.

     O alvo é 24px, que é onde o texto da faixa começa: 16 de padding mais a
     régua de 8. O alinhamento é com o CONTEÚDO da faixa, não com o pixel
     zero dela. .dica-programacao fica de fora de propósito — ela é
     centralizada, e o comentário dela explica por quê. */
  .festival-info,
  .abas-dia {
    padding-left: var(--e4);
    padding-right: var(--e4);
  }

  /* padding-bottom preservado: são os 170px que dão folga aos botões
     flutuantes. Trocar o atalho `padding` por completo apagaria isso. */
  .app-content {
    padding-left: var(--e5);
    padding-right: var(--e5);
  }

  /* Quem posiciona os blocos de conteúdo passa a ser o .app-content. Sem
     isto eles somam o padding dele ao próprio. */
  .lineup {
    padding-left: 0;
    padding-right: 0;
  }

  /* Seis palcos empilhados viram três linhas de dois. Medido no Rock in
     Rio: 22 atrações em 6 palcos num dia — no desktop a grade põe três
     lado a lado, e no celular ela caía para uma coluna, deixando seis
     cabeçalhos coloridos com três ou quatro nomes cada. A moldura pesava
     mais que o conteúdo. */
  .lineup {
    grid-template-columns: 1fr 1fr;
    gap: var(--e2);
  }

  .lineup-palco-nome {
    padding: var(--e2) var(--e3);
    font-size: var(--t-atracao);
  }

  .lineup-atracoes li {
    padding: 7px var(--e3);
    font-size: var(--t-atracao);
  }

  /* Uma coluna, declarada. Com a largura de um telefone o `columns: 200px`
     do desktop já resultava em uma — mas receber uma por aritmética é
     diferente de escolher uma. Duas colunas foram recusadas com o caso na
     mão: o Coala tem "Marcos Valle e Ana Frango Elétrico", 34 caracteres,
     que quebraria em três linhas numa coluna de 150px. `columns` decide por
     largura disponível, não por comprimento de texto. */
  .lineup-sem-palco .lineup-atracoes { columns: auto; }

  /* .lista-marco e .barra-nav grudam no MESMO scrollport (o documento;
     .app-content não cria overflow próprio) e as duas nasciam em top: 0. A
     barra é opaca e vence no z-index (4 contra 2), então o marcador ficava
     inteiramente escondido atrás dela assim que grudava — visível só
     enquanto está a mais de --barra-nav-altura-celular do topo, ou seja,
     exatamente enquanto NÃO está grudado. --barra-nav-altura-celular
     desloca o ponto de grude do marcador pra logo abaixo da barra. Não
     resolve subir o z-index do marcador: aí ele passaria por cima do link
     "Todos os festivais", que é o único caminho de volta da página. */
  .lista-marco {
    top: var(--barra-nav-altura-celular);
  }

  /* De duas linhas altas para uma. A atração deixa de ser centralizada e em
     caixa alta e vira texto corrido à esquerda; o horário perde o chip roxo
     e vira coluna discreta. Cabe quase o dobro de shows por tela. */
  .lista-item {
    gap: var(--e3);
    padding: var(--e2) var(--e3);
  }

  /* Mesma faixa de aviso, sobre o padding menor do celular. */
  .lista-item.conflito,
  .lista-item.selecionado {
    padding-bottom: calc(var(--e2) + var(--e5));
  }

  .lista-item.conflito::before,
  .lista-item.selecionado::after {
    bottom: var(--e2);
  }

  /* Os mesmos lados da regra base — conflito à direita, selecionado à
     esquerda. Esta media query vem DEPOIS e não acrescenta especificidade,
     então quem repetir aqui o lado antigo desfaz a troca só no celular,
     que é exatamente onde ela importa. */
  .lista-item.conflito::before { right: var(--e3); }
  .lista-item.selecionado::after { left: var(--e3); }

  .lista-item.conflito:not(.selecionado)::before,
  .lista-item.selecionado:not(.conflito)::after {
    left: var(--e3);
    right: var(--e3);
  }

  .lista-horario {
    background: none;
    color: var(--tinta-tenue);
    padding: 0;
    font-size: var(--t-atracao);
    font-variant-numeric: tabular-nums;
  }

  /* flex: 1 é 1 1 0%: a base do nome vira zero, então ele nunca é o motivo
     de a linha quebrar — quem decide isso agora é .lista-item voltar a ser
     flex-wrap: wrap no celular (herdado da regra base; o nowrap que estava
     aqui foi removido, acima). flex-basis: auto também foi removido de
     propósito: ele tirava a atração da base zero, e com .lista-item em
     nowrap, o pseudo-elemento "✓ Selecionado" (flex-basis: 100%, sem
     min-width: 0) era forçado pra mesma linha do horário e do palco — os
     dois flex-shrink: 0 — e .lista-atracao, a única que sobra, virava
     ~35-40px a 390px, picada pelo overflow-wrap: anywhere. Sem nowrap e sem
     ellipsis: o nome quebra em quantas linhas precisar, que é requisito da
     spec. */
  .lista-atracao {
    flex: 1;
    min-width: 0;
    margin-top: 0;
    text-align: left;
    font-size: var(--t-corpo);
    text-transform: none;
    overflow-wrap: anywhere;
  }

  .palco-badge { font-size: var(--t-nota); padding: 2px 6px; }
}

/* O fato do site é o único clicável da barra, então precisa parecer link —
   mas sem sublinhado, que brigaria com o alinhamento dos outros dois fatos
   ao lado. A cor da marca é o que o distingue; o ícone herda por
   currentColor, como todos os outros. */
.fato-site {
  color: var(--marca);
  text-decoration: none;
}

.fato-site:hover { text-decoration: underline; }
