/* ============================================================
   Shell da área interna — sidebar + cabeçalho
   ============================================================ */

.app {
  display: grid;
  grid-template-columns: 268px 1fr;
  min-height: 100vh;
  transition: grid-template-columns var(--transition-base);
}

/* Recolhida não é oculta: vira um TRILHO de ícones. Some o que é texto — nome,
   cargo, xp, rótulo das categorias, sublistas — e fica o que orienta: o avatar
   com o nível e um ícone por domínio. Zerar a coluna tirava a navegação
   inteira da tela e obrigava a expandir de volta a cada troca de análise. */
.app.is-recolhido {
  grid-template-columns: var(--trilho) 1fr;
}

:root {
  --trilho: 72px;
}

/* --- O que desaparece no trilho --- */

.is-recolhido .usuario-info,
.is-recolhido .nav-categoria-nome,
.is-recolhido .nav-chevron,
.is-recolhido .nav-cabecalho,
.is-recolhido .nav-paginas-caixa,
.is-recolhido .sidebar-logo {
  display: none;
}

/* --- Bloco do usuário --- */
/* O avatar encolhe e a moldura e a faixa do banner acompanham sozinhas: as
   duas são derivadas de --usuario-avatar.

   `.app` no seletor não é enfeite: sem ele isto empata em especificidade com
   `.sidebar-usuario.is-compacto`, que vem depois no arquivo e vencia por
   ordem — no Portal de Administração o trilho não encolhia nada. */
.app.is-recolhido .sidebar-usuario {
  --usuario-topo: 14px;
  --usuario-avatar: 40px;
  padding-bottom: 14px;
  gap: 0;
}

/* O selo encolhe junto, senão "Nv. 30" ficaria mais largo que o próprio
   avatar. É o único texto que sobrevive no trilho — foi o pedido. */
.is-recolhido .usuario-nivel {
  height: 15px;
  padding: 0 4px;
  border-radius: 5px;
  font-size: 9px;
  right: -6px;
  bottom: -4px;
}

/* --- Navegação --- */
/* Sem o rótulo, o botão vira um quadrado com o ícone no meio. O `justify-content`
   é necessário porque o layout original alinha à esquerda para acomodar o texto. */
.is-recolhido .nav-home,
.is-recolhido .nav-extra,
.is-recolhido .nav-categoria-botao {
  justify-content: center;
  padding-left: 0;
  padding-right: 0;
}

.is-recolhido .nav-lista,
.is-recolhido .sidebar-extras,
.is-recolhido .sidebar-nav {
  padding-left: 8px;
  padding-right: 8px;
}

.is-recolhido .sidebar-rodape {
  padding: 10px 0;
}

/* ---------- Sidebar ---------- */

.sidebar {
  display: flex;
  flex-direction: column;
  background: var(--bg-secondary);
  border-right: 1px solid var(--border-color);
  overflow: hidden;
  position: sticky;
  top: 0;
  height: 100vh;
}

/* ---------- Bloco de usuário (topo) ---------- */
/* Botão inteiro clicável: leva à área de perfil/configuração (a construir).
   Layout vertical — foto em cima, nome e cargo centralizados abaixo. */

.sidebar-usuario {
  --usuario-topo: 26px;
  --usuario-avatar: 78px;
  /* Raio de referência das molduras. DERIVADO do retrato, e não um número
     solto: as três medidas do bloco vêm de --usuario-avatar, e a moldura era a
     única que não vinha — foi assim que ela sobreviveu inteira quando o avatar
     encolheu para o trilho. 0,2 do diâmetro é a proporção que os tamanhos
     escritos à mão já praticavam (15/78 e 11/54). */
  --moldura-base: calc(var(--usuario-avatar) * 0.2);

  position: relative; /* âncora do banner */
  display: flex;
  flex-direction: column;
  align-items: center;
  /* A moldura é pseudo-elemento: não ocupa espaço no layout. As maiores do
     catálogo avançam 1,25× do raio base para fora do retrato, então um vão
     fixo seria comido por elas — a maior chegava a encostar no nome. O vão é
     esse avanço mais o respiro de verdade. */
  gap: calc(var(--moldura-base) * 1.25 + 13px);
  width: 100%;
  padding: var(--usuario-topo) 18px 22px;
  /* Obrigatório: é um <button>, e base.css não zera o fundo. Sem esta linha o
     elemento cai no ButtonFace do navegador — cinza claro no bloco inteiro. */
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--border-color);
  flex-shrink: 0;
  transition: background var(--transition-fast);
}

/* ---------- Bloco de usuário compacto ----------
   Vale nas telas em que a sidebar virou menu de outra coisa (hoje o Portal de
   Administração). Fica a identidade — foto, nível, nome, cargo; sai o que é
   gamificação — barra de XP e vitrine de medalhas, que o JS nem chega a
   desenhar porque o markup delas não existe neste modo.

   Os dois números saem das MESMAS variáveis do bloco normal: `--usuario-avatar`
   governa o retrato, a faixa do banner e o raio da moldura — todos derivados
   dele —, então mudar só este mantém o resto correto sem uma segunda conta. */
.sidebar-usuario.is-compacto {
  --usuario-topo: 18px;
  --usuario-avatar: 54px;
  padding-bottom: 16px;
}

/* ---------- Anatomia de uma superfície de banner ---------- */
/* Três planos, e não uma pilha de background só. O motivo é o sol: as listras
   precisam ser recortadas pelo círculo, e camada de background não recorta
   camada de background. Então o sol vira um elemento de verdade, com
   border-radius — e aí o próprio recorte curva as pontas das faixas.
   Com o sol no meio, os outros dois planos têm de existir separados:
     fundo do elemento → céu (atrás do sol)
     ::before          → sol
     ::after           → serra e piso (na frente do sol)
   `--banner-faixa` é a altura da cena; tudo se dimensiona a partir dela, e é
   isso que faz o desenho ser o MESMO nas três superfícies apesar de larguras
   de 268px, 860px e 110px. A versão anterior media o sol pelo menor lado da
   caixa, então ele encolhia no cartão largo enquanto as listras não. */

.sidebar-usuario {
  --banner-faixa: calc(var(--usuario-topo) + var(--usuario-avatar));
}

.sidebar-usuario,
.perfil-banner,
.cosm-previa-banner,
.cv-banner,
.com-podio-banner {
  background-image: var(--banner-ceu, none);
  background-size: 100% var(--banner-faixa);
  background-position: top;
  background-repeat: no-repeat;
}

/* Sol. Quadrado por aspect-ratio e redondo por border-radius: as listras
   moram no mesmo background e saem recortadas pela curva. */
.sidebar-usuario::before,
.perfil-banner::before,
.cosm-previa-banner::before,
.cv-banner::before,
.com-podio-banner::before {
  content: "";
  position: absolute;
  left: 50%;
  top: calc(var(--banner-faixa) * 0.05);
  height: calc(var(--banner-faixa) * 0.88);
  aspect-ratio: 1;
  transform: translateX(-50%);
  border-radius: 50%;
  background-image: var(--sol, none);
  /* A mesma dissolução do primeiro plano, convertida para as coordenadas do
     disco: os 70% da faixa caem em (70−5)/88 ≈ 74% da altura do sol. Sem isto
     o pé do disco reaparecia por baixo do piso, que é translúcido justamente
     nesse trecho. */
  -webkit-mask-image: linear-gradient(180deg, #000 74%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 74%, transparent 100%);
  pointer-events: none;
}

/* Serra e piso, à frente do sol. Ocupa a faixa inteira. */
.sidebar-usuario::after,
.perfil-banner::after,
.cosm-previa-banner::after,
.cv-banner::after,
.com-podio-banner::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: var(--banner-faixa);
  background-image: var(--banner-fundo, none);
  background-size: var(--banner-tamanho, cover);
  background-position: var(--banner-pos, center);
  background-repeat: var(--banner-repete, repeat);
  /* Corte suave no pé: sem a máscara, cada banner precisaria terminar
     transparente por conta própria e um deles acabaria com linha dura.
     Só os últimos 30%: banners com desenho no rodapé precisam de chão, e uma
     dissolução longa demais os apagaria. */
  -webkit-mask-image: linear-gradient(180deg, #000 70%, transparent 100%);
  mask-image: linear-gradient(180deg, #000 70%, transparent 100%);
  pointer-events: none;
}

/* O conteúdo passa por cima da faixa. */
.sidebar-usuario > * {
  position: relative;
  z-index: 1;
}

/* O hover é um véu por dentro, e não uma troca de background: o banner ocupa
   o background, e trocá-lo no hover apagaria o cosmético justo na hora em que
   a pessoa está mirando o bloco. */
.sidebar-usuario:hover {
  box-shadow: inset 0 0 0 999px var(--veu-hover);
}

/* Onde a foto vai entrar quando houver upload. Por ora exibe as iniciais.
   Fundo fixo, neutro — o que muda por domínio é o anel ao redor, feito com
   box-shadow (segue o border-radius, ao contrário de border+outline). Os dois
   anéis criam um respiro: o interno na cor da sidebar, o externo no acento
   do domínio. A transição anima a troca de cor ao navegar. */
/* Um vão só, na cor do fundo, entre a foto e a moldura. Aqui existia também um
   anel no acento do domínio, que trocava de cor conforme a tela aberta — saiu:
   a moldura é o que dá identidade ao retrato agora, e dois anéis concêntricos
   disputando o mesmo lugar deixavam a moldura em segundo plano. O domínio
   continua marcado no menu, na trilha e nos gráficos. */
.usuario-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--usuario-avatar);
  height: var(--usuario-avatar);
  border-radius: 50%;
  background: var(--bg-elevated);
  color: var(--text-primary);
  font-size: 26px;
  font-weight: 700;
  flex-shrink: 0;
  object-fit: cover;
  /* 5px, e não 8: é este vão que define onde a moldura COMEÇA, porque a
     sombra pertence ao avatar (z-index 1) e tapa o miolo do pseudo-elemento.
     Encolhê-lo alargou a faixa de desenho de 3px para 10px sem empurrar a
     borda externa — que não podia crescer, sob pena de encostar no logo do
     banner Mobidash. */
  box-shadow: 0 0 0 5px var(--bg-secondary);
  position: relative;
  z-index: 1;
}

/* Âncora do selo de nível. Sem largura própria: encolhe no avatar, senão o
   selo se posicionaria pela largura da sidebar inteira.
   --moldura-base vem herdado de .sidebar-usuario, que precisa do mesmo número
   para calcular o vão até o nome. */
.usuario-retrato {
  position: relative;
  display: inline-flex;
}

/* Foto padrão da sidebar e do cabeçalho: a marca em cinza claro. Percentual e
   não pixel, para servir aos três tamanhos (78px na sidebar, 40px no trilho,
   36px no cabeçalho) sem uma regra para cada. */
/* Os retratos da Comunidade entram na mesma regra: é a MESMA marca, no mesmo
   papel de foto ausente, e uma segunda regra só para eles acabaria divergindo
   no dia em que a proporção mudasse aqui. */
.usuario-avatar.is-sem-foto .avatar-marca,
.avatar.is-sem-foto .avatar-marca,
.com-gente-foto.is-sem-foto .avatar-marca,
.com-podio-foto.is-sem-foto .avatar-marca,
.cv-foto.is-sem-foto .avatar-marca {
  width: 58%;
  height: 58%;
  color: var(--text-muted);
  stroke-width: 1.6;
}

/* Selo de nível sobre o avatar. Prata, e não o acento do domínio: o nível é do
   usuário, não da análise aberta — trocar de cor ao navegar sugeriria que ele
   muda com a área. O metal é o mesmo das medalhas, com o brilho fora de centro
   que dá o relevo; cor chapada aqui leria como etiqueta. */
.usuario-nivel {
  position: absolute;
  right: -2px;
  bottom: -2px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Retângulo de cantos arredondados, não pílula: o raio é uma fração da
     altura, então as pontas ficam macias sem virar cápsula. */
  height: 19px;
  padding: 0 8px;
  border-radius: 6px;
  background: radial-gradient(circle at 32% 26%,
    var(--metal-prata-1), var(--metal-prata-2) 78%);
  color: var(--metal-prata-tinta);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.01em;
  line-height: 1;
  white-space: nowrap;
  /* Sem halo de recorte. Ele existia para separar o selo do avatar, mas era
     pintado em --bg-secondary: sobre o cinza do retrato virava um contorno
     escuro em volta do "Nv. 2", que é o oposto do efeito pretendido. O metal
     prata já contrasta com a foto sozinho. */
  /* Acima do avatar, que sobe para z-index 1 para passar sobre a moldura.
     Sem isto o selo ficaria por baixo da foto. */
  z-index: 2;
}

.usuario-nivel[hidden] { display: none; }

/* ---------- Molduras ---------- */
/* Recompensa por nível, de 5 em 5.
 *
 * ANATOMIA. Dois discos atrás do retrato, ambos maiores que ele. O miolo de
 * cada um fica escondido pela sombra do avatar, que é opaca e está por cima —
 * então o que se vê de cada disco é um ANEL, e a espessura desse anel é a
 * diferença entre o raio do disco e o raio da sombra. Daí os dois:
 *
 *   ::before  disco externo  → traços longos, arcos, varredura
 *   ::after   disco interno  → traços curtos, fios, agulha
 *
 * Como os dois partem do MESMO raio interno (a borda da sombra) e param em
 * raios diferentes, sobrepor um traçado em cada um dá marcas de comprimentos
 * diferentes — que é o que transforma um anel liso num bisel graduado.
 *
 * O VOCABULÁRIO é de instrumento de medição, não de ornamento heráldico:
 * `repeating-conic-gradient` produz raios a partir do centro, ou seja, traços
 * de escala; `conic-gradient` produz arcos, ou seja, setores e ponteiros;
 * `radial-gradient` produz anéis concêntricos. Nenhuma imagem envolvida.
 *
 * SILHUETA. O que separa uma moldura da outra não pode ser só cor e textura —
 * com todas no mesmo raio e na mesma espessura, o contorno fica idêntico e
 * elas viram a mesma peça pintada de sete jeitos. Então cada uma escolhe:
 *
 *   --m-f1 / --m-f2   quanto cada disco se afasta, como MÚLTIPLO do raio da
 *                     superfície (--moldura-base). Assim a proporção é da
 *                     moldura e a escala é da tela, e as duas não brigam.
 *   --m-vazio         corta o miolo do disco por máscara, empurrando a borda
 *                     interna para fora. É o que permite um anel SOLTO, com
 *                     folga escura entre ele e o retrato — coisa que a sombra
 *                     do avatar sozinha não faz.
 *
 * Daí saem contornos de verdade diferentes: bisel espesso colado na foto,
 * anel fino solto, mostrador com agulha para fora, dois fios concêntricos,
 * nós projetados, e a peça de três camadas do nível máximo.
 *
 * Regra que não se quebra: cosmético não ocupa superfície que carrega dado. */

