@font-face { font-family: 'Toyota Type'; font-weight: 900; font-style: normal;
  src: url('../Assets/fonts/ToyotaType-Black.otf') format('opentype'); font-display: block; }
@font-face { font-family: 'Toyota Type'; font-weight: 900; font-style: italic;
  src: url('../Assets/fonts/ToyotaType-BlackIt.otf') format('opentype'); font-display: block; }
@font-face { font-family: 'Toyota Type'; font-weight: 700; font-style: normal;
  src: url('../Assets/fonts/ToyotaType-Bold.otf') format('opentype'); font-display: block; }
@font-face { font-family: 'Toyota Type'; font-weight: 600; font-style: normal;
  src: url('../Assets/fonts/ToyotaType-Semibold.otf') format('opentype'); font-display: block; }
@font-face { font-family: 'Toyota Type'; font-weight: 600; font-style: italic;
  src: url('../Assets/fonts/ToyotaType-SemiboldIt.otf') format('opentype'); font-display: block; }
@font-face { font-family: 'Toyota Type'; font-weight: 400; font-style: normal;
  src: url('../Assets/fonts/ToyotaType-Regular.otf') format('opentype'); font-display: block; }

:root {
  --dourado: #C9A961;
  --navy: #2C3550;
  --escuro: #1B1F26;
  --alerta: #E4322B;
  --claro: #F2F2F0;
}

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

html, body {
  width: 100%; height: 100%;
  overflow: hidden;
  background: #000;
  font-family: 'Toyota Type', system-ui, sans-serif;
}

#palco {
  position: absolute; top: 0; left: 0;
  width: 1920px; height: 1080px;
  transform-origin: 0 0;
  overflow: hidden;
}

#cenario, #largada { position: absolute; inset: 0; width: 1920px; height: 1080px; }
#pista, #hud, #telas { position: absolute; inset: 0; }
#telas { pointer-events: none; }

/* As camadas ganham z-index explícito por causa da ponte (ver .ponte, mais
   abaixo). Um carro tem de poder subir acima da ponte e descer abaixo dela,
   e isso obriga a mexer no z-index dos carros; sem estes três valores, um
   carro acima da ponte subia também acima do HUD e das telas, e via-se por
   cima da contagem decrescente. Com o z-index posto, cada camada fica
   fechada na sua e as trocas lá dentro não escapam. */
#pista { z-index: 1; }
#hud { z-index: 2; }
#telas { z-index: 3; }

/* O recorte da estrada de cima, por cima dos carros. Ver o comentário no
   index.html: é a mesma imagem do cenário, mascarada com a forma da estrada
   que passa por cima no cruzamento. */
.ponte { position: absolute; inset: 0; z-index: 2; pointer-events: none; }

/* A bandeira acima da ponte: está pintada na estrada de cima, e o recorte da
   ponte É essa estrada - por baixo dele, desaparecia por inteiro. */
#largada { z-index: 3; }

.depuracao { position: absolute; inset: 0; pointer-events: none; display: none; }
.depuracao.visivel { display: block; }
.depuracao i {
  position: absolute; width: 9px; height: 9px;
  margin: -4.5px 0 0 -4.5px; border-radius: 50%;
}

.trilho, .camada-largada { position: absolute; inset: 0; width: 1920px; height: 1080px; }

/* Esconde a moldura de 1920×1080 que o track.svg traz do ficheiro original.
   Duas restrições no seletor, e cada uma corrigiu um bug diferente:

   `.trilho` e não todos os SVG - a bandeira axadrezada do win.svg é feita
   inteirinha de <rect>, e com a regra a apanhá-la desaparecia toda, deixando
   a medição que decide onde os carros partem a devolver uma caixa de tamanho
   zero.

   E é preciso devolver a vida ao <rect> do recorte, porque a primeira regra o
   apanha também: o track.svg guarda as duas raias dentro de
   <g clip-path="url(#clip-path)">, e esse clipPath é feito de um <rect>. Um
   filho de clipPath com `display: none` sai do recorte, o recorte fica VAZIO,
   e tudo o que ele corta desaparece - que são precisamente as duas raias. O
   jogo pintava-lhes a cor do carro a cada corrida e nunca se via nada: o que
   estava no ecrã eram as linhas brancas pintadas no BG.png.

   Duas regras, e não um `> g >` a separar os dois casos pela profundidade,
   como esteve aqui. Essa versão dizia "a moldura está em svg > g > rect" e
   deixou de ser verdade no dia em que alinharComOCenario() passou a embrulhar
   o ficheiro inteiro num <g> para o deslocar: a moldura caiu para
   svg > g > g > rect, a regra deixou de lhe chegar, e a linha cinzenta de
   1920x1080 do ficheiro reapareceu por cima da pista. Não deu erro nenhum -
   só uma moldura cinzenta no projetor.

   Assim escrito, a profundidade deixa de importar: esconde-se tudo o que é
   <rect> lá dentro, seja onde for, e abre-se a exceção pelo que ela é (está
   dentro de um clipPath), não por onde calha estar. */
