/* ==================================================================
   SimuFísica 3.0 — CSS compartilhado do redesign (design system dos
   simuladores migrados: hoje pendulo-duplo2/ e lancamento-projeteis2/).
   Staging temporário — assets/css/sf3/, fora de assets/css/mainApp*.css
   (produção, os outros ~48 simuladores) — pra não afetar quem ainda usa
   o layout antigo. Quando a migração 3.0 for promovida (docs/
   redesign-3.0.md §6), este arquivo é o que vira o CSS compartilhado
   definitivo (mover pra assets/css/redesign.css ou equivalente, resolver
   nome final ali).
   Só regras GENÉRICAS aqui (tokens, cards .bloco, sliders, toggles, barra
   inferior, modais, painel "Gráfico"/Plotly, .sf3-ajustes-grid etc.) — CSS
   que só faz sentido pra UM simulador (ex. ordem "order" dos ícones da
   barra inferior de cada app, grid-column de um painel específico, o card
   "v = ..." de gravitacao2) NÃO deve morar aqui (09/08/2026, pedido do
   usuário — manutenção fica complicada tendo que mexer num arquivo global
   pra consertar um simulador só). Esse CSS vai num <style> dentro do
   próprio simulacoes/<slug>/index.html, logo depois do <link> pra este
   arquivo — convenção já usada por armadilha-magneto-optica2/gas-ideal2/
   circuito-rlc2/cargas-em-um-condutor2/espectrometria-massa2/
   interferencia-filmes-finos2/reflexao-refracao-dispersao2/
   transicoes-pulsos-luz2 desde a migração deles; pendulo-duplo2/
   lancamento-projeteis2/conservacao-energia-mecanica2/calorimetria2/
   movimento-retilineo2/gravitacao2 (migrados antes dessa convenção existir)
   tiveram o CSS específico deles migrado pra cá nessa mesma data. Seletores
   escopados por .sf3-app-<slug> continuam usados nesses <style> locais
   (auto-documentação de qual simulador é dono da regra), mesmo não sendo
   estritamente necessário pra isolamento — cada HTML só carrega o próprio
   <style>.
   ================================================================== */
body.sf3-redesign {
	/* Sobrescreve o padrão de 15.75px vindo do :root de assets/css/mainApp2.css
	   (arquivo compartilhado, não dá pra editar direto) — o JS (mainApp.js
	   local, mudarOrientacao()/resetarFonteSimulador()) só troca essa variável
	   no resize ou no duplo-clique de reset; no carregamento inicial da
	   página, antes de qualquer resize, quem vale é este valor daqui. Título
	   dos painéis, breadcrumb, barra inferior e o selo "t = ..." usam
	   calc(var(--fonte-simulador-px) * fator), então sobem junto na mesma
	   proporção. Se o usuário já tiver customizado a fonte (A-/A+, salvo no
	   localStorage), o JS sobrescreve isso com um estilo inline, que sempre
	   vence — esse valor aqui só é o padrão "de fábrica". */
	--fonte-simulador-px: 17.05px;
	/* --fonte-barra-px (usada pelos ícones/rótulos da barra inferior) é
	   definida no :root de mainApp.css como calc(var(--fonte-simulador-px) * 0.85)
	   — como isso é calculado no <html> (que não recebe nosso override acima,
	   só o <body>), ela "congela" usando o 15.75px do :root e é esse valor
	   fixo que os descendentes herdam. Redeclarando aqui, ela recalcula usando
	   o --fonte-simulador-px já sobrescrito neste escopo.
	   * var(--barra-escala, 1) — ver comentário completo na regra genérica
	   de item da barra inferior ("min-width", Etapa "Barra inferior" abaixo)
	   sobre o auto-encolhimento da barra (ajustarEscalaBarraInferior(),
	   mainApp.js). --barra-escala só existe (inline em <body>, sempre 1 até
	   o JS decidir diminuir) quando o JS detecta que a barra quebrou pra 2
	   linhas — sem essa var setada, var(--barra-escala, 1) cai no fallback
	   1 e nada muda aqui. */
	--fonte-barra-px: calc(var(--fonte-simulador-px) * 0.85 * var(--barra-escala, 1));
	--sf3-accent: #2B78C5;
	--sf3-bg: #f8fafc;
	--sf3-border: #e2e8f0;
	--sf3-text: #0f172a;
	--sf3-text-muted: #64748b;
	/* Largura da alça do divisor arrastável canvas/#parametros (paisagem) —
	   ver .sf3-resizer abaixo. Um só valor, referenciado tanto no CSS do
	   elemento quanto nos grid-template-columns por dispositivo, pra não
	   duplicar o número em 4 lugares. */
	--sf3-resizer-w: 10px;

	--fundo: var(--sf3-bg);
	--bloco: #ffffff;
	--checkbox: var(--sf3-accent);
	--slider-range-fundo: #e2e8f0;
	--slider-range-seletor: var(--sf3-accent);

	/* Cor de fundo do <canvas> (assets/css/mainApp2.css: `canvas { background-color:
	   var(--simulacao) }`, padrão #FFF4E7) — leve ajuste de tom pro bege do mockup CD. */
	--simulacao: #fdf6ea;
	font-family: 'Inter', sans-serif;
}

/* ---- Pêndulo 1 / Pêndulo 2 lado a lado quando a coluna lateral tem
   espaço (container query — igual ao mockup CD, independe do dispositivo/
   orientação, só da largura disponível de #parametros). Empilhados por
   padrão (fallback também para navegadores sem suporte a container query). ---- */
body.sf3-redesign #parametros {
	container-type: inline-size;
	container-name: sf3-sidepanel;
	/* Anula as margens de compensação do layout fixo antigo (mainApp2.css:
	   margin-top:-2px/margin-right:-5px em paisagem, margin-left/-right:-2px
	   em retrato) — descolavam o topo do painel do topo do canvas e comiam
	   parte do padding-right pensado pra igualar o espaço com a lateral
	   esquerda. No grid fluido novo essas correções não fazem mais sentido. */
	margin: 0;
	/* #parametros tem altura fixa (calc(100vh - ...), Etapas 2-4) — sem isso,
	   o grid estica as linhas (grafico/sf3-panels-grid/checkbox) pra preencher
	   o espaço sobrando, inflando os cards com espaço em branco por dentro
	   em vez de deixar a sobra como espaço vazio embaixo, no fim da coluna
	   (mesmo visual do mockup CD: painéis "grudados" no topo).
	   padding: os cards não tinham nenhuma margem própria (ver .bloco acima),
	   então sem isso eles ficavam colados nas bordas do viewport (paisagem:
	   direita; retrato: esquerda e direita, já que #parametros vira largura
	   cheia da tela embaixo do canvas).
	   padding-top: 0 — em paisagem, canvas e #parametros dividem a mesma
	   linha do grid (#principal), então sem padding-top o topo do primeiro
	   card já alinha exatamente com o topo do canvas. Em retrato, o espaço
	   vertical entre canvas e #parametros já vem do gap do #principal (16px,
	   igual ao padding lateral aqui embaixo) — um padding-top aqui somaria
	   16px extra e deixaria a margem superior maior que as laterais. */
	align-content: start;
	/* Em retrato, cards em colunas vizinhas podem ter alturas bem diferentes.
	   Impede que um card colapsado seja esticado à altura do seu vizinho. */
	align-items: start;
	padding: 0 16px 16px 16px;
}
body.sf3-redesign .sf3-panels-grid {
	display: grid;
	grid-template-columns: 1fr;
	align-items: start;
	gap: 16px;
}
@container sf3-sidepanel (min-width: 500px) {
	body.sf3-redesign .sf3-panels-grid {
		grid-template-columns: 1fr 1fr;
	}
}
/* 3 colunas a partir de 800px de largura de #parametros — padrão validado
   em lancamento-projeteis (20/08/2026) e adotado como padrão geral daqui
   pra frente. O painel com o grid de toggles (.sf3-ajustes-grid, ver
   abaixo) identifica a si mesmo via :has() em vez de por ID (#checkbox não
   é universal a todos os simuladores) e ocupa a linha inteira, mesmo
   quando não é o último item do grid. Simuladores com layout específico
   (ex. grid-template-areas nomeadas, pra evitar vão vazio entre painéis de
   altura desigual) sobrescrevem isso localmente, como já faziam com o
   breakpoint de 500px. */
@container sf3-sidepanel (min-width: 800px) {
	body.sf3-redesign .sf3-panels-grid {
		grid-template-columns: 1fr 1fr 1fr;
	}
	body.sf3-redesign .sf3-panels-grid > .bloco:has(.sf3-ajustes-grid) {
		grid-column: 1 / -1;
	}
}

/* ---- Painel "Gráfico" ----
   Mesmo card .bloco dos outros painéis (Pêndulo 1/2, Ajustes), sempre
   presente no fluxo (não mais um <div id="grafico"> que só aparecia via
   JS ao escolher um item no antigo dropdown "Gráfico" da barra inferior).
   Ordem no DOM (index.html) já é: #grafico, .sf3-panels-grid, #checkbox —
   em paisagem isso já entrega "gráfico em cima do Pêndulo 1" sem precisar
   de "order" (pedido do usuário). Só retrato precisa inverter a posição
   do gráfico pra "embaixo da linha Pêndulo 1 + Pêndulo 2" — ver regra de
   "order" logo abaixo, dentro do @media (orientation: portrait) genérico
   (vale pra qualquer perfil: mobile, tablet, desktop retrato). */
@media (orientation: portrait) {
	body.sf3-redesign .sf3-panels-grid { order: 1; }
	body.sf3-redesign #grafico { order: 2; }
	body.sf3-redesign #checkbox { order: 3; }

}
/* Sem isso, #grafico (item da coluna única "auto" de #parametros) nunca
   encolhe abaixo do min-content do que está dentro dele — e o Plotly deixa
   um atributo width="Npx" fixo no <svg>, herdado do último render real, que
   conta como esse min-content. Normalmente isso nunca aparece (o Plotly
   recalcula esse width sozinho a cada resize, "responsive: true" em
   b8d451a227.js, então o valor preso sempre bate com o espaço disponível).
   Mas colapsar e reabrir o painel (display:none e volta) faz o Plotly ficar
   sem nenhum resize real pra reagir por um tempo — se a orientação virar
   nesse meio-tempo, o width="Npx" antigo trava #grafico (e por tabela
   #parametros) numa largura maior que o painel, e o gráfico "vaza"
   pra fora do card. min-width:0 deixa a coluna encolher para a largura real
   disponível de novo, o que também dá ao Plotly uma mudança de tamanho de
   verdade para reagir. */
body.sf3-redesign #grafico {
	min-width: 0;
}
body.sf3-redesign .sf3-grafico-fase {
	margin-bottom: 2px;
}
body.sf3-redesign #plot {
	width: 100%;
}

/* ---- Painéis (cards) ---- */
body.sf3-redesign .bloco {
	/* #painel-pendulo-verde/-vermelho/#checkbox ainda têm a classe "grid-container"
	   do markup antigo (display:grid; grid-template-columns:auto auto, definida em
	   assets/css/mainApp.css) — com só titulo-bloco (grid-column:1/-1) e bloco-corpo
	   como filhos, o corpo caía inteiro na 1ª coluna e a 2ª ficava vazia à direita
	   (o espaço em branco reportado). Anula o grid herdado: o card agora empilha
	   normalmente (titulo-bloco em cima, bloco-corpo embaixo, ambos 100% da largura).
	   margin: 0 anula a margem antiga de mainApp2.css (3px, e 1.5vw à esquerda em
	   paisagem) — a distância entre os cards agora é só o gap do grid/flex, sem
	   somar as duas coisas (era a causa do espaço extra entre os painéis lado a
	   lado e entre a coluna de parâmetros e o canvas). */
	display: block;
	margin: 0;
	background: #ffffff;
	border: 1px solid var(--sf3-border);
	border-radius: 14px;
	box-shadow: 0 1px 2px rgba(15,23,42,.04);
	/* --sf3-bloco-padding guarda o mesmo valor do padding, só pra
	   .titulo-bloco ler abaixo (área entre o título e o topo do card fica
	   clicável — ver comentário lá). Herdada por qualquer contexto que
	   redefina o padding do card (ex. #parametros .bloco em smartphone,
	   mais abaixo) — redefinir só a variável já basta, sem duplicar a
	   lógica de margin-top/padding-top do título pra cada contexto. */
	--sf3-bloco-padding: 18px;
	padding: var(--sf3-bloco-padding);
}
/* Painel condicional (ex. #painel-pendulo2 de pendulo-esferico, mostrado só
   quando N===2): a regra .bloco acima (display:block, mesma especificidade
   de [hidden]) é CSS de autor, que sempre vence a folha de estilo do
   navegador — inclusive a regra nativa "[hidden] { display: none }" — então
   um .bloco com o atributo HTML hidden ficava visível mesmo assim (bug real,
   pego em teste do usuário). [hidden] aqui é só pra especificidade/ordem;
   o efeito é sempre display:none, sobrescrevendo o display:block acima. */
body.sf3-redesign .bloco[hidden] {
	display: none;
}
/* #checkbox tem a classe "item" (markup antigo) além de "bloco" — a regra
   ".item { padding: 0 0 14px 0 }" mais abaixo tem a mesma especificidade e
   vence por ordem, zerando o padding do card. Seletor por ID pra garantir
   que o padding do card do Ajustes sempre vença, independente da ordem. */
body.sf3-redesign #checkbox {
	padding: 18px;
}
/* margin-top negativo + padding-top do mesmo tamanho "puxam" a caixa do
   header pra cima, cobrindo a faixa de padding-top do .bloco (entre o topo
   do card e o título) sem mudar a posição visual do texto (o padding-top
   empurra o conteúdo de volta pra onde estava). Como o header inteiro é o
   .bloco-toggle (clique tratado em redesign.js), essa faixa passa a
   responder ao clique/cursor:pointer igual ao resto do título — só falta
   fazer isso, o listener já existe. calc()+var() em vez de valor fixo:
   segue --sf3-bloco-padding do .bloco pai (herdada), então continua
   batendo mesmo se o padding do card mudar de contexto (ex. smartphone). */
body.sf3-redesign .titulo-bloco {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	text-align: left;
	border-bottom: none;
	padding: 0;
	margin: calc(var(--sf3-bloco-padding, 18px) * -1) 0 10px 0;
	padding-top: var(--sf3-bloco-padding, 18px);
	font-size: calc(var(--fonte-simulador-px) * 1.05);
	font-weight: 700;
	color: var(--sf3-text);
	cursor: pointer;
	user-select: none;
}
/* cursor: pointer explícito — sem isso, ".titulo-bloco span { cursor: default }"
   de mainApp2.css (legado, de antes do header inteiro virar toggle) vencia a
   cascata (nenhuma regra daqui mexia em cursor pro span), e o mouse virava
   seta bem em cima do texto do título, no meio de uma área que devia ser
   inteiramente clicável. */
body.sf3-redesign .titulo-bloco span { padding-left: 0; font-weight: 500; font-family: 'Inter', sans-serif; cursor: pointer; }
body.sf3-redesign .bloco-corpo { display: block; }
body.sf3-redesign .item { padding: 0 0 0px 0; }
body.sf3-redesign .item:last-child { padding-bottom: 0; }
body.sf3-redesign .item label { font-weight: 400; color: var(--sf3-text); font-family: Inter, sans-serif;}
body.sf3-redesign .question > i,
body.sf3-redesign #question > i { color: #94a3b8; font-size: calc(var(--fonte-simulador-px) * .78); }

/* ---- Linha do rótulo (símbolo = valor / botão de ajuda) e linha de min/max,
   por cima do slider — mesmo padrão visual do mockup (item-header em cima,
   slider no meio, min/max embaixo) ---- */
body.sf3-redesign .item-header {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 8px;
	font-size: calc(var(--fonte-simulador-px) * 1.1);
	color: #334155;
}
body.sf3-redesign .item-minmax {
	display: flex;
	justify-content: space-between;
	font-size: calc(var(--fonte-simulador-px) * .65);
	color: #8d949c;
	margin-top: 2px;
}

/* ---- Valores editáveis (θ, L, ω, m, h) — input[type=number] no lugar
   dos antigos <label contenteditable> (ver parametrosEditaveis.js) ---- */
/* Codex (2026-08-07): wrapper genérico de conjuntos de sliders que devem
   ocupar duas colunas apenas em desktops amplos, sem afetar tablet/mobile.
   Ele fica dentro de .bloco-corpo, pois o toggle SF3 altera o display deste. */
@media (min-width: 1401px) and (orientation: landscape) {
	body.sf3-redesign .sf3-sliders-grid-desktop-amplo {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 16px 24px;
		align-items: start;
	}
}
/* Anula ".item:last-child:nth-child(odd of .item)" (assets/css/mainApp2.css)
   dentro deste grid — aquela regra é do padrão legado de 2 colunas fixas
   (evita o último .item de posição ímpar sobrar sozinho numa coluna,
   forçando full-span) e nunca prevê o grid de nível 2 aqui (2 ou 3 colunas
   por largura do painel, ver memória "padrao-grid-paineis-largura"). Com 3
   sliders (3ª coluna cheia) ou 5 (padrão de gravitacao/#parametrosMassas),
   o último item é ímpar e a regra antiga sequestra ele pra uma linha cheia
   sozinho, quebrando o layout (bug real, achado em consumo-energia-eletrica
   20/08/2026 — sintoma: grid computa 3 colunas certinho, mas o 3º slider
   aparece isolado numa linha de baixo, ocupando a largura toda). auto
   devolve o item pro fluxo normal do grid — o próprio container query já
   decide quantas colunas existem, não precisa de proteção contra órfão
   aqui. Especificidade: "body" (tipo) desempata contra a regra antiga
   (mesma contagem de classes/pseudo-classes, 4), sem precisar de
   !important. */
body.sf3-redesign .sf3-sliders-grid-desktop-amplo > .item:last-child {
	grid-column: auto;
}

body.sf3-redesign .valor-editavel {
	font: inherit;
	font-weight: 700;
	color: var(--sf3-text);
	width: 3em; /* largura real definida via JS (ajustarLarguraValor), cresce com os dígitos */
	border: 1px solid transparent;
	border-radius: 6px;
	background: transparent;
	padding: 1px 0 1px 3px;
	-moz-appearance: textfield;
}
body.sf3-redesign .valor-editavel:hover {
	border-color: var(--sf3-border);
}
body.sf3-redesign .valor-editavel:focus {
	outline: none;
	border-color: var(--sf3-accent);
	background: #ffffff;
}
/* Sem isso, um campo desabilitado (ex: travarCamposIniciais() em
   lancamento-projeteis/b8d451a227.js, trava theta/v0/y0 depois do
   lançamento) ficava com a mesma cor de texto de um campo editável --
   "color" do seletor acima tem mais especificidade que o graytext padrão
   do navegador pra <input disabled>. Mesmo tratamento (cinza + cursor
   not-allowed) já usado em .slider:disabled, poucas linhas acima. */
body.sf3-redesign .valor-editavel:disabled {
	color: #94a3b8;
	cursor: not-allowed;
}

body.sf3-redesign .bloco-chevron {
	border: none;
	background: none;
	color: #94a3b8;
	cursor: pointer;
	width: 24px;
	height: 24px;
	flex-shrink: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	transition: transform .15s ease, color .15s ease;
}
body.sf3-redesign .bloco-chevron:hover { color: var(--sf3-accent); }
/* Convenção do mockup CD (invertida em relação a acordeões comuns):
   expandido -> seta apontando pra direita (rotate -90); recolhido -> seta
   apontando pra baixo (0deg, orientação natural do ícone chevron-down). */
body.sf3-redesign .bloco-chevron.aberto { transform: rotate(-90deg); }