.usuario-retrato::before,
.perfil-retrato::before,
.cosm-previa::before {
  content: "";
  position: absolute;
  /* O fallback importa: sem ele, uma superfície que esqueça --moldura-base faz
     o calc virar inválido e a moldura some sem erro nenhum. */
  inset: calc(-1 * var(--moldura-base, 15px) * var(--m-f1, 1));
  border-radius: 50%;
  background: var(--moldura-anel, none);
  box-shadow: var(--moldura-brilho, none);
  -webkit-mask-image: var(--m-mascara, radial-gradient(circle closest-side,
    transparent 0 var(--m-vazio, 0%), #000 var(--m-vazio, 0%)));
  mask-image: var(--m-mascara, radial-gradient(circle closest-side,
    transparent 0 var(--m-vazio, 0%), #000 var(--m-vazio, 0%)));
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  z-index: 0;
}

.usuario-retrato::after,
.perfil-retrato::after,
.cosm-previa::after {
  content: "";
  position: absolute;
  inset: calc(-1 * var(--moldura-base, 15px) * var(--m-f2, 0.66));
  border-radius: 50%;
  background: var(--moldura-ornato, none);
  /* A máscara padrão só corta o miolo. Uma moldura pode trocá-la por um
     desenho inteiro (--m-mascara2) e aí o fundo vira só a tinta da forma. */
  -webkit-mask-image: var(--m-mascara2, radial-gradient(circle closest-side,
    transparent 0 var(--m-vazio2, 0%), #000 var(--m-vazio2, 0%)));
  mask-image: var(--m-mascara2, radial-gradient(circle closest-side,
    transparent 0 var(--m-vazio2, 0%), #000 var(--m-vazio2, 0%)));
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  z-index: 0;
}

.moldura--padrao { --moldura-anel: none; }

/* ---------- As cinco peças forjadas ----------
 * Todas seguem o mesmo esqueleto, para poderem partilhar coordenadas:
 *
 *   ::before  metal   — aro e ornamento, recortados por --m-mascara
 *   ::after   gema    — só as pedras, recortadas por --m-mascara2
 *
 * Os dois discos têm o mesmo tamanho (--m-f1 = --m-f2 = 2), então os dois
 * SVGs partilham o mesmo viewBox de 100×100 e as peças encaixam sem conta
 * de conversão. A gema fica no ::after porque ele pinta por cima: no ::before
 * o metal a cobriria.
 *
 * O metal é um gradiente CÔNICO de claro/escuro alternado — é o que dá o
 * reflexo de superfície curva. Cor chapada aqui lê como adesivo.
 *
 * Geometria comum: aro entre os raios 31 e 38 do viewBox; ornamento de 38 até
 * no máximo 48, que é o limite antes da borda da caixa. O raio 31 fica por
 * dentro da sombra do retrato, garantindo que não sobre fresta. */

/* N5 · ESCALA — aço escovado com oito abas de encaixe. A mais sóbria: sem
   gema, sem ponta, só a peça usinada. */
.moldura--escala {
  --m-f1: 2;
  --moldura-anel: conic-gradient(from 140deg,
    #eef3f8, #7d8b9b, #f6f9fc, #66727f, #d7dfe8, #8b98a7, #eef3f8);
  --m-mascara: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cg fill='white'%3E%3Ccircle cx='50' cy='50' r='34.5' fill='none' stroke='white' stroke-width='7'/%3E%3Cpath d='M47.2 13.5 52.8 13.5 51.6 6.8 48.4 6.8Z'/%3E%3Cpath d='M47.2 13.5 52.8 13.5 51.6 6.8 48.4 6.8Z' transform='rotate(45 50 50)'/%3E%3Cpath d='M47.2 13.5 52.8 13.5 51.6 6.8 48.4 6.8Z' transform='rotate(90 50 50)'/%3E%3Cpath d='M47.2 13.5 52.8 13.5 51.6 6.8 48.4 6.8Z' transform='rotate(135 50 50)'/%3E%3Cpath d='M47.2 13.5 52.8 13.5 51.6 6.8 48.4 6.8Z' transform='rotate(180 50 50)'/%3E%3Cpath d='M47.2 13.5 52.8 13.5 51.6 6.8 48.4 6.8Z' transform='rotate(225 50 50)'/%3E%3Cpath d='M47.2 13.5 52.8 13.5 51.6 6.8 48.4 6.8Z' transform='rotate(270 50 50)'/%3E%3Cpath d='M47.2 13.5 52.8 13.5 51.6 6.8 48.4 6.8Z' transform='rotate(315 50 50)'/%3E%3C/g%3E%3C/svg%3E");
}

/* N10 · AMOSTRA — bronze com oito pontas e quatro gemas nos eixos. */
.moldura--amostra {
  --m-f1: 2;
  --m-f2: 2;
  --moldura-anel: conic-gradient(from 140deg,
    #f4cf9c, #8a5227, #ffe4bd, #6b3c19, #d59a63, #8a5227, #f4cf9c);
  --moldura-ornato: conic-gradient(from 200deg, #fff0c9, #f5b31b, #b97a0c, #fff0c9);
  --m-mascara: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cg fill='white'%3E%3Ccircle cx='50' cy='50' r='34.5' fill='none' stroke='white' stroke-width='7'/%3E%3Cpath d='M46.6 14 53.4 14 50 4.5Z' transform='rotate(22.5 50 50)'/%3E%3Cpath d='M46.6 14 53.4 14 50 4.5Z' transform='rotate(67.5 50 50)'/%3E%3Cpath d='M46.6 14 53.4 14 50 4.5Z' transform='rotate(112.5 50 50)'/%3E%3Cpath d='M46.6 14 53.4 14 50 4.5Z' transform='rotate(157.5 50 50)'/%3E%3Cpath d='M46.6 14 53.4 14 50 4.5Z' transform='rotate(202.5 50 50)'/%3E%3Cpath d='M46.6 14 53.4 14 50 4.5Z' transform='rotate(247.5 50 50)'/%3E%3Cpath d='M46.6 14 53.4 14 50 4.5Z' transform='rotate(292.5 50 50)'/%3E%3Cpath d='M46.6 14 53.4 14 50 4.5Z' transform='rotate(337.5 50 50)'/%3E%3C/g%3E%3C/svg%3E");
  --m-mascara2: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cg fill='white'%3E%3Cpath d='M50 10.5 54.2 15.5 50 20.5 45.8 15.5Z'/%3E%3Cpath d='M50 10.5 54.2 15.5 50 20.5 45.8 15.5Z' transform='rotate(90 50 50)'/%3E%3Cpath d='M50 10.5 54.2 15.5 50 20.5 45.8 15.5Z' transform='rotate(180 50 50)'/%3E%3Cpath d='M50 10.5 54.2 15.5 50 20.5 45.8 15.5Z' transform='rotate(270 50 50)'/%3E%3C/g%3E%3C/svg%3E");
}

/* N15 · MEDIDOR — prata com duas asas de chanfro na base e a gema âmbar
   encaixada entre elas. */
.moldura--medidor {
  --m-f1: 2;
  --m-f2: 2;
  --moldura-anel: conic-gradient(from 140deg,
    #f2f5f9, #838f9d, #ffffff, #616d7a, #dbe2ea, #8d99a7, #f2f5f9);
  --moldura-ornato: conic-gradient(from 200deg, #ffe9a8, #f5b31b, #b8790a, #ffe9a8);
  --m-mascara: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cg fill='white'%3E%3Ccircle cx='50' cy='50' r='34.5' fill='none' stroke='white' stroke-width='7'/%3E%3Cpath d='M35.6 77.4 6.5 71.5 17.8 81.2 5.2 84.6 20.5 90.2 39.6 84.6 38.4 78.6Z'/%3E%3Cpath d='M64.4 77.4 93.5 71.5 82.2 81.2 94.8 84.6 79.5 90.2 60.4 84.6 61.6 78.6Z'/%3E%3C/g%3E%3C/svg%3E");
  --m-mascara2: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cpath fill='white' d='M50 79 58 88.5 50 98 42 88.5Z'/%3E%3C/svg%3E");
  --moldura-brilho: 0 0 13px rgba(245, 179, 27, 0.28);
}

/* N20 · VARREDURA — fio duplo com coroa de louros na base e as gemas nos
   dois polos. */
.moldura--varredura {
  --m-f1: 2;
  --m-f2: 2;
  --moldura-anel: conic-gradient(from 140deg,
    #d9fbf6, #2f9e92, #f0fffd, #227a70, #7fded2, #35a89b, #d9fbf6);
  --moldura-ornato: conic-gradient(from 200deg, #e6fffb, #4fd1c5, #1c8478, #e6fffb);
  --m-mascara: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cg fill='white'%3E%3Ccircle cx='50' cy='50' r='37' fill='none' stroke='white' stroke-width='1.7'/%3E%3Ccircle cx='50' cy='50' r='32.6' fill='none' stroke='white' stroke-width='1.3'/%3E%3Cellipse cx='76.4' cy='81.4' rx='7.4' ry='3.1' transform='rotate(-8 76.4 81.4)'/%3E%3Cellipse cx='65.8' cy='87.9' rx='7.8' ry='3.3' transform='rotate(6 65.8 87.9)'/%3E%3Cellipse cx='53' cy='91.2' rx='7.2' ry='3' transform='rotate(14 53 91.2)'/%3E%3Cellipse cx='71.6' cy='75.4' rx='6.2' ry='2.7' transform='rotate(-38 71.6 75.4)'/%3E%3Cellipse cx='61.4' cy='81.6' rx='6' ry='2.6' transform='rotate(-24 61.4 81.6)'/%3E%3Cellipse cx='23.6' cy='81.4' rx='7.4' ry='3.1' transform='rotate(8 23.6 81.4)'/%3E%3Cellipse cx='34.2' cy='87.9' rx='7.8' ry='3.3' transform='rotate(-6 34.2 87.9)'/%3E%3Cellipse cx='47' cy='91.2' rx='7.2' ry='3' transform='rotate(-14 47 91.2)'/%3E%3Cellipse cx='28.4' cy='75.4' rx='6.2' ry='2.7' transform='rotate(38 28.4 75.4)'/%3E%3Cellipse cx='38.6' cy='81.6' rx='6' ry='2.6' transform='rotate(24 38.6 81.6)'/%3E%3C/g%3E%3C/svg%3E");
  --m-mascara2: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cg fill='white'%3E%3Cpath d='M50 3.5 56 11 50 18.5 44 11Z'/%3E%3Cpath d='M50 81.5 56 89 50 96.5 44 89Z'/%3E%3C/g%3E%3C/svg%3E");
  --moldura-brilho: 0 0 14px rgba(79, 209, 197, 0.26);
}

/* N25 · CONSTELAÇÃO — asas de pena nos flancos e três estrelas na coroa. */
.moldura--constelacao {
  --m-f1: 2;
  --m-f2: 2;
  --moldura-anel: conic-gradient(from 140deg,
    #ece6ff, #6d4bb8, #faf8ff, #543a99, #c4b5fd, #7c5ccc, #ece6ff);
  --moldura-ornato: conic-gradient(from 200deg, #fff6d5, #f5c93b, #b8860b, #fff6d5);
  --m-mascara: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cg fill='white'%3E%3Ccircle cx='50' cy='50' r='34.5' fill='none' stroke='white' stroke-width='6.4'/%3E%3Cpath d='M14.4 43.5C9.4 42.8 6.4 45.6 5.6 48.9 8.9 47.2 11.5 47.3 13.9 48.6Z'/%3E%3Cpath d='M13.4 51.4C8 51.6 5.2 54.7 4.8 58 7.8 55.8 10.6 55.4 13.2 56.3Z'/%3E%3Cpath d='M14.8 59.2C9.9 60.4 7.6 63.8 7.6 67 10.2 64.2 12.8 63.2 15.4 63.5Z'/%3E%3Cpath d='M85.6 43.5C90.6 42.8 93.6 45.6 94.4 48.9 91.1 47.2 88.5 47.3 86.1 48.6Z'/%3E%3Cpath d='M86.6 51.4C92 51.6 94.8 54.7 95.2 58 92.2 55.8 89.4 55.4 86.8 56.3Z'/%3E%3Cpath d='M85.2 59.2C90.1 60.4 92.4 63.8 92.4 67 89.8 64.2 87.2 63.2 84.6 63.5Z'/%3E%3C/g%3E%3C/svg%3E");
  --m-mascara2: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cg fill='white'%3E%3Cpath d='M50 2.4 52.3 8.3 58.6 8.6 53.7 12.6 55.3 18.7 50 15.2 44.7 18.7 46.3 12.6 41.4 8.6 47.7 8.3Z'/%3E%3Cpath d='M31.6 8.2 33.3 12.5 37.9 12.7 34.3 15.6 35.5 20 31.6 17.4 27.7 20 28.9 15.6 25.3 12.7 29.9 12.5Z'/%3E%3Cpath d='M68.4 8.2 70.1 12.5 74.7 12.7 71.1 15.6 72.3 20 68.4 17.4 64.5 20 65.7 15.6 62.1 12.7 66.7 12.5Z'/%3E%3C/g%3E%3C/svg%3E");
  --moldura-brilho: 0 0 15px rgba(139, 92, 246, 0.3);
}

/* N30 · PRISMA — o espectro DERRETENDO: anel rente à foto e gotas escorrendo
   pela borda de baixo.
   As gotas são uma MÁSCARA em SVG sobre o mesmo gradiente cônico, e não um
   desenho colorido: assim cada gota herda a cor do espectro no ângulo em que
   está, e as duas peças nunca desafinam.
   O FORMATO importa mais do que parece. Haste de largura constante com uma
   bola na ponta lê como alfinete; gota de verdade é larga onde nasce,
   estrangula no meio e incha na ponta — daí cada uma ser um `path` com bézier
   dos dois lados, e não um retângulo com um círculo. E a borda de onde ela
   escorre precisa estar inchada: os círculos sobre o aro são esse lóbulo, sem
   eles a gota parece pendurada num aro que continua perfeito.
   O disco das gotas é bem maior que o do anel (2× contra 0,8×) porque elas
   precisam de espaço para pingar — dentro de uma máscara, o que cai fora da
   caixa some.
   Estática de propósito: é o único elemento que fica em tela o tempo todo, e
   movimento perpétuo ali cansa em uma semana. */
.moldura--prisma {
  --m-f1: 0.8;
  --m-f2: 2;
  --moldura-anel: conic-gradient(from 0deg, #e27070, #f5b31b, #7bae3f,
                                 #4fd1c5, #4a7ddb, #8b5cf6, #e27070);
  --moldura-ornato: conic-gradient(from 0deg, #e27070, #f5b31b, #7bae3f,
                                   #4fd1c5, #4a7ddb, #8b5cf6, #e27070);
  --m-mascara2: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'%3E%3Cg fill='white'%3E%3Ccircle cx='77.2' cy='72.8' r='3.2'/%3E%3Ccircle cx='68.8' cy='80.1' r='4.2'/%3E%3Ccircle cx='54.9' cy='85.2' r='4.4'/%3E%3Ccircle cx='40.8' cy='84.3' r='3.9'/%3E%3Ccircle cx='28.2' cy='78' r='4'/%3E%3Ccircle cx='18.7' cy='66.7' r='3.4'/%3E%3Ccircle cx='15.7' cy='59.2' r='2.9'/%3E%3Cpath d='M65.6 80.1C68.22 86.4 66.6 90.92 66.6 92.9A2.2 2.2 0 0 0 71 92.9C71 90.92 69.38 86.4 72 80.1Z'/%3E%3Cpath d='M51.3 85.2C54.25 88.56 52.3 88.26 52.3 90.6A2.6 2.6 0 0 0 57.5 90.6C57.5 88.26 55.55 88.56 58.5 85.2Z'/%3E%3Cpath d='M37.8 84.3C40.26 88.92 38.5 90.93 38.5 93A2.3 2.3 0 0 0 43.1 93C43.1 90.93 41.34 88.92 43.8 84.3Z'/%3E%3Cpath d='M24.8 78C27.59 80.1 26.3 79.39 26.3 81.1A1.9 1.9 0 0 0 30.1 81.1C30.1 79.39 28.81 80.1 31.6 78Z'/%3E%3Cpath d='M15.9 66.7C18.2 73.84 16.5 79.52 16.5 81.5A2.2 2.2 0 0 0 20.9 81.5C20.9 79.52 19.2 73.84 21.5 66.7Z'/%3E%3C/g%3E%3C/svg%3E");
  --moldura-brilho: 0 0 20px rgba(139, 92, 246, 0.38);
}

/* ---------- Banners ---------- */
/* Recompensa por insígnia. Fica só no bloco do usuário — a sidebar inteira é
   superfície de navegação e é o que está em tela 100% do tempo; textura ali
   competiria com 21 itens de menu, com o estado ativo e com as medalhas. */

/* Todos ancorados no ALTO: a faixa começa no topo e morre no pé da foto, então
   o peso da cor tem de estar onde ela nasce. Um degradê que só ficasse forte
   embaixo apareceria cortado justo no ponto mais carregado. */

.banner--nenhum   { --banner-fundo: none; }

.banner--alvorada {
  --banner-fundo: linear-gradient(180deg,
    rgba(239, 159, 39, 0.22), rgba(239, 159, 39, 0.05) 72%, rgba(239, 159, 39, 0));
}

/* Explorador — o banner da casa: preto, o lime da marca descendo da borda de
   cima e uma linha de série cortando a cena, com a marca no canto.
   A LINHA é feita de cinco segmentos, um por camada. Cada um é um gradiente
   cuja faixa de cor fica perpendicular ao eixo: `to top left` deixa a faixa na
   diagonal que sobe, `to top right` na que desce. Ligando as caixas pelos
   vértices sai uma poligonal de verdade — que nenhum repeating-gradient faz,
   porque ele só repete o mesmo passo.
   O logo é o SVG que já vive no projeto, não um desenho novo: dimensionado
   pela ALTURA (auto 18%), senão ele mudaria de tamanho relativo em cada
   superfície, que é o erro que o sol do Horizonte cometia. */
.banner--mobidash {
  /* O lime nasce cheio só na borda e cai rápido: é luz entrando por cima, não
     uma tarja. Parar em 8% com opacidade alta virava laje. */
  --banner-ceu: linear-gradient(180deg,
    rgba(203, 244, 28, 0.92) 0%, rgba(203, 244, 28, 0.4) 3.5%,
    rgba(150, 190, 22, 0.16) 12%, rgba(40, 56, 8, 0.45) 28%,
    #060803 58%, rgba(5, 7, 3, 0) 100%);
  --banner-fundo:
    /* marca */
    url("../img/logo-horizontal.svg"),
    /* marcadores nos vértices, onde a série muda de direção */
    radial-gradient(circle closest-side,
      #eaff78 0 40%, rgba(216, 250, 60, 0.75) 54%, rgba(203, 244, 28, 0) 74%),
    radial-gradient(circle closest-side,
      #eaff78 0 40%, rgba(216, 250, 60, 0.75) 54%, rgba(203, 244, 28, 0) 74%),
    radial-gradient(circle closest-side,
      #eaff78 0 40%, rgba(216, 250, 60, 0.75) 54%, rgba(203, 244, 28, 0) 74%),
    radial-gradient(circle closest-side,
      #eaff78 0 40%, rgba(216, 250, 60, 0.75) 54%, rgba(203, 244, 28, 0) 74%),
    /* A SÉRIE, em SVG embutido. Gradiente não curva: a poligonal de dez
       camadas que estava aqui só sabia fazer retas, e por isso quebrava em
       bico nos vértices. Uma bézier cúbica passando pelos mesmos seis pontos
       resolve — e de quebra troca dez camadas por uma.
       Os pontos de controle saem de Catmull-Rom com tensão 1/6, que é o que
       faz a curva passar EXATAMENTE pelos vértices em vez de só se aproximar
       — os marcadores acima dependem disso para não flutuarem fora da linha.
       `vector-effect: non-scaling-stroke` mantém a espessura constante mesmo
       com o desenho esticado em X (a cena vai de 268px a 860px de largura). */
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 40' preserveAspectRatio='none'%3E%3Cg fill='none' stroke-linecap='round' stroke-linejoin='round' vector-effect='non-scaling-stroke'%3E%3Cpath d='M0 32.8C3.33 31.47 13.33 25.47 20 24.8 26.67 24.13 33.33 30.1 40 28.8 46.67 27.5 53.33 18.47 60 17 66.67 15.53 73.33 21.42 80 20 86.67 18.58 96.67 10.42 100 8.5' stroke='rgba(203,244,28,0.17)' stroke-width='7' vector-effect='non-scaling-stroke'/%3E%3Cpath d='M0 32.8C3.33 31.47 13.33 25.47 20 24.8 26.67 24.13 33.33 30.1 40 28.8 46.67 27.5 53.33 18.47 60 17 66.67 15.53 73.33 21.42 80 20 86.67 18.58 96.67 10.42 100 8.5' stroke='rgb(216,250,60)' stroke-width='2.2' vector-effect='non-scaling-stroke'/%3E%3C/g%3E%3C/svg%3E"),
    /* grade de leitura */
    repeating-linear-gradient(0deg,
      rgba(203, 244, 28, 0.07) 0 1px, transparent 1px 15px),
    repeating-linear-gradient(90deg,
      rgba(203, 244, 28, 0.06) 0 1px, transparent 1px 21px);
  /* Marcadores: a caixa é mais larga que alta de propósito. `circle
     closest-side` toma o menor lado como raio, então o ponto fica do mesmo
     tamanho relativo à ALTURA da cena nas três superfícies — que é a medida
     que todas partilham. */
  /* 22% de caixa, não de logo: o SVG tem 22% de folga em cima e embaixo, então
     só 56% da caixa é arte. O tamanho é ditado pela folga até o retrato — as
     molduras maiores do catálogo chegam a 1,25× do raio base, e a arte tem de
     começar depois disso. */
  --banner-tamanho:
    auto 22%,
    4% 9%, 4% 9%, 4% 9%, 4% 9%,
    100% 100%,
    100% 100%, 100% 100%;
  /* Logo no canto inferior direito: a poligonal sobe da esquerda para a
     direita, então é a única área que ela não cruza. No alto ela cruzaria, e
     à esquerda o lime do logo sumiria dentro do lime do topo.
     Encostado em 100%: o SVG tem 12,4% de folga em cada lateral, então a arte
     para sozinha antes da borda e a margem visual sai certa — passar disso
     cortava a marca. Nessa posição a arte começa em 195px na sidebar, contra
     os 188px onde termina o anel da moldura, e fica 5px abaixo da curva. Os
     dois vãos são pequenos: mexer no tamanho do retrato, no raio da moldura
     ou na altura da curva pede conferir aqui. */
  --banner-pos:
    100% 70%,
    18.75% 63.2%, 39.58% 74.2%, 60.42% 41.8%, 81.25% 50%,
    center,
    center, center;
  --banner-repete:
    no-repeat,
    no-repeat, no-repeat, no-repeat, no-repeat,
    no-repeat,
    repeat, repeat;
}

/* Imersão — telemetria. Histograma sobre grade técnica: a cara de quem senta
   e cava dados. Ciano monocromático, para não se confundir nem com o lime da
   marca nem com as cores de domínio, que aqui significariam algo. */
.banner--telemetria {
  --banner-ceu: linear-gradient(180deg,
    #0d1b2e 0%, #0a1526 56%, rgba(9, 18, 32, 0) 100%);
  --banner-fundo:
    /* histograma: três períodos diferentes se somam num perfil irregular */
    repeating-linear-gradient(90deg,
      transparent 0 1%, rgba(148, 226, 255, 0.9) 1% 3.2%, transparent 3.2% 9%),
    repeating-linear-gradient(90deg,
      transparent 0 4.4%, rgba(79, 209, 197, 0.78) 4.4% 6.6%, transparent 6.6% 13%),
    repeating-linear-gradient(90deg,
      transparent 0 8%, rgba(56, 168, 200, 0.7) 8% 10.6%, transparent 10.6% 21%),
    /* clarão rente à base, onde as barras nascem */
    linear-gradient(180deg, rgba(79, 209, 197, 0.28) 0%, rgba(79, 209, 197, 0) 34%),
    /* grade fina */
    repeating-linear-gradient(0deg,
      rgba(148, 226, 255, 0.11) 0 1px, transparent 1px 14px),
    repeating-linear-gradient(90deg,
      rgba(148, 226, 255, 0.09) 0 1px, transparent 1px 20px);
  --banner-tamanho:
    100% 30%, 100% 44%, 100% 58%,
    100% 30%,
    100% 100%, 100% 100%;
  --banner-pos:
    center bottom, center bottom, center bottom,
    center bottom,
    center, center;
  --banner-repete:
    repeat-x, repeat-x, repeat-x,
    no-repeat,
    repeat, repeat;
}

/* Cartógrafo — carta náutica. Malha fina, cruzes reforçadas a cada quatro
   células e as linhas de rumo em diagonal, tudo sobre um clarão que concentra
   o desenho atrás do retrato. Antes isto era só a textura de fundo das telas
   de análise, que a pessoa já vê de graça o dia inteiro. */
.banner--malha {
  --banner-fundo:
    repeating-linear-gradient(45deg,  rgba(123, 167, 201, 0.16) 0 1px, transparent 1px 52px),
    repeating-linear-gradient(-45deg, rgba(123, 167, 201, 0.16) 0 1px, transparent 1px 52px),
    repeating-linear-gradient(90deg,  rgba(123, 167, 201, 0.30) 0 1px, transparent 1px 56px),
    repeating-linear-gradient(0deg,   rgba(123, 167, 201, 0.30) 0 1px, transparent 1px 56px),
    repeating-linear-gradient(90deg,  rgba(123, 167, 201, 0.12) 0 1px, transparent 1px 14px),
    repeating-linear-gradient(0deg,   rgba(123, 167, 201, 0.12) 0 1px, transparent 1px 14px),
    radial-gradient(74% 96% at 50% 30%,
      rgba(123, 167, 201, 0.20), rgba(123, 167, 201, 0) 72%);
}

/* Inabalável — a insígnia mais cara do catálogo (trinta dias úteis seguidos,
   seis semanas), então é o banner que mais tem o que mostrar: um horizonte
   synthwave — sol listrado, skyline e piso em fuga.
   Tudo em gradiente, sem imagem: fica nítido em qualquer tamanho, não pede
   pipeline de asset e a prévia do perfil usa exatamente as mesmas regras.
   TODA medida é %, jamais px — a prévia tem 34px de altura contra os 104px da
   sidebar, e só assim as duas mostram a mesma cena.
   A ordem das camadas é a profundidade: piso na frente, céu no fundo.
   A composição é ditada pelo retrato, que cobre dos 35% aos 65% da largura: o
   sol fica centrado e vira halo atrás da foto, enquanto a silhueta da cidade
   ocupa justamente as laterais, que é o que sobra à vista. Uma serra de
   montanhas foi tentada antes e se perdia atrás do sol. */
.banner--horizonte {
  --banner-fundo:
    /* Travessas do piso com espaçamento CRESCENTE (3, 8, 15, 25, 39, 58, 82%).
       Um repeating-linear-gradient dá linhas equidistantes, que não é
       perspectiva nenhuma.
       Cada linha tem uma borda de meio ponto percentual desbotando dos dois
       lados: parada dura em fração de pixel é o que produzia o serrilhado —
       com a rampa curta o próprio antialias do gradiente resolve a borda. */
    linear-gradient(180deg,
      transparent 0 2.6%,    rgba(255, 108, 226, 0.66) 3.1% 3.9%,  transparent 4.4% 7.6%,
      rgba(255, 104, 224, 0.62) 8.1% 9%,   transparent 9.5% 14.5%,
      rgba(255, 100, 222, 0.6)  15% 16%,   transparent 16.5% 24.5%,
      rgba(255, 96, 220, 0.57)  25% 26.2%, transparent 26.7% 38.4%,
      rgba(255, 92, 218, 0.54)  39% 40.5%, transparent 41% 57.4%,
      rgba(255, 88, 216, 0.5)   58% 59.8%, transparent 60.3% 81.3%,
      rgba(255, 84, 214, 0.46)  82% 84.2%, transparent 84.7%),
    /* Linhas de fuga. O vértice do cone fica ACIMA da camada (-55%), e não no
       horizonte: convergindo dentro do quadro elas viravam um borrão nos
       poucos pixels em volta do ponto. Mesma rampa curta nas bordas. */
    repeating-conic-gradient(from 157deg at 50% -55%,
      transparent 0 0.12deg, rgba(255, 104, 226, 0.62) 0.34deg 0.78deg,
      transparent 1deg 6.6deg),
    /* Brilho rente ao horizonte: separa a serra do piso sem precisar de linha. */
    linear-gradient(180deg,
      rgba(255, 90, 220, 0.3) 0%, rgba(255, 90, 220, 0) 26%),
    linear-gradient(180deg, #2a0d55, #140832),
    /* Serra: SETE cunhas, estreitas e sobrepostas, formam uma crista contínua
       de ponta a ponta. Com cinco cunhas largas sobravam vãos — a base de um
       triângulo é h·tan(35°), então caixa larga demais deixa buraco. Todas
       ancoradas no pé, e é o piso (camada da frente) que corta as bases no
       horizonte. Miolo roxo com as encostas acesas em rosa: o contorno de
       neon sem camada extra. */
    conic-gradient(from 145deg at 50% 0%, rgba(255, 122, 194, 0.85) 0 1.5deg,
      #2b1052 1.5deg 68.5deg, rgba(255, 122, 194, 0.85) 68.5deg 70deg, transparent 70deg),
    conic-gradient(from 145deg at 50% 0%, rgba(255, 142, 205, 0.9) 0 1.5deg,
      #351566 1.5deg 68.5deg, rgba(255, 142, 205, 0.9) 68.5deg 70deg, transparent 70deg),
    conic-gradient(from 145deg at 50% 0%, rgba(255, 108, 184, 0.8) 0 1.5deg,
      #250e48 1.5deg 68.5deg, rgba(255, 108, 184, 0.8) 68.5deg 70deg, transparent 70deg),
    conic-gradient(from 145deg at 50% 0%, rgba(255, 142, 205, 0.9) 0 1.5deg,
      #351566 1.5deg 68.5deg, rgba(255, 142, 205, 0.9) 68.5deg 70deg, transparent 70deg),
    conic-gradient(from 145deg at 50% 0%, rgba(255, 108, 184, 0.8) 0 1.5deg,
      #250e48 1.5deg 68.5deg, rgba(255, 108, 184, 0.8) 68.5deg 70deg, transparent 70deg),
    conic-gradient(from 145deg at 50% 0%, rgba(255, 142, 205, 0.9) 0 1.5deg,
      #351566 1.5deg 68.5deg, rgba(255, 142, 205, 0.9) 68.5deg 70deg, transparent 70deg),
    conic-gradient(from 145deg at 50% 0%, rgba(255, 122, 194, 0.85) 0 1.5deg,
      #2b1052 1.5deg 68.5deg, rgba(255, 122, 194, 0.85) 68.5deg 70deg, transparent 70deg);
  --banner-tamanho:
    100% 30%, 100% 30%, 100% 30%, 100% 30%,
    22% 46%, 22% 60%, 22% 40%, 22% 54%, 22% 42%, 22% 58%, 22% 44%;
  --banner-pos:
    center bottom, center bottom, center bottom, center bottom,
    0% 100%, 16.6% 100%, 33.3% 100%, 50% 100%, 66.6% 100%, 83.3% 100%, 100% 100%;
  --banner-repete: no-repeat;

  /* Sol. Vai no ::before, que é um círculo de verdade — então estas listras
     são recortadas pela curva e terminam acompanhando a borda do disco, em
     vez de saírem em quina pelos lados. O topo fica liso, como na referência.
     Como a caixa É o disco, as porcentagens são a altura do próprio sol. */
  --sol:
    linear-gradient(180deg,
      transparent 0 31%,     rgba(30, 11, 70, 0.95) 31.6% 35%,
      transparent 35.6% 41%, rgba(30, 11, 70, 0.95) 41.6% 45.2%,
      transparent 45.8% 51%, rgba(30, 11, 70, 0.95) 51.6% 55.4%,
      transparent 56% 61%,   rgba(30, 11, 70, 0.95) 61.6% 65.6%,
      transparent 66.2% 71%, rgba(30, 11, 70, 0.95) 71.6% 75.8%,
      transparent 76.4% 81%, rgba(30, 11, 70, 0.95) 81.6% 86%,
      transparent 86.6% 91%, rgba(30, 11, 70, 0.95) 91.6% 96.2%,
      transparent 96.8%),
    linear-gradient(180deg, #ffe3a0 0%, #ffb072 32%, #fd7396 66%, #e83f89 100%);

  /* Céu, no fundo do elemento. Termina transparente para a faixa morrer na
     cor da superfície, seja ela qual for. */
  --banner-ceu: linear-gradient(180deg,
    #3a1470 0%, #24105a 46%, #180c3c 80%, rgba(22, 11, 58, 0) 100%);
}

.usuario-info {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  min-width: 0;
  max-width: 100%;
}

/* XP como terceira linha, discreta: é contexto do selo, não um dado que
   compete com o nome. */
/* Progresso DENTRO do nível: o número em cima, a barra embaixo. Substituiu a
   pílula com o xp acumulado — aquele número não tinha régua, e "185 xp" não
   diz se falta pouco ou muito para o próximo nível.

   Sem moldura de pílula agora: a barra já é a forma, e o contorno em volta do
   par número+barra empilharia duas bordas num bloco de 148px.

   Vem ANTES do nome, encostado no selo de nível que fica no avatar. O respiro
   embaixo é maior que o de cima: é ele que separa o grupo de progresso do de
   identidade, já que o `gap` de 3px do bloco não daria conta — sem isso, a
   barra e o nome viram uma pilha só de quatro linhas iguais. */
.usuario-xp {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  margin: 2px 0 9px;
  /* Medida própria, e não 100% do bloco. O `.usuario-info` é uma coluna
     centrada: a largura dele é a do filho mais largo, ou seja, a do NOME.
     Herdando isso, a barra mediria 103px para "Lucas Rodrigues" e outra coisa
     para "Ana Luz" — a mesma fração de nível pareceria progressos diferentes
     conforme quem está logado. `max-width` para ceder se a sidebar apertar. */
  width: 148px;
  max-width: 100%;
}

.usuario-xp[hidden] { display: none; }

.usuario-xp-topo {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--fogo-tinta);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
}

/* O trilho é o "vazio" do guia — fundo, nunca a cor do dado. */
.usuario-xp-trilho {
  display: block;
  width: 100%;
  height: 6px;
  border-radius: 20px;
  background: var(--bg-tertiary);
  border: 1px solid var(--fogo-borda);
  overflow: hidden;
}

/* Anima ao chegar do banco: o progresso nasce em zero e corre até a posição.
   É um movimento só, na carga — não um laço. */
.usuario-xp-preenche {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--fogo);
  transition: width var(--transition-base);
}

/* ---------- Metais das insígnias ---------- */
/* Cada elemento que representa uma medalha carrega o par de cores do seu
   degrau; as regras de desenho só consomem --m*. Ficam aqui, e não no
   perfil.css, porque a sidebar existe em toda tela — inclusive nas que não
   carregam o CSS do perfil. Acrescentar um degrau é acrescentar seis linhas. */

.metal--bronze {
  --m1: var(--metal-bronze-1);   --m2: var(--metal-bronze-2);
  --m-tinta: var(--metal-bronze-tinta);
  --m-fundo: var(--metal-bronze-fundo);   --m-borda: var(--metal-bronze-borda);
}
.metal--prata {
  --m1: var(--metal-prata-1);    --m2: var(--metal-prata-2);
  --m-tinta: var(--metal-prata-tinta);
  --m-fundo: var(--metal-prata-fundo);    --m-borda: var(--metal-prata-borda);
}
.metal--ouro {
  --m1: var(--metal-ouro-1);     --m2: var(--metal-ouro-2);
  --m-tinta: var(--metal-ouro-tinta);
  --m-fundo: var(--metal-ouro-fundo);     --m-borda: var(--metal-ouro-borda);
}
.metal--platina {
  --m1: var(--metal-platina-1);  --m2: var(--metal-platina-2);
  --m-tinta: var(--metal-platina-tinta);
  --m-fundo: var(--metal-platina-fundo);  --m-borda: var(--metal-platina-borda);
}

/* ---------- Vitrine na sidebar ---------- */
/* Quarta linha do bloco, logo abaixo do XP. Só exibição: o bloco inteiro já é
   um botão para o perfil, e é lá que a vitrine se monta. Nasce oculta e some
   de novo quando não há nada equipado — três buracos tracejados no menu
   seriam ruído permanente em troca de nada. */

.usuario-vitrine {
  display: inline-flex;
  gap: 6px;
  margin-top: 7px;
}

.usuario-vitrine[hidden] { display: none; }

.usuario-medalha {
  display: grid;
  place-items: center;
  width: 23px;
  height: 23px;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 26%, var(--m1), var(--m2) 78%);
  color: var(--m-tinta);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.32),
              0 0 0 2px var(--bg-secondary),
              0 0 0 3px var(--m-borda);
}

.usuario-medalha .icone {
  width: 11px;
  height: 11px;
}

/* Lugar livre. Sem anel e sem gradiente: é ausência de medalha, não medalha
   apagada. Mesmo tracejado da vitrine do perfil, um tom acima — aqui o círculo
   tem metade do diâmetro, então metade do perímetro para se fazer notar. */
.usuario-medalha.is-vazia {
  background: none;
  color: var(--text-muted);
  border: 1px dashed var(--text-muted);
  box-shadow: none;
  opacity: 0.75;
}

.usuario-medalha.is-vazia .icone {
  width: 8px;
  height: 8px;
}

/* Preenchido, não contornado: a 10px o traço do raio vira um borrão. */
.usuario-xp-icone {
  width: 10px;
  height: 10px;
  flex-shrink: 0;
  fill: currentColor;
  stroke: none;
}

.usuario-nome {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.usuario-cargo {
  font-size: 11.5px;
  color: var(--text-muted);
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- Navegação (meio) ---------- */

.sidebar-nav {
  flex: 1;
  overflow-y: auto;
  /* padding-top folgado afasta a navegação do bloco de usuário. */
  padding: 26px 12px 24px;
}

/* Item de início — mesma anatomia de um botão de categoria, mas sem chevron
   nem contador, porque é uma tela única (a home), não um grupo. */
.nav-home {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 11px 12px;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-size: 13.5px;
  font-weight: 600;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.nav-home:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.nav-home.is-ativa {
  background: var(--accent-soft);
  color: var(--text-primary);
}

/* ---------- Itens do menu lateral (modo menu) ---------- */

.nav-cfgs {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 0 12px;
}

/* Herda o desenho do `.nav-home` — mesmo tamanho, mesmo hover, mesmo estado
   ativo. É de propósito: o Início fica logo acima na mesma lista, e dois
   desenhos diferentes de item de menu um em cima do outro leriam como duas
   listas.

   O item é só ícone e nome. Uma pastilha de situação já morou aqui à direita e
   saiu: em 224px ela disputava a linha com o nome, e no trilho tinha de sumir —
   desaparecia justo quando o menu vira só ícones. Ver `.ad-secao-selo`. */
.nav-cfg .nav-categoria-nome {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Cabeçalho da seção: título "Análises" + botão de recolher/expandir tudo. */
.nav-cabecalho {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 6px 0 12px;
  margin: 22px 0 12px;
}

.sidebar-nav-titulo {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Verde enquanto houver categoria aberta — mesma leitura da seta da categoria:
   verde = algo expandido. Com todas fechadas (is-expandir), volta ao cinza. */
.nav-recolher {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--brand);
  flex-shrink: 0;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.nav-recolher.is-expandir {
  color: var(--text-muted);
}

.nav-recolher:hover {
  background: var(--bg-hover);
}

.nav-recolher.is-expandir:hover {
  color: var(--text-secondary);
}

.nav-recolher-icone {
  width: 15px;
  height: 15px;
  transition: transform var(--transition-base);
}

/* Todas fechadas: a seta aponta para baixo, indicando "expandir". */
.nav-recolher.is-expandir .nav-recolher-icone {
  transform: rotate(180deg);
}

/* ---------- Rodapé com a marca ---------- */

/* Faixa entre a navegação e o logo. Existe separada da <nav> porque aquela
   rola: um destino que não é análise não pode sumir junto com a lista quando
   ela passa da altura da janela. */
.sidebar-extras {
  padding: 0 12px 14px;
  flex-shrink: 0;
}

/* Conteúdo centrado, e não alinhado à esquerda como os itens de análise. O
   alinhamento à esquerda vale enquanto há uma lista: são vários itens e a
   coluna de ícones dá a régua. Aqui é um item sozinho, encostado no logo — que
   é centralizado —, e a régua da lista acabou dez linhas acima. Centrado, ele
   e o logo dividem o mesmo eixo.

   A caixa continua ocupando a largura toda: o alvo do clique é a faixa
   inteira, como nos demais. */
.nav-extra {
  justify-content: center;
}

/* O rótulo de categoria nasce com `flex: 1` — nas listas é ele que empurra o
   chevron para a direita. Aqui isso engoliria a folga e não sobraria nada para
   centrar. */
.nav-extra .nav-categoria-nome {
  flex: 0 1 auto;
}

.sidebar-rodape {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px 20px;
  border-top: 1px solid var(--border-color);
  flex-shrink: 0;
}

.sidebar-logo {
  width: 124px;
  height: auto;
  opacity: 0.85;
}

/* NO TEMA CLARO, TROCA O ARQUIVO. A palavra MOBI é branca no logo, e a sidebar
   também é branca — o resultado era o suporte e o "DASH" flutuando sozinhos,
   com metade da marca invisível.

   `content` num elemento substituído troca a imagem que ele exibe, mantendo o
   `alt` e o dimensionamento do <img>. É o que permite resolver isto sem uma
   linha de JavaScript: nada precisa ouvir a troca de tema, nada precisa refazer
   a sidebar. A alternativa seria reescrever o `src` no clique — que funciona,
   mas põe conhecimento de tema dentro do shell.js para uma decisão que é
   inteiramente de aparência.

   A regra vale só na sidebar. O login não entra: ele é sempre escuro, e lá o
   logo branco é o certo. */
:root[data-tema="claro"] .sidebar-logo {
  content: url("../img/logo-horizontal-claro.svg");
}

.nav-lista {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

/* ---------- Categoria (pai) ---------- */

.nav-categoria-botao {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 11px 12px;
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  font-size: 13.5px;
  font-weight: 600;
  text-align: left;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.nav-categoria-botao:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

.nav-categoria.is-aberta .nav-categoria-botao {
  color: var(--text-primary);
}

/* Ícones sempre no verde Mobidash — legível sobre o fundo quase preto em
   qualquer estado (aberto, fechado, home ativa). */
.nav-icone {
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  color: var(--brand);
}

/* Cinza no lugar do verde de marca. O verde marca ANÁLISE; o que não é análise
   não deve disputar o mesmo peso no olhar. Acende junto com o texto no hover,
   senão o item pareceria desabilitado. */
.nav-icone--neutro {
  color: var(--text-secondary);
  transition: color var(--transition-fast);
}

.nav-extra:hover .nav-icone--neutro {
  color: var(--text-primary);
}

/* min-width:0 + overflow permite o nome encolher (com reticências) em vez de
   empurrar a seta. É isso que mantém a seta sempre no mesmo ponto à direita,
   independentemente do tamanho do texto da categoria. */
.nav-categoria-nome {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nav-chevron {
  width: 13px;
  height: 13px;
  flex-shrink: 0;
  color: var(--text-muted);
  transition: transform var(--transition-base), color var(--transition-fast);
}

/* Categoria aberta: a seta acompanha o verde do ícone, reforçando o estado. */
.nav-categoria.is-aberta .nav-chevron {
  transform: rotate(90deg);
  color: var(--brand);
}

/* ---------- Páginas (filhas) ---------- */
/* grid-template-rows 0fr → 1fr anima a abertura sem precisar saber a altura do
   conteúdo, que é o que `height: auto` não permite animar.
   A caixa intermediária é obrigatória: `grid-template-rows` define UMA linha,
   então aplicar a grade direto no <ul> colapsaria só o primeiro <li> e deixaria
   os demais em linhas implícitas, fora do controle da animação. */

.nav-paginas-caixa {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--transition-base);
}

.nav-categoria.is-aberta .nav-paginas-caixa {
  grid-template-rows: 1fr;
}

.nav-paginas {
  overflow: hidden;
}

.nav-paginas > li:first-child {
  padding-top: 3px;
}

.nav-paginas > li:last-child {
  padding-bottom: 6px;
}

.nav-pagina {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px 9px 22px;
  margin-left: 19px;
  border-left: 1px solid var(--border-color);
  color: var(--text-secondary);
  font-size: 13px;
  transition: color var(--transition-fast), background var(--transition-fast);
}

.nav-pagina:hover {
  color: var(--text-primary);
  background: var(--bg-hover);
}

.nav-marca {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--border-color-light);
  flex-shrink: 0;
  transition: background var(--transition-fast), box-shadow var(--transition-fast);
}

.nav-pagina.is-ativa {
  color: var(--text-primary);
  font-weight: 600;
  background: var(--accent-soft);
}

.nav-pagina.is-ativa .nav-marca {
  background: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* ---------- Coluna principal ---------- */

.principal {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.cabecalho {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  height: var(--header-height);
  padding: 0 28px;
  border-bottom: 1px solid var(--border-color);
  /* Mesmo tom da sidebar: as duas formam a moldura escura que emoldura a tela
     de trabalho, e precisam ser lidas como uma peça só. */
  background: var(--bg-secondary);
  position: sticky;
  top: 0;
  z-index: 10;
}

.cabecalho-esq {
  display: flex;
  align-items: center;
  gap: 16px;
  min-width: 0;
}

.cabecalho-toggle,
.cabecalho-voltar,
.btn-tema,
.btn-config,
.btn-sair {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  background: transparent;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  color: var(--text-secondary);
  flex-shrink: 0;
  transition: background var(--transition-fast), color var(--transition-fast),
              border-color var(--transition-fast);
}

.cabecalho-toggle:hover,
.cabecalho-voltar:hover,
.btn-tema:hover,
.btn-config:hover {
  background: var(--bg-hover);
  color: var(--text-primary);
}

/* ---------- Troca de tema ----------
   Sol e lua ocupam o MESMO ponto — empilhados por `position: absolute` dentro
   de um botão relativo — e a troca é uma cruzando a outra. Se fossem irmãos no
   fluxo, o botão teria de ter o dobro da largura para caber os dois, ou
   `display:none` num deles; e `display:none` não anima, que é justamente o que
   se quer aqui: o gesto de "virar a chave" fica mais legível que um ícone que
   simplesmente troca de forma entre um quadro e outro.

   O giro é de 90°, não de 180°: meia volta faria os raios do sol voltarem
   exatamente onde estavam (o desenho é simétrico a cada 45°) e o movimento
   pareceria não ter acontecido. */
.btn-tema {
  position: relative;
  overflow: hidden;
}

.btn-tema-sol,
.btn-tema-lua {
  position: absolute;
  display: flex;
  transition: opacity var(--transition-base), transform var(--transition-base);
}

.btn-tema .icone {
  width: 16px;
  height: 16px;
}

/* No escuro, aparece o SOL — o botão oferece clarear. */
.btn-tema-lua {
  opacity: 0;
  transform: rotate(-90deg) scale(0.6);
}

/* No claro, os papéis se invertem. */
:root[data-tema="claro"] .btn-tema-sol {
  opacity: 0;
  transform: rotate(90deg) scale(0.6);
}

:root[data-tema="claro"] .btn-tema-lua {
  opacity: 1;
  transform: none;
}

/* Quem pediu menos movimento recebe a troca sem o giro. A mudança de opacidade
   fica: sem ela não haveria transição nenhuma, e o ícone saltaria. */
@media (prefers-reduced-motion: reduce) {
  .btn-tema-sol,
  .btn-tema-lua { transform: none !important; }
}

/* Só existe onde a página define Shell.aoVoltar — hoje, apenas o perfil. */
.cabecalho-voltar:hover {
  border-color: var(--border-color-light);
}

.btn-sair:hover {
  background: var(--danger-soft);
  border-color: var(--danger);
  color: var(--danger-tinta);
}

/* ---------- Próxima análise ---------- */
/* Fica depois da trilha, e não no canto direito junto do sair: é continuação
   da leitura "E-commerce / Visão Executiva  →  próxima", e o olho já está ali.
   `margin-left` pequeno em vez do gap do container, para colar na trilha e não
   parecer um controle solto. */
/* Os dois passos da fila de análises, lado a lado. Juntos e não separados por
   outra coisa: são um par, e afastá-los faria cada um parecer um comando
   diferente em vez das duas direções do mesmo. */
.cabecalho-passos {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-left: 14px;
  min-width: 0;
}

.cabecalho-passo {
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 5px 11px;
  background: transparent;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-pill, 20px);
  color: var(--text-secondary);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  flex-shrink: 0;
  transition: background var(--transition-fast), color var(--transition-fast),
              border-color var(--transition-fast);
}

/* O respiro é menor do lado da seta: ela já é mais leve que o texto, e o
   padding igual dos dois lados a deixava parecendo solta. */
.cabecalho-passo.is-proxima  { padding-right: 8px; }
.cabecalho-passo.is-anterior { padding-left: 8px; }

.cabecalho-passo:hover {
  background: var(--bg-hover);
  border-color: var(--border-color-light);
  color: var(--text-primary);
}

.cabecalho-passo[hidden] { display: none; }

.passo-seta {
  width: 13px;
  height: 13px;
  /* A seta anda um pouco no hover: reforça a direção sem precisar de rótulo
     maior. É deslocamento de 2px, não animação em laço. */
  transition: transform var(--transition-fast);
}

/* Mesmo ícone, virado. Um segundo chevron no catálogo seria a mesma forma
   escrita duas vezes, com o risco de as duas divergirem. */
.is-anterior .passo-seta { transform: rotate(180deg); }

.cabecalho-passo.is-proxima:hover  .passo-seta { transform: translateX(2px); }
.cabecalho-passo.is-anterior:hover .passo-seta { transform: rotate(180deg) translateX(2px); }

.cabecalho-toggle .icone,
.btn-config .icone,
.btn-sair .icone {
  width: 16px;
  height: 16px;
}

.trilha {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 13.5px;
  min-width: 0;
}

.trilha-categoria {
  color: var(--text-muted);
  white-space: nowrap;
}

.trilha-sep {
  color: var(--border-color-light);
}

.trilha-pagina {
  color: var(--text-primary);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cabecalho-dir {
  display: flex;
  align-items: center;
  gap: 13px;
  flex-shrink: 0;
}

/* ---------- Sequência (gamificação) ---------- */
/* Âncora do popover. O painel é posicionado a partir daqui, alinhado à direita
   para não vazar da janela quando o cabeçalho está no canto. */

/* ---------- Caixa de avisos ---------- */
/* Vizinha da pílula de sequência e do mesmo tamanho: as duas são o mesmo tipo
   de coisa — um resumo que abre num popover. */

.caixa {
  position: relative;
  flex-shrink: 0;
}

.caixa-botao {
  position: relative;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border: 1px solid var(--border-color-light);
  border-radius: 50%;
  background: var(--bg-secondary);
  color: var(--text-muted);
  transition: background var(--transition-fast), border-color var(--transition-fast),
              color var(--transition-fast);
}

.caixa-botao:hover {
  background: var(--bg-hover);
  border-color: var(--text-muted);
  color: var(--text-secondary);
}

.caixa-icone {
  width: 15px;
  height: 15px;
}

/* Com aviso novo, o botão acende em VERMELHO — não no âmbar da sequência que
   fica ao lado. As duas coisas são diferentes: o âmbar é um estado permanente
   (quantos dias você emendou), o vermelho é uma pendência que some quando você
   olha. Na mesma cor, o sino aceso se perdia dentro do bloco de gamificação. */
.caixa.is-nova .caixa-botao {
  background: var(--alerta-fundo);
  /* A cor e a borda são governadas pela animação; estes valores valem antes do
     primeiro quadro e quando a animação está desligada. */
  color: var(--alerta);
  border-color: var(--alerta-borda);
  animation: respirar-alerta 1.8s ease-in-out infinite;
}

/* Respiração, não pisca. O que diferencia uma da outra é a curva, não só o
   tempo: `ease-in-out` acelera e desacelera, então não há transição brusca em
   ponto nenhum e o olho lê como algo vivo em vez de um alarme. Por isso também
   não vai a zero — o mínimo é um vermelho apagado, não o cinza: o sino nunca
   deixa de parecer aceso, só varia de intensidade.
   Abaixo de ~1,2s a curva deixa de segurar a leitura e vira intermitência. */
@keyframes respirar-alerta {
  0%, 100% {
    color: var(--alerta-fraco);
    border-color: var(--alerta-borda-fraca);
    box-shadow: 0 0 0 0 rgba(238, 77, 77, 0);
  }
  50% {
    color: var(--alerta);
    border-color: var(--alerta-borda);
    box-shadow: 0 0 9px 0 var(--alerta-brilho);
  }
}

/* `prefers-reduced-motion` NÃO desliga esta animação, e isso é deliberado.
   A preferência existe para conter MOVIMENTO — o que desloca, escala ou faz
   parallax e provoca desconforto vestibular. Aqui nada se move: é uma variação
   de cor num elemento parado, do mesmo tipo que um `:hover` com transição.
   Desligá-la por completo era largo demais e tirava do usuário o único aviso
   de que há algo esperando por ele.
   O que a preferência corta é só o BRILHO, que é o que mais chama o olho
   periférico. O ritmo NÃO muda: alongar o ciclo aqui entregaria, justamente a
   quem tem a preferência ligada, uma versão mais lenta do que foi pedida. */
@media (prefers-reduced-motion: reduce) {
  @keyframes respirar-alerta {
    0%, 100% { color: var(--alerta-fraco); border-color: var(--alerta-borda-fraca); }
    50%      { color: var(--alerta);       border-color: var(--alerta-borda); }
  }
}

/* Sem aviso, o sino volta ao cinza da barra: vermelho permanente viraria
   paisagem e deixaria de chamar atenção quando houvesse algo de fato. */
/* Canto inferior esquerdo, e não o superior direito de praxe: ali a bolinha
   caía sobre a curva do sino e as duas formas redondas se confundiam. No canto
   oposto ela fica sobre a área vaga do desenho. */
.caixa-selo {
  position: absolute;
  bottom: 1px;
  left: 1px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--alerta);
  /* O anel recorta a bolinha do SINO, e o sino está no cabeçalho — que é
     --bg-secondary. Aqui estava --bg-primary, o que dava no mesmo enquanto os
     dois tons eram vizinhos no escuro; no tema claro deixariam de ser. */
  box-shadow: 0 0 0 2px var(--bg-secondary);
}

.caixa-selo[hidden] { display: none; }

.caixa-painel {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: 40;
  width: 320px;
  padding: 14px 6px 8px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--sombra-modal);
}

.caixa-painel[hidden] { display: none; }

.caixa-topo {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 0 12px 10px;
  border-bottom: 1px solid var(--border-color);
}

.caixa-titulo {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--fogo-tinta);
}

.caixa-contagem {
  margin-left: auto;
  font-size: 11px;
  color: var(--text-muted);
}

.caixa-lista {
  max-height: 320px;
  overflow-y: auto;
  padding: 6px 0 0;
  list-style: none;
}

.msg {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 9px 12px 10px;
  border-radius: var(--radius-md);
}

/* Só os avisos que levam a algum lugar reagem ao mouse. O de carga de dados é
   informação e fica inerte, sem prometer um destino que não tem. */
.msg.is-acionavel { cursor: pointer; }
.msg.is-acionavel:hover { background: var(--bg-tertiary); }

.msg.is-acionavel:focus-visible {
  outline: none;
  background: var(--bg-tertiary);
  box-shadow: inset 0 0 0 1px var(--fogo-borda);
}

.msg-icone {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  flex-shrink: 0;
  margin-top: 1px;
  border-radius: 50%;
  background: var(--bg-elevated);
  color: var(--text-secondary);
}

.msg-icone .icone { width: 13px; height: 13px; }

/* A cor do ícone diz o assunto sem precisar de rótulo: carga de dados em
   turquesa, progresso em âmbar. */
.msg--atualiza .msg-icone {
  background: rgba(79, 209, 197, 0.14);
  color: #4fd1c5;
}

.msg--nivel .msg-icone,
.msg--cosmetico .msg-icone {
  background: var(--fogo-fundo);
  color: var(--fogo-tinta);
}

.msg-corpo { min-width: 0; flex: 1; }

.msg-titulo {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-primary);
}

.msg-texto {
  margin-top: 2px;
  font-size: 11px;
  line-height: 1.45;
  color: var(--text-muted);
}

.msg-quando {
  flex-shrink: 0;
  font-size: 10px;
  color: var(--text-muted);
  white-space: nowrap;
  padding-top: 2px;
}

.seq {
  position: relative;
  flex-shrink: 0;
}

.seq-pilula {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  padding: 0 11px 0 9px;
  border: 1px solid var(--border-color-light);
  border-radius: 20px;
  background: var(--bg-secondary);
  color: var(--text-muted);
  transition: background var(--transition-fast), border-color var(--transition-fast),
              color var(--transition-fast);
}

.seq-pilula:hover {
  background: var(--bg-hover);
  border-color: var(--text-muted);
}

.seq-chama {
  width: 14px;
  height: 14px;
  flex-shrink: 0;
}

.seq-numero {
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.01em;
}

/* Com sequência viva a pílula acende em âmbar — cor de "fogo", deliberadamente
   fora da paleta de domínio para não ser lida como uma análise. */
.seq.is-ativa .seq-pilula {
  color: var(--fogo-tinta);
  border-color: var(--fogo-borda);
  background: var(--fogo-fundo);
}

.seq.is-ativa .seq-pilula:hover {
  border-color: var(--fogo);
}

/* ---------- Popover ---------- */

.seq-painel {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: 40;
  width: 260px;
  padding: 18px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--sombra-modal);
}

.seq-painel[hidden] {
  display: none;
}

.seq-titulo {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px 4px 8px;
  border: 1px solid var(--fogo-borda);
  border-radius: 20px;
  background: var(--fogo-fundo);
  color: var(--fogo-tinta);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.seq-destaque {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin-top: 14px;
}

.seq-destaque strong {
  font-size: 40px;
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
}

.seq-destaque span {
  font-size: 15px;
  font-weight: 600;
  color: var(--text-secondary);
}

.seq-frase {
  margin-top: 10px;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--text-secondary);
}

.seq-frase strong {
  color: var(--fogo-tinta);
  font-weight: 700;
}

/* Tirinha dos 7 dias: colunas iguais para as caixas ficarem alinhadas mesmo
   com letras de larguras diferentes. */
.seq-semana {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 6px;
  margin-top: 16px;
}

.seq-dia {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
}

.seq-dia-caixa {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 26px;
  border-radius: var(--radius-sm);
  background: var(--bg-elevated);
  border: 1px solid transparent;
  color: var(--fogo-tinta);
}

.seq-dia.is-ativo .seq-dia-caixa {
  background: var(--fogo-fundo);
  border-color: var(--fogo-borda);
}

/* Hoje ainda sem atividade: contorno cheio, convidando a marcar. */
.seq-dia.is-hoje:not(.is-ativo) .seq-dia-caixa {
  background: transparent;
  border-color: var(--fogo);
}

/* A tinta do check é FIXA, e não --bg-primary como era. O âmbar embaixo dela
   também é fixo (a gamificação fica de fora da troca de acento de propósito),
   então quem escreve sobre ele não pode acompanhar o tema: no claro o
   --bg-primary é claro, e daria branco sobre âmbar. */
.seq-dia.is-hoje.is-ativo .seq-dia-caixa {
  background: var(--fogo);
  color: #1e1603;
  border-color: var(--fogo);
}

.seq-check {
  width: 13px;
  height: 13px;
  stroke-width: 2.6;
}

/* Sábado e domingo: não contam para a sequência, então a caixa é só um
   contorno tracejado — presente, mas visivelmente fora da contagem. */
.seq-dia.is-bonus .seq-dia-caixa {
  background: transparent;
  border-style: dashed;
  border-color: var(--border-color-light);
}

.seq-dia.is-bonus.is-ativo .seq-dia-caixa {
  border-style: solid;
  border-color: var(--fogo-borda);
  background: var(--fogo-fundo);
}

/* Dias que ainda não chegaram: nem marcados, nem perdidos. */
.seq-dia.is-futuro .seq-dia-caixa {
  background: transparent;
  border: 1px solid var(--border-color);
}

.seq-dia.is-futuro .seq-dia-letra {
  color: var(--border-color-light);
}

.seq-dia-letra {
  font-size: 10px;
  font-weight: 600;
  color: var(--text-muted);
}

.seq-dia.is-ativo .seq-dia-letra {
  color: var(--fogo-tinta);
}

.seq-legenda {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border-color);
  font-size: 10.5px;
  line-height: 1.5;
  color: var(--text-muted);
}

.cabecalho-saudacao {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.35;
}

.saudacao-texto {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
}

.saudacao-data {
  font-size: 11px;
  color: var(--text-muted);
}

/* Mesmo tratamento do avatar da sidebar: fundo fixo, anel no acento do
   domínio. Menor, então um anel só (sem o respiro interno). */
.avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--bg-elevated);
  color: var(--text-primary);
  font-size: 12.5px;
  font-weight: 700;
  flex-shrink: 0;
  object-fit: cover;
  box-shadow: 0 0 0 2px var(--accent);
  transition: box-shadow var(--transition-base);
}

/* ---------- Conteúdo ---------- */

/* A tela de trabalho é a única superfície clara da interface: sidebar,
   cabeçalho e cartões ficam escuros em volta e por cima dela. A malha vive
   aqui, e não nas telas de análise: é fundo de página, e sumir ao sair de uma
   análise faria a interface parecer trocar de material. */
.conteudo {
  flex: 1;
  padding: 28px;
  background-color: var(--bg-canvas);
  background-image: var(--grade-pontos);
  background-size: var(--grade-passo) var(--grade-passo);
}

/* Estado vazio — enquanto as telas de análise não existem. */
.vazio {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: calc(100vh - var(--header-height) - 56px);
  gap: 14px;
}

.vazio-marca {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1px dashed var(--border-color-light);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent-tinta);
}

.vazio-marca .icone {
  width: 19px;
  height: 19px;
}

.vazio-titulo {
  font-size: 17px;
  font-weight: 600;
  color: var(--text-primary);
}

.vazio-texto {
  font-size: 13.5px;
  color: var(--text-secondary);
  max-width: 380px;
  line-height: 1.6;
}

/* ---------- Responsivo ---------- */

@media (max-width: 1000px) {
  .app { grid-template-columns: 224px 1fr; }
  .cabecalho-saudacao { display: none; }
  .conteudo { padding: 20px; }
}

@media (max-width: 720px) {
  /* A sidebar sai do fluxo e passa a sobrepor, senão sobra pouco espaço
     para o conteúdo.

     OS DOIS SELETORES SÃO NECESSÁRIOS, e não é redundância: `.app.is-recolhido`
     lá em cima tem DUAS classes, e media query NÃO SOMA ESPECIFICIDADE. Um
     `.app` sozinho aqui perde para ele — e como a sidebar vira `fixed` e sai do
     grid, o conteúdo caía na coluna do trilho e ficava com 72px de largura,
     com 303px de preto ao lado. Foi assim que o app apareceu no celular. */
  .app,
  .app.is-recolhido { grid-template-columns: 1fr; }

  .sidebar {
    position: fixed;
    left: 0; top: 0; bottom: 0;
    width: 268px;
    z-index: 30;
    transition: transform var(--transition-base);
  }
  /* FECHADA ATÉ O SHELL ESTAR DE PÉ, e esta é a metade que faltava.
     Quem fecha o menu no celular é `is-recolhido`, e essa classe é escrita
     dentro do `Shell.init` — que é assíncrono e espera a sessão antes de
     chegar lá. Até isso acontecer o `.app` não tem classe nenhuma, e "sem
     classe" significa ABERTO: o navegador pintava a sidebar por inteiro, e ela
     recolhia quando o JS enfim rodava.

     Era mais visível justamente onde incomoda — no celular, recarregando com a
     rede do aparelho, o retângulo de 268px ficava lá o tempo da consulta. E
     nem conteúdo tinha: `montarSidebar` também só roda no init, então o que
     aparecia era uma faixa escura vazia.

     `is-pronto` é escrita no fim do init. Antes dela, o menu está fechado
     porque ainda não houve chance de ninguém pedir para abri-lo — que é a
     verdade, dita em CSS e sem depender de JavaScript algum ter rodado. */
  .app:not(.is-pronto) .sidebar,
  .app.is-recolhido .sidebar { transform: translateX(-100%); }

  /* O fundo que escurece o resto quando o menu está aberto. Existe por um
     motivo prático e não decorativo: com a sidebar aberta em 268px de 375, ela
     cobre o botão que a fecha — o app abria no celular sem saída. Tocar fora
     agora fecha, que é o gesto que todo mundo tenta primeiro. */
  .sidebar-fundo {
    position: fixed;
    inset: 0;
    z-index: 29;              /* abaixo da sidebar (30), acima de todo o resto */
    background: rgba(0, 0, 0, 0.55);
    border: none;
    opacity: 1;
    transition: opacity var(--transition-base);
  }

  /* Menu fechado: o fundo some. `visibility` junto com `opacity` porque só
     transparente ele continuaria interceptando o toque. */
  .app:not(.is-pronto) .sidebar-fundo,
  .app.is-recolhido .sidebar-fundo {
    opacity: 0;
    visibility: hidden;
  }

  /* E SEM TRANSIÇÃO até estar pronto. Com ela, o instante em que `is-pronto`
     entra viraria uma animação de 200ms da sidebar deslizando para fora — que
     é exatamente o lampejo que esta regra existe para evitar, só que mais
     lento e mais chamativo. A transição volta assim que o shell assume, e é aí
     que ela serve: para o gesto de abrir e fechar. */
  .app:not(.is-pronto) .sidebar,
  .app:not(.is-pronto) .sidebar-fundo { transition: none; }

  .cabecalho { padding: 0 18px; }

  /* UMA BARRA DE ROLAGEM SÓ, e ela é a da página.
     Aqui havia `overflow-y: auto`, escrito quando `.conteudo` tinha
     `overflow: hidden` no desktop e o conteúdo do celular era recortado. Esse
     `hidden` não existe mais — a regra base de `.conteudo` não tem overflow
     nenhum —, e o que sobrou foi um segundo contexto de rolagem aninhado dentro
     do primeiro.
     No celular isso é o pior caso possível: o dedo rola um dos dois conforme
     onde encostou, e a página parece travar sem motivo. Sem a linha, o conteúdo
     cresce e quem rola é a página, que é o que se espera de uma. */
}

/* Fora do celular o fundo não existe: no desktop a sidebar divide espaço com o
   conteúdo em vez de cobri-lo, e escurecer a tela não faria sentido nenhum. */
@media (min-width: 721px) {
  .sidebar-fundo { display: none; }
}

/* ============================================================
   Configurações — o menu da engrenagem
   ============================================================
   Mesma anatomia dos outros dois popovers do cabeçalho (sequência e avisos):
   invólucro relativo, painel ancorado à direita e escondido por `hidden`. Os
   três compartilham o fechar-ao-clicar-fora e o Esc, num handler só. */

.cfg { position: relative; }

.cfg-painel {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  z-index: 40;
  width: 300px;
  padding: 8px;
  background: var(--bg-secondary);
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  box-shadow: var(--sombra-modal);
}

.cfg-painel[hidden] { display: none; }

.cfg-titulo {
  padding: 6px 10px 8px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.cfg-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  width: 100%;
  padding: 9px 10px;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  text-align: left;
  cursor: pointer;
  transition: background var(--transition-fast);
}

.cfg-item:hover { background: var(--bg-tertiary); }

.cfg-item-icone { display: flex; padding-top: 1px; color: var(--brand); }
.cfg-item-icone .icone { width: 15px; height: 15px; }

.cfg-item-txt { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.cfg-item-nome { font-size: 12.5px; font-weight: 600; color: var(--text-primary); }
.cfg-item-nota { font-size: 10.5px; line-height: 1.4; color: var(--text-muted); }

/* Situação atual da opção, à direita. Sem ela um menu de liga-desliga não diz
   se está ligado — e aí a única forma de saber é acionando. */
.cfg-item-estado {
  flex: 0 0 auto;
  align-self: center;
  padding: 2px 8px;
  border-radius: 999px;
  border: 1px solid var(--border-color);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-muted);
}

/* ---------- Controles da apresentação ----------
   No cabeçalho, ao lado da trilha: enquanto a apresentação roda, esta é a única
   faixa da tela que não muda a cada vinte segundos — e é onde a mão volta para
   pausar. Antes ficavam numa barra flutuando no rodapé, longe de tudo. */

.slide-ctrl {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-left: 14px;
  padding: 4px 5px 4px 11px;
  border: 1px solid var(--border-color-light);
  border-radius: 999px;
  background: var(--bg-tertiary);
}

.slide-ctrl[hidden] { display: none; }

.slide-rot {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text-secondary);
  white-space: nowrap;
}

/* Ponto que pulsa: diz "está correndo" sem um relógio regressivo, que exigiria
   um segundo temporizador só para redesenhar o número. Parado quando pausado —
   é o sinal mais direto de que o tempo não está passando. */
.slide-pulso {
  width: 8px;
  height: 8px;
  flex: 0 0 8px;
  border-radius: 50%;
  background: var(--brand);
  animation: slide-pulso 1.6s ease-in-out infinite;
}

.slide-ctrl.is-pausado .slide-pulso {
  animation: none;
  background: var(--text-muted);
}

.slide-ctrl.is-pausado .slide-rot { color: var(--text-muted); }

@keyframes slide-pulso {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.25; }
}

@media (prefers-reduced-motion: reduce) {
  .slide-pulso { animation: none; }
}

.slide-bt {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background var(--transition-fast), color var(--transition-fast);
}

.slide-bt:hover { background: var(--bg-hover); color: var(--text-primary); }
.slide-bt .icone { width: 13px; height: 13px; }

/* Parar é a ação destrutiva do grupo: encerra a apresentação, e não é o que se
   quer ao passar o mouse procurando a pausa. Vermelho só no hover — colorido em
   repouso ele puxaria o olho de volta a cada troca de tela. */
.slide-bt.is-parar:hover {
  background: var(--danger-soft);
  color: var(--danger-tinta);
}

/* ---------- Suporte ---------- */

.sup-dialogo {
  width: min(440px, calc(100vw - 32px));
  /* O reset global zera a margem de tudo, e é justamente o `margin: auto` que
     centraliza um `<dialog>` modal contra o `inset: 0` do navegador. */
  margin: auto;
  padding: 0;
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  background: var(--bg-secondary);
  color: var(--text-primary);
  overflow: hidden;
}

.sup-dialogo::backdrop { background: var(--veu-modal); }

.sup-fechar {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  background: var(--bg-tertiary);
  color: var(--text-muted);
  cursor: pointer;
}

.sup-fechar:hover { color: var(--text-primary); background: var(--bg-hover); }
.sup-fechar .icone { width: 13px; height: 13px; }

.sup { padding: 24px; }

.sup-rot {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--brand);
  margin-bottom: 8px;
}

.sup-rot .icone { width: 14px; height: 14px; }

.sup-titulo {
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -0.02em;
  margin-bottom: 10px;
}

.sup-texto {
  font-size: 12.5px;
  line-height: 1.65;
  color: var(--text-secondary);
  margin-bottom: 16px;
}

.sup-texto strong { color: var(--text-primary); }

.sup-canais { display: flex; flex-direction: column; gap: 6px; }

.sup-canal {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 12px;
  border: 1px solid var(--border-color);
  border-radius: var(--radius-sm);
  background: var(--bg-tertiary);
  color: var(--text-secondary);
  font-size: 12.5px;
  text-decoration: none;
  transition: border-color var(--transition-fast), color var(--transition-fast);
}

.sup-canal:hover { color: var(--text-primary); border-color: var(--border-color-light); }
.sup-canal .icone { width: 15px; height: 15px; color: var(--brand); }

.sup-pe {
  margin-top: 16px;
  padding-top: 13px;
  border-top: 1px solid var(--border-color);
  font-size: 11px;
  line-height: 1.55;
  color: var(--text-muted);
}


/* ============================================================
   CELULAR — o cabeçalho escolhe o que cabe
   ============================================================
   Medido em 375px: os itens somavam 319px mais espaçamentos, e o resultado não
   era "apertado" — era SOBREPOSTO. O `.cabecalho-esq` encolhia para 29px
   segurando um botão de 34, e a trilha continuava pintando texto por cima dos
   controles da direita.

   Não dá para diminuir tudo até caber: seriam nove alvos de toque de 20px numa
   faixa de 48. A saída é escolher o que sai — e o critério é a REDUNDÂNCIA:
   fica o que não existe em outro lugar da tela.
   ============================================================ */

@media (max-width: 720px) {
  /* O botão do menu não encolhe. Ele é a única saída da tela quando o menu
     está fechado; espremê-lo foi o que criou a sobreposição. */
  .cabecalho-esq { flex-shrink: 0; }

  /* SAI A TRILHA: logo abaixo dela está o título da análise, em corpo grande.
     Dizer "Logística › Visão Executiva" acima de um "Visão Executiva" é gastar
     a faixa mais disputada da tela para repetir. */
  .trilha { display: none; }

  /* ANTERIOR E PRÓXIMA FICAM, mas só como seta.
     Eles saíam daqui porque custavam 100px e chegavam truncados a "Próxi…" —
     e o problema era o RÓTULO, não o botão. Sem o texto cada um vira um alvo
     de 32px, o mesmo tamanho do "?" e do tema ao lado, e passar de uma análise
     para a outra deixa de exigir abrir a gaveta e achar o item seguinte.

     O `title` continua lá para quem usa leitor de tela ou passa o dedo. */
  /* Colados na borda: o `.cabecalho` já tem 18px de respiro lateral, e um
     `margin-left` em cima disso empurrava o par para o meio da faixa. Negativo
     porque a seta é um ícone redondo e o olho lê a borda do CÍRCULO, não a
     caixa dele — 2px a menos e ele encosta onde parece encostar. */
  .cabecalho-passos { margin-left: -2px; gap: 6px; }

  /* CENTRADO DE VERDADE. O estilo base tem `padding: 5px 11px` para o par
     ícone+texto e, logo abaixo, um `padding` menor do lado da seta — os dois
     sobreviviam ao `width: 32px` e empurravam o chevron para fora do meio do
     círculo. Zerar o padding e mandar centrar nos dois eixos é o que faltava. */
  .cabecalho-passo {
    width: 32px;
    height: 32px;
    padding: 0 !important;
    justify-content: center;
    align-items: center;
    gap: 0;
    border-radius: 50%;
  }

  .cabecalho-passo span { display: none; }
  .cabecalho-passo .passo-seta { width: 15px; height: 15px; }

  /* NAS ANÁLISES, SÓ O AVATAR.
     Com as duas setas na barra, o nome e o cargo chegavam a "Luc… / Anali…" —
     e um nome truncado não informa nem enfeita. O retrato com o nível já diz
     quem está logado, que é o que aquele canto precisa dizer.

     `:has(.cabecalho-passo:not([hidden]))` e não uma classe no `<body>`: os
     botões já nascem com `hidden` quando não há análise aberta, e essa é a
     mesma condição — perguntar ao DOM evita um segundo lugar para manter em
     concordância com o primeiro. */
  .cabecalho:has(.cabecalho-passo:not([hidden])) .cab-eu-txt { display: none; }
  .cabecalho:has(.cabecalho-passo:not([hidden])) .cabecalho-eu { padding-right: 0; }

  /* SAI O AVATAR: o mesmo retrato, maior e com nome e cargo, abre o menu.
     E o caminho para o perfil continua lá dentro. */
  .cabecalho-dir .avatar { display: none; }

  /* FICAM: menu, avisos, sequência, tema, configurações e sair — 223px, que
     cabem com folga. Nenhum deles aparece em outro lugar da tela. */
}


/* ============================================================
   BARRA INFERIOR — a navegação do celular
   ============================================================
   Só existe abaixo de 720px. No desktop a sidebar já é a navegação, e uma
   segunda barra seria um segundo caminho para o mesmo lugar.

   Fica embaixo porque é onde o polegar alcança. A mão que segura o aparelho
   não chega ao topo sem trocar a pegada — e é por isso que iPhone, Instagram e
   quase todo aplicativo puseram a navegação ali, depois de anos com ela no
   cabeçalho.
   ============================================================ */

.barra-mobile,
.folha,
.folha-fundo { display: none; }

@media (max-width: 720px) {
  /* A altura da barra, publicada como variável. Quem lê: o botão flutuante do
     assistente (assistente.css), que precisa pousar ACIMA dela. Sem um número
     compartilhado, os dois arquivos guardariam 56px cada um, e mudar a barra
     deixaria o botão sobreposto a ela sem ninguém perceber.

     Só existe dentro deste @media, e é por isso que o outro lado usa
     `var(--barra-inferior-altura, 0px)`: no desktop não há barra, e o zero do
     fallback é a resposta certa. */
  :root { --barra-inferior-altura: 56px; }

  .barra-mobile {
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 28;                     /* abaixo da sidebar (30) e do fundo (29) */
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    background: var(--bg-secondary);
    border-top: 1px solid var(--border-color);
    /* A faixa do iPhone. `env()` vale zero em aparelho sem ela, então a mesma
       linha serve os dois — e sem isso o último botão fica sob a barra de
       gestos, que o sistema intercepta antes da página. */
    padding-bottom: env(safe-area-inset-bottom, 0px);
  }

  .barra-bt {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    /* 56px de altura: abaixo disso o alvo fica menor que a recomendação de
       toque (44px) somada ao rótulo. */
    min-height: 56px;
    padding: 7px 4px 8px;
    background: none;
    border: none;
    font: inherit;
    color: var(--text-secondary);
    cursor: pointer;
    transition: color var(--transition-fast);
  }

  .barra-bt:active { color: var(--accent-tinta); }

  .barra-bt svg {
    width: 21px;
    height: 21px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.9;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  .barra-rot {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.01em;
  }

  /* O retrato entra no lugar do ícone, no mesmo tamanho, para os quatro alvos
     terem o mesmo peso visual. */
  .barra-avatar {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    object-fit: cover;
  }

  .barra-bt--perfil .barra-avatar.is-sem-foto {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-terciario, rgba(255,255,255,0.06));
  }

  .barra-avatar.is-sem-foto svg { width: 13px; height: 13px; }

  /* A bolinha de aviso novo. Espelha a do sino — quem decide é o código da
     caixa; aqui é só reflexo. */
  .barra-bt { position: relative; }

  .barra-selo {
    position: absolute;
    top: 8px;
    right: calc(50% - 16px);
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--negativo, #e5484d);
    border: 2px solid var(--bg-secondary);
  }

  .barra-selo[hidden] { display: none; }

  /* O conteúdo precisa terminar ACIMA da barra, senão o último cartão fica
     escondido atrás dela — e ninguém rola o que não sabe que existe.
     O valor sai da variável que mede a barra, no fim deste arquivo. */

  /* O botão de menu do CABEÇALHO sai: a barra assumiu esse papel, e dois
     botões para a mesma coisa em telas opostas é confusão, não redundância. */
  .cabecalho-toggle { display: none; }

  /* Avisos SAI do cabeçalho: a barra inferior passou a oferecê-lo, e o mesmo
     sino em dois lugares da mesma tela é duplicação — a bolinha acenderia nos
     dois e a pessoa tocaria no que estivesse mais perto, sem saber que era o
     mesmo. Fica o que a barra NÃO tem: o voltar e a sequência. */
  /* Some o SINO, não o `.caixa` inteiro: o botão da barra clica neste sino
     para reaproveitar a marcação de lido, e um contêiner escondido levaria o
     painel junto — o toque não mostraria nada. */
  .cabecalho-dir .caixa-botao { display: none; }

  /* O MENU DA ENGRENAGEM, pelo mesmo motivo e com a mesma forma do de avisos.
     Ele é aberto pelo item "Configurações" da folha da conta — que sobe da
     base, junto do dedo — e abria ancorado no cabeçalho, a uma tela de
     distância de onde o toque aconteceu. Duas gavetas em cantos opostos para
     um gesto só.

     `max-height` menor que a de avisos: esta lista tem cinco itens com nome e
     descrição, e sem teto ela cobriria a tela inteira. */
  .cfg-painel {
    position: fixed;
    left: 8px; right: 8px; top: auto;
    bottom: calc(66px + env(safe-area-inset-bottom, 0px));
    z-index: 41;
    width: auto;
    max-height: 70vh;
    overflow-y: auto;
  }

  /* E o painel deixa de pender do cabeçalho: ancorado nele, abriria no topo,
     longe do dedo que acabou de tocar embaixo. Vira folha, como a da conta. */
  .caixa-painel {
    position: fixed;
    left: 8px; right: 8px; top: auto;
    bottom: calc(66px + env(safe-area-inset-bottom, 0px));
    z-index: 41;
    width: auto;
    max-height: 60vh;
    overflow-y: auto;
  }

  /* E com ele saem os controles que a folha da conta oferece — Configurações e
     Sair estão lá dentro, com nome e descrição.

     O TEMA FICA, ao lado do "?". Ele estava nesta lista, e a folha prometia
     "Tema e suporte" num item que abre o menu da engrenagem — onde tema não
     existe: a lista de lá tem Slide Show, Portal, Instalar, Refazer o tour e
     Suporte. O resultado é que no celular NÃO HAVIA como trocar o tema, e a
     única pista apontava para o lugar errado.

     Devolvê-lo ao cabeçalho é o conserto mais curto e o mais honesto: trocar
     de claro para escuro é um interruptor, e interruptor mora à vista — não a
     dois toques dentro de uma folha e um menu. */
  .cabecalho-dir .btn-config,
  .cabecalho-dir #btn-sair { display: none; }

  /* ---------- A folha da conta ---------- */
  /* Sobe da base, e não é popover ancorado ao botão: ancorada, abriria para
     cima com 4px de folga e nasceria colada na borda da tela. */

  .folha-fundo {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 40;
    background: rgba(0, 0, 0, 0.55);
  }

  .folha {
    display: block;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 41;
    padding: 8px 10px calc(14px + env(safe-area-inset-bottom, 0px));
    background: var(--bg-secondary);
    border-top: 1px solid var(--border-color-light);
    border-radius: 16px 16px 0 0;
    box-shadow: var(--sombra-modal);
  }

  .folha[hidden],
  .folha-fundo[hidden] { display: none; }

  .folha-topo {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 12px 14px;
    border-bottom: 1px solid var(--border-color);
    margin-bottom: 6px;
  }

  .folha-avatar {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
  }

  .folha-avatar.is-sem-foto {
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-terciario, rgba(255,255,255,0.06));
  }

  .folha-avatar.is-sem-foto svg { width: 22px; height: 22px; }

  .folha-nome {
    margin: 0;
    font-size: 14.5px;
    font-weight: 700;
    color: var(--text-primary);
  }

  .folha-cargo {
    margin: 2px 0 0;
    font-size: 12px;
    color: var(--text-secondary);
  }

  .folha-item {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    /* 52px: alvo confortável para o polegar numa lista vertical. */
    min-height: 52px;
    padding: 8px 12px;
    background: none;
    border: none;
    border-radius: var(--radius-md);
    font: inherit;
    text-align: left;
    color: var(--text-primary);
    cursor: pointer;
  }

  .folha-item:active { background: var(--bg-hover, rgba(255,255,255,0.05)); }

  .folha-item-icone {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    border-radius: var(--radius-sm);
    background: var(--bg-terciario, rgba(255,255,255,0.06));
    color: var(--accent-tinta);
  }

  .folha-item-icone svg {
    width: 17px; height: 17px;
    fill: none; stroke: currentColor; stroke-width: 1.9;
    stroke-linecap: round; stroke-linejoin: round;
  }

  .folha-item-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
  .folha-item-nome { font-size: 14px; font-weight: 600; }
  .folha-item-nota { font-size: 11.5px; color: var(--text-secondary); }

  /* O SLIDE SHOW some do menu de configurações no celular. É modo de
     apresentação em TV: escolher telas e tempos numa lista de 21 itens no
     aparelho é tarefa que ninguém termina. Escondido por CSS e não removido da
     lista, para o desktop continuar com ele sem uma segunda lista para manter. */
  .cfg-item[data-acao="slideshow"] { display: none; }

  /* E o PORTAL sai daqui porque a folha da conta passou a oferecê-lo direto,
     um toque antes. Mantê-lo nos dois faria a mesma tela aparecer em dois
     níveis do mesmo menu — quem visse um não saberia do outro. */
  .cfg-item[data-acao="admin"] { display: none; }
}

/* ============================================================
   Identidade no cabeçalho — só no celular
   ============================================================
   Em telas estreitas a barra lateral vira gaveta, e com ela some o único lugar
   que mostrava quem está logado, em que nível e com que cargo. O que sobrava no
   topo era a saudação — "Bom dia, Lucas" e a data por extenso —, que gasta duas
   linhas para dizer menos do que um nome e um cargo.

   Aqui a mesma informação da sidebar entra DEITADA, que é a forma que cabe numa
   barra de 56px: retrato à esquerda com o selo de nível, nome e cargo
   empilhados à direita. */

.cabecalho-eu { display: none; }

@media (max-width: 720px) {
  /* A saudação e o avatar solto saem: os dois viram este bloco. */
  .cabecalho-dir .cabecalho-saudacao,
  .cabecalho-dir > .avatar { display: none; }

  .cabecalho-eu {
    display: flex;
    align-items: center;
    gap: 9px;
    min-width: 0;
    padding: 3px 6px 3px 3px;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: inherit;
    cursor: pointer;
    text-align: left;
  }

  .cabecalho-eu:active { background: var(--bg-tertiary); }

  .cab-eu-retrato {
    position: relative;
    flex: none;
    display: block;
    width: 32px;
    height: 32px;
  }

  .cab-eu-avatar {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    object-fit: cover;
    display: block;
    border: 1px solid var(--border-color);
    background: var(--bg-tertiary);
  }

  .cab-eu-avatar.is-sem-foto {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
  }

  .cab-eu-avatar.is-sem-foto .avatar-marca { width: 17px; height: 17px; }

  /* SÓ O NÚMERO, sem o "Nv.". Ele cabe no retrato grande da sidebar e não cabe
     num disco de 16px — e ao lado do nome e do cargo o número não fica ambíguo
     como ficaria sozinho no canto de um avatar, onde aquele lugar costuma
     significar contagem de avisos. */
  .cab-eu-nivel {
    position: absolute;
    right: -3px;
    bottom: -3px;
    min-width: 16px;
    height: 16px;
    padding: 0 3px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 9.5px;
    font-weight: 800;
    line-height: 1;
    color: var(--on-accent);
    background: var(--accent);
    border: 2px solid var(--bg-primary);
    border-radius: 999px;
  }

  .cab-eu-nivel[hidden] { display: none; }

  /* `min-width: 0` para o texto poder encolher dentro do flex — sem isso um
     nome comprido empurra a sequência e os avisos para fora da barra em vez de
     ser cortado. */
  .cab-eu-txt {
    display: flex;
    flex-direction: column;
    gap: 1px;
    min-width: 0;
  }

  .cab-eu-nome,
  .cab-eu-cargo {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 34vw;
  }

  .cab-eu-nome {
    font-size: 12.5px;
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1.15;
  }

  .cab-eu-cargo {
    font-size: 10.5px;
    color: var(--text-muted);
    line-height: 1.15;
  }

  /* A FOLGA DO RODAPÉ, refeita a partir da variável.
     Era `72px` escrito à mão, um número que não correspondia a nada: a barra
     mede `--barra-inferior-altura` mais a faixa de gestos do aparelho. E o
     `env()` só passou a valer agora, com o `viewport-fit=cover` no meta — sem
     ele o iPhone devolve zero, e era por isso que a barra cobria o rodapé de
     "Filtro aplicado" mesmo com o cálculo aqui parecendo certo. */
  .conteudo {
    padding-bottom: calc(var(--barra-inferior-altura, 56px) + 40px
                         + env(safe-area-inset-bottom, 0px));
  }
}

/* ============================================================
   Instalar no iPhone
   ============================================================
   O iOS não dispara `beforeinstallprompt` em navegador nenhum — nem no Safari,
   nem no Chrome do iPhone, que por baixo é o mesmo motor. Lá a instalação é um
   gesto manual, e o item de menu sumia justamente onde instalar mais importa:
   um aplicativo na tela inicial do celular é o que faz a plataforma ser aberta
   de novo amanhã.

   O que se pode fazer é ensinar o gesto. Ver `montarInstalarIOS` no shell.js. */

.ios-dialogo {
  width: min(400px, calc(100vw - 32px));
  /* O reset global zera a margem de tudo, e é o `margin: auto` que centraliza
     um `<dialog>` modal contra o `inset: 0` do navegador. Mesma nota do
     `.sup-dialogo` — e a repetição aqui é de propósito: quem mexer neste bloco
     não vai ler o outro. */
  margin: auto;
  padding: 22px 22px 18px;
  border: 1px solid var(--border-color-light);
  border-radius: var(--radius-lg);
  background: var(--bg-secondary);
  color: var(--text-primary);
}

.ios-dialogo::backdrop { background: var(--veu-modal); }

.ios-titulo {
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -0.02em;
  margin-bottom: 8px;
}

.ios-texto {
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-secondary);
}

.ios-passos {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 18px 0;
  padding: 0;
  list-style: none;
}

.ios-passos li {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--text-secondary);
}

.ios-passos b { color: var(--text-primary); }

.ios-num {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  font-size: 11.5px;
  font-weight: 800;
  color: var(--on-accent);
  background: var(--accent);
}

/* O ícone de compartilhar fica NA LINHA do texto, alinhado pela base, porque
   ele é parte da frase — "toque em Compartilhar [ícone]" — e não uma ilustração
   ao lado dela. É esse desenho que a pessoa vai procurar na barra do Safari;
   descrevê-lo por escrito só funciona para quem já sabe qual é. */
.ios-icone {
  display: inline-flex;
  vertical-align: -4px;
  margin-left: 4px;
  padding: 2px;
  border-radius: 5px;
  background: var(--bg-tertiary);
  color: var(--accent);
}

.ios-icone svg { width: 15px; height: 15px; }

.ios-nota {
  font-size: 11.5px;
  line-height: 1.55;
  color: var(--text-muted);
  padding-top: 12px;
  border-top: 1px solid var(--border-color);
  margin-bottom: 16px;
}

.ios-nota b { color: var(--text-secondary); }

/* Estilo próprio, e não `.btn-primario`: aquele mora no perfil.css, que só é
   carregado na tela de perfil — e este diálogo abre de qualquer página. Um
   botão sem estilo em cinco das seis telas é o tipo de defeito que só aparece
   depois de publicado. */
.ios-bt {
  width: 100%;
  padding: 10px 16px;
  font-size: 13px;
  font-weight: 700;
  color: var(--on-accent);
  background: var(--accent);
  border: 0;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: filter var(--transition-base);
}

.ios-bt:hover { filter: brightness(1.08); }

/* ============================================================
   Celular: a identidade à esquerda, o resto à direita
   ============================================================
   A primeira versão pôs o bloco de identidade onde ele nasceu no HTML — no meio
   do grupo da direita, entre a sequência e o botão de ajuda. Lido na tela, o
   resultado era um cabeçalho com tudo amontoado à direita e o canto esquerdo
   vazio.

   Quem é você fica à ESQUERDA, que é onde se lê primeiro e onde a barra lateral
   o mostrava. Sequência e ajuda vão para a direita, juntos: os dois são
   controles, e controles moram no mesmo canto.

   Feito por `order` e não remontando o HTML: a marcação continua sendo uma só
   para as duas larguras, e o desktop — onde este bloco nem aparece — não fica
   sabendo. */

@media (max-width: 720px) {
  /* A direita passa a ocupar a faixa inteira, senão o `margin-right: auto`
     abaixo não tem espaço para empurrar contra. */
  .cabecalho-dir {
    flex: 1;
    min-width: 0;
    gap: 10px;
  }

  /* `order: -1` o leva para o começo do grupo; `margin-right: auto` empurra
     todo o resto para a outra ponta. */
  .cabecalho-eu {
    order: -1;
    margin-right: auto;
  }

  /* Sequência e ajuda mantêm a ordem em que estão no HTML — a sequência antes
     do "?" —, e as duas ficam depois do vão. */
  .cabecalho-dir .seq,
  .cabecalho-dir .btn-ajuda { flex: none; }
}

/* ============================================================
   A FAIXA DE CIMA — instalado na tela de início do iPhone
   ============================================================
   Aqui o `apple-mobile-web-app-status-bar-style` é `black-translucent`, e ele
   faz o que promete: a página ocupa a tela INTEIRA, por baixo do relógio, do
   sinal e da bateria. No navegador isso não aparece, porque a barra de endereço
   ocupa esse espaço; instalado, o cabeçalho nasce debaixo do relógio.

   O efeito não é só estético. Com o assistente aberto, o "X" de fechar fica sob
   a bateria — e a área de toque ali pertence ao sistema, não à página. O painel
   abria e não fechava.

   `env(safe-area-inset-top)` é a altura que o aparelho reserva, e vale zero em
   tudo que não tem entalhe — a mesma regra serve ao iPhone 12, ao SE e ao
   Android. Ela só passou a existir com o `viewport-fit=cover` no meta, que
   entrou na 1.11.0 pelo lado de baixo; este é o lado de cima da mesma moeda.
   ============================================================ */

.cabecalho {
  padding-top: env(safe-area-inset-top, 0px);
  /* A altura CRESCE com a faixa, em vez de o conteúdo subir para dentro dela.
     Só `padding-top` deixaria o cabeçalho com a altura de sempre e o conteúdo
     espremido na metade de baixo. */
  height: calc(var(--header-height) + env(safe-area-inset-top, 0px));
}

/* A gaveta vai do topo à base da tela, então tem a mesma faixa a respeitar —
   sem isto o retrato e o nível ficam debaixo do relógio quando ela abre. */
.sidebar { padding-top: env(safe-area-inset-top, 0px); }