.trilho rect { display: none; }
.trilho clipPath rect { display: inline; }

/* O filme de espera. Tapa o palco inteiro - foi a escolha feita: o filme do
   cliente aparece tal como foi feito, sem marca nem texto por cima.

   z-index 4, acima de #telas (3), porque tapa a tela de atração que continua
   ativa por baixo a sondar o servidor. `object-fit: cover` porque o ficheiro
   é 1920x1080 exatamente como o palco - hoje não corta nada, e no dia em que
   entrar um ficheiro com outra proporção enche o ecrã em vez de deixar duas
   barras pretas.

   `visibility` e não `display`: um <video> com display:none pode ser
   descarregado pelo browser, e o filme voltava a carregar 31 MB de cada vez
   que entrasse. Assim fica montado, só invisível. */
.filme {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  background: #000;
  z-index: 4;
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.6s ease;
}
.filme.ativo { visibility: visible; opacity: 1; }

/* As partículas do despiste. z-index acima dos carros: as faíscas saem de
   baixo do carro e têm de se ver por cima dele, senão metade delas nasce
   escondida. `pointer-events: none` porque não há aqui nada para clicar e
   estas aparecem às dezenas. */
#particulas { position: absolute; inset: 0; z-index: 5; pointer-events: none; }
.particula {
  position: absolute;
  /* Centrada no ponto por `translate` e não por uma margem fixa: os tamanhos
     são sorteados dentro de um intervalo, e uma margem só acertava num deles. */
  transform-origin: 50% 50%;
  margin: 0;
  translate: -50% -50%;
  border-radius: 50%;
}

/* Acima da ponte por omissão. Só desce - para debaixo dela - no troço em que
   a raia passa mesmo por baixo da outra estrada, e é js/jogo.js que põe e
   tira a classe. */
.carro { position: absolute; top: 0; left: 0; width: 0; height: 0; z-index: 4; }
.carro.sob-ponte { z-index: 1; }

.carro .sprite {
  position: absolute;
  width: 110px; height: auto;
  margin: -30.5px 0 0 -55px; /* centra o sprite 110×61 no ponto do trilho */
  filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.45));
}

.carro .halo {
  position: absolute;
  width: 92px; height: 92px;
  margin: -46px 0 0 -46px;
  border-radius: 50%;
  opacity: 0.35;
  filter: blur(9px);
}

.carro .etiqueta {
  position: absolute;
  left: 50%; top: 0;
  transform: translate(-50%, -78px);
  padding: 3px 12px;
  white-space: nowrap;
  /* Cinto de segurança, não a defesa principal - essa é o limite de 16
     caracteres validado no servidor. Com `white-space: nowrap` a etiqueta
     não pode quebrar linha (segue o carro nas curvas, e não há altura extra
     reservada para uma segunda linha), por isso `overflow-wrap` sozinho não
     a salvaria de um nome anormalmente comprido; o `max-width` pelo menos
     trava a caixa em vez de a deixar crescer sem limite. */
  max-width: 220px;
  overflow: hidden;
  overflow-wrap: anywhere;
  font: italic 900 20px/1 'Toyota Type', sans-serif;
  text-transform: uppercase;
  color: var(--claro);
  background: rgba(27, 31, 38, 0.85);
  border-bottom: 3px solid;
  border-radius: 4px;
}