/* ---- Sliders ---- */
body.sf3-redesign .slider,
body.sf3-redesign .slider2 {
	-webkit-appearance: none;
	appearance: none;
	width: 100%;
	height: 6px;
	border-radius: 999px;
	opacity: 1;
	background: linear-gradient(to right, var(--sf3-accent) 0%, var(--sf3-accent) var(--fill, 50%), #e2e8f0 var(--fill, 50%), #e2e8f0 100%);
	margin: 2px 0 6px;
}
/* .slider2 é o único que vem seguido de marcações de tick (.range__field,
   ver bloco mais abaixo) — como thumb e ticks são elementos estáticos
   (sem position), a pintura segue a ordem do DOM e o fieldset (que vem
   depois no HTML) cobre a bolinha do slider onde os dois se sobrepõem.
   position:relative cria contexto de empilhamento próprio, que pinta acima
   de conteúdo estático irmão independente da ordem no DOM. */
body.sf3-redesign .slider2 {
	position: relative;
	z-index: 1;
}
body.sf3-redesign .slider::-webkit-slider-thumb,
body.sf3-redesign .slider2::-webkit-slider-thumb {
	-webkit-appearance: none;
	width: 18px;
	height: 18px;
	border-radius: 50%;
	background: #ffffff;
	border: 3px solid var(--sf3-accent);
	box-shadow: 0 1px 3px rgba(15,23,42,.25);
	cursor: pointer;
}
body.sf3-redesign .slider::-moz-range-thumb,
body.sf3-redesign .slider2::-moz-range-thumb {
	width: 18px;
	height: 18px;
	border-radius: 50%;
	background: #ffffff;
	border: 3px solid var(--sf3-accent);
	box-shadow: 0 1px 3px rgba(15,23,42,.25);
	cursor: pointer;
}
body.sf3-redesign .slider::-moz-range-track,
body.sf3-redesign .slider2::-moz-range-track {
	height: 6px;
	border-radius: 999px;
	background: transparent;
}

/* Estado desabilitado: assets/css/mainApp.css (compartilhado, não editável)
   deixa o thumb com opacity:.4 !important — como o thumb é sólido (cobre o
   fim do trilho azul), ficando translúcido revela que o trilho para um
   pouco antes da borda visível da bolinha (offset de raio do thumb nativo
   do input range). Mantemos o thumb opaco e sinalizamos "desabilitado"
   só pela cor (cinza), assim a borda da bolinha volta a cobrir exatamente
   onde o trilho termina. */
body.sf3-redesign .slider:disabled::-webkit-slider-thumb,
body.sf3-redesign .slider2:disabled::-webkit-slider-thumb {
	opacity: 1 !important;
	background: #f1f5f9;
	border-color: #94a3b8;
	cursor: not-allowed !important;
}
body.sf3-redesign .slider:disabled::-moz-range-thumb,
body.sf3-redesign .slider2:disabled::-moz-range-thumb {
	opacity: 1 !important;
	background: #f1f5f9;
	border-color: #94a3b8;
	cursor: not-allowed !important;
}
body.sf3-redesign .slider:disabled,
body.sf3-redesign .slider2:disabled {
	background: linear-gradient(to right, #94a3b8 0%, #94a3b8 var(--fill, 50%), #e2e8f0 var(--fill, 50%), #e2e8f0 100%);
}

/* Marcações de tick (.range__field > svg#lTicks) abaixo de alguns sliders:
   o <svg> é um elemento inline por padrão, então o <fieldset> que o envolve
   cria uma caixa de linha (line box) cuja altura acompanha o line-height do
   font-size herdado — cresce com "Aumentar fonte" e empurra as marcações
   pra baixo, abrindo um vão entre elas e o slider. display:block remove essa
   caixa de linha, deixando a altura do fieldset = altura real do svg (fixa),
   o que torna o ajuste de posição (margin-top no <fieldset>, por instância)
   independente do tamanho de fonte. */
body.sf3-redesign .range__field svg {
	display: block;
}

/* ---- Toggles "Mostrar trajetória" / "Acelerar" (sf-toggle, igual ao mockup CD,
   no lugar do form-switch do Bootstrap) ---- */
body.sf3-redesign .sf-toggle {
	display: flex;
	align-items: center;
	gap: 10px;
	font-size: calc(var(--fonte-simulador-px) * .92);
	color: #334155;
	cursor: pointer;
}
body.sf3-redesign .sf-toggle input {
	position: absolute;
	opacity: 0;
	width: 0;
	height: 0;
}
body.sf3-redesign .sf-toggle .track {
	display: inline-block;
	width: 38px;
	height: 22px;
	border-radius: 999px;
	background: #cbd5e1;
	position: relative;
	flex-shrink: 0;
	transition: background .15s;
}
body.sf3-redesign .sf-toggle .track::after {
	content: "";
	position: absolute;
	top: 2px;
	left: 2px;
	width: 18px;
	height: 18px;
	border-radius: 50%;
	background: #ffffff;
	box-shadow: 0 1px 2px rgba(15,23,42,.3);
	transition: transform .15s;
}
body.sf3-redesign .sf-toggle input:checked + .track { background: var(--sf3-accent); }
body.sf3-redesign .sf-toggle input:checked + .track::after { transform: translateX(16px); }
body.sf3-redesign .sf3-ajustes-row {
	display: flex;
	align-items: center;
	gap: 24px;
	flex-wrap: wrap;
}
body.sf3-redesign .sf3-ajustes-row .item {
	flex: 1;
	min-width: 180px;
	padding: 0;
}

/* ---- Painel "Ajustes" com muitos toggles (ex. lancamento-projeteis2: 8
   itens — Grid/Energia/Projeções/Componentes de velocidade/Vetor
   velocidade/Trajetória) — em vez de .sf3-ajustes-row (flex numa linha só,
   pensado pra 2 itens, ex. pendulo-duplo2), usa um grid de 1 ou 2 colunas
   via a mesma container query de #parametros (.sf3-panels-grid, acima). */
body.sf3-redesign .sf3-ajustes-grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: 12px 24px;
}
@container sf3-sidepanel (min-width: 420px) {
	body.sf3-redesign .sf3-ajustes-grid {
		grid-template-columns: 1fr 1fr;
	}
}
/* 3 colunas de toggles a partir de 800px — acompanha o breakpoint de 3
   colunas de .sf3-panels-grid acima, já que nesse ponto o painel Ajustes
   passa a ocupar a linha inteira (3 colunas de largura) em vez de 1. */
@container sf3-sidepanel (min-width: 800px) {
	body.sf3-redesign .sf3-ajustes-grid {
		grid-template-columns: 1fr 1fr 1fr;
	}
}

/* ---- Segmented control (ex.: "Barreira fixa"/"Barreira móvel",
   "Senoidal"/"Impulsos quadrados") — pra grupos de <input type="radio">
   (par ou mais opções nomeadas, mutuamente exclusivas). Nem .sf-toggle
   (switch binário — dois deles lado a lado pra emular radio confunde o
   usuário, parece dois booleanos independentes) nem legenda do Plotly
   servem pra "escolher 1 de N opções nomeadas"; ver docs/redesign-3.0.md
   §39. Opção marcada preenchida com --sf3-accent (mesma cor de "ligado"
   dos outros controles do site) em vez de só fundo branco + texto azul —
   o contraste era baixo demais (17/08/2026, pedido do usuário). Simulador
   pode sobrescrever a cor da opção marcada com uma regra própria mais
   específica quando o significado for semântico (ex.: bandeira tarifária
   verde/amarela/vermelha em consumo-energia-eletrica). */
body.sf3-redesign .sf3-segmented {
	display: flex;
	gap: 3px;
	background: var(--sf3-bg);
	border: 1px solid var(--sf3-border);
	border-radius: 10px;
	padding: 3px;
	margin-top: 4px;
}
/* Espaço entre grupos consecutivos dentro de um card (segmented controls,
   grids de toggles .sf3-ajustes-grid) — sem isso, dois grupos diferentes
   (ex. "Unidade de velocidade" seguido de "Rastros"/"Mesmo percurso")
   ficavam colados, só com os 4px de margin-top que .sf3-segmented já tem
   por padrão (pensado só pra separar do título do card, não de outro
   grupo). Pedido do usuário, 20/08/2026 — generalizado pra todos os
   simuladores (CSS compartilhado, não só onde foi notado a 1ª vez).
   :not(:first-child) evita espaço extra indesejado no topo do card quando
   o grupo é o 1º item de .bloco-corpo. Mais específico que a regra acima
   (2 seletores + pseudo-classe vs. 1 classe), então vence sem precisar de
   !important. */
body.sf3-redesign .bloco-corpo > .sf3-segmented:not(:first-child),
body.sf3-redesign .bloco-corpo > .sf3-ajustes-grid:not(:first-child) {
	margin-top: 16px;
}
body.sf3-redesign .sf3-segmented-option {
	position: relative;
	flex: 1;
	margin: 0; /* .sf3-segmented-option é um <label>; zera o margin-bottom
	              padrão do Bootstrap, que deixava o espaço inferior maior
	              que o superior dentro do flex de .sf3-segmented */
	text-align: center;
	padding: 7px 8px;
	border-radius: 8px;
	font-size: calc(var(--fonte-simulador-px) * .82);
	font-weight: 600;
	color: var(--sf3-text-muted);
	cursor: pointer;
	user-select: none;
	transition: background .15s, color .15s;
}
body.sf3-redesign .sf3-segmented-option input {
	position: absolute;
	inset: 0;
	opacity: 0;
	margin: 0;
	cursor: pointer;
}
body.sf3-redesign .sf3-segmented-option:has(input:checked) {
	background: var(--sf3-accent);
	color: #ffffff;
	box-shadow: 0 1px 3px rgba(43,120,197,.4);
}

/* ---- Controle de fonte A-/A+ ---- */
body.sf3-redesign .btn-fonte {
	border-radius: 7px;
	border: 1px solid var(--sf3-border);
	font-family: 'Inter', sans-serif;
}

/* ---- Ajuda cursor ----
   Empilhado embaixo do botão da toolbox (--layer-group), não ao lado —
   mesma posição do mockup CD (top:66px, mesmo "right" da toolbox). */
body.sf3-redesign #help-cursor {
	top: 66px !important;
	right: 16px !important;
	background: rgba(255,255,255,.85);
	border: 1px solid var(--sf3-border);
	border-radius: 50%;
	width: 40px;
	height: 40px;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 18px;
	box-shadow: 0 2px 8px rgba(15,23,42,.08);
	color: #334155;
	opacity: 1;
}
body.sf3-redesign #help-cursor:hover { color: var(--sf3-accent); }

/* ---- Selo de variáveis flutuante sobre o canvas ----
   Base compartilhada (classe, não mais por ID: pendulo-duplo2 usa
   #tempo-badge, um pill simples e não-interativo com só "t = ... s";
   lancamento-projeteis2 usa #variaveis, um card colapsável e arrastável
   com t/x/y/vx/vy — ver regras específicas de #variaveis logo abaixo). */
body.sf3-redesign .sf3-badge-flutuante {
	position: absolute;
	top: 16px;
	left: 16px;
	background: rgba(255,255,255,.85);
	backdrop-filter: blur(6px);
	border: 1px solid var(--sf3-border);
	border-radius: 999px;
	padding: 6px 14px;
	/* Era 13px fixo — não acompanhava o A-/A+ do simulador nem o novo padrão
	   de fonte. calc() na mesma proporção de antes (13/15.75) pra crescer
	   junto com --fonte-simulador-px, como o resto (título dos painéis,
	   breadcrumb, barra inferior). */
	font-size: calc(var(--fonte-simulador-px) * 1.1);
	font-weight: 600;
	color: #334155;
	box-shadow: 0 1px 2px rgba(15,23,42,.06);
	/* Era 5 — perdia para #toolbox (mainApp2.css, z-index:1000, compartilhado
	   entre simuladores) quando o badge de variáveis fica na mesma região do
	   canto superior do canvas, ficando parcialmente encoberto pelos botões
	   #toolbox/#help-cursor. Mesmo stacking context (ambos filhos diretos de
	   #canvas), então basta superar o maior concorrente. */
	z-index: 1001;
	pointer-events: none;
}
/* Fonte fixa em smartphone (pedido do usuário, 05/08/2026) — mesmo
   raciocínio das janelas do Problema (redesign.css, seção "Janelas do
   'Problema'"): sem isso, o A-/A+ do usuário reinflava o selo de
   variáveis (#variaveis/#tempo-badge) numa tela já apertada. */
body.sf3-redesign.sf3-mobile .sf3-badge-flutuante {
	font-size: 16px;
}

/* ---- #variaveis (lancamento-projeteis2): variante "card" ----
   Múltiplas variáveis (título fixo "Variáveis" no header; t/x/y/vx/vy no
   corpo colapsável), posição inicial no topo e centralizada só na largura
   do canvas (top fixo + left:50%/translateX, sem centralizar verticalmente
   — diferente da 1ª versão), e interativa (troca pointer-events:none por
   auto): colapsável — reaproveita .bloco-toggle/[data-panel]/.bloco-corpo,
   o mesmo mecanismo genérico dos painéis laterais (redesign.js já escuta
   qualquer .bloco-toggle[data-panel] do documento, inclusive persistência
   em localStorage, escopada por appName) — e arrastável (mousedown/
   touchstart no header, lógica local em b8d451a227.js, já que só este
   simulador tem essa necessidade por ora). Ao arrastar, b8d451a227.js
   passa a setar left/top em px e zera o transform. */
body.sf3-redesign #variaveis {
	top: 16px;
	left: 50%;
	transform: translateX(-50%);
	border-radius: 10px;
	padding: 8px 12px;
	pointer-events: auto;
}
body.sf3-redesign #variaveis .sf3-badge-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	cursor: grab;
}
body.sf3-redesign #variaveis .sf3-badge-header:active { cursor: grabbing; }
/* .bloco-chevron (24x24, pensado pros cards grandes da lateral) fica
   desproporcional neste card compacto — reduz só aqui. */
body.sf3-redesign #variaveis .bloco-chevron {
	width: 18px;
	height: 18px;
	font-size: calc(var(--fonte-simulador-px) * .8);
}
body.sf3-redesign #variaveis .bloco-corpo {
	margin-top: 6px;
	padding-top: 6px;
	border-top: 1px solid var(--sf3-border);
	text-align: left;
	line-height: 1.6;
	/* Largura fixa (em ch, acompanha A-/A+ igual ao resto do card) — sem
	   isso, o card muda de largura a cada frame conforme x/y/vx/vy mudam de
	   número de dígitos (ex.: "0.00" -> "-123.45"), fazendo o card "pular"
	   horizontalmente enquanto arrastado/centralizado. Valor medido (16/08/2026,
	   getBoundingClientRect) pro pior caso plausível de v_x/v_y (4 dígitos +
	   sinal + decimais, "vy = -1234.56 m/s" ≈ 14.5ch) em cada uma das 2
	   colunas de .sf3-badge-colunas abaixo, dobrado + espaço pro gap — 23ch
	   ficava justo demais e "m/s" quebrava linha mesmo em valores comuns.
	   Textos ainda maiores que isso quebram linha dentro da própria coluna
	   (aumenta altura, não largura). */
	width: 32ch;
}
/* ---- #variaveis: colunas posição / velocidade ----
   Pedido do usuário (16/08/2026): x/y de um lado, vx/vy do outro, em vez de
   uma lista vertical única — mais compacto e agrupa por natureza da
   grandeza. t fica fora da grade, como resumo de linha inteira (não é
   posição nem velocidade). display:grid (não flex) pra dar às 2 colunas a
   mesma largura (1fr 1fr), independente do texto de cada uma. */
body.sf3-redesign #variaveis .sf3-badge-colunas {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 0 10px;
}
body.sf3-redesign #variaveis .sf3-badge-colunas div {
	font-variant-numeric: tabular-nums;
}
body.sf3-redesign #variaveis #badge-t {
	margin-top: 4px;
	padding-top: 4px;
	border-top: 1px solid var(--sf3-border);
	text-align: center;
	font-variant-numeric: tabular-nums;
}

/* ---- Mensagem de orientação bloqueada ----
   Card centrado usado por simuladores que não suportam um perfil/orientação
   específico (hoje só conservacao-energia-mecanica2, retrato smartphone —
   index.html/b8d451a227.js). Escondido por padrão via display:none (não
   pelo atributo HTML "hidden": #mensagem tem classe .bloco-container-like
   própria — se dependêssemos de [hidden] aqui, a regra "display:flex" logo
   abaixo, de mesma especificidade e origem "author", sempre venceria a
   regra de baixa especificidade do agente de usuário para [hidden], que
   nunca conseguiria esconder o elemento de volta; ver MDN sobre esse
   problema). JS alterna a classe .visivel (b8d451a227.js,
   adequarDispositivo()) — nunca o atributo "hidden". Reaproveitável por
   qualquer simulador futuro com a mesma necessidade, sem precisar de CSS
   novo por app. */
body.sf3-redesign #mensagem {
	display: none;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 12px;
	text-align: center;
	max-width: 320px;
	margin: 40px auto;
	padding: 32px 24px;
	background: #ffffff;
	border: 1px solid var(--sf3-border);
	border-radius: 14px;
	box-shadow: 0 1px 2px rgba(15,23,42,.04);
	color: var(--sf3-text);
	font-size: calc(var(--fonte-simulador-px) * 1.05);
}
body.sf3-redesign #mensagem.visivel {
	display: flex;
}
body.sf3-redesign #mensagem i {
	font-size: 32px;
	color: var(--sf3-accent);
}
/* Ícone "gire o aparelho": fa-mobile-alt sozinho (parado, sempre em pé)
   não deixava claro que a ação pedida era rotacionar a TELA, não só
   "usar um celular" — anima o mesmo ícone girando de pé (retrato) até
   deitado (paisagem, -90deg) e volta, e um badge de seta (fa-sync-alt)
   fica sobreposto no canto reforçando "rotacionar". */
body.sf3-redesign #mensagem .sf3-rotate-device {
	position: relative;
	width: 44px;
	height: 44px;
	display: flex;
	align-items: center;
	justify-content: center;
}
body.sf3-redesign #mensagem .sf3-rotate-device-phone {
	font-size: 32px;
	color: var(--sf3-accent);
	animation: sf3-girar-celular 2.4s ease-in-out infinite;
}
body.sf3-redesign #mensagem .sf3-rotate-device-arrow {
	position: absolute;
	right: -6px;
	bottom: -2px;
	font-size: 13px;
	color: var(--sf3-accent);
	background: #ffffff;
	border-radius: 50%;
	padding: 3px;
	box-shadow: 0 1px 2px rgba(15,23,42,.12);
}
@keyframes sf3-girar-celular {
	0%, 30% { transform: rotate(0deg); }
	65%, 100% { transform: rotate(-90deg); }
}

/* ---- Toolbox de anotação ----
   #toolbox (compartilhado) não é flex — em fluxo normal de bloco,
   #btn-main (1º filho) fica em cima e #tool-options (2º filho) embaixo
   dele, empurrando o container pra baixo/largo conforme o painel abre.
   Como aqui o painel deve abrir para o LADO (flex-direction:row abaixo),
   isso deslocava o botão "camadas" pra longe do canto: o container
   (top:16;right:16) cresce pra ~210px de largura por causa do painel, e
   #btn-main, alinhado à esquerda do bloco por padrão, sobra longe da
   borda direita do canvas. Fixamos #toolbox num âncora de 40x40 no
   canto (mesmo tamanho do botão) e posicionamos os dois filhos via
   position:absolute dentro dela — botão sempre no canto (top:0;right:0),
   painel sempre colado à esquerda do botão (right:48px = 40 do botão +
   8px de gap), independente do estado aberto/fechado. */
body.sf3-redesign #toolbox {
	top: 16px !important;
	right: 16px !important;
	width: 40px;
	height: 40px;
}
body.sf3-redesign #btn-main {
	position: absolute;
	top: 0;
	right: 0;
}
body.sf3-redesign #tool-options {
	position: absolute;
	top: 0;
	right: 48px;
	/* width fixo (não só max-width): posicionado agora, sem "left", o
	   shrink-to-fit de um bloco absoluto com flex-wrap colapsa pra
	   largura de 1 item só (cada botão numa linha) em vez de tentar
	   preencher até o max-width antes de quebrar linha. */
	width: 180px;
	flex-direction: row;
	flex-wrap: wrap;
	background: rgba(255,255,255,.9);
	backdrop-filter: blur(10px);
	border: 1px solid var(--sf3-border);
	border-radius: 14px;
	padding: 8px;
	box-shadow: 0 6px 20px rgba(15,23,42,.1);
}
body.sf3-redesign .tool-btn {
	width: 34px;
	height: 34px;
	border-radius: 9px;
	background: none;
	box-shadow: none;
	color: #475569;
}
body.sf3-redesign .tool-btn:hover {
	background: #eaf3fb;
	color: var(--sf3-accent);
	transform: none;
}
body.sf3-redesign .tool-btn.active {
	background: var(--sf3-accent);
	color: #ffffff;
}
body.sf3-redesign #btn-main {
	width: 40px;
	height: 40px;
	border-radius: 50%;
	border: 1px solid var(--sf3-border);
	background: rgba(255,255,255,.85);
	backdrop-filter: blur(6px);
	box-shadow: 0 2px 8px rgba(15,23,42,.08);
	display: flex;
	align-items: center;
	justify-content: center;
	color: #334155;
	opacity: 1;
}
body.sf3-redesign #btn-main:hover,
body.sf3-redesign #btn-main.ativo { color: var(--sf3-accent); }

