/* app.css — estilos do domínio do M2F.
 *
 * 🟢 O bloco da PORTARIA é porte literal do `app.less` do producoes (linhas 823 em
 * diante), que é a tela que o dono aprovou em produção. É CSS puro: usa só
 * `var(--nexus-*)` do core e `@keyframes`, sem uma construção de LESS — por isso
 * viaja sem compilação, que o fork ainda não tem.
 *
 * ⚠️ Nasceu com dono. O comentário que o `index.html` carregava dizia que não havia
 * `app.css` porque não havia uma regra própria; agora há, e o link voltou.
 */

/* 🔴 `--nexus-radius-md` NÃO EXISTE — nem no core, nem no producoes. O CSS da
 * portaria o usa em cinco lugares, e um `border-radius: var(--indefinida)` é
 * declaração inválida: o navegador a descarta e o canto fica RETO. Na portaria de
 * hoje esses cinco cantos são retos por acidente, não por desenho.
 * Definido aqui no valor entre `--nexus-radius` (8px) e `--nexus-radius-lg` (12px),
 * que é o que o nome pede. Quando o core ganhar o seu, esta linha sai. */
:root { --nexus-radius-md: 10px; }

.prt {
	/* Acima do painel companheiro do core por DIZER isso, e não por empatar com ele.
	   Era `6000` cravado até 16/09/2026, achado inspecionando a `.nexus-sidebar`
	   (sticky, 5000) no navegador — decisão informada, mas que valia UMA vez e
	   envelheceria calada no dia em que o core mexesse nos literais dele. O token
	   chegou no Nexus v0.916 e a conta passou a acompanhar o core sozinha.
	   O `+ 1` é o que a medição original não pegou: 6000 EMPATAVA com `#nexus-panel` e
	   `#nexus-notify-container`, e empate em z-index resolve por ordem no DOM. Sem efeito
	   hoje — esta superfície não monta o painel —, mas agora está dito em vez de dar sorte.
	   Segue abaixo do `.nexus-global-backdrop` (`--nexus-z-overlay`, 9999) de propósito: o
	   loader do boot continua por cima de tudo, inclusive daqui.
	   ⚠️ O fallback do `var()` não é enfeite. Este `app.css` e o `nexus.css` do core são
	   dois arquivos com precache próprio, e um cliente pode ficar com o do core atrasado:
	   sem o token e sem fallback a declaração inteira vira inválida, o z-index cai para
	   `auto` e a portaria abre POR BAIXO da sidebar — no escuro, na porta. */
	position: fixed; inset: 0; z-index: calc(var(--nexus-z-panel, 6000) + 1);
	background: #000; color: #fff;
	display: flex; flex-direction: column;
	/* Margem estéril nas laterais: com o cansaço a pega relaxa e a base da palma
	   repousa sobre a borda, roubando toques. Nada acionável encosta na beirada. */
	padding: env(safe-area-inset-top) env(safe-area-inset-right)
	         env(safe-area-inset-bottom) env(safe-area-inset-left);
}

/* Escolha do evento */
.prt-eventos { flex: 1; overflow-y: auto; padding: var(--nexus-space-md); }
.prt-pergunta { font-size: 1.1rem; margin: 0 0 var(--nexus-space-md); opacity: .85; }
.prt-lista { display: flex; flex-direction: column; gap: var(--nexus-space-sm); }