/* A pilha, e não cada aviso, é que está posicionada. É isto que dá o
   comportamento de toast sem uma linha de JavaScript: um aviso escondido tem
   `display: none` e sai do fluxo, por isso o que estiver à vista - seja o do
   jogador 1, o do 2, ou os dois - começa sempre no mesmo topo, e o segundo só
   desce quando o primeiro está mesmo lá a ocupar espaço. */
.avisos {
  position: absolute;
  top: 110px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}

.aviso-fora {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 10px 34px 10px 16px;
  font: italic 900 44px/1 'Toyota Type', sans-serif;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--escuro);
  background: var(--claro);
  /* A cor do carro no topo, posta por montarCorrida() (js/jogo.js) na mesma
     variável que o painel e a barra de velocidade já usam. O valor de reserva
     é o vermelho de alerta, para o aviso nunca ficar sem borda se por algum
     motivo a variável faltar. */
  border-top: 8px solid var(--cor-carro, var(--alerta));
  border-radius: 6px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
}

/* O `display: flex` acima venceria o `display: none` que o browser dá a
   [hidden]: uma regra de autor ganha sempre à folha do agente, por muito
   específica que esta seja. Sem esta linha os dois avisos ficavam
   permanentemente no ecrã, desde o arranque e durante a corrida toda. */
.aviso-fora[hidden] { display: none; }

.aviso-fora img { width: 120px; height: auto; }


.painel {
  position: absolute;
  width: 380px;
  padding: 16px 20px;
  color: var(--claro);
  background: rgba(27, 31, 38, 0.82);
  border-radius: 8px;
}
/* Os dois painéis em cima, um em cada canto - e não um em cima e outro em
   baixo. O olho de quem está no stand fica na zona do circuito, ao centro:
   com os dois no mesmo alinhamento horizontal, comparar voltas e tempos é
   um movimento só, em vez de um salto de 1080px de altura. */
.painel[data-jogador="1"] { top: 40px; left: 40px; }
.painel[data-jogador="2"] { top: 40px; right: 40px; }

/* --cor-carro é posta no .painel por criarHud() (js/hud.js), a partir da
   mesma COR_DA_CARROCARIA que pinta a raia do circuito e o sprite. O
   valor de reserva só entra se o painel for montado sem ela - não acontece
   no jogo, mas evita uma barra invisível se alguém montar o HUD à mão. */
.painel-nome {
  max-width: 100%;
  overflow-wrap: anywhere;
  font: italic 900 34px/1.1 'Toyota Type', sans-serif;
  text-transform: uppercase;
  border-bottom: 4px solid var(--cor-carro, var(--dourado));
  padding-bottom: 6px;
}
.painel-voltas { margin-top: 10px; font: 600 22px/1 'Toyota Type', sans-serif; }
.painel-tempo {
  font: italic 900 44px/1 'Toyota Type', sans-serif;
  font-variant-numeric: tabular-nums;
}

.barra {
  position: relative;
  height: 18px;
  margin-top: 12px;
  background: rgba(255, 255, 255, 0.14);
  border-radius: 9px;
  overflow: hidden;
}
.barra-preenchimento {
  position: absolute; inset: 0;
  transform-origin: 0 50%;
  transform: scaleX(0);
  background: var(--cor-carro, var(--dourado));
}
.barra-marcador {
  position: absolute; top: -3px; left: 0;
  width: 4px; height: 24px;
  background: var(--claro);
  box-shadow: 0 0 6px rgba(0, 0, 0, 0.8);
}
.painel.perigo .barra-preenchimento { background: var(--alerta); }
.painel.perigo .painel-tempo { color: var(--alerta); }

.tela {
  position: absolute; inset: 0;
  display: none;
  flex-direction: column;
  align-items: center; justify-content: center;
  gap: 18px;
  text-align: center;
  color: var(--claro);
}
.tela.ativa { display: flex; }

/* A tela "corrida" não escurece nem desenha nada: é só a pista à vista. */
.tela:not([data-tela="corrida"]) {
  background: rgba(27, 31, 38, 0.72);
}

/* --- tela de atração: a fotografia dos dois AYGO a ocupar o ecrã ----------
   A marca em cima, CITY RACE em baixo, e a foto entre as duas - `space-between`
   em vez do `center` que as outras telas usam. Sem o tom escuro por cima: esta
   é a única tela onde a imagem É o conteúdo, e escurecê-la só a apagava. */