/* ---- Breadcrumb ---- */
body.sf3-redesign .breadcrumb-simulador { color: #475569; font-weight: 400; font-family: 'Inter', sans-serif; font-size: calc(var(--fonte-simulador-px) * .85); }
body.sf3-redesign .breadcrumb-link { color: #002c93; font-weight: 400; text-decoration: none; outline: none; }
body.sf3-redesign .breadcrumb-sep { color: #94a3b8; }
body.sf3-redesign .breadcrumb-current { color: rgb(32 33 35); font-weight: 400; font-family: 'Inter', sans-serif; font-size: calc(var(--fonte-simulador-px) * .85); }

/* ---- Barra inferior ----
   #barraInferior não carrega mais class="navBottom" no HTML (removida —
   era o único resquício do sistema antigo de DUAS barras diferentes,
   .navBottom pra mobile e .barraDesktop pra desktop, trocadas via JS em
   b8d451a227.js). Enquanto a classe existia, a maioria das propriedades
   já vinha sendo vencida por especificidade (ID > classe, mesmo truque
   de sempre), mas pelo menos uma escapava: ".navBottom a, .navBottom
   span { transform: translateY(-6px) }" é um seletor descendente (sem
   ">"), então também batia no <span data-toggle="dropdown"> um nível
   mais fundo dentro de .btn-group (Exemplos/Gráfico/Download) — nada
   aqui redeclarava "transform" pra ESSE span específico, só pro item de
   nível mais alto, e o resultado era esses 3 botões meio deslocados pra
   cima dos vizinhos. Sem a classe, zero regras antigas alcançam
   #barraInferior; display:flex/align-items (que vinham de .navBottom)
   agora são declarados aqui mesmo. */
body.sf3-redesign #barraInferior {
	display: flex;
	align-items: center;
	/* .navBottom/.barraDesktop (removida a primeira, comentário acima;
	   a segunda ainda é setada pelo JS em telas grandes, mas não muda
	   nada — já não sobra propriedade não-sobrescrita pra ela vencer)
	   eram position:fixed (uma colada embaixo da tela, a outra
	   flutuando centralizada) — a barra não empurrava nem era empurrada
	   pelo resto do layout, e o "espaço" entre canvas/painéis e barra
	   (relatado pelo usuário) era só a folga do antigo orçamento
	   calc(100vh - Npx) de #principal, chutado pra sobrar espaço pra
	   ela por baixo. Agora #barraInferior é o 2º filho do flex column
	   de #main (ver #main na Etapa 1 acima) — fica estática, no fluxo,
	   colada direto embaixo do grid, sem gap, tanto em paisagem quanto
	   depois de rolar os painéis em retrato. position:relative só pra
	   ancorar o painel "Mais" (retrato smartphone, Etapa 3 abaixo). */
	position: relative;
	/* backdrop-filter (abaixo) cria stacking context próprio pra
	   #barraInferior — sem z-index aqui, esse contexto entra na ordem de
	   empilhamento da raiz com z-index:auto, que PERDE de qualquer
	   descendente-positioned com z-index explícito em outro lugar da
	   página, mesmo um valor baixo (#variaveis/.sf3-badge-flutuante,
	   z-index:5 — bloco "Selo de variáveis flutuante" acima). Isso prendia
	   o <ul class="dropdown-menu"> de Exemplos/Download (Bootstrap,
	   z-index:1000, mas dentro do stacking context de #barraInferior)
	   atrás de #variaveis mesmo com 1000 > 5 nominalmente — comparação de
	   z-index só vale dentro do MESMO stacking context; quem perdia pra
	   #variaveis lá na raiz era a caixa de #barraInferior inteira. Só
	   precisa ficar acima de 5. */
	z-index: 10;
	flex-shrink: 0;
	bottom: auto;
	left: auto;
	right: auto;
	top: auto;
	width: auto;
	max-width: none;
	margin: 0;
	border-radius: 0;
	height: auto;
	min-height: 0;
	max-height: none;
	padding: 6px 10px;
	box-sizing: border-box;
	background-color: rgba(255,255,255,.95);
	backdrop-filter: blur(6px);
	border-top: 1px solid var(--sf3-border);
	box-shadow: 0 -1px 2px rgba(15,23,42,.04);
	/* Nunca deixa selecionar texto/ícone daqui (pedido do usuário,
	   20/08/2026): arrastar o .sf3-resizer perto da barra inferior — mais
	   fácil em mobile, onde a barra ocupa uma faixa maior — engatilhava
	   seleção de texto nela (o user-select:none que o JS do resizer põe em
	   <body> durante o arraste, redesign.js, não é suficiente sozinho: o
	   toque pode iniciar o gesto de seleção ANTES do listener de
	   pointerdown do resizer processar, ou a barra tem seus próprios
	   elementos focáveis). -webkit-touch-callout:none extra pro menu de
	   long-press (copiar/compartilhar) do Safari/Chrome iOS não aparecer
	   nela também. */
	user-select: none;
	-webkit-user-select: none;
	-webkit-touch-callout: none;
}
/* Item (ícone em cima, rótulo embaixo) — mesmo desenho em qualquer
   dispositivo, no lugar do par .navBottom/.barraDesktop. ">.btn-group"
   cobre Exemplos/Gráfico/Download (dropup); o botão-gatilho de cada um
   fica um nível mais fundo dentro do .btn-group (regra seguinte) — o
   outro filho do .btn-group é o próprio <ul class="dropdown-menu">
   (position:absolute via Bootstrap, não participa do fluxo). */
body.sf3-redesign #barraInferior {
	/* flex-wrap:wrap — rede de segurança: se a janela for estreita demais
	   pra 10 itens no tamanho natural (ver "flex:0 0 auto" abaixo, cada
	   item do tamanho do próprio conteúdo, não dividido em partes iguais
	   do espaço disponível), o excedente quebra pra uma 2ª linha em vez
	   de espremer/sobrepor o texto dos rótulos. */
	flex-wrap: wrap;
	row-gap: 2px;
	/* .navBottom/.barraDesktop (mainApp.css) usam justify-content:space-around
	   — espalha os itens pra preencher a largura toda. No mockup CD a
	   linha de ícones (.navbottom-pd) usa justify-content:center: em
	   telas largas os itens ficam agrupados no centro, com o fundo da
	   barra (branco/blur) sobrando dos dois lados, em vez de esticar. */
	justify-content: center;
	gap: 6px;
}
/* Seletores duplicados (">X" direto em #barraInferior E dentro de
   #nav-secondary-wrap) de propósito: display:contents (regra mais abaixo)
   faz o wrapper "sumir" visualmente/no layout flex, mas NÃO muda a árvore
   do DOM — um combinador ">" (filho direto) casa pela estrutura real do
   HTML, então ".btn-group"/"span" continuam sendo filhos de
   #nav-secondary-wrap, não de #barraInferior, e "#barraInferior > .btn-group"
   sozinho nunca bateria. */
body.sf3-redesign #barraInferior > a,
body.sf3-redesign #barraInferior > span,
body.sf3-redesign #barraInferior > button,
body.sf3-redesign #barraInferior > .btn-group,
body.sf3-redesign #nav-secondary-wrap > a,
body.sf3-redesign #nav-secondary-wrap > span,
body.sf3-redesign #nav-secondary-wrap > button,
body.sf3-redesign #nav-secondary-wrap > .btn-group {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 4px;
	/* Tamanho pelo próprio conteúdo (ícone/rótulo), não flex:1 dividindo
	   o espaço em 10 partes iguais — com rótulos de tamanhos bem
	   diferentes ("Home" x "Tela cheia"), flex:1 forçava todo item pra
	   a mesma largura estreita e o texto mais comprido vazava por cima
	   do vizinho (white-space:nowrap não deixa quebrar dentro do rótulo). */
	flex: 0 0 auto;
	/* Mas só "content-sized" (min-width:0, era o valor antigo aqui) deixava
	   cada item com uma largura BEM diferente do vizinho — rótulo curto
	   ("Info", "Home") faz uma caixa estreita, rótulo comprido ("Tela
	   cheia", "Download") faz uma caixa bem mais larga. Ícone/rótulo ficam
	   centralizados dentro da própria caixa (align-items:center, acima),
	   então o CENTRO de cada item é o centro da própria caixa — com
	   gap fixo (6px, regra de #barraInferior acima) só entre as BORDAS,
	   a distância entre CENTROS de itens vizinhos variava bastante de par
	   pra par (a largura de cada item entra na conta dos dois lados).
	   Sem mudar o resto do design (ainda sem flex:1, ainda cada item do
	   tamanho do próprio conteúdo), um min-width igual pra todos resolve:
	   todo item passa a ocupar essa mesma largura mínima — inclusive os
	   rótulos mais compridos, contanto que o min-width seja maior que o
	   conteúdo de todos eles — e a distância entre centros vira constante
	   (min-width + gap) em qualquer dispositivo/idioma de rótulo do mesmo
	   tamanho. O multiplicador/soma abaixo foi calibrado medindo a largura
	   real do item mais largo ("Tela cheia") nos 3 perfis de dispositivo
	   (desktop --fonte-barra-px maior, mobile e tablet menores) — a largura
	   do texto escala linear com --fonte-barra-px (mesma fonte/peso em
	   todo lugar), e a fórmula abaixo deixa uma folga de ~3px sobre o
	   maior rótulo real em todos os 3 perfis. Se um rótulo mudar (nova
	   tradução, novo item) e ficar mais largo que "Tela cheia", reconferir
	   essa folga.
	   ⚠️ 26px→20px (04/08/2026): `lancamento-projeteis2` tem 10 itens na
	   barra (contra os 9 de `pendulo-duplo2`) e passou a "quebrar" pra 2
	   linhas em larguras médias (~1024px desktop, ~768px tablet retrato) —
	   a folga antiga (~7px) foi calibrada só pros 9 itens do pêndulo.
	   Reduzida pra caber os 10 sem quebrar linha (testado em 1024px
	   desktop e 768px tablet retrato); ainda serve os 9 itens do pêndulo
	   com folga um pouco menor, mas positiva. Se um próximo simulador
	   tiver ainda mais itens que não couberem nem com essa folga menor, o
	   `flex-wrap:wrap` continua como rede de segurança (quebra pra 2
	   linhas em vez de sobrepor texto) — mas prefira reduzir o NÚMERO de
	   itens na barra (mover algo pra dentro de um painel, por exemplo)
	   antes de espremer a folga ainda mais.
	   ⚠️ --barra-escala (20/08/2026, pedido do usuário): toda a calibração
	   acima é fixa por PERFIL de dispositivo (sf3-mobile/tablet/desktop) e
	   por FAIXA de largura (@media max-width específicos, Etapas 3/4 abaixo)
	   — cobre os casos já testados manualmente, mas qualquer combinação de
	   janela/zoom/nº de itens fora dessas faixas (ex. desktop com a janela
	   redimensionada estreita — sf3-desktop nunca ganhou um "aperto" pra
	   largura curta, só mobile/tablet tiveram) ainda podia quebrar pra 2
	   linhas, como reportado (print). Em vez de mapear mais um breakpoint
	   manual, ajustarEscalaBarraInferior() (mainApp.js) mede depois de
	   renderizar se a barra ocupa mais de 1 linha e, se sim, escreve
	   --barra-escala < 1 em <body> (reduzindo --fonte-barra-px, que cascateia
	   pra AQUI e pro font-size de ícone/rótulo, Etapa "Barra inferior" acima)
	   até caber ou bater no piso (0.55) — funciona em cima de QUALQUER
	   perfil/largura/orientação, sem precisar conhecer o dispositivo. Roda
	   em todo load/resize e sempre que adequarBarraInferior() roda (mudança
	   de orientação). var(--barra-escala, 1): fallback 1 (sem encolher)
	   enquanto o JS não detectar quebra nenhuma — não muda o comportamento
	   calibrado manualmente abaixo em nenhum caso já coberto, só entra em
	   ação nos casos que escapavam de toda a calibração fixa. */
	min-width: calc(var(--fonte-barra-px) * 3.4 + 20px);
	width: auto;
	height: auto;
	padding: 6px 10px;
	transform: none;
	overflow: visible;
	color: #475569;
	border: none;
	background: none;
	border-radius: 12px;
	margin: 0;
	cursor: pointer;
	font-family: 'Inter', sans-serif;
	transition: background .15s ease, color .15s ease;
}
/* Ordem visual dos itens da barra inferior de cada simulador migrado (Home
   depois de Download, Apagar antes de Home etc.) foi movida pro <style>
   local de cada simulacoes/<slug>/index.html (09/08/2026) — CSS específico
   de um único simulador não deve morar neste arquivo global/compartilhado,
   só regras genéricas que servem qualquer simulador migrado (ver cabeçalho
   do arquivo). */

body.sf3-redesign #barraInferior > .btn-group,
body.sf3-redesign #nav-secondary-wrap > .btn-group {
	padding: 0;
	/* Sem isso o .btn-group ficava position:static (o Bootstrap não dava
	   position:relative pra ele nesse contexto) e o <ul class="dropdown-menu">
	   (position:absolute) subia na árvore até achar #barraInferior — a
	   barra inteira — como containing block, abrindo colado na borda
	   esquerda da TELA em vez de em cima do próprio botão. Revertido pra
	   "static" dentro do painel "Mais" do smartphone retrato logo abaixo,
	   onde o comportamento já funcionava (containing block = o próprio
	   painel .aberto, não o .btn-group). */
	position: relative;
	/* display:block (não "flex", que a regra geral do item define lá em
	   cima) de propósito: em vários navegadores mobile (WebKit/Safari,
	   Firefox Android — reproduzido só em dispositivo real, nunca no
	   Chrome desktop usado pra testar aqui), um filho position:absolute
	   (o <ul class="dropdown-menu">) dentro de um flex container
	   flex-direction:column ainda contava pra altura do container ao
	   abrir — Exemplos/Gráfico/Download "cresciam" (e com align-items:
	   center do #barraInferior, todos os outros itens da barra subiam
	   junto pra recentralizar), aumentando a barra inteira. Em
	   display:block, "position:absolute não conta pra altura do pai" é
	   comportamento básico de layout em bloco, sem esse tipo de bug —
	   o <span> interno (100% da largura/altura) continua enchendo a
	   caixa do mesmo jeito, só que agora ela é dimensionada pelo fluxo
	   normal (só o próprio <span>, o <ul> nunca conta). */
	display: block;
}
/* Bootstrap por padrão abre o <ul class="dropdown-menu"> com "left:0"
   (colado na borda esquerda do próprio botão) — em telas largas (desktop)
   sobra espaço à direita e passa despercebido, mas em telas estreitas
   (tablet/smartphone), se o botão não estiver perto da borda esquerda,
   o menu (min-width ~170-180px, ver Bootstrap) estoura a borda direita
   da tela e aparece cortado. Centralizado em cima do próprio botão
   (mesma solução do mockup CD, ".nav-examples-menu") resolve nos dois
   casos. Revertido dentro do painel "Mais" do smartphone retrato logo
   abaixo, onde o .btn-group volta a ser position:static (containing
   block = o painel inteiro, não o botão) e "left:50%" faria o menu
   centralizar no painel em vez de no botão. */
body.sf3-redesign #barraInferior .dropdown-menu {
	left: 50%;
	right: auto;
	transform: translateX(-50%);
	/* Dropup (abre pra cima, bottom:100% via Bootstrap) sem limite de altura
	   antes disso: listas maiores (Exemplos/Download, alguns simuladores com
	   bastante item) estouravam o topo da tela em telas baixas (smartphone
	   paisagem, ~375px de altura) — itens do topo ficavam inacessíveis, sem
	   como rolar até eles. calc(100vh - 90px) sobra espaço suficiente pra
	   não colar no topo (barra inferior + folga); overflow-y:auto dá scroll
	   pro resto quando a lista não cabe. */
	max-height: calc(100vh - 90px);
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
}
body.sf3-redesign #barraInferior > .btn-group > span,
body.sf3-redesign #nav-secondary-wrap > .btn-group > span {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 4px;
	width: 100%;
	height: 100%;
	/* Igual ao padding dos outros itens da barra (6px 10px) — antes estava
	   6px 4px (menos horizontal), deixando Exemplos/Gráfico/Download com
	   padding visivelmente menor que Iniciar/Reiniciar/Home/etc. */
	padding: 6px 10px;
	box-sizing: border-box;
	/* Sem isso o span (sem classe própria) herdava "color:black" de
	   ".barraDesktop a, .barraDesktop span" / "color:#2b2b2b" de
	   ".navBottom a, .navBottom span" (mainApp.css) — mais específico
	   que o inherit implícito, deixava só o ícone de Exemplos/Gráfico/
	   Download mais escuro que os outros itens da barra. */
	color: inherit;
}
body.sf3-redesign #barraInferior i {
	font-size: clamp(15px, calc(var(--fonte-barra-px) * 1.35), 22px);
	color: inherit;
	cursor: pointer;
	margin: 0;
	width: auto;
	padding: 0;
}
body.sf3-redesign #barraInferior div {
	flex-grow: 0;
	font-size: clamp(9px, calc(var(--fonte-barra-px) * .68), 13px);
	font-weight: 600;
	line-height: 1.1;
	white-space: nowrap;
	text-align: center;
	margin-top: 0;
	position: static;
	transform: none;
	color: inherit;
}
@media (hover: hover) and (pointer: fine) {
	body.sf3-redesign #barraInferior > a:hover,
	body.sf3-redesign #barraInferior > span:hover,
	body.sf3-redesign #barraInferior > button:hover,
	body.sf3-redesign #barraInferior > .btn-group:hover,
	body.sf3-redesign #nav-secondary-wrap > a:hover,
	body.sf3-redesign #nav-secondary-wrap > span:hover,
	body.sf3-redesign #nav-secondary-wrap > .btn-group:hover {
		background: #eaf3fb;
		color: var(--sf3-accent);
	}
}
/* #barraInferior #btnIniciar (encadeado, não só ".sf3-redesign #btnIniciar")
   de propósito: a regra genérica de item logo acima ("#barraInferior >
   span" etc.) tem 2 seletores de tipo (body + span) contra 1 aqui — sem
   esse encadeamento ela venceria no empate de especificidade (mesmo nº
   de IDs/classes) e o "background:none" dela apagava o destaque. */
body.sf3-redesign #barraInferior #btnIniciar {
	background: #eaf3fb;
	color: var(--sf3-accent);
	/* Largura fixa (igual ao mockup CD, width:76px) — "Iniciar"/"Pausar"
	   têm larguras de texto diferentes; sem isso o item usa flex:0 0 auto
	   (tamanho pelo próprio conteúdo, regra genérica acima) e o botão
	   mudava de largura ao alternar o rótulo, empurrando os ícones
	   seguintes pra direita/esquerda a cada play/pause. */
	flex: 0 0 72px;
	width: 72px;
}
/* Destaque dinâmico Iniciar/Pausar — igual ao mockup CD (playBg/playColor
   trocam com o estado "running"): azul enquanto parado ("Iniciar", regra
   acima), âmbar enquanto rodando ("Pausar"). Classe "rodando" alternada
   em b8d451a227.js (iniciar(), condicoesIniciais()) e mainApp.js
   (resetarEstadoInicial()), nos mesmos pontos que já trocam ícone/rótulo. */
body.sf3-redesign #barraInferior #btnIniciar.rodando {
	background: #fdf3e3;
	color: #8a6a1f;
}
/* #nav-secondary-wrap (Exemplos/Gráfico/Download/Tela cheia/Info/Salvar) —
   display:contents por padrão: o wrapper "desaparece" da árvore de caixas
   e os 6 itens voltam a ser filhos diretos de #barraInferior pra tudo o
   que já foi definido acima (flex:1, ícone+rótulo etc.), como se o div
   nem existisse. Ou seja, em qualquer tela (desktop/tablet, ou mobile em
   paisagem) a barra continua com todos os 10 botões, um desenho só.
   #btnMais só existe pro caso de retrato smartphone (ver Etapa 3
   abaixo); escondido aqui incondicionalmente, é essa Etapa que revela. */