.prt-evento {
	display: flex; flex-direction: column; gap: 4px;
	min-height: 64px; padding: var(--nexus-space-sm) var(--nexus-space-md);
	background: #161b22; color: inherit;
	border: 1px solid #2a323d; border-radius: var(--nexus-radius-md);
	text-align: left; font: inherit; cursor: pointer;
}
.prt-evento:active { background: #222b36; }
.prt-evento-titulo { font-weight: 600; font-size: 1.05rem; }
.prt-evento-data { font-size: .85rem; opacity: .7; }
/* "Você está aqui" no cartão do evento (18/09/2026): a dica que evita o toque no
   evento errado quando há dois na mesma noite. Entra DEPOIS de a lista pintar — o GPS
   não segura a tela —, então tem linha própria e não desloca o que já está lido. */
.prt-evento-perto { display: block; font-size: .8rem; opacity: .75; margin-top: 2px; }
.prt-evento-aqui { opacity: 1; font-weight: 600; color: #34d399; }
.prt-vazio { opacity: .7; line-height: 1.5; padding: var(--nexus-space-md); }

/* Rodapé da escolha de evento: quem está logado, e a saída. Discreto e no fim
   da lista de propósito — sair APAGA a fila de envio, então não pode disputar o
   toque com o evento que o porteiro veio escolher. */
.prt-rodape {
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--nexus-space-sm); flex-wrap: wrap;
	margin-top: var(--nexus-space-lg); padding-top: var(--nexus-space-md);
	border-top: 1px solid #2a323d;
}
.prt-conta { font-size: .85rem; opacity: .6; }
.prt-sair {
	min-height: 44px; padding: 0 var(--nexus-space-md);
	background: none; color: inherit; opacity: .75;
	border: 1px solid #2a323d; border-radius: var(--nexus-radius-md);
	font: inherit; cursor: pointer;
}
.prt-sair:active { opacity: 1; background: #222b36; }

/* Câmera */
.prt-scanner { position: relative; flex: 1; overflow: hidden; }
.prt-video { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Mira do QR: cruz fina de 64px, não moldura fechada — moldura pequena só faz o
   operador caçar alinhamento milimétrico, e a mão oscila junto. Discreta de
   propósito.

   ⚠️ Este comentário afirmava que "o decodificador varre o quadro inteiro", e
   era FALSO: o padrão da lib é o quadrado central de 2/3 do menor lado, o que
   num stream retrato 720×1280 dava 480×480 — 67 % da largura e **37 % da
   altura**. QR no terço de cima ou de baixo não era lido, e nada na tela dizia
   isso. Desde a v0.390 a janela é 92 % do quadro (`regiaoDeAnalise` em
   portaria.js), então a afirmação passou a ser quase verdadeira — e a cruz, que
   só diz "aponte para cá", voltou a ser honesta. Medido em
   docs/portaria-leitura-qr.md §1. */
.prt-mira {
	position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
	width: 64px; height: 64px; opacity: .45; pointer-events: none;
	&::before, &::after { content: ''; position: absolute; background: rgba(255,255,255,.8); }
	&::before { left: 50%; top: 0; width: 1px; height: 100%; }
	&::after { top: 50%; left: 0; height: 1px; width: 100%; }
}

/* A legenda da mira, no rodapé. Discreta de propósito: quem já opera não a lê,
   e quem abre a tela pela primeira vez descobre o que a cruz quer sem
   treinamento. `opacity` baixa + sombra é o que a mantém legível sobre vídeo
   claro ou escuro sem uma barra opaca comendo campo de visão.

   Some por SELETOR IRMÃO, sem uma linha de JS: quando o cartão do convidado ou
   a moldura do rosto estão na tela, a instrução é outra e a base pertence ao
   veredito. Fazer isso no JS custaria mais um ponto onde a tela pode ficar
   dessincronizada do estado — e aqui gravar é publicar. */
.prt-dica {
	position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
	margin: 0; padding: var(--nexus-space-sm) var(--nexus-space-md);
	padding-bottom: calc(var(--nexus-space-sm) + env(safe-area-inset-bottom));
	font-size: .82rem; text-align: center; opacity: .6; color: #fff;
	text-shadow: 0 1px 6px rgba(0,0,0,.9);
	pointer-events: none;
}
#prt-moldura:not([hidden]) ~ .prt-dica,
#prt-resultado:not([hidden]) ~ .prt-dica { display: none; }

/* Máscara de ENQUADRAR O ROSTO — a peça que a 2ª geração do legado perdeu.
   Borda tracejada + vinheta de 100vmax em volta: comunica "encaixe aqui" sem
   uma palavra, e é o que garante que a foto anti-fraude seja do convidado, não
   do papel do ingresso. `pulso` chama o olho sem piscar. */
.prt-moldura {
	position: absolute; top: 46%; left: 50%; transform: translate(-50%, -50%);
	width: min(74vw, 340px); aspect-ratio: 3 / 4;
	/* Quatro cantos em L, sem tracejado fechado e sem escurecer o fundo
	   (escolha do dono, 16/09/2026, depois de ver a versão com vinheta). É a
	   linguagem de mira que todo app de câmera usa: guia o enquadramento sem
	   tampar a cena nem competir com o rosto que está sendo fotografado. */
	pointer-events: none;
	background:
		linear-gradient(#fff, #fff) left  top    / 28px 3px no-repeat,
		linear-gradient(#fff, #fff) left  top    / 3px 28px no-repeat,
		linear-gradient(#fff, #fff) right top    / 28px 3px no-repeat,
		linear-gradient(#fff, #fff) right top    / 3px 28px no-repeat,
		linear-gradient(#fff, #fff) left  bottom / 28px 3px no-repeat,
		linear-gradient(#fff, #fff) left  bottom / 3px 28px no-repeat,
		linear-gradient(#fff, #fff) right bottom / 28px 3px no-repeat,
		linear-gradient(#fff, #fff) right bottom / 3px 28px no-repeat;
	filter: drop-shadow(0 0 3px rgba(0,0,0,.7));
	animation: prt-pulso 2s ease-in-out infinite;
}
/* Opacidade, não cor: anima no compositor e não repinta os oito gradientes. */
@keyframes prt-pulso {
	0%, 100% { opacity: 1; }
	50%      { opacity: .5; }
}

/* Topo: nome do evento e a saída. Gradiente em vez de barra sólida — barra
   opaca comeria ~115px de campo de visão, que é o que o legado fazia. */
.prt-topo {
	position: absolute; top: 0; left: 0; right: 0;
	display: flex; align-items: center; justify-content: space-between;
	gap: var(--nexus-space-sm);
	padding: var(--nexus-space-sm) var(--nexus-space-md);
	background: linear-gradient(rgba(0,0,0,.7), transparent);
}
/* Nome e janela do evento, empilhados. O `min-width: 0` é o que permite o
   ellipsis funcionar dentro de um filho de flex — sem ele o nome longo empurra
   o botão de trocar fora da tela em vez de truncar. */
/* ⚠️ `prt-topo-evento`, e não `prt-evento`: esse nome já é o CARD da escolha de
   evento (passo 1), com fundo e borda próprios — reaproveitá-lo aqui punha um
   retângulo cinza no meio da faixa da câmera. */
.prt-topo-evento {
	flex: 1; min-width: 0;
	display: flex; flex-direction: column; gap: 1px;
}
.prt-evento-nome {
	font-weight: 600; font-size: .95rem;
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* A janela do evento: menor e apagada, porque é contexto e não veredito. Quem
   decide algo com ela decide ANTES da fila chegar; o que manda na tela continua
   sendo o cartão do convidado. */
.prt-janela {
	font-size: .72rem; opacity: .7; font-variant-numeric: tabular-nums;
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Faltando 30min para terminar, a janela deixa de ser contexto: acende. */
.prt-janela-fim { opacity: 1; color: #fcd34d; }

/* Trocar de evento: MESMO idioma discreto das ferramentas raras (redondo,
   translúcido, opacidade baixa) — pedido do dono em 16/09, a borda quadrada
   com 1px a .35 de branco gritava mais que o nome do evento ao lado.
   Os 44px continuam: "discreto" é peso visual e posição, nunca alvo que erra.
   ⚠️ O `font: inherit` que vinha DEPOIS de `font-size: 1.2rem` zerava o
   tamanho do emoji sem ninguém notar — removido, agora há um só. */
.prt-trocar {
	width: 44px; height: 44px; padding: 0; flex: 0 0 auto;
	display: flex; align-items: center; justify-content: center;
	font: inherit; font-size: 1.05rem; line-height: 1;
	background: rgba(0,0,0,.35); color: #fff; opacity: .65;
	border: 1px solid rgba(255,255,255,.12); border-radius: 50%;
	cursor: pointer;
}
.prt-trocar:active { opacity: 1; background: rgba(255,255,255,.2); }

/* O gráfico do tempo: 2px na base da faixa. `transform: scaleX()` em vez de
   `width` — anima no compositor e não relayoutiza a faixa a cada minuto, mesma
   razão que pôs o anel em `stroke-dasharray`. */
.prt-tempo {
	position: absolute; top: 0; left: 0; right: 0;
	height: 2px; overflow: hidden;
	background: rgba(255,255,255,.12);
	> i {
		display: block; height: 100%;
		background: rgba(255,255,255,.55);
		transform-origin: left center;
		transform: scaleX(0);
		transition: transform .6s ease;
	}
}

/* O placar é uma BARRA, não três números grandes. O legado fazia do contador o
   elemento mais pesado da tela inteira — mais que o nome do convidado —, e ele
   não muda nenhuma decisão do porteiro. Aqui dá a noção de andamento de relance
   e o detalhe abre sob demanda. */
.prt-placar {
	/* Na MESMA linha do nome do evento e do botão de trocar (pedido do dono):
	   tudo o que é contexto mora numa faixa só, e o resto da tela é câmera. */
	display: flex; align-items: center; gap: 6px; flex: 0 0 auto;
	min-height: 44px; padding: 0;
	background: none; border: 0; color: #fff; font: inherit; cursor: pointer;
}
.prt-anel {
	width: 34px; height: 34px; flex: 0 0 auto;
	transform: rotate(-90deg);   /* começa no topo, como um relógio */
	> circle { fill: none; stroke-width: 3.5; }
}
.prt-anel-trilho { stroke: rgba(255,255,255,.22); }
.prt-anel-arco {
	stroke: #34d399; stroke-linecap: round;
	stroke-dasharray: 0 97.4;   /* 2·π·15.5 */
	transition: stroke-dasharray .4s ease;
}
.prt-placar-texto { font-size: .8rem; opacity: .85; font-variant-numeric: tabular-nums; }
/* Fila pendente tinge a barra de âmbar: não é erro, é trabalho que não subiu. */
.prt-placar-fila .prt-anel-arco { stroke: #f59e0b; }
.prt-placar-fila .prt-placar-texto { color: #fcd34d; opacity: 1; }

/* O elo com os outros aparelhos: 8px de ponto, e nada mais.
   Verde quando algum colega responde, âmbar quando há algo a dizer a quem
   montou a operação. Sem texto, sem toast, sem animação de alarme — a regra
   desta tela é que infraestrutura NÃO interrompe quem está na porta, e a
   explicação inteira mora no painel "Como vai a portaria".
   Mesma paleta do anel (#34d399 = entradas) e da fila (#f59e0b): uma terceira
   cor aqui faria ler significado onde não há. */
.prt-elo {
	width: 8px; height: 8px; flex: 0 0 auto; border-radius: 50%;
	background: rgba(255,255,255,.3);
}
.prt-elo-ligado { background: #34d399; }
/* Pisca DEVAGAR, e só no caso que pede ação humana. O `prt-pulso` já existe
   nesta folha e é o mesmo idioma do resto da tela. */
.prt-elo-alerta { background: #f59e0b; animation: prt-pulso 2.4s ease-in-out infinite; }

/* O QR do pareamento. Fundo BRANCO e sólido, e não translúcido: este código é
   lido pela câmera de OUTRO celular, então contraste aqui é requisito de
   função. Destoar do tema escuro da tela é o ponto. */
.prt-pareamento-corpo {
	padding: var(--nexus-space-md);
	display: flex; flex-direction: column; align-items: center; gap: var(--nexus-space-md);
}
.prt-pareamento-qr {
	background: #fff; padding: var(--nexus-space-sm); border-radius: 8px;
	line-height: 0;
	> svg { width: min(62vw, 260px); height: auto; display: block; }
	&:empty { display: none; }
}
.prt-pareamento-dica { margin: 0; text-align: center; font-size: .9rem; opacity: .85; max-width: 32ch; }
/* O aviso de rede no painel de detalhe: âmbar, porque é a única coisa ali que
   pede ação — e a ação é de quem montou a operação, não do porteiro. */
.prt-aviso-rede {
	margin: var(--nexus-space-sm) 0 0; font-size: .85rem; line-height: 1.4;
	color: #fcd34d;
}
.prt-parear { margin-top: var(--nexus-space-md); }

/* Ferramentas, no arco do polegar. Ficam VISÍVEIS com o cartão aberto: no
   legado sumiam, e o porteiro não conseguia acender a lanterna justamente na
   hora de conferir um rosto contra a foto. */
/* `bottom: 42%` era geometria de COLUNA: quatro botões empilhados precisavam
   começar alto para o de baixo não encostar no cartão do convidado. Com um só,
   isso vira um botão solto no meio da lateral. Desceu para a faixa que a §9.5 já
   reservou — a foto do cartão termina em 281px e a coluna começava em 311px —,
   que é onde o polegar chega sem reposicionar a mão. */
.prt-ferramentas {
	position: absolute; right: var(--nexus-space-sm); bottom: 28%;
	display: flex; flex-direction: column; align-items: flex-end;
	gap: var(--nexus-space-sm);
}
/* 🔴 Sem esta linha o `hidden` da coluna não esconde NADA: o atributo aplica
   `display: none` pela folha do navegador, e qualquer `display` de autor — o
   `flex` logo acima — ganha dele. O `mostrarMoldura()` seta `.hidden = true` na
   captura, e sem isto a coluna continuaria na tela, com o bug invisível no
   código (o JS "funciona", o CSS é que decide). */
.prt-ferramentas[hidden] { display: none; }
/* 🔦 Sobrou uma, e ela mudou de peso e de lugar em 17/09, a pedido do dono
   ("pode ficar, mas talvez reposicionado, e sem borda").
   A coluna tinha QUATRO botões e o desenho era de coluna: círculos com contorno,
   empilhados no meio da lateral, empurrados para cima pelo cartão. Com um item
   só, contorno vira moldura sem função — não separa de vizinho nenhum — e a
   altura de 42% deixa o único botão da tela no meio do caminho do polegar.
   Sem borda, e mais embaixo: o fundo translúcido já o destaca sobre a imagem, e
   é a lanterna que se acende com a fila andando. */
.prt-ferramenta {
	width: 56px; height: 56px; padding: 0;
	display: flex; align-items: center; justify-content: center;
	background: rgba(0,0,0,.45); backdrop-filter: blur(8px);
	color: #fff; font-size: 1.4rem;
	border: 0; border-radius: 50%;
	cursor: pointer;
}
.prt-ferramenta:active { background: rgba(255,255,255,.2); }
/* Os raros: menores e mais discretos, mas ainda com 44px de alvo — "escondido"
   é sobre PESO VISUAL e posição, nunca sobre virar um alvo que erra. */
.prt-ferramenta-rara {
	width: 44px; height: 44px; font-size: 1.05rem;
	background: rgba(0,0,0,.35); opacity: .65;
	border-color: rgba(255,255,255,.12);
}
.prt-ferramenta-rara:active { opacity: 1; }

.prt-ferramenta-ativa {
	background: rgba(255,200,0,.35); border-color: rgba(255,200,0,.5);
	box-shadow: 0 0 12px rgba(255,200,0,.3);
}
/* O botão de ajuda NÃO é vermelho, e isso é deliberado: vermelho é a cor da
   recusa, e em visão periférica cansada o olho bate no vermelho e lê "barrado".
   Roxo não colide com nenhum veredito. */
.prt-ajuda { background: rgba(109,40,217,.75); border-color: rgba(167,139,250,.6); }

/* O cartão de resultado. Ancorado na BASE, com gradiente que deixa o topo
   transparente: a cara do convidado continua visível enquanto o porteiro lê o
   nome — e continua visível para ser ENQUADRADA na moldura. */
.prt-resultado {
	position: absolute; left: 0; right: 0; bottom: 0;
	display: flex; flex-direction: column; align-items: flex-start;
	gap: 4px; padding: var(--nexus-space-md);
	padding-bottom: calc(var(--nexus-space-md) + env(safe-area-inset-bottom));
	background: linear-gradient(to bottom, transparent, rgba(0,0,0,.82) 42%);
	animation: prt-sobe .2s ease;
}
@keyframes prt-sobe { from { opacity: 0; transform: translateY(16px); } }

.prt-icone {
	width: 44px; height: 44px; flex: 0 0 auto;
	display: flex; align-items: center; justify-content: center;
	border-radius: 50%; font-size: 1.4rem; font-weight: 700;
}
/* O nome do convidado é o maior elemento do cartão — é o dado que decide, e o
   legado o deixava menor que o contador do topo. */
.prt-titulo { font-size: 1.5rem; font-weight: 800; line-height: 1.15; text-shadow: 0 1px 6px rgba(0,0,0,.8); }
.prt-nome { font-size: 1.05rem; text-shadow: 0 1px 6px rgba(0,0,0,.8); }
.prt-detalhes { display: flex; gap: var(--nexus-space-sm); flex-wrap: wrap; margin-top: 2px; }
.prt-tipo, .prt-mesa {
	padding: 4px 12px; border-radius: 20px; font-size: .9rem; font-weight: 700;
	background: rgba(0,0,0,.45); backdrop-filter: blur(4px);
	border: 1px solid currentColor;
}
.prt-detalhe { font-size: .9rem; opacity: .9; line-height: 1.35; text-shadow: 0 1px 6px rgba(0,0,0,.8); }
/* A instrução de enquadrar o rosto: é ela que ensina o fluxo sem treinamento. */
.prt-instrucao { font-size: .95rem; font-weight: 600; color: #a7f3d0; margin-top: 2px; }

/* Cor é reforço, nunca o único sinal: cada desfecho também muda ícone e texto.
   Fundos escuros dessaturados — ver a nota sobre escotoma no topo do bloco. */
.prt-ok    { background: linear-gradient(to bottom, transparent, rgba(6,46,30,.92) 42%); }
.prt-ok    .prt-icone { background: rgba(52,211,153,.22); color: #6ee7b7; }
.prt-ok    .prt-tipo, .prt-ok .prt-mesa { color: #6ee7b7; }
/* `max-height` junto da cor porque o seletor era declarado DUAS vezes (o
   sensor do stylelint cobra, e com razão: duas fontes para a mesma regra).
   Rolar é melhor que cortar o horário, que é o dado da contestação. */
.prt-usado {
	background: linear-gradient(to bottom, transparent, rgba(69,39,6,.92) 42%);
	max-height: 92%; overflow-y: auto;
}
.prt-usado .prt-icone { background: rgba(245,158,11,.22); color: #fcd34d; }
.prt-nao   { background: linear-gradient(to bottom, transparent, rgba(69,10,10,.92) 42%); }
.prt-nao   .prt-icone { background: rgba(239,68,68,.22); color: #fca5a5; animation: prt-treme .4s ease; }
@keyframes prt-treme {
	0%, 100% { transform: translateX(0); }
	25% { transform: translateX(-6px); }
	75% { transform: translateX(6px); }
}

/* A foto da primeira entrada. GRANDE: o legado a reduziu a 100px com um toque
   para ampliar, e ela é justamente a evidência que encerra a discussão no
   portão — o porteiro vira a tela e mostra. */
.prt-foto {
	width: 128px; height: 170px; object-fit: cover;
	border-radius: var(--nexus-radius-md);
	border: 2px solid rgba(255,255,255,.55);
	margin-bottom: var(--nexus-space-xs);
	cursor: zoom-in;
}
.prt-lightbox {
	position: absolute; inset: 0; z-index: 10;
	display: grid; place-items: center;
	background: rgba(0,0,0,.95); backdrop-filter: blur(10px);
	cursor: zoom-out;
	> img { max-width: 100%; max-height: 100%; object-fit: contain; }
}

/* Registrar: largura inteira, 64px, na base — onde o polegar descansa. */
.prt-acao {
	margin-top: var(--nexus-space-sm);
	min-height: 64px; width: 100%;
	background: #fff; color: #111;
	border: 0; border-radius: var(--nexus-radius-md);
	font: inherit; font-size: 1.15rem; font-weight: 700;
	cursor: pointer;
}
.prt-acao:active { background: #d9d9d9; }

/* Cancelar no ALTO do cartão, longe do polegar (decisão do dono): o toque
   acidental acontece na base, que é onde o botão dominante mora. 44px é o piso
   de alvo — "menos acessível" é sobre POSIÇÃO, nunca sobre tamanho. */
.prt-cancelar {
	position: absolute; top: 6px; right: 6px;
	min-width: 44px; min-height: 44px;
	background: rgba(0,0,0,.4); color: #fff; font-size: 1.1rem;
	border: 1px solid rgba(255,255,255,.4); border-radius: 50%;
	cursor: pointer;
}

/* O sucesso não deixa cartão: um flash curto e a câmera já está pronta. */
.prt-flash {
	position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
	z-index: 9; pointer-events: none;
	max-width: 80%; padding: 14px 26px; border-radius: 26px;
	background: rgba(6,78,59,.92); color: #d1fae5;
	border: 1px solid rgba(110,231,183,.5);
	font-size: 1.15rem; font-weight: 700; text-align: center;
	/* 2,4 s, casado com o `FLASH_MS` do portaria.js — os dois são o MESMO tempo
	   em dois arquivos, e destoar é invisível no código e gritante na tela: o
	   elemento sai de `opacity:0` ao fim da animação e só é removido do DOM pelo
	   timeout, então um CSS mais curto deixa um retângulo transparente por cima
	   da câmera, e um CSS mais longo corta a frase no meio da leitura. */
	animation: prt-flash 2.4s ease forwards;
}
@keyframes prt-flash {
	0%   { opacity: 0; transform: translate(-50%, -50%) scale(.85); }
	/* A entrada continua em ~290 ms (12 % de 2,4 s): o aviso tem de aparecer no
	   tempo do gesto, não da leitura. O que cresceu é o PLANALTO — a frase fica
	   legível até 80 % antes de começar a subir e sumir. */
	12%  { opacity: 1; transform: translate(-50%, -50%) scale(1); }
	80%  { opacity: 1; }
	100% { opacity: 0; transform: translate(-50%, -62%) scale(1); }
}

.prt-aviso {
	position: absolute; left: 0; right: 0; top: 0; z-index: 4;
	margin: 0; padding: var(--nexus-space-md);
	background: #7f1d1d; line-height: 1.4;
}

/* Painéis de tela cheia: busca, ajuda e detalhe */
.prt-busca, .prt-ajuda-painel, .prt-painel {
	/* `.prt-painel` e NÃO `.prt-detalhe`: aquele nome já era do texto de detalhe
	   dentro do cartão, e o span herdava `position:absolute; inset:0` — virava
	   uma camada preta de tela cheia. Medido no navegador em 16/09/2026; nenhum
	   erro no console, só o layout impossível. */
	position: absolute; inset: 0; z-index: 3;
	background: #0b0f14; display: flex; flex-direction: column;
}
.prt-busca-topo { display: flex; gap: var(--nexus-space-sm); padding: var(--nexus-space-sm); }
.prt-busca-campo {
	flex: 1; min-height: 56px; padding: 0 var(--nexus-space-sm);
	background: #161b22; color: #fff;
	border: 1px solid #2a323d; border-radius: var(--nexus-radius-md);
	font: inherit; font-size: 1.05rem;
}
.prt-busca-fechar {
	min-width: 56px; min-height: 56px; padding: 0;
	font-size: 1.2rem; line-height: 1;
	background: transparent; color: #fff;
	border: 1px solid rgba(255,255,255,.45); border-radius: var(--nexus-radius-md);
	font-family: inherit; cursor: pointer;
}
.prt-ajuda-titulo { flex: 1; align-self: center; font-size: 1.05rem; font-weight: 600; }
.prt-busca-resultados, .prt-detalhe-corpo {
	flex: 1; overflow-y: auto;
	padding: 0 var(--nexus-space-sm) var(--nexus-space-sm);
	display: flex; flex-direction: column; gap: 6px;
}
/* Duas linhas à esquerda (nome, e onde a pessoa senta), estado à direita
   atravessando as duas. Grid com áreas NOMEADAS, e não flex com
   `space-between`: com três filhos irmãos o auto-placement põe "onde" na
   coluna do estado, e o resultado só aparece torto na tela do porteiro. */
.prt-achado {
	display: grid; align-items: center; gap: 0 var(--nexus-space-sm);
	grid-template-columns: 1fr auto;
	grid-template-areas: "nome estado" "onde estado";
	min-height: 64px; padding: var(--nexus-space-sm);
	background: #161b22; color: inherit;
	border: 1px solid #2a323d; border-radius: var(--nexus-radius-md);
	text-align: left; font: inherit; cursor: pointer;
}
.prt-achado-nome { grid-area: nome; font-weight: 600; }
/* Mesa · tipo · "mesmo pedido". O `:empty` some do layout em vez de deixar uma
   linha em branco no cartão de quem não tem mesa nem tipo. */
.prt-achado-onde {
	grid-area: onde; font-size: .78rem; opacity: .7;
	overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
	&:empty { display: none; }
}
.prt-achado-estado { grid-area: estado; font-size: .8rem; opacity: .75; white-space: nowrap; }
.prt-achado[disabled] { opacity: .5; cursor: default; }

/* Detalhe da contagem, sob demanda */
.prt-numeros { display: flex; gap: var(--nexus-space-sm); }
.prt-numeros > span {
	flex: 1; display: flex; flex-direction: column; align-items: center; gap: 2px;
	padding: var(--nexus-space-sm); border-radius: var(--nexus-radius-md);
	background: #161b22; border: 1px solid #2a323d;
	font-size: .75rem; opacity: .8; text-align: center;
	> b { font-size: 1.6rem; font-weight: 800; opacity: 1; font-variant-numeric: tabular-nums; }
}
.prt-numeros-menor > span > b { font-size: 1.2rem; }
.prt-secao { margin: var(--nexus-space-md) 0 4px; font-size: .8rem; opacity: .7; }

/* Últimos acessos: lista de CONFERÊNCIA, não relatório — dez linhas, sem
   ordenação, sem filtro. O relatório é a /analise. A hora é tabular para as
   colunas se alinharem sem tabela, e o nome trunca porque a hora é o que não
   pode sumir: ela é a resposta de "acabei de registrar essa pessoa?". */
.prt-ultimos {
	list-style: none; margin: 0; padding: 0;
	> li {
		display: flex; align-items: baseline; gap: var(--nexus-space-sm);
		padding: 6px 0; border-bottom: 1px solid #222a33;
		font-size: .9rem;
	}
	> li:last-child { border-bottom: 0; }
}
.prt-ultimos-nome { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prt-ultimos-hora { font-variant-numeric: tabular-nums; opacity: .8; }
.prt-ultimos-quem {
	font-size: .72rem; opacity: .6;
	padding: 1px 6px; border: 1px solid #2a323d; border-radius: 10px;
}

/* Evento e conta, no fim do painel. Ficam depois de tudo de propósito: as duas
   ações daqui saem da operação (uma troca o evento, a outra apaga a fila), e
   rolar até elas é a barreira que as mantém longe do dedo de quem está na fila. */
.prt-operacao { display: flex; flex-direction: column; }
.prt-operacao-linha {
	display: flex; gap: var(--nexus-space-sm); align-items: baseline;
	padding: 6px 0; font-size: .9rem;
	> b { font-size: .75rem; opacity: .6; text-transform: uppercase; letter-spacing: .04em; }
}
/* "Sair" não compete com "Trocar de evento": mesmo alvo de toque, menos peso —
   é a mesma regra do `.prt-trocar` da faixa, onde discrição é peso visual e
   nunca alvo que erra. */
.prt-acao-discreta {
	background: transparent; color: #e6edf3;
	border: 1px solid #2a323d; font-weight: 600; font-size: 1rem;
}
.prt-acao-discreta:active { background: #1c232c; }

/* Pedir ajuda, primeiro item do menu (17/09). Roxo, como o ✋ era na coluna: a cor
   sobreviveu à mudança de lugar porque é por ela que o botão se acha sem ler.
   A LISTA de supervisores mora aqui quando não há escolha salva — ver o porquê da
   contagem de toques no comentário de `blocoDeAjuda()`. */
/* ── O idioma do menu: LINHA, não bloco ─────────────────────────────────────
   Veredito do dono sobre a v0.418, com a tela na mão: cinco `.prt-acao` brancos
   de 64px empilhados — parear, buscar, sincronizar, trocar de evento, sair —
   gritavam mais que o conteúdo, e "Sair da conta" (que APAGA a fila de envio)
   tinha exatamente o mesmo peso de "Buscar convidado".

   É o mesmo erro que a lista roxa tinha, com outra cor: destaque repetido não
   destaca. O `.prt-acao` cheio continua existindo para onde ele nasceu — o
   cartão do convidado, onde há UMA ação e ela é o ponto da tela. Aqui dentro,
   ação é linha. */
.prt-menu-linha {
	display: flex; align-items: center; gap: var(--nexus-space-sm);
	min-height: 48px; width: 100%; text-align: left;
	padding: 0 4px; border: 0; border-bottom: 1px solid #222a33;
	background: transparent; color: #e6edf3;
	font: inherit; font-size: .95rem; cursor: pointer;
}
.prt-menu-linha:active { background: #1c232c; }
.prt-menu-linha > i { font-style: normal; opacity: .8; width: 1.4em; text-align: center; }
/* Sair APAGA a fila de envio (com pergunta antes). Não pode parecer igual a
   trocar de evento: a cor não carrega o aviso sozinha — o rótulo diz "Sair" e o
   diálogo do core explica o que se perde —, mas ela impede o toque distraído. */
.prt-menu-linha-sair { color: #fca5a5; }
/* Nome + horário do evento empilhados dentro da linha do menu. A `.prt-menu-linha`
   é de 48px e cresce: dois eventos na mesma noite se distinguem pela DATA, então
   ela não pode ser o que trunca. */
.prt-menu-evento {
	display: flex; flex-direction: column; gap: 1px; min-width: 0;
	padding: 6px 0; line-height: 1.25;
	> small { font-size: .78rem; opacity: .65; }
}

/* O botão CHEIO é para quando há UM: o supervisor já escolhido. Aí o roxo faz o
   que sempre fez — achar sozinho, sem ler. */
.prt-acao-socorro {
	background: #4c1d95; color: #ede9fe;
	border: 1px solid #6d28d9;
}
.prt-acao-socorro:active { background: #5b21b6; }

/* 🔴 A LISTA é outra coisa, e a diferença veio do aparelho do dono: com um botão
   cheio por contato vieram SETE, 448px de roxo empilhado, e o menu foi a 1745px
   para 1082 de tela. Cor repetida sete vezes não destaca nada — só grita.
   O roxo fica no título da seção; as linhas seguem o idioma compacto de
   "Últimos acessos", que já é o padrão deste painel. 44px é o piso de alvo. */
.prt-secao-socorro { color: #c4b5fd; opacity: 1; }
/* 🔴 Teto de altura, e é o segundo corte da mesma lista. Compacta ela ficou em
   7×44 = 308px — ainda a primeira tela inteira do menu, antes de qualquer
   número. Com o teto, a lista mostra ~4 nomes e rola dentro de si: quem quer
   socorro acha no primeiro olhar, e quem abriu o menu para ver como vai a
   portaria não precisa rolar para chegar lá. */
.prt-menu-ajuda,
/* 🗓️ A lista de "Trocar para" (18/09) entra no MESMO seletor, e não numa regra
   irmã: o que ela precisa é exatamente o que a lista de socorro aprendeu em
   17/09 — teto com rolagem interna, moldura dizendo que há mais abaixo, e o
   `flex-shrink: 0` sem o qual um flex item com `overflow` encolhe até 2px de
   altura com os botões inteiros dentro. Regra separada nasceria igual e
   divergiria na primeira correção. */
.prt-menu-eventos {
	display: flex; flex-direction: column;
	/* 🔴 `flex-shrink: 0` não é ajuste fino — sem ele a lista SOME.
	   O `#prt-detalhe-corpo` é flex column, e um flex item com `overflow`
	   diferente de `visible` perde a proteção do `min-height: auto` (a regra manda
	   computá-lo como 0 nesse caso). Aí o item encolhe até o conteúdo inteiro
	   caber em nada: medido no aparelho em 17/09 — **container com 2px de altura,
	   7 botões de 44px dentro dele**, e na tela só o rótulo "Pedir ajuda a" com
	   uma linha embaixo. O DOM estava certo, os botões tinham altura, e mesmo
	   assim não havia lista para tocar.
	   Ironia útil de registrar: foi o `max-height` + `overflow` que eu acrescentei
	   para conter a lista "gritante" que abriu esse buraco. */
	flex-shrink: 0;
	max-height: 176px; overflow-y: auto;
	/* A borda diz que há mais coisa abaixo — lista que rola sem moldura parece
	   lista que acabou. */
	border: 1px solid #222a33; border-radius: var(--nexus-radius-md);
	padding: 0 6px;
}
.prt-socorro-linha {
	min-height: 44px; width: 100%; text-align: left;
	padding: 0 4px; border: 0; border-bottom: 1px solid #222a33;
	background: transparent; color: #e6edf3;
	font: inherit; font-size: .95rem; cursor: pointer;
}
.prt-socorro-linha:last-child { border-bottom: 0; }
.prt-socorro-linha:active { background: #2a2140; }

/* Permissões: nome + para que serve + estado, e o botão só onde ele tem chance.
   Linha de DIAGNÓSTICO, não de configuração — por isso é compacta e não imita a
   grade do /perfil. */
/* O select da lente. `<select>` nativo de propósito: o menu do sistema já é
   rolável, acessível e do tamanho certo em qualquer aparelho — lista escrita à
   mão aqui seria mais código para fazer pior, que é a mesma razão pela qual o
   filtro de data do NexusTable usa `<input type="date">`. */
.prt-select {
	width: 100%; min-height: 48px; padding: 0 10px;
	background: #161b22; color: #e6edf3;
	border: 1px solid #2a323d; border-radius: var(--nexus-radius-md);
	font: inherit; font-size: .95rem;
}

.prt-permissoes { display: flex; flex-direction: column; }
.prt-permissao {
	display: flex; align-items: center; gap: var(--nexus-space-sm);
	padding: 8px 0; border-bottom: 1px solid #222a33;
}
.prt-permissao:last-child { border-bottom: 0; }
.prt-permissao-nome {
	flex: 1; min-width: 0; display: flex; flex-direction: column; font-size: .9rem;
	> small { font-size: .72rem; opacity: .55; }
}
.prt-permissao-estado {
	font-size: .72rem; padding: 2px 8px; border-radius: 10px; white-space: nowrap;
	border: 1px solid currentColor;
}
/* Verde/vermelho/âmbar não carregam o significado sozinhos: o texto ao lado diz
   "Permitido", "Bloqueado", "Vai perguntar". Cor aqui é reforço, nunca o dado —
   é a regra que a /analise já segue nos chips de motivo. */
.prt-permissao-ok { color: #6ee7b7; }
.prt-permissao-nao { color: #fca5a5; }
.prt-permissao-talvez { color: #fcd34d; }
.prt-permissao-pedir {
	min-height: 36px; padding: 0 12px;
	background: #1c232c; color: #e6edf3;
	border: 1px solid #2a323d; border-radius: var(--nexus-radius-md);
	font: inherit; font-size: .85rem; cursor: pointer;
}
.prt-permissao-pedir:active { background: #2a323d; }
.prt-permissao-pedir[disabled] { opacity: .5; }
/* Barras por hora: a FORMA importa (quando encheu), não o número exato. */
.prt-barras { display: flex; align-items: flex-end; gap: 6px; height: 110px; }
.prt-barra {
	flex: 1; display: flex; flex-direction: column; justify-content: flex-end;
	align-items: center; gap: 4px; height: 100%;
	> i { display: block; width: 100%; height: var(--h); background: #34d399; border-radius: 4px 4px 0 0; }
	> small { font-size: .7rem; opacity: .6; }
}

/* Foto e texto LADO A LADO. Empilhados, o cartão de "já entrou" passava da
   altura da tela em 375×812 e o nome saía do quadro — medido em 16/09/2026.
   Lado a lado, o porteiro vê o rosto e lê o horário no mesmo golpe de vista,
   que é exatamente o gesto de virar a tela para o convidado. */
.prt-faixa { display: flex; gap: var(--nexus-space-sm); align-items: flex-start; width: 100%; }
.prt-faixa .prt-foto { margin-bottom: 0; flex: 0 0 auto; }
.prt-corpo { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
/* Com foto, o nome pode quebrar em duas linhas em vez de estourar a largura. */
.prt-faixa .prt-titulo { font-size: 1.25rem; }

/* A foto de quem já entrou, GRANDE — pedido do dono em 16/09/2026, com dois
   usos concretos: comparar o rosto na frente com o que entrou (pode ser
   reentrada de quem saiu) e APRESENTAR ao convidado em caso de contestação.
   Como o cartão de recusa agora fica na tela até o operador tocar em Continuar,
   há espaço para ela ocupar de verdade — não precisa caber num relance.

   Só no desfecho `usado`: nos outros a foto não existe. */
.prt-usado .prt-faixa {
	flex-direction: column; align-items: center;
	/* Abre espaço para a coluna de ferramentas: sem isto a foto grande passa por
	   baixo dos botões, e justamente o de PEDIR AJUDA — que é o que o operador
	   precisa alcançar num caso contestado. */
	padding-right: 68px;
}
.prt-usado .prt-faixa .prt-foto {
	width: auto; height: min(46vh, 340px); aspect-ratio: 3 / 4;
	border-width: 3px; border-color: rgba(252,211,77,.8);
	align-self: center;
}
.prt-usado .prt-corpo { align-items: center; text-align: center; }
/* Continuar: mesma altura do Registrar, e é o único caminho de saída de um
   desfecho ruim. Contorno em vez de branco sólido — não pode ser confundido,
   de relance, com o botão que libera alguém. */
.prt-continuar {
	background: transparent; color: #fff;
	border: 2px solid rgba(255,255,255,.7);
}
.prt-continuar:active { background: rgba(255,255,255,.18); }

/* ── Mapa do salão (/mapa) ───────────────────────────────────────────────────
   Porte do bloco `.mapa-*` do `app.less` do producoes, traduzido à mão para CSS
   puro (o fork não tem build de LESS) e com a paleta remapeada: lá as situações
   são de VENDA (disponível/avulsa/vendida), aqui são de OCUPAÇÃO.

   O desenho é montado pelo app em três camadas — dependências e paredes vêm do
   LOCAL, as mesas vêm do EVENTO — e nenhum estilo vem de dentro do SVG. Era o
   contrário no legado: o arquivo trazia o próprio <style>, o tema do app não
   alcançava nada lá dentro, e as classes de situação que o JS aplicava perdiam
   para o `#mesas rect {fill:none}` de lá — a cor simplesmente não aparecia. */

.mapa-legenda { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 8px; }
.mapa-legenda-item {
	display: inline-flex; align-items: center; gap: 6px;
	font-size: 0.85rem; color: var(--nexus-text-muted);
}

/* Paleta: cor PURA (saturação máxima), distinta em matiz, aplicada como
   preenchimento translúcido e traço cheio. NÃO usa as variáveis de tema do Nexus,
   de propósito — elas são calibradas para texto e botão sobre o fundo do tema, e
   no escuro chegavam tão próximas umas das outras que as situações se confundiam.
   Matiz puro sobrevive aos dois fundos: no claro o fill vira pastel, no escuro
   vira sombra da cor, e nos dois o traço cheio identifica. */
:root {
	--mapa-vazia:     #00e05a;
	--mapa-parcial:   #00a6ff;
	--mapa-reservada: #ffc400;
	--mapa-cheia:     #ff1744;
}

.mapa-amostra {
	width: 14px; height: 14px; border-radius: 4px;
	border: 1px solid var(--nexus-border); background: var(--nexus-bg-surface);
}
.mapa-amostra.st-vazia     { background: rgb(0 224 90 / 45%);  border-color: var(--mapa-vazia); }
.mapa-amostra.st-parcial   { background: rgb(0 166 255 / 45%); border-color: var(--mapa-parcial); }
.mapa-amostra.st-reservada { background: rgb(255 196 0 / 45%); border-color: var(--mapa-reservada); }
.mapa-amostra.st-cheia     { background: rgb(255 23 68 / 45%); border-color: var(--mapa-cheia); }
.mapa-amostra.st-oculta    { background: transparent; border-style: dashed; }

.mapa-aviso { color: var(--nexus-text-muted); font-size: 0.85rem; margin: 0 0 8px; }

/* Rodapé: o que escrever na mesa (interruptores) e a mesma conta em soma. Fica
   abaixo do desenho porque é leitura de apoio — o mapa é o assunto. */
.mapa-rodape {
	display: flex; align-items: center; justify-content: space-between;
	gap: 16px; flex-wrap: wrap; margin-top: 12px;
}
.mapa-lugares { display: flex; gap: 12px; flex-wrap: wrap; }
.mapa-lugar {
	display: inline-flex; align-items: center; gap: 8px;
	cursor: pointer; font-size: 0.9rem;
}

/* Os cartões de total, e a moldura que diz qual deles está escrito nas mesas. */
.mesa-painel-stats { display: flex; gap: 8px; flex-wrap: wrap; }
.mesa-stat {
	display: flex; align-items: center; gap: 8px;
	padding: 6px 12px; border-radius: 8px;
	background: var(--nexus-bg-subtle); border: 1px solid var(--nexus-border);
}
.mesa-stat-label {
	font-size: 0.72rem; text-transform: uppercase; letter-spacing: .04em;
	color: var(--nexus-text-muted);
	display: flex; align-items: center; min-height: 20px;
}
.mesa-stat-valor { font-size: 1.1rem; font-weight: 700; }
/* O total do interruptor ligado é o mesmo número que está nas mesas — a moldura
   diz isso sem precisar de legenda. */
.mesa-stat.is-ativo { border-color: var(--nexus-primary); }
.mesa-stat.is-ativo .mesa-stat-label { color: var(--nexus-primary); }

/* O palco rola por si; a planta acompanha a largura disponível. */
.mapa-palco {
	overflow: auto; border: 1px solid var(--nexus-border);
	border-radius: 8px; background: var(--nexus-bg-subtle); padding: 8px;
}

/* 🔴 Tamanho do mapa: quem manda é a ALTURA, não a largura.
   Antes era `width:100%` puro, e numa tela larga a planta virava um retângulo
   altíssimo — o salão de 15000×19000 dava 2072px de altura contra ~950 de
   viewport. Duas telas e meia de rolagem, com os interruptores e os totais
   sempre abaixo da dobra. A pergunta que esta tela responde é "onde estão as
   mesas cheias", e ela exige ver o salão inteiro de uma vez: mapa que não cabe
   é mapa que não responde.

   `--mapa-ratio` (largura ÷ altura do viewBox) é gravada pelo `mapa.js` na
   montagem: cada local tem a sua planta, então o CSS não tem como saber. Sem
   ela o fallback é 1 — quadrado, conservador: erra para menor, nunca estoura.
   `dvh` e não `vh` por causa da barra do navegador no celular.

   O piso de 560px é o outro lado da conta, e ele importa: caber não vale nada
   se o número da mesa ficar ilegível. Medido — num laptop de 768 de altura a
   conta dava 322px de largura, e aí o círculo da mesa fica com ~13px, sem
   leitura possível. Com o piso, tela baixa volta a rolar um pouco, o que é o
   comportamento certo: melhor rolar do que não conseguir ler. */
.mapa-svg {
	--mapa-altura: max(320px, calc(100dvh - 360px));
	width: 100%;
	max-width: max(560px, calc(var(--mapa-altura) * var(--mapa-ratio, 1)));
	margin-inline: auto;
}
.mapa-svg svg { width: 100%; height: auto; display: block; }

/* Planta do local: paths preenchidos (traço vetorizado). Cor do tema, senão a
   parede preta do arquivo some no tema escuro. Dependências recuam — são
   contexto (banheiro, cozinha, palco), não a estrutura que orienta a leitura. */
.mapa-svg #paredes { fill: var(--nexus-text); }
.mapa-svg #dependencias { fill: var(--nexus-text-muted); opacity: .45; }

/* `--traco` e o corpo da numeração saem do tamanho da própria mesa (`calibrar()`,
   no mapa.js): a mesma folha serve a uma planta de viewBox 15.000 e a outra de
   1.000, que com espessura fixa sairiam grossa demais ou invisível.

   O `:is(rect, circle, ellipse, polygon, path)` é a segunda lição do producoes: a
   mesa pode ser desenhada como quiserem — no salão de teste é um <circle>, no
   exemplo do contrato um <rect rx>. Pintar só `rect` deixava o desenho todo de
   uma cor só, que foi o primeiro sintoma em produção. */
#mesas > g { cursor: pointer; }
#mesas text { fill: var(--nexus-text); }
#mesas :is(rect, circle, ellipse, polygon, path) {
	stroke: var(--nexus-text); fill: none;
	stroke-width: var(--traco, 20); transition: fill .12s ease;
}
#mesas .mapa-mesa:hover :is(rect, circle, ellipse, polygon, path) {
	stroke-width: calc(var(--traco, 20) * 2);
}
/* Traço na cor cheia + preenchimento translúcido: é o traço que separa as
   situações no tema escuro, onde o fill fica quase da cor do fundo. */
#mesas .mapa-mesa.st-vazia :is(rect, circle, ellipse, polygon, path) {
	fill: rgb(0 224 90 / 38%); stroke: var(--mapa-vazia);
}
#mesas .mapa-mesa.st-parcial :is(rect, circle, ellipse, polygon, path) {
	fill: rgb(0 166 255 / 38%); stroke: var(--mapa-parcial);
}
#mesas .mapa-mesa.st-reservada :is(rect, circle, ellipse, polygon, path) {
	fill: rgb(255 196 0 / 38%); stroke: var(--mapa-reservada);
}
#mesas .mapa-mesa.st-cheia :is(rect, circle, ellipse, polygon, path) {
	fill: rgb(255 23 68 / 38%); stroke: var(--mapa-cheia);
}
#mesas .mapa-mesa.st-oculta :is(rect, circle, ellipse, polygon, path) {
	fill: none;
	stroke-dasharray: calc(var(--traco, 20) * 3) calc(var(--traco, 20) * 2);
}
/* O número da métrica: fora da mesa, sem roubar o clique dela. */
#mesas .mapa-badge {
	fill: var(--nexus-text); font-weight: 700; pointer-events: none;
	paint-order: stroke; stroke: var(--nexus-bg-surface);
	stroke-width: calc(var(--traco, 20) * 0.6);
}

/* Geometria colada no cadastro (planta em /locais, mesas em /eventos): dobrada
   num <details> para não empurrar o cadastro de verdade para baixo, e
   monoespaçada porque o que se confere aqui é coordenada, não texto. */
.mapa-campos {
	border: 1px solid var(--nexus-border); border-radius: 8px;
	padding: 8px 12px;
}
.mapa-campos > summary { cursor: pointer; font-weight: 600; padding: 4px 0; }
.mapa-campos > .nexus-field { margin-top: 8px; }
.mapa-campos :is(textarea, input) {
	font-family: ui-monospace, "Cascadia Code", "Droid Sans Mono", monospace;
	font-size: 0.8rem;
}
.mapa-campos textarea { white-space: pre; overflow-wrap: normal; overflow-x: auto; }