.tela[data-tela="atracao"] {
  justify-content: space-between;
  padding: 60px 0;
  /* Fundo em duas camadas: a fotografia, e por cima um gradiente que escurece
     APENAS o topo e o rodapé, onde a marca e o CITY RACE assentam. O meio
     fica limpo - é onde estão os carros, e é por eles que esta tela existe.
     Um tom uniforme por cima de tudo (o que `.tela:not([data-tela="corrida"])`
     faz às outras telas) apagava-os. */
  background:
    linear-gradient(to bottom,
      rgba(27, 31, 38, 0.55) 0%,
      rgba(27, 31, 38, 0) 26%,
      rgba(27, 31, 38, 0) 52%,
      rgba(27, 31, 38, 0.72) 100%),
    url('../Assets/intro/intro.webp') center / cover no-repeat;
}
.atracao-rodape {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
}
/* CITY RACE em cima da foto: o contorno claro perde-se contra o céu, que nas
   panorâmicas é quase branco. A sombra devolve-lhe a borda sem lhe encher o
   interior, que é vazado de propósito. */
.tela[data-tela="atracao"] .titulo {
  filter: drop-shadow(0 6px 22px rgba(0, 0, 0, 0.8));
}
.tela[data-tela="atracao"] .marca,
.tela[data-tela="atracao"] .instrucao,
.tela[data-tela="atracao"] .proxima {
  text-shadow: 0 4px 18px rgba(0, 0, 0, 0.8);
}

.marca { font: 600 34px/1 'Toyota Type', sans-serif; letter-spacing: 0.28em; }
.marca b { font-weight: 900; }

.titulo {
  font: italic 900 150px/0.9 'Toyota Type', sans-serif;
  text-transform: uppercase;
  -webkit-text-stroke: 3px var(--claro);
  color: transparent;
}

.proxima { font: italic 900 54px/1.1 'Toyota Type', sans-serif; text-transform: uppercase; }
/* Erro de servidor. Fila vazia é um estado normal de stand e não mostra nada;
   isto só aparece quando o pedido falha mesmo, e por isso está na cor de
   alerta - é a diferença entre "ainda ninguém se inscreveu" e "a base caiu". */
.erro-servidor {
  max-width: 900px;
  font: 600 26px/1.4 'Toyota Type', sans-serif;
  color: var(--alerta);
}
.instrucao { font: 600 26px/1 'Toyota Type', sans-serif; letter-spacing: 0.2em; opacity: 0.85; }

/* --- tela VS: uma faixa em diagonal por jogador ---------------------------
   Cada faixa leva a fotografia do AYGO da cor que essa pessoa escolheu, e o
   nome no lado OPOSTO ao carro - que muda com a cor, porque as panorâmicas
   têm o carro ora à direita ora à esquerda. Ver LADO_DO_CARRO em js/jogo.js.

   O corte é `clip-path` e não duas imagens já recortadas: a diagonal fica no
   CSS, onde se ajusta sem reexportar nada, e a mesma fotografia serve as duas
   posições. Os dois polígonos não se tocam - o de cima acaba nos 60%/30% e o
   de baixo começa nos 64%/34% - e essa lacuna deixa passar o fundo escuro da
   tela, que é o risco diagonal a separá-las. */
.tela[data-tela="vs"] { display: none; padding: 0; }
.tela[data-tela="vs"].ativa { display: block; }

/* Cada faixa é uma banda de meia altura, não o ecrã inteiro recortado. A
   diferença decide se o carro aparece: numa caixa de 1920x583, o `cover`
   destas panorâmicas (7500x2880) escala pela LARGURA e corta em cima e em
   baixo, por isso a largura toda cabe e o carro fica onde o fotógrafo o pôs.
   Com a faixa a ocupar o ecrã todo, escalava pela altura e cortava dos lados
   - ficava o céu e o alcatrão do meio, e o carro de fora.

   As duas bandas sobrepõem-se (0-54% e 46-100%) e é o `clip-path` que corta a
   diagonal dentro dessa sobreposição. Os dois cortes são paralelos e deixam
   entre si uma nesga de 1,7%, por onde passa o fundo escuro da tela: é esse o
   risco que as separa. */