body.sf3-redesign #nav-secondary-wrap {
	display: contents;
}
/* !important: a regra genérica de item ("#barraInferior > button", acima)
   tem mais seletores de tipo (body+button) e venceria o empate de
   especificidade, com "display:flex" apagando este "display:none" —
   mesma pegadinha do #btnIniciar (comentário acima). A exceção em
   retrato smartphone (Etapa 3 abaixo) tem uma classe a mais
   (.sf3-mobile) e já vence por especificidade normal, sem precisar de
   !important lá. */
body.sf3-redesign #btnMais {
	display: none !important;
}

/* ==================================================================
   Etapa 1 — simulador ocupando a tela toda (desktop, paisagem E retrato
   — blocos dentro de "if (!mobile) {...}" em adequarDispositivo(), no
   b8d451a227.js local). Vale para as duas orientações porque
   orientacao() é só window.innerHeight > innerWidth, e no desktop isso
   muda com o simples redimensionar da janela. Mobile/tablet/iPad
   (isMobile.any()/isIpad.ipad()) ficam para uma etapa futura.
   ================================================================== */
/* #main = coluna flex ocupando a tela toda: filhos diretos são .inner
   (breadcrumb + grid, cresce/encolhe) e nav#barraInferior (barra, altura
   pelo conteúdo, sempre por último). Substitui a abordagem antiga de
   prever um orçamento de altura pra cada peça via calc(100vh - Npx)
   (chute manual, causa dos gaps entre canvas/painéis e a barra relatados
   pelo usuário) — com flex, a barra fica sempre colada embaixo do
   conteúdo, sem gap, e o navegador calcula o resto sozinho.
   !important porque loadHeader.js (compartilhado) e b8d451a227.js
   (local) setam #main.style.display="block" via inline style pra
   revelar a página (inline sempre vence regra de classe sem !important). */
body.sf3-redesign #main {
	display: flex !important;
	flex-direction: column;
	/* 100vh no Safari mobile (iPhone/iPad) usa a altura da MAIOR viewport
	   possível (como se a barra de ferramentas do navegador já estivesse
	   escondida) — com overflow:hidden aqui, o #barraInferior (último
	   filho do flex column) fica parcialmente ou totalmente encoberto
	   pela barra do Safari quando ela está visível (só reaparecia
	   escondendo-a manualmente, "Ocultar Barra de Ferramentas"). 100dvh
	   acompanha o tamanho real e visível da viewport, escondendo/mostrando
	   dinamicamente junto com a barra do navegador. Fallback 100vh primeiro
	   (navegador sem suporte a dvh ignora a linha seguinte). */
	height: 100vh;
	height: 100dvh;
	overflow: hidden;
	padding: 0;
}
/* Notch/câmera-ilha em celulares com tela recortada (iPhone com notch,
   Dynamic Island, etc.) em modo PAISAGEM: o recorte fica na lateral
   esquerda (nesse simulador, testado com o aparelho rotacionado desse
   jeito — o lado direito fica por conta do usuário girar o aparelho, não
   tratado aqui de propósito, ver comentário do usuário 2026-08-05),
   invadindo a borda do canvas — sem viewport-fit=cover (já presente na
   <meta name="viewport">, index.html) a página nem saberia da área
   recortada; com ele, env(safe-area-inset-left) informa quanto reservar.
   Só em ".inner" (breadcrumb + grid canvas/painéis), NÃO em "#main"
   inteiro: #barraInferior é IRMÃ de ".inner" dentro de #main (comentário
   acima), então fica de fora — a barra continua de ponta a ponta, sem
   respiro nenhum, como se o notch não existisse (pedido do usuário).
   *0.8 (não o valor bruto do env()): sobra um pouco mesmo no valor cheio;
   ajustar esse fator se ainda sobrar/faltar respiro num aparelho real. */
body.sf3-redesign #wrapper > * > .inner {
	max-width: none;
	padding: 0;
	padding-left: calc(env(safe-area-inset-left, 0px) * 0.8);
}
body.sf3-redesign .inner {
	display: flex;
	flex-direction: column;
	/* .inner (mainApp.css, compartilhado) tem "align-items:center;
	   justify-content:center" — pensado pra um .inner sem display:flex
	   próprio (herdado/ignorado até então). Como ligamos flex aqui, os
	   dois passam a valer de verdade: align-items:center (eixo
	   transversal = largura, coluna) faz #principal encolher pro próprio
	   conteúdo (shrink-to-fit) em vez de esticar pra 100% da largura —
	   com um grid-template-columns:1fr por dentro, isso essa vira uma
	   referência circular que o navegador resolve pro tamanho mínimo do
	   conteúdo (~39px, só a bolinha do pêndulo). stretch/flex-start
	   sobrescrevem os dois pra voltar ao comportamento esperado. */
	align-items: stretch;
	justify-content: flex-start;
	/* .inner (mainApp.css) também tem "max-height: calc(100vh - 90px)" —
	   sobrava exatamente esse tanto de espaço em branco embaixo da barra
	   (fora do flex column, abaixo dela) porque .inner nunca crescia até
	   o fim de #main de verdade. */
	max-height: none;
	flex: 1;
	min-height: 0;
}
/* padding 10px 24px igual ao mockup CD (SimuFísica Simulador Pendulo
   Duplo Redesign.dc.html, sf3-crumb) — os 10px de baixo abrem um respiro
   entre o breadcrumb e o canvas/painéis (antes era 0, colados).
   flex-shrink:0 — breadcrumb sempre no tamanho do conteúdo, quem cresce/
   encolhe pra preencher o resto da coluna é #principal (regra abaixo). */
body.sf3-redesign #breadcrumbSimulador {
	flex-shrink: 0;
	padding: 10px 24px;
	margin-bottom: 0;
}
/* Smartphone: elimina a barra inteira (não só o texto) — pedido do
   usuário pra recuperar o espaço vertical, já que o padding acima ainda
   ocupava altura mesmo com o texto vazio (JS não populava o breadcrumb
   em mobile, ver mainApp.js). Desktop e tablet mantêm. */
body.sf3-redesign.sf3-mobile #breadcrumbSimulador {
	display: none;
}
/* #principal preenche o resto da coluna de .inner (breadcrumb já tirou a
   fatia dele acima) — min-height:0 é o que permite o grid encolher
   abaixo do tamanho do conteúdo em vez de estourar a coluna (senão um
   item de flex nunca fica menor que o "min-content" por padrão). As
   colunas/linhas do grid em si (largura do canvas x painéis, 50vh/55vh
   do canvas em retrato etc.) continuam vindo das regras por dispositivo
   nas Etapas 2-4 abaixo — aqui é só quem entrega a altura disponível. */
body.sf3-redesign #principal {
	flex: 1;
	min-height: 0;
	/* Contexto de posicionamento pro .sf3-resizer (position:absolute)
	   logo abaixo — não muda nada visualmente por si só. */
	position: relative;
}

/* ==================================================================
   Divisor arrastável entre #canvas e #parametros — pedido do usuário
   (19/08/2026). DELIBERADAMENTE FORA do grid (position:absolute, não
   um filho real de #principal pro grid) — não é um capricho: dezenas
   de simuladores redefinem #principal.style.gridTemplateColumns (JS
   próprio, ex. calorimetria/circuito-rlc) OU têm um <style> local com
   grid-template-columns de só 2 trilhas com especificidade maior que a
   regra genérica (ex. armadilha-magneto-optica/cavidades-opticas/
   cargas-em-um-condutor2, canvas com aspect-ratio travado). Se o
   divisor fosse um 3º FILHO real do grid, qualquer uma dessas 2
   trilhas quebra o layout inteiro (o filho sobrando é espremido/cai
   numa linha implícita) — foi exatamente o bug relatado em
   calorimetria/conservacao-energia-mecanica/cargas-em-um-condutor/
   reflexao-refracao-dispersao/armadilha-magneto-optica (19-20/08/2026).
   Pior: alguns simuladores MEDEM #canvas logo depois de escrever essa
   inline style (ex. conservacao-energia-mecanica calcula fatorCorrecao
   a partir de Lx) — com o grid quebrado nesse instante, a medida saía
   errada e a física renderizava deformada, mesmo depois do layout se
   corrigir visualmente um instante depois.
   Como position:absolute tira o item do fluxo do grid (spec: não
   participa do sizing/placement das trilhas), #principal SEMPRE
   continua com exatamente 2 filhos reais pro grid, não importa quem
   define grid-template-columns — elimina esse bug inteiro na raiz, em
   vez de tentar reagir a cada variante depois que ela quebra. redesign.js
   posiciona o elemento (left/height) via JS, medindo #parametros.
   Some em retrato (grid empilha em linhas, sem fronteira horizontal) e
   em qualquer layout que não resolva pra exatamente 2 trilhas nesse
   instante (ex. breakpoint específico de algum simulador que empilha
   canvas/painel mesmo em paisagem) — ver atualizarVisibilidade() em
   redesign.js. */
body.sf3-redesign .sf3-resizer {
	position: absolute;
	top: 0;
	height: 100%;
	width: var(--sf3-resizer-w);
	margin-left: calc(var(--sf3-resizer-w) / -2);
	cursor: col-resize;
	touch-action: none;
	background: transparent;
	-webkit-tap-highlight-color: transparent;
}
body.sf3-redesign .sf3-resizer::after {
	content: '';
	position: absolute;
	top: 0;
	bottom: 0;
	left: 50%;
	width: 3px;
	transform: translateX(-50%);
	border-radius: 2px;
	background: var(--sf3-border);
	transition: background-color .15s ease;
}
body.sf3-redesign .sf3-resizer:hover::after,
body.sf3-redesign .sf3-resizer:focus-visible::after,
body.sf3-redesign .sf3-resizer.sf3-resizer-arrastando::after {
	background: var(--sf3-accent);
}
body.sf3-redesign .sf3-resizer:focus-visible {
	outline: 2px solid var(--sf3-accent);
	outline-offset: -2px;
}
@media (orientation: portrait) {
	body.sf3-redesign .sf3-resizer {
		display: none;
	}
}

/* Botão de colapsar/expandir o bloco de painéis (pedido do usuário,
   20/08/2026) — filho de .sf3-resizer/.sf3-resizer-v, centralizado sobre a
   própria alça, sempre visível (não só no hover, pra ser descobrível).
   Ícone trocado via JS (fa-chevron-right/left horizontal,
   fa-chevron-down/up vertical — ver atualizarBotaoResizer()/V() em
   redesign.js) conforme o estado colapsado/expandido. */
body.sf3-redesign .sf3-resizer-toggle {
	position: absolute;
	top: 50%;
	left: 50%;
	/* z-index: sem isso, a linha (::after, "conteúdo gerado" — empilha
	   como se fosse o ÚLTIMO filho de .sf3-resizer/-v, depois deste botão
	   na ordem de pintura) ficava por CIMA do botão, cobrindo metade dele
	   (relatado pelo usuário, 21/08/2026). */
	z-index: 1;
	transform: translate(-50%, -50%);
	width: 22px;
	height: 22px;
	padding: 0;
	border-radius: 50%;
	border: 1px solid var(--sf3-border);
	background: #ffffff;
	color: var(--sf3-text-muted);
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 11px;
	line-height: 1;
	cursor: pointer;
	box-shadow: 0 1px 3px rgba(15, 23, 42, .15);
	transition: color .15s ease, border-color .15s ease;
}
body.sf3-redesign .sf3-resizer-toggle:hover,
body.sf3-redesign .sf3-resizer-toggle:focus-visible {
	color: var(--sf3-accent);
	border-color: var(--sf3-accent);
	outline: none;
}
/* Colapsado: a alça fica pinada na borda de #principal (largura/altura do
   painel = 0), então o botão — centralizado sobre ela por padrão — ficaria
   metade pra fora do container. Desloca ele inteiro pro lado de DENTRO
   (canvas) em vez de ficar partido na borda. */
body.sf3-redesign .sf3-resizer.sf3-resizer-colapsado .sf3-resizer-toggle {
	transform: translate(-100%, -50%);
}
body.sf3-redesign .sf3-resizer-v.sf3-resizer-colapsado .sf3-resizer-toggle {
	transform: translate(-50%, -100%);
}

/* Botão que oculta/mostra #barraInferior por completo (pedido do usuário,
   22/08/2026) — só em smartphone paisagem (display:flex só é ligado lá
   embaixo, dentro do @media (orientation:landscape) de sf3-mobile).
   Filho de <body> (redesign.js), não de #barraInferior: precisa continuar
   visível/clicável mesmo com a barra inteira em display:none, senão não
   haveria como voltar a mostrá-la. #barraInferior é irmã de ".inner"
   dentro de #main (flex column, Etapa 1) — sumindo ela, ".inner"/
   #principal (flex:1) crescem sozinhos até o fim da tela, sem precisar de
   nenhum ajuste de altura aqui. position:fixed com "bottom" recalculado
   via JS (posicionar(), redesign.js): colado acima da barra quando ela
   está visível (não sobrepõe nenhum ícone), ou colado na própria borda da
   tela quando colapsada. Mesma linguagem visual do .sf3-resizer-toggle
   acima, só maior (alvo de toque em mobile, não desktop). */
body.sf3-redesign .sf3-barra-toggle {
	display: none;
	position: fixed;
	right: 10px;
	z-index: 60;
	width: 34px;
	height: 34px;
	padding: 0;
	border-radius: 50%;
	border: 1px solid var(--sf3-border);
	background: #ffffff;
	color: var(--sf3-text-muted);
	align-items: center;
	justify-content: center;
	font-size: 14px;
	line-height: 1;
	cursor: pointer;
	box-shadow: 0 2px 6px rgba(15, 23, 42, .18);
	transition: bottom .15s ease;
}
body.sf3-redesign .sf3-barra-toggle:hover,
body.sf3-redesign .sf3-barra-toggle:focus-visible {
	color: var(--sf3-accent);
	border-color: var(--sf3-accent);
	outline: none;
}

/* Cluster fixo (canto inferior direito) que aparece só quando a barra
   está colapsada E o simulador tem #btnReiniciar (pedido do usuário,
   23/08/2026) — guarda o botão de expandir a barra (.sf3-barra-toggle) e
   o próprio #btnReiniciar (nó real, reparentado por redesign.js, não
   clonado — mantém o onclick/id originais). display:none por padrão,
   redesign.js troca pra "flex" só quando colapsada; simuladores sem
   Reiniciar (ex. ressonancias-sistema-dois-niveis) nunca chegam a criar
   esse cluster — cai pro botão de expandir sozinho, como antes desta
   mudança. Ordem de inserção no JS (Reiniciar, depois toggle) decide a
   ordem visual: toggle por último fica colado na borda direita — a
   MESMA posição que ele já ocupa sozinho (right:10px) em simuladores sem
   Reiniciar (mudança de ideia do usuário, 23/08/2026: a 1ª versão
   colocava Reiniciar por último, mas isso deslocava o toggle — o
   controle crítico, único jeito de recuperar a barra inteira — pra uma
   posição diferente conforme o simulador tinha ou não Reiniciar, quebrando
   o padrão de onde procurar esse botão). Reiniciar (extra, não crítico)
   fica vizinho, um pouco mais pra dentro. */
body.sf3-redesign .sf3-barra-flutuante-cluster {
	display: none;
	position: fixed;
	right: 10px;
	bottom: 10px;
	z-index: 60;
	align-items: center;
	gap: 8px;
}
/* Dentro do cluster o botão de expandir vira item de flex normal — quem
   já está ancorado por "right"/"bottom" é o CONTAINER, não mais ele
   sozinho (evita os dois competirem pelo mesmo "right:10px"). */
body.sf3-redesign .sf3-barra-flutuante-cluster .sf3-barra-toggle {
	position: static;
}
/* #btnReiniciar reparentado (redesign.js) sai de dentro de #barraInferior
   — perde toda a herança de estilo dos seletores descendentes que só
   valem lá (regra genérica de item "#barraInferior > span", clamps de
   fonte em "#barraInferior i"/"#barraInferior div", Etapa "Barra
   inferior"). Precisa de estilo próprio pra continuar legível fora dela:
   mesma linguagem visual do .sf3-barra-toggle (branco, borda, sombra),
   só retangular/pílula (ícone + rótulo lado a lado) em vez de circular —
   consistente com o próprio elemento (era ícone-em-cima-rótulo-embaixo
   dentro da barra; de pé sozinho, lado a lado cabe melhor num alvo de
   toque baixo e largo). */
body.sf3-redesign .sf3-barra-reiniciar-flutuante {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: 6px;
	padding: 8px 14px;
	border-radius: 20px;
	border: 1px solid var(--sf3-border);
	background: #ffffff;
	color: #002c93;
	box-shadow: 0 2px 6px rgba(15, 23, 42, .18);
	cursor: pointer;
	font-size: 13px;
	line-height: 1;
}
body.sf3-redesign .sf3-barra-reiniciar-flutuante i {
	font-size: 14px;
}
body.sf3-redesign .sf3-barra-reiniciar-flutuante div {
	font-size: 12px;
	font-weight: 500;
}

/* ---- Divisor arrastável entre #canvas e #parametros — retrato ----
   Mesmo princípio do .sf3-resizer acima (position:absolute, fora do grid,
   posicionado via JS medindo os elementos de verdade — ver .sf3-resizer-v
   em redesign.js), só que a barra é DEITADA (cursor row-resize): em
   retrato o grid empilha canvas (1ª linha) sobre #parametros (2ª linha),
   então a fronteira arrastável aqui é HORIZONTAL, arrastada no eixo Y.
   Elemento IRMÃO separado do .sf3-resizer (não o mesmo <div> reaproveitado)
   porque os dois convivem no DOM o tempo todo — cada um só aparece na
   própria orientação (media query abaixo/acima), e têm eixo de arraste e
   fórmula de posicionamento diferentes. Reaproveita --sf3-resizer-w (só a
   espessura da barra — o nome já é genérico o bastante; vira "height" em
   vez de "width" aqui). */
body.sf3-redesign .sf3-resizer-v {
	position: absolute;
	left: 0;
	width: 100%;
	height: var(--sf3-resizer-w);
	margin-top: calc(var(--sf3-resizer-w) / -2);
	cursor: row-resize;
	touch-action: none;
	background: transparent;
	-webkit-tap-highlight-color: transparent;
}
body.sf3-redesign .sf3-resizer-v::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	top: 50%;
	height: 3px;
	transform: translateY(-50%);
	border-radius: 2px;
	background: var(--sf3-border);
	transition: background-color .15s ease;
}
body.sf3-redesign .sf3-resizer-v:hover::after,
body.sf3-redesign .sf3-resizer-v:focus-visible::after,
body.sf3-redesign .sf3-resizer-v.sf3-resizer-arrastando::after {
	background: var(--sf3-accent);
}
body.sf3-redesign .sf3-resizer-v:focus-visible {
	outline: 2px solid var(--sf3-accent);
	outline-offset: -2px;
}
@media (orientation: landscape) {
	body.sf3-redesign .sf3-resizer-v {
		display: none;
	}
}

/* Alça de altura do painel "Gráfico" (pedido do usuário, 20/08/2026 —
   prova de conceito em pendulos-acoplados). Diferente de .sf3-resizer/-v
   acima (position:absolute, fora do grid, arrastando uma fronteira de
   #principal), esta alça arrasta só a altura inline de #plot (Plotly),
   aplicada/lida por JS específico de cada simulador (ver b8d451a227.js).
   position:absolute ancorada no PADDING do próprio .bloco (não no fluxo
   depois de #plot) — pedido do usuário, 21/08/2026: em fluxo, a linha
   ficava perto de #plot mas longe da borda do card (a distância até a
   borda era o padding:18px do .bloco inteiro, por cima do espaço que a
   própria alça já ocupava, poluindo visualmente). Ancorar em bottom:0
   (que pra um elemento absolute é a borda INTERNA do padding-box, ou
   seja, a borda do card) com a altura de --sf3-resizer-w faz a linha
   central (::after, 50% da altura) cair a metade de --sf3-resizer-w da
   borda de verdade — com --sf3-resizer-w:10px, são ~5px, o pedido do
   usuário. :has() escopa o position:relative só ao .bloco que realmente
   tem a alça (painel "Gráfico"), sem mexer no posicionamento dos demais
   painéis. */
body.sf3-redesign .bloco:has(.sf3-plot-resizer) {
	position: relative;
}
body.sf3-redesign .sf3-plot-resizer {
	position: absolute;
	left: 18px;
	right: 18px;
	bottom: 0;
	height: var(--sf3-resizer-w);
	cursor: row-resize;
	touch-action: none;
	background: transparent;
	-webkit-tap-highlight-color: transparent;
}
body.sf3-redesign .sf3-plot-resizer::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	top: 50%;
	height: 3px;
	transform: translateY(-50%);
	border-radius: 2px;
	background: var(--sf3-border);
	transition: background-color .15s ease;
}
body.sf3-redesign .sf3-plot-resizer:hover::after,
body.sf3-redesign .sf3-plot-resizer:focus-visible::after,
body.sf3-redesign .sf3-plot-resizer.sf3-resizer-arrastando::after {
	background: var(--sf3-accent);
}
body.sf3-redesign .sf3-plot-resizer:focus-visible {
	outline: 2px solid var(--sf3-accent);
	outline-offset: -2px;
}

body.sf3-redesign canvas {
	border: none;
	border-radius: 0;
	box-shadow: none;
}
/* Moldura igual à dos painéis (.bloco: mesma cor/espessura de borda e
   mesmo box-shadow) — canto reto (border-radius:0) porque o canvas
   encosta nas bordas do viewport (Etapa 1 acima); arredondar cortaria
   a borda visível bem no meio, revelando o fundo da página atrás. */
body.sf3-redesign #canvas {
	border: 1px solid var(--sf3-border);
	border-radius: 0;
	box-shadow: 0 1px 2px rgba(15,23,42,.04);
}

/* ==================================================================
   Etapa 2 — grid fluido via CSS puro (desktop), no lugar da maioria
   dos ajustes que adequarDispositivo() fazia via JS (gridTemplateColumns/
   width/height/maxWidth inline em #parametros, #painel-pendulo-verde,
   #checkbox, #grafico). O JS (b8d451a227.js local) passa a só: (1)
   adicionar a classe "sf3-desktop" ao body quando !mobile, e (2) medir
   o retângulo final do #canvas via getBoundingClientRect() — depois
   que o grid já decidiu o tamanho — para definir a resolução interna
   do <canvas> (raster) e a âncora x0/y0 da física, e configurar o
   Plotly. Nada disso tem equivalente em CSS, o resto tem.
   Escopo: só quando "sf3-desktop" está presente, ou seja, só desktop —
   mobile/tablet/iPad continuam 100% como estavam, sem essa classe.
   ================================================================== */
body.sf3-redesign.sf3-desktop #principal {
	gap: 16px;
}

/* Barra inferior um pouco maior em desktop (mais espaço de tela disponível
   do que em mobile/tablet) — redeclara --fonte-barra-px aqui, que cascateia
   pros ícones/rótulos dentro de #barraInferior, e sobe também o teto dos
   clamp() (definidos em body.sf3-redesign #barraInferior i/div, mais acima)
   só pra este escopo, senão o valor maior batia no teto.
   PRA AJUSTAR O TAMANHO: mexa no "1.15" abaixo (1.0 = mesmo tamanho de
   tablet; quanto maior, maior o ícone e o rótulo juntos, na mesma
   proporção). Se aumentar esse número e não notar diferença, bateu no teto
   dos clamp() logo abaixo (30px pro ícone, 17px pro rótulo) — suba os
   tetos junto. */
body.sf3-redesign.sf3-desktop #barraInferior {
	/* * var(--barra-escala, 1) — ver comentário no --fonte-barra-px de
	   "body.sf3-redesign" (raiz) e na regra de "min-width" da Etapa "Barra
	   inferior": mesmo auto-encolhimento, só redeclarado aqui de novo porque
	   esta regra já redeclara --fonte-barra-px com outro multiplicador
	   (1.15 em vez de 0.85) e sobrescreveria o var(--barra-escala) aplicado
	   lá se não repetir aqui também. */
	--fonte-barra-px: calc(var(--fonte-simulador-px) * 1.15 * var(--barra-escala, 1));
	padding: 10px 16px;
	/* Espaçamento entre ícones cresce com a largura da tela, sem nunca
	   ficar menor que 6px em telas estreitas nem passar de 32px em telas
	   grandes (clamp cuida dos dois limites sozinho).
	   ⚠️ 1.3vw/40px→0.7vw/32px (04/08/2026): com os 10 itens de
	   `lancamento-projeteis2` (9 gaps), o valor antigo de 1.3vw somava
	   ~120px de gap sozinho em telas de ~1024px, empurrando a barra pra
	   quebrar em 2 linhas — ver comentário equivalente no min-width dos
	   itens, logo acima ("Etapa 3"). Em telas grandes o espaçamento fica
	   um pouco mais discreto que antes (32px de teto, não mais 40px), mas
	   ainda cresce com a largura da tela. */
	gap: clamp(6px, 0.7vw, 32px);
}
body.sf3-redesign.sf3-desktop #barraInferior i {
	font-size: clamp(15px, calc(var(--fonte-barra-px) * 1.35), 30px);
}
body.sf3-redesign.sf3-desktop #barraInferior div {
	font-size: clamp(9px, calc(var(--fonte-barra-px) * .68), 17px);
}

body.sf3-redesign.sf3-desktop #canvas,
body.sf3-redesign.sf3-desktop #parametros {
	min-width: 0;
	min-height: 0;
}

body.sf3-redesign.sf3-desktop canvas {
	width: 100% !important;
	height: 100% !important;
}

body.sf3-redesign.sf3-desktop #parametros {
	width: auto !important;
	height: auto !important;
	max-width: none !important;
	max-height: none !important;
}

@media (orientation: landscape) {
	body.sf3-redesign.sf3-desktop #principal {
		/* canvas ~63% da largura, sidebar ~37% por padrão — proporção fixa
		   via fr, com um mínimo de 260px na sidebar só pra não espremer
		   demais em janelas bem estreitas. --sf3-painel-w (JS, arraste do
		   .sf3-resizer) sobrescreve a sidebar pra uma largura fixa em px
		   quando o usuário ajusta manualmente; até lá, o fallback 37fr
		   mantém a proporção de sempre. */
		grid-template-columns: minmax(0, 63fr) minmax(260px, var(--sf3-painel-w, 37fr));
		grid-template-rows: 1fr;
	}
	body.sf3-redesign.sf3-desktop #parametros {
		grid-template-columns: auto;
		/* Margens laterais iguais ao espaço entre Pêndulo 1/Pêndulo 2 (gap de
		   16px do .sf3-panels-grid): a distância canvas->painel já vem inteira
		   do gap de 16px do #principal, então zera o padding-left aqui (senão
		   somaria 16+16=32, maior que o gap entre os painéis). O padding-right
		   já é 16px, herdado da regra base — mesma medida. Em telas pequenas
		   cada pixel de margem importa. */
		padding-left: 0;
	}
}

@media (orientation: portrait) {
	body.sf3-redesign.sf3-desktop #principal {
		grid-template-columns: 1fr;
		/* canvas = 50% da altura da TELA (vh), não do #principal reduzido —
		   mesma convenção usada em mobile/tablet (vh direto). dvh depois do
		   vh (fallback) pelo mesmo motivo do #main: acompanhar a barra de
		   ferramentas do Safari mobile em vez da maior viewport possível.
		   --sf3-painel-h (JS, arraste do .sf3-resizer-v) sobrescreve a
		   altura do canvas quando o usuário ajusta manualmente — mesmo
		   mecanismo de --sf3-painel-w em paisagem (Divisor arrastável,
		   acima), só que aqui é a 1ª trilha (canvas) que fica embrulhada
		   em vez da 2ª: #parametros já era a trilha flexível (minmax(0,
		   1fr)) nesse layout, então é o CANVAS que tem o valor fixo a
		   sobrescrever. */
		grid-template-rows: minmax(120px, var(--sf3-painel-h, 50vh)) minmax(0, 1fr);
		grid-template-rows: minmax(120px, var(--sf3-painel-h, 50dvh)) minmax(0, 1fr);
		/* gap:0 (zera o 16px da regra base) — em retrato #parametros rola
		   sozinho (overflow-y:auto, assets/css/mainApp2.css) sem mover o
		   canvas (linha 1 do grid, fixa); um "gap" do GRID fica FORA da
		   área que rola, então continuava visível como uma faixa vazia
		   entre canvas e painel mesmo depois de rolar pra baixo. Trocado
		   por padding-top no próprio #parametros logo abaixo — aí o respiro
		   mora DENTRO da área que rola e some assim que o usuário rola um
		   pouco, igual ao mockup CD (.sf3-grid gap:0 + .sf3-sidepanel
		   padding-top:16px, só em retrato). */
		gap: 0;
	}
	body.sf3-redesign.sf3-desktop #parametros {
		padding-top: 16px;
	}
	/* Ícones maiores em desktop retrato — pedido do usuário (31/08/2026):
	   mesmo problema do tablet retrato (comentário equivalente logo abaixo,
	   Etapa "sf3-tablet"), mas aqui a barra usa justify-content:center
	   (regra genérica "Etapa Barra inferior" lá em cima) — o espaço
	   sobrando virava margem dos dois lados da barra, nunca ícone maior,
	   porque --fonte-barra-px do desktop também nunca mudava entre
	   retrato/paisagem (sempre *1.15). 1.15→1.3→1.2 só neste escopo (1.3
	   inicial ficou grande demais, ajustado a pedido do usuário — ~4%
	   maior que paisagem). Tetos do clamp() do ícone/rótulo (30px/17px,
	   regra de sf3-desktop lá em cima) também sobem, mesmo motivo do
	   comentário ali — com 1.2 eles nem chegam a ser atingidos, mas ficam
	   como teto de segurança pra fonte do usuário no máximo (botão A+).
	   Pior caso (10 itens, `lancamento-projeteis`) testado em 1101px de
	   largura (janela mais estreita ainda classificada sf3-desktop,
	   telaX>1100 — ver adequarDispositivo() no hashed JS de cada
	   simulador) com folga; ajustarEscalaBarraInferior() (mainApp.js)
	   continua como rede de segurança pra janelas ainda mais estreitas ou
	   fonte do usuário no máximo (botão A+). */
	body.sf3-redesign.sf3-desktop #barraInferior {
		--fonte-barra-px: calc(var(--fonte-simulador-px) * 1.2 * var(--barra-escala, 1));
	}
	body.sf3-redesign.sf3-desktop #barraInferior i {
		font-size: clamp(15px, calc(var(--fonte-barra-px) * 1.35), 34px);
	}
	body.sf3-redesign.sf3-desktop #barraInferior div {
		font-size: clamp(9px, calc(var(--fonte-barra-px) * .68), 19px);
	}
}

/* ==================================================================
   Etapa 3 — mobile (smartphone). Mesmo princípio da Etapa 2: grid via
   CSS, JS só mede o #canvas (getBoundingClientRect) pra resolução do
   <canvas> e ajusta o Plotly/slider de comprimento (que dependem de
   número real). Escopo "sf3-mobile", adicionado só quando
   dispositivo()==="smartphone" — tablet/iPad ainda usam o
   adequarDispositivo() original (próxima etapa).
   ================================================================== */
body.sf3-redesign.sf3-mobile #principal {
	gap: 0px;
}

body.sf3-redesign.sf3-mobile #canvas,
body.sf3-redesign.sf3-mobile #parametros {
	min-width: 0;
	min-height: 0;
}

body.sf3-redesign.sf3-mobile canvas {
	width: 100% !important;
	height: 100% !important;
}

body.sf3-redesign.sf3-mobile #parametros {
	width: auto !important;
	height: auto !important;
	max-width: none !important;
	max-height: none !important;
}

/* Barra inferior um pouco maior em mobile (pedido do usuário — oposto do
   ajuste em sf3-desktop acima: lá "mais espaço de tela" justificava reduzir,
   aqui a tela é pequena mas os ícones são o alvo de toque principal, então
   um pouco maior ajuda). --fonte-barra-px sobe de 0.85 (padrão, mainApp.css)
   pra 1.0; o teto do clamp() do ícone (22px, regra genérica acima) também
   sobe, senão o aumento não apareceria (bateria no teto sem mudar nada,
   mesma pegadinha comentada em sf3-desktop). O do rótulo não precisa subir,
   o valor novo já fica abaixo do teto de 13px.
   padding-bottom: dispositivos modernos (iPhone com Face ID, Android com
   navegação por gestos) têm uma barra/linha de gesto colada na borda
   inferior da tela, perto demais dos ícones — env(safe-area-inset-bottom)
   é o valor que o próprio sistema informa pra essa área (funciona graças a
   "viewport-fit=cover" na <meta name="viewport">, index.html); soma-se aos
   6px de padding-bottom já herdados da regra genérica de #barraInferior
   pra abrir um respiro extra. Em aparelhos sem essa barra (Android mais
   antigo, sem gestos) o valor do env() é 0 e nada muda. */
body.sf3-redesign.sf3-mobile #barraInferior {
	/* * var(--barra-escala, 1) — mesmo motivo do sf3-desktop acima (regra
	   redeclara --fonte-barra-px com multiplicador próprio, 1 em vez de
	   0.85/1.15, então precisa repetir o var(--barra-escala) aqui também). */
	--fonte-barra-px: calc(var(--fonte-simulador-px) * 1 * var(--barra-escala, 1));
	padding-bottom: calc(6px + env(safe-area-inset-bottom, 0px));
}
body.sf3-redesign.sf3-mobile #barraInferior i {
	font-size: clamp(15px, calc(var(--fonte-barra-px) * 1.35), 25px);
}

/* Painéis de #parametros mais compactos em smartphone (pedido do usuário,
   18/08/2026 — validado primeiro só em massa-mola, depois generalizado pra
   todos os simuladores sf3-redesign, já que nenhuma destas regras depende
   de nada específico de um simulador, só do perfil de dispositivo).
   1ª tentativa (texto do título sempre escondido, só o chevron) deixava o
   cabeçalho em branco quando o painel estava colapsado — sem nenhum outro
   conteúdo visível, o usuário perdia a referência de qual painel era qual.
   Correção: título continua sempre visível, só menor (fonte e margem
   reduzidas) — cabeçalho mais compacto em vez de vazio, sem mexer na
   posição dos sliders (evita o chevron ficar por cima de um slider, risco
   de layout apontado pelo usuário). Remove A-/A+ (.controle-fonte). */
body.sf3-redesign.sf3-mobile #parametros .titulo-bloco {
	margin-bottom: 0;
}
body.sf3-redesign.sf3-mobile #parametros .titulo-bloco span {
	font-size: calc(var(--fonte-simulador-px) * .85);
}
body.sf3-redesign.sf3-mobile #parametros .controle-fonte {
	display: none;
}
body.sf3-redesign.sf3-mobile #parametros .bloco {
	--sf3-bloco-padding: 10px;
	padding: var(--sf3-bloco-padding);
}
/* Mais agressivo (pedido do usuário, 18/08/2026): espaço em smartphone é
   muito curto, vale mais espremer gap/padding do que preservar as medidas
   "confortáveis" de desktop/tablet. #parametros tem "gap: 10px !important"
   em mainApp2.css (legado) — precisa de !important aqui também pra vencer
   (a especificidade já é maior por causa da classe sf3-mobile a mais, mas
   !important só perde pra !important de especificidade maior, não pra
   normal). */
body.sf3-redesign.sf3-mobile #parametros {
	gap: 8px !important;
	padding: 0 10px 10px 10px;
}
body.sf3-redesign.sf3-mobile .sf3-panels-grid {
	gap: 8px;
}
body.sf3-redesign.sf3-mobile .sf3-grafico-fase {
	margin-bottom: 0;
}
/* Espaçamento vertical entre sliders (pedido do usuário, 18/08/2026) —
   regulado em 3 lugares dentro de cada .item: .item-header (altura ditada
   pelo <input> de .valor-editavel, não pela linha de texto), .slider
   (margin: 2px 0 6px) e .item-minmax (margin-top: 2px). O
   margin-bottom:6px do slider é o raio do thumb (18px, estoura 6px pra
   cada lado do trilho de 6px) — é o que impede o thumb de cobrir os
   números min/max logo abaixo; não mexo nele. Resto é puro respiro, dá
   pra cortar sem colidir com nada. */
body.sf3-redesign.sf3-mobile #parametros .valor-editavel {
	padding: 0 0 0 3px;
}
body.sf3-redesign.sf3-mobile #parametros .slider,
body.sf3-redesign.sf3-mobile #parametros .slider2 {
	margin-top: 0;
}
body.sf3-redesign.sf3-mobile #parametros .item-minmax {
	margin-top: 0;
}

/* #help-cursor sobe pro lugar do #toolbox em smartphone (pedido do
   usuário, 18/08/2026) — #toolbox é escondido em telas de toque pequenas
   (mainApp2.css, "Esconder toolbox em telas pequenas"), deixando o canto
   superior direito do canvas vazio e o #help-cursor "flutuando" sozinho
   mais abaixo (top:66px, posição pensada pra ficar embaixo do botão da
   toolbox). Sem o toolbox ali, o ícone de ajuda pode ocupar o canto —
   ganha lugar mais lógico, sem competir por espaço com mais nada (os dois
   nunca aparecem juntos no mesmo dispositivo). Precisa de !important pra
   vencer o "top:66px !important" da regra base (mesma lógica do gap de
   #parametros acima: !important só perde pra !important de especificidade
   maior, e aqui a especificidade já é maior por causa do .sf3-mobile). */
body.sf3-redesign.sf3-mobile #help-cursor {
	top: 16px !important;
}