.vs-faixa { position: absolute; left: 0; right: 0; overflow: hidden; }
.vs-faixa[data-lado="1"] { top: 0; height: 54%; clip-path: polygon(0 0, 100% 0, 100% 82%, 0 100%); }
/* `bottom: 0` e não `height: 54%`: encostar ao fundo garante que não sobra uma
   nesga do fundo da tela por baixo, seja qual for o arredondamento da altura. */
.vs-faixa[data-lado="2"] { top: 46%; bottom: 0; clip-path: polygon(0 18%, 100% 0, 100% 100%, 0 100%); }

.vs-faixa img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}

/* O nome sobre a fotografia. A sombra não é enfeite: as panorâmicas vão de um
   céu quase branco a asfalto quase preto, e texto claro sem sombra
   desaparece na metade clara de algumas delas. */
.vs-nome {
  position: absolute;
  transform: translateY(-50%);
  /* Uma linha só, sempre: quem trata de o fazer caber é ajustarNomeVs(), em
     js/jogo.js, que encolhe o corpo da letra depois de medir o nome. Sem o
     nowrap a medição não servia de nada - o texto quebrava linha antes de
     chegar ao limite, e um nome de 16 letras descia por fora da banda. */
  white-space: nowrap;
  font: italic 900 132px/0.92 'Toyota Type', sans-serif;
  text-transform: uppercase;
  color: var(--claro);
  text-shadow: 0 6px 26px rgba(0, 0, 0, 0.75);
}
/* 27% e 73% são o meio de cada banda: a de cima vai de 0 a 54%, a de baixo de
   46 a 100%. Posicionados contra a tela, e já não contra a faixa, porque é
   isso que os tira de dentro do recorte e os põe acima do X. */
.vs-nome[data-lado="1"] { top: 27%; }
.vs-nome[data-lado="2"] { top: 73%; }
.vs-nome[data-nome="esquerda"] { left: 90px; text-align: left; }
.vs-nome[data-nome="direita"] { right: 90px; text-align: right; }

/* O X da marca por cima das duas fotografias. Fica acima das faixas (e por
   isso também dos nomes, que vivem dentro delas: o `clip-path` da faixa cria
   um contexto de empilhamento, e nada lá de dentro pode subir acima de um
   irmão). A instrução vem depois no HTML e continua por cima de tudo, que é
   onde tem de estar para se ler sempre. */
.camada-x { position: absolute; inset: 0; }
.camada-x svg { width: 100%; height: 100%; display: block; }

/* `fill: none`, e não `display: none` como o .trilho faz: o ficheiro traz um
   retângulo branco de 1920x1080 por fundo, mas os <rect> que lhe definem os
   clipPath são <rect> na mesma - escondê-los desativava o recorte, porque um
   filho de clipPath com display:none sai do recorte. Tirar o preenchimento
   apaga o fundo e deixa a geometria intacta. */
.camada-x rect { fill: none; }


.contagem {
  font: italic 900 340px/1 'Toyota Type', sans-serif;
  color: var(--claro);
  text-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
}

/* `position: relative` para passarem à frente do X dourado. Sem isto, o X -
   que é um elemento posicionado - pinta por cima de conteúdo em fluxo normal,
   por muito que venha antes no documento, e o texto ficava riscado. */
.final-elogio, .final-nome, .final-frase, .final-pessoal {
  position: relative;
}

.final-elogio, .final-nome {
  font: italic 900 190px/1 'Toyota Type', sans-serif;
  text-transform: uppercase;
}
/* Uma linha só; quem trata de a fazer caber é ajustarParaLargura(), em
   js/jogo.js - o nome do vencedor pode ter 16 letras. */
.final-nome { white-space: nowrap; }
/* Peso 600, não 900: no mockup a frase é visivelmente mais leve que o nome, e
   é esse contraste que faz o nome saltar. 600 e não 700 porque a fonte só tem
   itálico verdadeiro nos pesos 900 e 600 (ToyotaType-BlackIt e -SemiboldIt) -
   pedir 700 dava um itálico sintetizado pelo browser a partir do Bold, que
   inclina as letras em vez de as desenhar inclinadas e destoa do nome logo
   por cima. */
.final-frase {
  font: italic 600 150px/1.05 'Toyota Type', sans-serif;
  text-transform: uppercase;
}
.final-pessoal { display: flex; flex-direction: column; align-items: center; gap: 12px; }