@media (orientation: portrait) {
	body.sf3-redesign.sf3-mobile #principal {
		grid-template-columns: 1fr;
		/* dvh depois do vh (fallback) — ver comentário no #main sobre a
		   barra de ferramentas do Safari mobile. --sf3-painel-h — ver
		   comentário equivalente em sf3-desktop retrato acima. */
		grid-template-rows: minmax(120px, var(--sf3-painel-h, 55vh)) minmax(0, 1fr);
		grid-template-rows: minmax(120px, var(--sf3-painel-h, 55dvh)) minmax(0, 1fr);
		/* gap:0 — ver comentário equivalente em sf3-desktop retrato acima
		   (o gap do grid fica fora da área que #parametros rola sozinho,
		   então continuava visível mesmo depois de rolar). */
		gap: 0;
	}
	body.sf3-redesign.sf3-mobile #parametros {
		padding-top: 8px;
	}
	/* Barra com só 5 ícones em smartphone retrato (pedido do usuário):
	   Iniciar, Reiniciar, Home, Resetar (nesta ordem no HTML, ver
	   index.html) e "Mais" — os 6 itens secundários (Exemplos, Gráfico,
	   Download, Tela cheia, Info, Salvar) somem da barra e passam a
	   morar dentro do painel que "Mais" abre, sem duplicar nenhum botão
	   (mesmos nós do DOM, só reposicionados via CSS: display:contents
	   vira display:none/flex aqui). */
	body.sf3-redesign.sf3-mobile #nav-secondary-wrap {
		display: none;
	}
	/* "order" (Etapa "Barra inferior" acima) reordena Home pra depois de
	   Download na fileira "cheia" (desktop/tablet/paisagem) — mas #btnHome
	   continua filho direto de #barraInferior, então também participa
	   desta fileira reduzida (só 5 itens, os outros 5 estão em
	   #nav-secondary-wrap, display:none acima). Sem resetar "order" aqui,
	   Home (order:6) apareceria depois de Resetar (order:3) nesta fileira
	   também — reset pra 0 em todos os 5 restaura a ordem do DOM
	   (Iniciar/Reiniciar/Home/Resetar/Mais), a mesma de sempre.
	   Seletor por ID (não só "> a/span/button" genérico): as regras de
	   "order" da fileira cheia (acima) também usam ID encadeado com
	   #barraInferior (ex.: "#barraInferior #btnHome"), 2 ids de
	   especificidade — um reset "> a/span/button" (só 1 id, #barraInferior)
	   perde esse empate e é ignorado. Repetir o mesmo encadeamento de ID
	   aqui iguala a especificidade; a classe .sf3-mobile a mais (regra só
	   existe dentro de "body.sf3-redesign.sf3-mobile", a de cima é só
	   "body.sf3-redesign") desempata a favor deste reset. */
	body.sf3-redesign.sf3-mobile #barraInferior #btnIniciar,
	body.sf3-redesign.sf3-mobile #barraInferior #btnReiniciar,
	body.sf3-redesign.sf3-mobile #barraInferior #btnHome,
	body.sf3-redesign.sf3-mobile #barraInferior #btnResetar,
	body.sf3-redesign.sf3-mobile #barraInferior #btnMais {
		order: 0;
	}
	/* O min-width uniforme da regra genérica de item (calibrado pra caber
	   "Tela cheia", o rótulo mais largo entre os 9-10 itens da barra
	   completa — desktop, tablet, smartphone PAISAGEM) é largo demais pra
	   esses 5 (Iniciar/Reiniciar/Home/Resetar/Mais): força a barra pra
	   2 linhas em larguras de tela comuns (~390px), quando content-sized
	   ela sempre coube numa linha só. Aqui não sobra o mesmo espaço de
	   tela que justificou a uniformização lá — então esse valor menor é
	   uma calibração à parte, pensada só pros 5 rótulos possíveis nesta
	   fileira ("Iniciar" é o mais largo, ~72px no tamanho de fonte mobile
	   padrão): reduz bastante a diferença entre eles sem arriscar quebrar
	   a linha. gap/padding um pouco mais enxutos aqui (6px/10px → 4px/6px,
	   só nesta fileira) abrem a folga que faltava pra caber os 5 numa
	   linha só até smartphones de 360px de largura (testado). */
	body.sf3-redesign.sf3-mobile #barraInferior {
		gap: 4px;
		padding-left: 6px;
		padding-right: 6px;
	}
	body.sf3-redesign.sf3-mobile #barraInferior > a,
	body.sf3-redesign.sf3-mobile #barraInferior > span,
	body.sf3-redesign.sf3-mobile #barraInferior > button {
		min-width: calc(var(--fonte-barra-px) * 2.6 + 15px);
	}
	/* .aberto alternada por alternarMenuMais() (mainApp.js) no clique do
	   #btnMais — painel flutuante ancorado em #barraInferior (position:
	   relative, ver regra base acima), abrindo pra cima (bottom:100%)
	   igual ao overflow menu do mockup CD. */
	body.sf3-redesign.sf3-mobile #nav-secondary-wrap.aberto {
		/* Sem max-height/overflow-y:auto de propósito: Exemplos/Gráfico/
		   Download (dropup) abrem um <ul class="dropdown-menu"> próprio pra
		   cima, position:absolute relativo ao próprio botão — um ancestral
		   com overflow diferente de "visible" recorta esse submenu (mesmo
		   sendo absolute, overflow:hidden/auto do ancestral ainda vale).
		   Com só 5-6 itens o painel não chega a precisar rolar. */
		display: flex;
		flex-direction: column;
		gap: 2px;
		position: absolute;
		bottom: 100%;
		right: 8px;
		margin-bottom: 8px;
		width: max-content;
		min-width: 190px;
		background: #ffffff;
		border: 1px solid var(--sf3-border);
		border-radius: 12px;
		box-shadow: 0 10px 28px rgba(15,23,42,.14);
		padding: 6px;
		z-index: 50;
	}
	/* Dentro do painel aberto, cada item vira uma linha (ícone + rótulo
	   lado a lado) em vez do ícone-em-cima-rótulo-embaixo da barra —
	   ">*" pega os filhos diretos (as/spans/.btn-group), sem afetar o
	   <span data-toggle="dropdown"> um nível mais fundo dentro de
	   .btn-group nem o <ul class="dropdown-menu"> (Bootstrap cuida da
	   posição desses, não mexemos). */
	body.sf3-redesign.sf3-mobile #nav-secondary-wrap.aberto > * {
		flex-direction: row;
		justify-content: flex-start;
		width: 100%;
		flex: none;
		gap: 10px;
		padding: 9px 12px;
		margin: 0;
	}
	/* Reverte o "position:relative" do .btn-group (regra geral, mais acima)
	   só aqui dentro do painel "Mais": esse caso já funcionava do jeito
	   antigo (o dropdown-menu sobe usando o próprio painel .aberto —
	   position:absolute — como containing block, ficando ancorado acima
	   do painel inteiro, não só da linha do Exemplos). */
	body.sf3-redesign.sf3-mobile #nav-secondary-wrap.aberto > .btn-group {
		position: static;
	}
	/* Reverte a centralização "left:50%/transform" (regra geral, mais
	   acima) só aqui: com o .btn-group voltando a position:static logo
	   acima, o containing block do dropdown-menu passa a ser o painel
	   .aberto inteiro (position:absolute), não o botão — "left:50%"
	   centralizaria no painel, não no botão, mudando um comportamento
	   que já funcionava (menu ancorado a partir da borda esquerda do
	   painel, igual sempre foi). */
	/* left:0 (comentário acima) estourava a borda direita da tela: o painel
	   ".aberto" já fica colado nela (right:8px, regra acima), então o menu
	   crescendo a partir da borda ESQUERDA do painel (max-content, ~300px+
	   com itens como "Dinâmica de cinco corpos (caótico)") sempre passava
	   do viewport em smartphone retrato — texto cortado sem como rolar
	   horizontalmente (bug real, reportado pelo usuário). right:0 ancora
	   pela borda direita do painel (perto da borda direita da tela) e
	   cresce pra ESQUERDA, ficando dentro da viewport; max-width com
	   box-sizing:border-box é rede de segurança pra telas muito estreitas. */
	body.sf3-redesign.sf3-mobile #nav-secondary-wrap.aberto .dropdown-menu {
		left: auto;
		right: 0;
		max-width: calc(100vw - 16px);
		box-sizing: border-box;
		transform: none;
	}
	body.sf3-redesign.sf3-mobile #nav-secondary-wrap.aberto > .btn-group > span {
		flex-direction: row;
		justify-content: flex-start;
		gap: 10px;
		padding: 0;
	}
	body.sf3-redesign.sf3-mobile #nav-secondary-wrap.aberto div {
		font-size: calc(var(--fonte-simulador-px) * .78);
	}
	body.sf3-redesign.sf3-mobile #btnMais {
		display: flex !important;
	}
}

@media (orientation: landscape) {
	body.sf3-redesign.sf3-mobile #principal {
		grid-template-columns: minmax(0, 1fr) minmax(200px, var(--sf3-painel-w, 300px));
		grid-template-rows: 1fr;
	}
	/* Só existe em smartphone paisagem (pedido do usuário, 22/08/2026) —
	   é aí que a altura de tela é o recurso escasso; em retrato a barra já
	   é reduzida (5 ícones + "Mais", bloco acima) e sobra mais altura. */
	body.sf3-redesign.sf3-mobile .sf3-barra-toggle {
		display: flex;
	}
	/* Smartphone paisagem: os 10 ícones (nada colapsa pro painel "Mais"
	   aqui, só em retrato) ficavam espremidos no centro da barra
	   (justify-content:center + gap:6px da regra base), sobrando bastante
	   fundo em branco/blur dos dois lados. Padding lateral em % (7.5% de
	   cada lado = 15% no total, ícones ocupando os 85% do meio) empurra o
	   CONTEÚDO pra dentro sem encolher a CAIXA de #barraInferior — usar
	   max-width/margin:auto aqui encolhia a caixa inteira (fundo branco/
	   blur, border-top, box-shadow inclusos), deixando um retângulo
	   flutuante feio no meio da tela em vez do fundo colado nas bordas.
	   space-between espalha os ícones borda a borda dentro da área útil. */
	body.sf3-redesign.sf3-mobile #barraInferior {
		padding-left: 5%;
		padding-right: 5%;
		gap: 4px;
		justify-content: space-between;
	}
	/* Aqui os 9 itens (Iniciar...Salvar, incluindo "Tela cheia") são os
	   mesmos da barra completa (desktop/tablet) — o min-width uniforme
	   já calibrado pra caber "Tela cheia" (regra genérica de item, Etapa
	   "Barra inferior" acima) serviria, mas a folga de ~7px calibrada lá
	   pensa nos 3 perfis (desktop/mobile/tablet) ao mesmo tempo, com peso
	   extra pro desktop (fonte maior). --fonte-barra-px do mobile não muda
	   entre retrato/paisagem (sempre "* 1", regra acima, fora de qualquer
	   media de orientação) — dá pra usar uma folga bem mais justa (~3px)
	   calibrada só pra esse valor fixo, e isso é o que sobra de espaço
	   pra caber os 9 itens numa linha só em telas como a do iPhone
	   12/13/14 em paisagem (844px), sem o excesso do padding/gap padrão
	   (reduzidos acima, mesma ideia do ajuste em retrato mais abaixo). */
	body.sf3-redesign.sf3-mobile #barraInferior > a,
	body.sf3-redesign.sf3-mobile #barraInferior > span,
	body.sf3-redesign.sf3-mobile #barraInferior > button,
	body.sf3-redesign.sf3-mobile #barraInferior > .btn-group,
	body.sf3-redesign.sf3-mobile #nav-secondary-wrap > a,
	body.sf3-redesign.sf3-mobile #nav-secondary-wrap > span,
	body.sf3-redesign.sf3-mobile #nav-secondary-wrap > button,
	body.sf3-redesign.sf3-mobile #nav-secondary-wrap > .btn-group {
		/* "> .btn-group" sozinho (Exemplos/Download) não bastava — igual à
		   regra genérica lá em cima (ver comentário nos seletores duplicados,
		   Etapa "Barra inferior"), #nav-secondary-wrap continua sendo o pai
		   real no DOM (display:contents só afeta o layout, não a árvore),
		   então "Tela cheia"/Info/Salvar (soltos, sem .btn-group) só batem
		   pelo "#nav-secondary-wrap > span". Sem isso ficavam de fora desta
		   regra e voltavam a usar o min-width da regra genérica (calibrado
		   pro desktop, mais largo — foi o que causou o wrap pra 2 linhas
		   detectado ao testar 844px de largura). */
		min-width: calc(var(--fonte-barra-px) * 4.05 + 10px);
	}
	/* Abaixo de 830px de largura a folga acima (calibrada só pro iPhone
	   12/13/14, 844px, o caso mais estreito testado até então) já não
	   sobra o suficiente — em smartphones menores/médios em paisagem
	   (iPhone SE, muitos Android compactos) os 9-10 ícones quebravam pra
	   2 linhas (pedido do usuário, 09/08/2026). Mesma ideia do aperto já
	   usado em tablet retrato (768px, Etapa 4 abaixo): reduz padding/gap/
	   min-width só nessa faixa mais estreita, sem mudar nada acima de
	   830px (onde a folga original já dá conta). Calibrado pro pior caso
	   (10 itens, ex. lancamento-projeteis2/gravitacao2) até ~570px de
	   largura (iPhone SE 1ª geração em paisagem). */
	@media (max-width: 829px) {
		body.sf3-redesign.sf3-mobile #barraInferior {
			padding-left: 2%;
			padding-right: 2%;
			gap: 2px;
		}
		body.sf3-redesign.sf3-mobile #barraInferior > a,
		body.sf3-redesign.sf3-mobile #barraInferior > span,
		body.sf3-redesign.sf3-mobile #barraInferior > button,
		body.sf3-redesign.sf3-mobile #barraInferior > .btn-group,
		body.sf3-redesign.sf3-mobile #nav-secondary-wrap > a,
		body.sf3-redesign.sf3-mobile #nav-secondary-wrap > span,
		body.sf3-redesign.sf3-mobile #nav-secondary-wrap > button,
		body.sf3-redesign.sf3-mobile #nav-secondary-wrap > .btn-group {
			min-width: calc(var(--fonte-barra-px) * 2.7 + 6px);
		}
		/* Só reduzir a folga (min-width acima) não bastava: rótulos mais
		   compridos ("Download", "Tela cheia", "Exemplos") já ocupam mais
		   que esse mínimo pelo próprio texto (min-width é só um PISO, não
		   força o item a ficar menor que o conteúdo) — o padding lateral de
		   cada item (10px de cada lado, regra genérica de item) que ainda
		   sobrava gordura pra cortar. Reduzido só nesta faixa estreita. */
		body.sf3-redesign.sf3-mobile #barraInferior > a,
		body.sf3-redesign.sf3-mobile #barraInferior > span,
		body.sf3-redesign.sf3-mobile #barraInferior > button,
		body.sf3-redesign.sf3-mobile #barraInferior > .btn-group,
		body.sf3-redesign.sf3-mobile #nav-secondary-wrap > a,
		body.sf3-redesign.sf3-mobile #nav-secondary-wrap > span,
		body.sf3-redesign.sf3-mobile #nav-secondary-wrap > button,
		body.sf3-redesign.sf3-mobile #nav-secondary-wrap > .btn-group {
			padding-left: 5px;
			padding-right: 5px;
		}
		/* Exemplos/Download (dropup, .btn-group): o padding reduzido acima é
		   do CONTAINER .btn-group — o <span> de gatilho por dentro dele tem
		   o próprio padding (regra genérica "> .btn-group > span", Etapa
		   "Barra inferior" acima), por isso continuavam mais largos que os
		   itens simples mesmo depois do ajuste acima. */
		body.sf3-redesign.sf3-mobile #barraInferior > .btn-group > span,
		body.sf3-redesign.sf3-mobile #nav-secondary-wrap > .btn-group > span {
			padding-left: 5px;
			padding-right: 5px;
		}
	}
}

/* ==================================================================
   Etapa 4 — tablet Android + iPad, tratados como um único perfil
   "sf3-tablet" (10-11"). Os dois branches originais de adequarDispositivo()
   eram quase idênticos; onde divergiam, o JS já prioriza os valores do
   iPad (ver comentário lá). Aqui o grid é essencialmente o mesmo padrão
   do desktop (Etapa 2) — canvas 1fr, sidebar de largura travada em
   paisagem; 55vh/resto em retrato, igual à proporção usada no iPad.
   ================================================================== */
body.sf3-redesign.sf3-tablet #principal {
	gap: 0px;
}

body.sf3-redesign.sf3-tablet #canvas,
body.sf3-redesign.sf3-tablet #parametros {
	min-width: 0;
	min-height: 0;
}

body.sf3-redesign.sf3-tablet canvas {
	width: 100% !important;
	height: 100% !important;
}

body.sf3-redesign.sf3-tablet #parametros {
	width: auto !important;
	height: auto !important;
	max-width: none !important;
	max-height: none !important;
}

/* Breadcrumb no tablet: texto ficava visualmente puxado pro topo da faixa
   (entre o topo da tela e o início do canvas), pedido do usuário pra
   descer um pouco — padding-top maior que o padding-bottom (regra
   genérica em #breadcrumbSimulador é 10px/10px) empurra o texto pra
   baixo dentro da mesma faixa, só neste perfil. */
body.sf3-redesign.sf3-tablet #breadcrumbSimulador {
	padding-top: 18px;
	padding-bottom: 10px;
}

/* Mesma ideia do ajuste em sf3-mobile paisagem (Etapa "Barra inferior"
   acima): o min-width uniforme da regra genérica (calibrado pra caber
   "Tela cheia" nos 3 perfis ao mesmo tempo, com folga maior por causa do
   desktop) é largo demais pro tablet em retrato — 768px de largura
   (iPad mini/iPad "normal" retrato) não sobra espaço pros 9 itens numa
   linha só com essa folga. --fonte-barra-px do tablet é sempre o valor
   base (* 0.85, não redeclarado em nenhum lugar pro tablet), igual em
   retrato/paisagem — dá pra usar a mesma folga justa calibrada só pra
   esse valor fixo, igual foi feito pro mobile.
   Regra fora de qualquer @media de orientação: vale pros dois casos
   (retrato E paisagem), já que --fonte-barra-px não muda entre eles.
   ⚠️ 22px→16px (04/08/2026): mesmo motivo do ajuste equivalente na regra
   genérica ("Etapa 3" acima) — os 10 itens de `lancamento-projeteis2`
   (contra 9 do pêndulo) quebravam pra 2 linhas em 768px de largura
   (retrato). Reduzida a folga (ainda positiva, ~2-3px sobre o rótulo
   mais largo) pra caber os 10 numa linha só. */
body.sf3-redesign.sf3-tablet #barraInferior > a,
body.sf3-redesign.sf3-tablet #barraInferior > span,
body.sf3-redesign.sf3-tablet #barraInferior > button,
body.sf3-redesign.sf3-tablet #barraInferior > .btn-group,
body.sf3-redesign.sf3-tablet #nav-secondary-wrap > a,
body.sf3-redesign.sf3-tablet #nav-secondary-wrap > span,
body.sf3-redesign.sf3-tablet #nav-secondary-wrap > button,
body.sf3-redesign.sf3-tablet #nav-secondary-wrap > .btn-group {
	min-width: calc(var(--fonte-barra-px) * 3.4 + 16px);
}

/* Ajuste equivalente ao de sf3-mobile (Etapa "Barra inferior" acima) —
   mesmo problema (barra/linha de gesto do sistema colada nos ícones),
   mas SÓ com env(safe-area-inset-bottom) (como no mobile) não fez
   diferença visível nem no iPad físico nem no emulado (testado pelo
   usuário 04/08/2026): o navegador simplesmente não reporta um valor
   >0 pra essa propriedade nesses tablets/contexto testado (só volta a
   valer alguma coisa em PWA instalado em tela cheia, por exemplo — não
   é o caso aqui), então a conta caía de volta nos mesmos 6px de sempre,
   sem mudança nenhuma.
   max(15px, env(...)) força um respiro mínimo de 15px sempre, MESMO
   quando o navegador não reporta env() nenhum (garante o efeito em
   qualquer tablet, independente de suporte) — e ainda respeita um
   valor de env() maior que 15px se algum dia existir (PWA instalado,
   outro navegador). Importante: é PADDING, não margin — pedido inicial
   do usuário era "#barraInferior.style.marginBottom", mas margin
   empurraria a CAIXA inteira (fundo branco/blur, border-top, box-
   shadow — tudo isso, ver regra genérica de #barraInferior) pra cima,
   expondo um vão embaixo dela com o fundo de #main/body (não o mesmo
   visual da barra) até a borda física da tela — exatamente o "fundo
   errado" que o usuário já esperava e pediu pra não esquecer. padding
   fica DENTRO da caixa: o fundo/blur da barra continua cobrindo até a
   borda física, só o CONTEÚDO (ícones/rótulos) sobe dentro dele. */
body.sf3-redesign.sf3-tablet #barraInferior {
	padding-bottom: calc(6px + max(10px, env(safe-area-inset-bottom, 0px)));
}

@media (orientation: portrait) {
	body.sf3-redesign.sf3-tablet #principal {
		grid-template-columns: 1fr;
		/* dvh depois do vh (fallback) — ver comentário no #main sobre a
		   barra de ferramentas do Safari mobile (vale pro iPad também).
		   --sf3-painel-h — ver comentário equivalente em sf3-desktop
		   retrato acima. */
		grid-template-rows: minmax(120px, var(--sf3-painel-h, 55vh)) minmax(0, 1fr);
		grid-template-rows: minmax(120px, var(--sf3-painel-h, 55dvh)) minmax(0, 1fr);
		/* gap:0 — ver comentário equivalente em sf3-desktop retrato acima
		   (o gap do grid fica fora da área que #parametros rola sozinho,
		   então continuava visível mesmo depois de rolar). */
		gap: 0;
	}
	body.sf3-redesign.sf3-tablet #parametros {
		padding-top: 16px;
	}
	/* Mesmo ajuste do smartphone paisagem (comentário lá, incluindo o
	   motivo de usar padding em vez de max-width/margin:auto) — tablet
	   retrato também mostra os 10 ícones sem colapsar, e sobrava espaço
	   nas duas bordas da barra. padding 7.5%→5%→3% e gap 6px→4px (mesma
	   lógica do ajuste em sf3-mobile paisagem, acima): com o min-width
	   uniforme (regra logo acima, fora deste @media), 768px de largura
	   (retrato) não sobra com a folga antiga — sem esse aperto os itens
	   quebravam pra 2 linhas num iPad mini/iPad "normal" em pé.
	   ⚠️ 5%→3% (04/08/2026): novo aperto por causa do 10º item de
	   `lancamento-projeteis2` — ver comentário equivalente no min-width,
	   logo acima. */
	body.sf3-redesign.sf3-tablet #barraInferior {
		padding-left: 3%;
		padding-right: 3%;
		gap: 4px;
		justify-content: space-between;
	}
	/* Ícones maiores em tablet retrato — pedido do usuário (31/08/2026):
	   com justify-content:space-between (regra acima) e min-width fixo por
	   item, o espaço sobrando nesta orientação virava só GAP extra entre os
	   ícones, nunca ícone maior — --fonte-barra-px do tablet nunca mudava
	   entre retrato/paisagem (comentário na regra de min-width, acima).
	   0.85→1.05 só neste escopo (~24% maior). Tetos do clamp() do ícone/
	   rótulo (22px/13px, regra genérica "Etapa Barra inferior" lá em cima)
	   também sobem, senão o valor maior batia no teto antes de crescer de
	   verdade (mesmo aviso do comentário original do sf3-desktop).
	   Pior caso (10 itens, `lancamento-projeteis`) testado em 768px de
	   largura (iPad mini/iPad "normal" retrato, a mais estreita): nesse
	   multiplicador o conteúdo não cabe mais numa linha só só de primeira,
	   mas ajustarEscalaBarraInferior() (mainApp.js) já encolhe
	   --barra-escala automaticamente até caber — sem quebrar linha, só sem
	   o boost completo pros simuladores com muitos itens. Simuladores com
	   menos itens (maioria) ganham o boost inteiro. */
	body.sf3-redesign.sf3-tablet #barraInferior {
		--fonte-barra-px: calc(var(--fonte-simulador-px) * 1.05 * var(--barra-escala, 1));
	}
	body.sf3-redesign.sf3-tablet #barraInferior i {
		font-size: clamp(15px, calc(var(--fonte-barra-px) * 1.35), 28px);
	}
	body.sf3-redesign.sf3-tablet #barraInferior div {
		font-size: clamp(9px, calc(var(--fonte-barra-px) * .68), 15px);
	}
}

@media (orientation: landscape) {
	body.sf3-redesign.sf3-tablet #principal {
		grid-template-columns: minmax(0, 1fr) minmax(300px, var(--sf3-painel-w, 420px));
		grid-template-rows: 1fr;
	}
	body.sf3-redesign.sf3-tablet #parametros {
		grid-template-columns: auto;
	}
	/* Tablet paisagem: tela mais larga que o retrato, 85% ficaria espaçado
	   demais entre ícones — 75% é o valor pedido pra este caso (padding
	   12.5% de cada lado = 25% no total). Padding em vez de max-width/
	   margin:auto pelo mesmo motivo comentado no smartphone paisagem
	   acima (não encolher o fundo/blur/box-shadow da caixa). */
	body.sf3-redesign.sf3-tablet #barraInferior {
		padding-left: 12.5%;
		padding-right: 12.5%;
		justify-content: space-between;
	}
}

/* ==================================================================
   RTL (ar, ur): #canvas fica sempre à esquerda e #parametros à direita,
   igual ao PT — a posição física dos dois não deve inverter com o idioma.
   Motivo: #canvas desenha conteúdo com significado espacial de verdade
   (régua, corpo caindo, eixos de gráfico) que não é texto e não deve
   espelhar.
   Causa raiz: #principal é display:grid (canvas = 1ª trilha, #parametros
   = 2ª — ver regras de #principal acima, por dispositivo/orientação)
   sem nenhum `direction` fixado; grid, por padrão, posiciona as trilhas
   seguindo o `dir` do documento, então com dir='rtl' a 1ª trilha
   (canvas) passa a renderizar à direita. `direction: ltr` aqui neutraliza
   isso só no posicionamento do GRID (funciona mesmo quando algum
   simulador redefine grid-template-columns via JS/inline style — só
   redefine as colunas, não a direção).
   `direction: rtl` de volta SÓ em #parametros (não em #canvas) — achado
   do usuário em queda-livre (31/08/2026): o overlay solto dentro de
   #canvas (ex. o card "Modo/Tempo/Velocidade/Eletroímã/Reiniciar") não
   foi desenhado pensando em RTL (posicionamento livre, sem padrão
   consistente entre simuladores) e forçar direction:rtl nele bagunçava
   texto/ícones sobrepostos. Decisão do usuário: deixar #canvas inteiro
   em LTR sempre (herda do #principal, sem override aqui), mesmo que o
   texto dentro dele fique "fora do padrão" do idioma — mexer nesse
   overlay caso a caso, simulador por simulador, não vale o risco. */
html[dir="rtl"] body.sf3-redesign #principal {
	direction: ltr;
}
html[dir="rtl"] body.sf3-redesign #principal > #parametros {
	direction: rtl;
}

/* Dropdowns Bootstrap (Exemplos, Download, "Mais" etc. — <ul class="dropdown-menu">
   com <li><span>texto</span></li>) herdam `text-align: left` fixo do bootstrap.min.css
   (Bootstrap 3 não tem build RTL aqui, e a regra usa a propriedade física, não
   `text-align: start`) — texto árabe/urdu saía alinhado à esquerda dentro de uma
   lista que já abre com `direction` herdado rtl do documento, lendo errado. Escopo
   amplo (não só #barraInferior): mesmo componente é reusado em outros dropdowns da
   página (ex. #navSalvar). */
html[dir="rtl"] .dropdown-menu {
	text-align: right;
}

/* Sliders (#parametros/.sf3-badge-flutuante input[type=range] — mesmo seletor do
   initSliderFill em redesign.js) representam uma grandeza numérica contínua (altura,
   velocidade, massa...), igual à régua desenhada em #canvas — não são texto, então
   ficam de fora do espelhamento RTL pelo mesmo motivo do #principal acima. Sem isso,
   o navegador (comportamento nativo de <input type="range"> sob dir='rtl') desenha o
   min à direita/max à esquerda, mas o preenchimento azul (--fill, calculado em
   redesign.js como "% da distância até o min", 0%=esquerda) continua assumindo
   min-esquerda/max-direita — a barra passa a andar pro lado oposto da bolinha ao
   arrastar. direction:ltr aqui prende o slider no min-esquerda/max-direita de sempre,
   sem precisar mexer no cálculo de --fill. */
html[dir="rtl"] #parametros input[type="range"],
html[dir="rtl"] .sf3-badge-flutuante input[type="range"] {
	direction: ltr;
}

/* ==================================================================
   Etapa 7 (SimuFísica 3.0 / pendulo-duplo2): modal "Abrir/Salvar/
   Deletar" (banco de dados). Réplica em CSS/HTML real do mockup CD
   "SimuFisica Simulador Pendulo Duplo Redesign.dc.html" (atualizado
   03/08/2026 pelo usuário especificamente pra esse modal — ver seção
   16 do redesign-3.0.md). A lógica (listaSimulacoes.js, assets/js/
   bancoDados.js) continua compartilhada com os outros ~48
   simuladores, então nada aqui toca HTML gerado por JS além de
   reaproveitar as mesmas classes (.list-group-item, .btn-primary/
   -secondary/-info/-danger, .badge-info) que esse JS já usa. Também
   cobre o popup de QR Code (#qrcode-container) e o diálogo de
   confirmação de exclusão (#customConfirm), que ficam fora do modal
   no DOM (anexados a document.body) mas fazem parte do mesmo fluxo. */

body.sf3-redesign #btnAbrirSalvar .modal-dialog {
	width: calc(100% - 20px);
	max-width: 640px;
}

body.sf3-redesign #btnAbrirSalvar .modal-content {
	border-radius: 16px;
	border: none;
	box-shadow: 0 24px 60px rgba(15, 23, 42, 0.28);
	max-height: 90vh;
	display: flex;
	flex-direction: column;
	overflow: hidden;
}

/* Fundo do modal com leve desfoque (mockup: rgba(15,23,42,.5) +
   backdrop-filter blur(2px)) — Bootstrap 3 anexa .modal-backdrop como
   filho direto do <body>, então dá pra estilizar por descendência. */
body.sf3-redesign .modal-backdrop.in {
	background-color: #0f172a;
	opacity: 0.5;
}
@supports (backdrop-filter: blur(1px)) {
	body.sf3-redesign .modal-backdrop.in {
		backdrop-filter: blur(2px);
	}
}

body.sf3-redesign #btnAbrirSalvar .modal-header {
	border-bottom: 1px solid var(--sf3-border);
	padding: 18px 24px;
	flex-shrink: 0;
}

body.sf3-redesign #btnAbrirSalvar .modal-title {
	font-family: 'Inter', sans-serif;
	font-size: var(--fonte-simulador-px);
	font-weight: 500;
	color: var(--sf3-text);
}

body.sf3-redesign #btnAbrirSalvar .modal-header .close {
	color: #94a3b8;
	opacity: 1;
	text-shadow: none;
	transition: color 0.15s;
}
body.sf3-redesign #btnAbrirSalvar .modal-header .close:hover {
	color: var(--sf3-accent);
}

body.sf3-redesign #btnAbrirSalvar .modal-body {
	padding: 20px 24px;
	font-size: 14px;
	color: var(--sf3-text);
	flex: 1;
	min-height: 0;
	display: flex;
	flex-direction: column;
	overflow: hidden;
}
/* Linhas de tamanho fixo dentro do modal-body — só #listaSimulacoes
   deve ceder espaço (ver regra logo abaixo) quando o modal atingir o
   teto de 90vh do .modal-content. */
body.sf3-redesign #btnAbrirSalvar .modal-body > .alert,
body.sf3-redesign #btnAbrirSalvar .sf3-db-topo,
body.sf3-redesign #btnAbrirSalvar #gridSalvar,
body.sf3-redesign #btnAbrirSalvar #ordemSimulacoes {
	flex-shrink: 0;
}

body.sf3-redesign #btnAbrirSalvar .modal-footer {
	border-top: 1px solid var(--sf3-border);
	padding: 14px 24px;
	flex-shrink: 0;
}

/* Cabeçalho "Olá, Nome! / Logout" — classe própria (sf3-db-topo) no
   lugar do style inline antigo porque boasVindas.js faz
   `elemento.style = ""` quando não há sessão (pra depois trocar o
   innerHTML por "Olá, visitante!"); com o layout preso a uma classe
   em vez de inline, ele sobrevive a esse reset. */
body.sf3-redesign #btnAbrirSalvar .sf3-db-topo {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 18px;
	font-size: var(--fonte-simulador-px);
	font-family: 'Inter', sans-serif;
	color: #334155;
}
body.sf3-redesign #btnAbrirSalvar .sf3-db-topo a {
	color: var(--sf3-accent);
	font-weight: 400;
	text-decoration: none;
}
body.sf3-redesign #btnAbrirSalvar .sf3-db-topo a:hover {
	text-decoration: underline;
}
/* Deslogado: boasVindas.js troca o innerHTML de .sf3-db-topo por um
   convite de login mais longo ("Olá, visitante!" + frase de
   login/cadastro) — ao lado, na mesma linha (space-between), fica
   apertado/feio. Mesmo sinal de #gridSalvar ausente usado na seção
   16.6 pra identificar o estado deslogado sem tocar no JS
   compartilhado; aqui só empilha os dois <div> em coluna. */
body.sf3-redesign #btnAbrirSalvar .modal-body:not(:has(#gridSalvar)) .sf3-db-topo {
	flex-direction: column;
	align-items: flex-start;
	gap: 4px;
}

/* Linha "Salvar como ..." + botão salvar/renomear */
body.sf3-redesign #btnAbrirSalvar #gridSalvar {
	align-items: center;
}
body.sf3-redesign #btnAbrirSalvar #inputSalvarSim {
	width: 100%;
	box-sizing: border-box;
	padding: 11px 14px;
	border: 1px solid var(--sf3-border);
	border-radius: 10px;
	font-family: 'inter', sans-serif;
	font-weight: 400;
	font-size: var(--fonte-simulador-px);
	color: var(--sf3-text);
	background: #fff;
	transition: border-color 0.15s, box-shadow 0.15s;
}
body.sf3-redesign #btnAbrirSalvar #inputSalvarSim:focus {
	outline: none;
	border-color: var(--sf3-accent);
	box-shadow: 0 0 0 3px rgba(43, 120, 197, 0.15);
}

/* Botão quadrado só com ícone (Salvar/Cancelar) */
body.sf3-redesign #btnAbrirSalvar .sf3-btn-icon {
	width: 46px;
	height: 46px;
	padding: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
}
body.sf3-redesign #btnAbrirSalvar .sf3-btn-icon i {
	font-size: 17px;
}
/* Botão de texto (Renomear) na mesma altura dos quadrados de ícone */
body.sf3-redesign #btnAbrirSalvar .sf3-btn-pill {
	height: 46px;
	padding: 0 16px;
	display: inline-flex;
	align-items: center;
}

/* Base comum a todos os botões do modal — cada grupo abaixo (nível
   superior vs. ação de item da lista) ganha padding/raio próprio. */
body.sf3-redesign #btnAbrirSalvar .btn,
body.sf3-redesign #qrcode-container .btn {
	font-weight: 500;
	box-shadow: none;
	border: none;
	transition: background-color 0.15s, border-color 0.15s;
}
body.sf3-redesign #btnAbrirSalvar .sf3-btn-icon,
body.sf3-redesign #btnAbrirSalvar .sf3-btn-pill,
body.sf3-redesign #btnAbrirSalvar .modal-footer .btn,
body.sf3-redesign #qrcode-container .btn {
	font-family: 'inter', sans-serif;
	font-size: calc(var(--fonte-simulador-px) * 0.95);
	border-radius: 10px;
}
/* Botões de ação de cada item da lista (Editar/Link/QR Code/Deletar) —
   o JS injeta as mesmas classes Bootstrap em 3 lugares diferentes
   (bancoDados.js, listaSimulacoes.js, ordenarSimulacoes.php — ver
   docs/banco-dados.md §12); estilizar por classe aqui cobre os três. */
body.sf3-redesign #btnAbrirSalvar .list-group-item .btn {
	border-radius: 8px;
	font-family: 'inter', sans-serif;
	font-size: calc(var(--fonte-simulador-px) * 0.85);
	padding: 8px 13px;
	display: inline-flex;
	align-items: center;
	gap: 6px;
}

/* Editar (item da lista) + Salvar/Renomear (topo) — accent sólido */
body.sf3-redesign #btnAbrirSalvar .btn-primary,
body.sf3-redesign #qrcode-container .btn-primary {
	background: var(--sf3-accent);
	color: #ffffff;
	width: 100%;
}
body.sf3-redesign #btnAbrirSalvar .btn-primary:hover,
body.sf3-redesign #btnAbrirSalvar .btn-primary:focus,
body.sf3-redesign #qrcode-container .btn-primary:hover,
body.sf3-redesign #qrcode-container .btn-primary:focus {
	background: #2166ac;
}

/* Link (item da lista) e Fechar (rodapé do popup de QR) — chip cinza */
body.sf3-redesign #btnAbrirSalvar .btn-secondary:not(.sf3-btn-icon),
body.sf3-redesign #btnAbrirSalvar .btn-default,
body.sf3-redesign #qrcode-container .btn-secondary {
	font-family: 'inter', sans-serif;
	/* font-size: var(--fonte-simulador-px * 1); */
	background: #f1f5f9;
	color: #334155;
}
body.sf3-redesign #btnAbrirSalvar .btn-secondary:not(.sf3-btn-icon):hover,
body.sf3-redesign #btnAbrirSalvar .btn-default:hover,
body.sf3-redesign #qrcode-container .btn-secondary:hover {
	background: #e2e8f0;
}

/* Cancelar (topo, ao lado de Renomear) — quadrado com borda, sem preencher */
body.sf3-redesign #btnAbrirSalvar .btn-secondary.sf3-btn-icon {
	background: #ffffff;
	border: 1px solid var(--sf3-border);
	color: #475569;
}
body.sf3-redesign #btnAbrirSalvar .btn-secondary.sf3-btn-icon:hover {
	background: #f1f5f9;
}

/* QR Code (item da lista) — chip teal */
body.sf3-redesign #btnAbrirSalvar .btn-info {
	background: #e6f7f5;
	color: #0d9488;
}
body.sf3-redesign #btnAbrirSalvar .btn-info:hover {
	background: #ccf1ec;
}

/* Deletar (item da lista) — chip vermelho */
body.sf3-redesign #btnAbrirSalvar .btn-danger {

	background: #fef2f2;
	color: #dc2626;
}
body.sf3-redesign #btnAbrirSalvar .btn-danger:hover {
	background: #fee2e2;
}

/* "Ordenar por" — vira par de pílulas neutras */
body.sf3-redesign #btnAbrirSalvar #ordemSimulacoes {
	align-items: center;
	gap: 10px;
}
body.sf3-redesign #btnAbrirSalvar #ordemSimulacoes > div:first-child {
	color: #334155;
	font-family: 'Inter', sans-serif;
	font-size: calc(var(--fonte-simulador-px) * 1.0);
}
body.sf3-redesign #btnAbrirSalvar #ordemSimulacoes button {
	border: 1px solid var(--sf3-border);
	background: #fff;
	color: #334155;
	border-radius: 999px;
	font-family: 'Inter', sans-serif;
	font-size: calc(var(--fonte-simulador-px) * 0.8);
	font-weight: 500;
	padding: 7px 14px;
}

/* Cards da lista de simulações salvas — substitui o cinza legado
   (.list-group-item já vem de assets/css/mainApp2.css com borda
   #999999/hover cinza; sobrescrevemos aqui, escopado). */
body.sf3-redesign #btnAbrirSalvar .list-group-item {
	border: 1px solid var(--sf3-border);
	border-radius: 12px;
	background: #fff;
	transition: box-shadow 0.12s, border-color 0.12s;
}
body.sf3-redesign #btnAbrirSalvar .list-group-item:hover {
	background: #fff;
	border-color: #cfe3f6;
	box-shadow: 0 4px 14px rgba(15, 23, 42, 0.06);
}
body.sf3-redesign #btnAbrirSalvar .list-group-item a {
	display: block;
	padding: 14px 16px;
	color: var(--sf3-text);
}
body.sf3-redesign #btnAbrirSalvar .list-group-item h4.mb-1 {
	font-family: 'Inter', sans-serif;
	font-size: calc(var(--fonte-simulador-px) * 0.95);
	font-weight: 500;
	margin: 0 0 10px;
	color: var(--sf3-text);
	display: flex;
	align-items: center;
	gap: 8px;
	flex-wrap: wrap;
}

/* Lista de simulações salvas com rolagem própria — "Salvar como ...",
   "Ordenar por" e o rodapé ficam sempre visíveis; só a lista rola,
   independente de quantas simulações o usuário tiver salvo. flex:1
   (em vez de um max-height fixo) faz a lista preencher o espaço que
   sobrar até o teto de 90vh do .modal-content — cresce com poucos
   itens, rola sozinha quando não cabe mais. */
body.sf3-redesign #btnAbrirSalvar #listaSimulacoes {
	flex: 1;
	min-height: 100px;
	overflow-y: auto;
	overflow-x: hidden;
	padding-right: 6px;
	margin-right: -6px;
	scrollbar-width: thin;
	scrollbar-color: #cbd5e1 transparent;
}
body.sf3-redesign #btnAbrirSalvar #listaSimulacoes::-webkit-scrollbar {
	width: 6px;
}
body.sf3-redesign #btnAbrirSalvar #listaSimulacoes::-webkit-scrollbar-track {
	background: transparent;
}
body.sf3-redesign #btnAbrirSalvar #listaSimulacoes::-webkit-scrollbar-thumb {
	background: #cbd5e1;
	border-radius: 999px;
}
body.sf3-redesign #btnAbrirSalvar #listaSimulacoes::-webkit-scrollbar-thumb:hover {
	background: #94a3b8;
}

/* Mensagem de lista vazia — texto vem de tComum('nenhumaSimulacaoSalva')
   (assets/js/sf3/i18nComum.js), inserido pelo próprio listaSimulacoes.js
   quando a lista fica sem itens; aqui só o estilo do estado vazio. */
body.sf3-redesign #btnAbrirSalvar .sf3-lista-vazia {
	display: block;
	text-align: center;
	padding: 28px 12px;
	color: #94a3b8;
	font-size: 13px;
}

/* Selo "Problema" — mesmo tratamento de badge/tint do design system
   (seção 14.3: tint pill = fundo #eaf3fb + texto --sf3-accent). Não
   representado no mockup (dados fake não incluem nenhum problema
   salvo), mantido como já estava — não contradiz o mockup, só não
   aparece nele. */
body.sf3-redesign #btnAbrirSalvar .badge-info {
	background: #eaf3fb;
	color: var(--sf3-accent);
	border-radius: 999px;
	font-weight: 600;
	font-size: 11px;
	padding: 3px 10px;
	display: inline-flex;
	align-items: center;
	gap: 4px;
}

/* Diálogo de confirmação de exclusão (#customConfirm/.confirm-box,
   estilo base em assets/css/mainApp2.css) — mesmo card/paleta do
   mockup; "Sim" confirma uma exclusão, então é vermelho (mockup:
   #dc2626/hover #b91c1c) em vez do verde herdado do Bootstrap, que
   invertia a semântica usual de destrutivo = vermelho. */
body.sf3-redesign #customConfirm .confirm-box {
	border-radius: 16px;
	border: none;
	box-shadow: 0 24px 60px rgba(15, 23, 42, 0.28);
	font-family: 'Inter', sans-serif;
	font-weight: 400;
	padding: 24px;
}
body.sf3-redesign #customConfirm .confirm-box p {
	color: #334155;
	font-size: calc(var(--fonte-simulador-px) * 0.95);
}
body.sf3-redesign #customConfirm .confirm-box button {
	border-radius: 10px;
	font-size: calc(var(--fonte-simulador-px) * 0.9);
	padding: 10px 22px;
}
body.sf3-redesign #confirmYes {
	background: #dc2626 !important;
}
body.sf3-redesign #confirmYes:hover {
	background: #b91c1c !important;
}
body.sf3-redesign #confirmNo {
	background: #fff !important;
	border: 1px solid var(--sf3-border) !important;
	color: #334155 !important;
}
body.sf3-redesign #confirmNo:hover {
	background: #f1f5f9 !important;
}

/* Popup de QR Code (criado dinamicamente por listaSimulacoes.js,
   estilo inline no JS) — só arredonda mais e suaviza a borda/sombra
   pra combinar com os cards; cores dos botões já cobertas acima. */
body.sf3-redesign #qrcode-container {
	border-radius: 16px !important;
	border: none !important;
	box-shadow: 0 24px 60px rgba(15, 23, 42, 0.28) !important;
}

/* ===== Modal Info (#btnInfo) — mesmo padrão do #btnAbrirSalvar acima,
   seguindo "SimuFisica Simulador Pendulo Duplo Redesign.dc.html" (pasta
   SimuFísica 3.0 Home Redesign-4). Um único modal de Informações, conteúdo
   estático organizado em .sf3-info-section/-label/-text(-refs) — mesma
   estrutura usada por todos os simuladores migrados até agora (pendulo-
   duplo2 e lancamento-projeteis2; este último tinha um 2º modal "Detalhes
   adicionais" + PPT/texto1/texto2 preenchidos por um mecanismo externo,
   removido — ver redesign-3.0.md §19). Não reintroduzir "#btnInfo2"/
   "#texto1"/"#texto2"/".sf3-info-ppt" sem checar se algum simulador migrado
   voltou a precisar. */
body.sf3-redesign #btnInfo .modal-dialog {
	width: calc(100% - 20px);
	max-width: 480px;
}

body.sf3-redesign #btnInfo .modal-content {
	border-radius: 16px;
	border: none;
	box-shadow: 0 24px 60px rgba(15, 23, 42, 0.28);
	max-height: 88vh;
	display: flex;
	flex-direction: column;
	overflow: hidden;
}

body.sf3-redesign #btnInfo .modal-header {
	border-bottom: 1px solid var(--sf3-border);
	padding: 18px 24px;
	flex-shrink: 0;
}

body.sf3-redesign #btnInfo .modal-title {
	font-family: 'Inter', sans-serif;
	font-size: var(--fonte-simulador-px);
	font-weight: 500;
	color: var(--sf3-text);
}

body.sf3-redesign #btnInfo .modal-header .close {
	color: #94a3b8;
	opacity: 1;
	text-shadow: none;
	transition: color 0.15s;
}
body.sf3-redesign #btnInfo .modal-header .close:hover {
	color: var(--sf3-accent);
}

body.sf3-redesign #btnInfo .modal-body {
	padding: 20px 24px;
	flex: 1;
	min-height: 0;
	overflow-y: auto;
	display: flex;
	flex-direction: column;
	gap: 16px;
}

body.sf3-redesign #btnInfo .sf3-info-label {
	font-size: calc(var(--fonte-simulador-px) * 0.85);
	font-weight: 600;
	color: #4a515a;
	text-transform: uppercase;
	letter-spacing: .04em;
	margin-bottom: 4px;
	font-family: 'Inter', sans-serif;
}
body.sf3-redesign #btnInfo .sf3-info-text {
	font-size: calc(var(--fonte-simulador-px) * 0.93);
	color: #334155;
	line-height: 1.5;
	font-family: 'Inter', sans-serif;
}
body.sf3-redesign #btnInfo .sf3-info-refs {
	counter-reset: sf3-ref;
}
body.sf3-redesign #btnInfo .sf3-info-refs > div {
	counter-increment: sf3-ref;
	position: relative;
	padding-left: 1.4em;
	margin-bottom: 10px;
}
body.sf3-redesign #btnInfo .sf3-info-refs > div:last-child {
	margin-bottom: 0;
}
body.sf3-redesign #btnInfo .sf3-info-refs > div::before {
	content: counter(sf3-ref) ".";
	position: absolute;
	left: 0;
	font-weight: 600;
	color: #64748b;
}
body.sf3-redesign #btnInfo .sf3-info-refs a {
	color: var(--sf3-accent);
	text-decoration: none;
}
body.sf3-redesign #btnInfo .sf3-info-refs a:hover {
	text-decoration: underline;
}

body.sf3-redesign #btnInfo .modal-footer {
	border-top: 1px solid var(--sf3-border);
	padding: 14px 24px;
	flex-shrink: 0;
}
body.sf3-redesign #btnInfo .modal-footer .grid-container {
	display: flex;
	justify-content: space-between;
	align-items: center;
	gap: 16px;
	width: 100%;
}
body.sf3-redesign #btnInfo .modal-footer .grid-item:first-child {
	font-size: calc(var(--fonte-simulador-px) * 0.75);
	color: var(--sf3-text-muted);
	font-family: 'Inter', sans-serif;
}
body.sf3-redesign #btnInfo .modal-footer #comoCitar {
	color: var(--sf3-accent);
	cursor: pointer;
	font-weight: 500;
	margin-top: 2px;
}
body.sf3-redesign #btnInfo .modal-footer #citacao {
	margin-top: 6px;
	color: #94a3b8;
}
body.sf3-redesign #btnInfo .modal-footer .btn-default {
	font-family: 'Inter', sans-serif;
	font-size: calc(var(--fonte-simulador-px) * 0.8);
	font-weight: 500;
	background: #f1f5f9;
	color: #334155;
	border: none;
	border-radius: 10px;
	padding: 10px 20px;
	box-shadow: none;
	flex-shrink: 0;
	transition: background-color 0.15s;
}
body.sf3-redesign #btnInfo .modal-footer .btn-default:hover {
	background: #e2e8f0;
}

/* ===== Janelas do "Problema" (lancamento-projeteis2) — Gerador de
   Problemas (.gp-janela, criada via JS por assets/problemas/js/
   interfaceGerador.js, também reaproveitada por mostrarAviso()) e
   janela de resultado (#blocoProblema, dentro do próprio index.html
   do simulador). Réplica em CSS real do mockup CD "SimuFisica
   Simulador Pendulo Duplo Redesign.dc.html" (pasta SimuFísica 3.0
   Home Redesign-4, janelas problemaOpen/problemaResultOpen) — o
   usuário colou lá uma janela de exemplo do lançamento de projéteis
   só pra capturar o design; pêndulo duplo não tem o botão "Problema".
   Fonte do mockup ('Plus Jakarta Sans') trocada por 'Inter' e
   tamanhos em var(--sf-scale) trocados por var(--fonte-simulador-px)
   pra bater com o resto do site — o mockup usa um sistema de escala
   próprio da ferramenta de design, não existente aqui. Escopado só
   por body.sf3-redesign (sem classe de app): tanto o HTML
   (#blocoProblema) quanto o JS (interfaceGerador.js/problemas.js)
   desse recurso são compartilhados entre simuladores — hoje só
   lancamento-projeteis2 tem "Problema" migrado, mas a regra vale pro
   próximo simulador que também tiver esse botão. As classes
   genéricas .janelaHeader/-Conteudo/-Corpo/-Rodape/-Grupo/-Opcao já
   são usadas nos dois HTMLs (gerador e resultado), então a maioria
   das regras abaixo cobre as duas janelas de uma vez só. */

body.sf3-redesign .gp-janela,
body.sf3-redesign #blocoProblema {
	border-radius: 16px;
	border: none;
	box-shadow: 0 24px 60px rgba(15, 23, 42, 0.28);
}

/* Altura máxima + rolagem interna (pedido do usuário, 05/08/2026): sem
   isso, a janela de edição de problema (3 textareas + dica + botão
   "Variáveis deste simulador", ver entrarModoEdicaoProblema() em
   problemas.js) e o gerador com muitos grupos de filtro podiam ficar
   mais altos que a tela num tablet em retrato. flex-column mantém
   cabeçalho e rodapé sempre visíveis (fora do scroll) — só o miolo
   (.janelaConteudo no gerador, .janelaCorpo no resultado, ver abaixo)
   rola. Valor igual ao já usado nos modais Info/Salvar (Etapa 7/Modal
   Info acima) e ao que o mockup do pêndulo duplo já especificava pra
   essas duas janelas. */
body.sf3-redesign .gp-janela,
body.sf3-redesign #blocoProblema {
	display: flex;
	flex-direction: column;
	max-height: 88vh;
}

/* .gp-janela era width/min-width/max-width:650px fixos (old
   mainApp2.css) — estourava em telas menores que ~650px (a media
   query de 600px do old CSS só mexe em max-height/border-radius, não
   em largura). Trocado por largura fluida com teto de 640px, igual
   ao mockup (width:100%; max-width:640px) e ao modal "Abrir/Salvar"
   (Etapa 7 acima). */
body.sf3-redesign .gp-janela {
	width: calc(100% - 20px);
	min-width: 0;
	max-width: 640px;
}

/* Era 50vw/min 800px/max 900px (old mainApp2.css) — cabia bem numa
   tela cheia mas estourava em telas menores. Trocado por largura
   fluida com teto de 640px (mesma fórmula do .gp-janela acima e do
   modal "Abrir/Salvar", Etapa 7): 50vw ficava estreito demais em
   viewports médios (~900-1000px vira só ~450-500px de janela), o que
   quebrava as 4 ações do rodapé (Editar/Copiar/Salvar/Variar) em 2
   linhas mesmo quando cabiam numa só. resize:none desliga o
   redimensionamento manual (old CSS tinha resize:both) — o usuário
   conseguia encolher a janela até esconder o rodapé de botões, o que
   ficava feio; a altura agora é sempre automática, seguindo o
   conteúdo. */
body.sf3-redesign #blocoProblema {
	width: calc(100% - 20px);
	min-width: 0;
	max-width: 640px;
	resize: none;
}

body.sf3-redesign .janelaHeader {
	padding: 18px 24px;
	background: #ffffff;
	border-bottom: 1px solid var(--sf3-border);
}
body.sf3-redesign .janelaHeader > span,
body.sf3-redesign #tituloProblemaTexto {
	display: flex;
	align-items: center;
	gap: 10px;
	font-family: 'Inter', sans-serif;
	font-size: calc(var(--fonte-simulador-px) * 1.1);
	font-weight: 700;
	color: var(--sf3-text);
}
body.sf3-redesign .janelaHeader i {
	color: var(--sf3-accent);
}
body.sf3-redesign .janelaHeader button {
	background: none;
	border: none;
	color: #94a3b8;
	cursor: pointer;
	padding: 4px 8px;
	font-size: 20px;
	line-height: 1;
	transition: color 0.15s;
}
body.sf3-redesign .janelaHeader button:hover {
	color: var(--sf3-accent);
}

body.sf3-redesign .janelaConteudo {
	padding: 20px 24px;
	gap: 20px;
	flex: 1;
	min-height: 0;
	overflow-y: auto;
}
body.sf3-redesign .janelaGrupo {
	border: 1px solid var(--sf3-border);
	border-radius: 12px;
	background: #ffffff;
	padding: 14px 16px;
}
body.sf3-redesign .janelaGrupo legend {
	font-family: 'Inter', sans-serif;
	font-size: calc(var(--fonte-simulador-px) * 0.78);
	font-weight: 600;
	color: var(--sf3-text-muted);
	text-transform: uppercase;
	letter-spacing: .04em;
}
body.sf3-redesign .janelaOpcao {
	font-family: 'Inter', sans-serif;
	font-size: calc(var(--fonte-simulador-px) * 0.88);
	color: #334155;
	padding: 7px 4px;
	margin: 0;
}
body.sf3-redesign .janelaOpcao input {
	accent-color: var(--sf3-accent);
	width: 16px;
	height: 16px;
}

/* #textoProblema também no seletor (não só .janelaCorpo): mainApp2.css
   tem uma regra por ID (#textoProblema{font-size:calc(...)}) que, por
   especificidade, ganhava de qualquer regra só-por-classe daqui — o
   font-size real ficava vindo do CSS antigo mesmo com esta regra
   presente. Combinar com o ID garante que esta vence. */
body.sf3-redesign .janelaCorpo,
body.sf3-redesign #textoProblema {
	font-family: 'Inter', sans-serif;
	font-size: var(--fonte-simulador-px);
	color: #334155;
	flex: 1;
	min-height: 0;
	overflow-y: auto;
}

body.sf3-redesign .janelaRodape {
	padding: 14px 24px;
	background: #ffffff;
	border-top: 1px solid var(--sf3-border);
	justify-content: flex-end;
	gap: 10px;
	flex-wrap: wrap;
}

/* #rodapeProblema (janela de resultado) tem 2 sub-linhas de botões, uma
   embaixo da outra — 4 ações em cima (Editar/Copiar/Salvar/Variar
   parâmetros), Voltar + Aplicar ao simulador embaixo (navegação/CTA
   principal, separados visualmente das ações). O .janelaRodape genérico
   acima continua sendo 1 única linha — é o que o gerador usa (só
   Cancelar/Gerar problema como filhos diretos); aqui vira coluna porque
   os filhos diretos passam a ser as 2 divs de sub-linha. */
body.sf3-redesign #rodapeProblema {
	flex-direction: column;
	align-items: stretch;
	gap: 10px;
}
/* Grid 2x2 fixo em vez de flex-wrap: com flex-wrap, o rótulo mais longo
   ("Variar parâmetros") força um flex-basis maior que os outros 3
   botões somados quase preenchem a linha sozinhos, sobrando ele
   sozinho "esticado" numa 2ª linha (flex-grow ocupando a linha
   inteira) — desequilibrado. Grid de 2 colunas iguais garante sempre
   2+2, com as mesmas larguras, em qualquer largura de janela. */
body.sf3-redesign .janelaRodapeAcoes {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 10px;
}
body.sf3-redesign .janelaRodapeAcoes .btn {
	text-align: center;
}

/* 4 colunas lado a lado nos perfis com mais espaço horizontal —
   desktop, tablet (qualquer orientação) e smartphone em paisagem
   (pedido do usuário, 05/08/2026). Só smartphone RETRATO fica no grid
   2x2 padrão acima. Mesmo padrão body.sf3-mobile + @media(orientation:
   landscape) já usado na barra inferior (Etapa "Barra inferior"). */
body.sf3-redesign.sf3-desktop .janelaRodapeAcoes,
body.sf3-redesign.sf3-tablet .janelaRodapeAcoes {
	grid-template-columns: repeat(4, 1fr);
}
@media (orientation: landscape) {
	body.sf3-redesign.sf3-mobile .janelaRodapeAcoes {
		grid-template-columns: repeat(4, 1fr);
	}
}
body.sf3-redesign .janelaRodapeNavegacao {
	display: flex;
	gap: 10px;
	justify-content: space-between;
}

body.sf3-redesign .janelaRodape .btn {
	font-family: 'Inter', sans-serif;
	font-size: calc(var(--fonte-simulador-px) * 0.85);
	font-weight: 500;
	border-radius: 10px;
	padding: 10px 18px;
	border: none;
	box-shadow: none;
	transition: background-color 0.15s;
}

/* Cancelar (gerador) / Editar / Variar parâmetros (resultado) — pílula neutra */
body.sf3-redesign .janelaRodape .btn-outline-secondary,
body.sf3-redesign .janelaRodape .btn-outline-dark {
	background: #f1f5f9;
	color: #334155;
}
body.sf3-redesign .janelaRodape .btn-outline-secondary:hover,
body.sf3-redesign .janelaRodape .btn-outline-dark:hover {
	background: #e2e8f0;
}

/* Gerar problema (gerador) / Aplicar ao simulador (resultado) — accent sólido */
body.sf3-redesign .janelaRodape .btn-primary {
	background: var(--sf3-accent);
	color: #ffffff;
	font-weight: 600;
}
body.sf3-redesign .janelaRodape .btn-primary:hover {
	background: #2166ac;
}

/* Copiar (resultado) — tint accent */
body.sf3-redesign .janelaRodape .btn-outline-primary {
	background: #eaf3fb;
	color: var(--sf3-accent);
}
body.sf3-redesign .janelaRodape .btn-outline-primary:hover {
	background: #d7e9f8;
}

/* Salvar (resultado) — tint teal */
body.sf3-redesign .janelaRodape .btn-outline-success {
	background: #e6f7f0;
	color: #0d9488;
}
body.sf3-redesign .janelaRodape .btn-outline-success:hover {
	background: #ccf1ec;
}

/* Voltar (resultado → gerador) fica em .janelaRodapeNavegacao (ver
   acima), à esquerda de "Aplicar ao simulador" via justify-content:
   space-between — não precisa de regra própria de posicionamento. */

@media (max-width: 600px) {
	body.sf3-redesign #blocoProblema {
		width: calc(100vw - 20px);
		min-width: 0;
	}
}

/* Fontes menores e FIXAS em smartphone (pedido do usuário, 05/08/2026):
   até aqui todo font-size das duas janelas vinha de
   calc(var(--fonte-simulador-px) * fator) — a mesma variável que o
   botão A-/A+ da barra de Ajustes controla (ver funcoes.js/redesign.js).
   Isso é o comportamento certo pro resto do simulador (texto acompanha a
   preferência do usuário), mas nessas duas janelas, num smartphone, um
   A+ alto reintroduz exatamente o problema que max-height/scroll (acima)
   e o grid 2x2 (janelaRodapeAcoes) foram feitos pra evitar — texto maior
   força mais quebras de linha, mais rolagem, botões mais apertados.
   Valores em px fixo (sem var()) travam essas duas janelas num tamanho
   compacto sempre, independente do ajuste global de fonte. Só
   body.sf3-mobile — desktop/tablet continuam escaláveis normalmente. */
body.sf3-redesign.sf3-mobile .janelaHeader > span,
body.sf3-redesign.sf3-mobile #tituloProblemaTexto {
	font-size: 15px;
}
body.sf3-redesign.sf3-mobile .janelaHeader button {
	font-size: 18px;
}
body.sf3-redesign.sf3-mobile .janelaGrupo legend {
	font-size: 10px;
}
body.sf3-redesign.sf3-mobile .janelaOpcao {
	font-size: 12px;
}
body.sf3-redesign.sf3-mobile .janelaCorpo,
body.sf3-redesign.sf3-mobile #textoProblema {
	font-size: 15px;
}
body.sf3-redesign.sf3-mobile .janelaRodape .btn {
	font-size: 12px;
}

/* Modo de edição livre do enunciado (botão "Editar" — entrarModoEdicaoProblema()
   em problemas.js): rótulos/textareas/dica/botão de ajuda ficam DENTRO de
   #textoProblema (substituindo o texto normal), mas são elementos com
   classe própria (.edicao-problema label/.textarea-problema-editavel/
   .dica-edicao-problema/.btn-ajuda-variaveis, mainApp2.css) — o font-size
   fixo do #textoProblema acima não os alcança, porque cada um já tem seu
   próprio font-size explícito (mais específico que herdar do pai).
   Esqueci essas 4 regras na 1ª passada de fontes fixas; sem elas a janela
   de edição continuava com a fonte escalável (grande) em smartphone. */
body.sf3-redesign.sf3-mobile .edicao-problema label {
	font-size: 12px;
}
body.sf3-redesign.sf3-mobile .textarea-problema-editavel {
	font-size: 12px;
}
body.sf3-redesign.sf3-mobile .dica-edicao-problema {
	font-size: 11px;
}
body.sf3-redesign.sf3-mobile .btn-ajuda-variaveis {
	font-size: 12px;
}
