/*
  A PALETA É A DA MARCA, e a marca mora em `assets/brand/README.md`.

  Core `#2563EB` no claro e `#3B82F6` no escuro, QA `#111827` e `#FFFFFF`. Os valores
  neutros e de estado acompanham o manual do cliente (`manual.html`).

  OS NOMES SÃO OS DAQUI, OS VALORES SÃO OS DE LÁ. O manual chama a tinta de `--ink` e o
  filete de `--line`; esta folha os chama de `--graphite` e `--mist`, e umas sessenta
  regras dependem disso. A correspondência, para quem for comparar as duas:

      manual            aqui              manual            aqui
      --ink             --graphite        --line            --mist
      --ink-soft        --slate           --line-soft       --mist-soft
      --ink-dim         --slate-dim       --accent-line     --accent-border
      --green           --positive        --amber           --warning
      --red             --danger

  Sem Tailwind e sem build: esta folha é servida direta pelo control plane.
*/
:root{
  --paper:#f9fafb; --surface:#ffffff; --warm:#f3f4f6;
  --mist:#e5e7eb; --mist-soft:#f0f2f5;
  --slate:#4b5563; --slate-dim:#6b7280; --graphite:#111827;
  /*
    O ACENTO TEM DUAS FORMAS, e a diferença aparece no botão primário.

    `--accent` é o azul do TEXTO e do filete: ele clareia no tema escuro, senão sumiria
    contra o fundo. `--accent-solid` é o azul do PREENCHIMENTO, e ele não muda entre os
    temas — é sobre ele que se escreve branco nos dois. Com um token só, o botão primário
    do tema escuro ficava azul-claro e obrigava a inverter a tinta para escura, que é uma
    peça com dois desenhos em vez de uma.
  */
  --accent:#2563eb; --accent-hover:#1d4ed8;
  --accent-solid:#2563eb; --accent-solid-hover:#1d4ed8;
  --accent-soft:#eff6ff; --accent-border:#bfdbfe;
  --positive:#16794a; --danger:#b42318; --danger-soft:#fff2f1;
  --warning:#a15c00; --warning-soft:#fff8e8;
  --radius:10px;
  /*
    Duas elevações: `--shadow-sm` assenta uma superfície um milímetro acima do papel, e
    `--shadow` descola dele o que flutua.
  */
  --shadow:0 18px 44px rgb(17 24 39 / .12);
  --shadow-sm:0 1px 2px rgb(17 24 39 / .05);
  /*
    A paleta CATEGÓRICA dos gráficos.

    Seis e não uma rampa: séries são categorias, não graus, e uma rampa contínua faz o
    olho ler ordem onde não há. A primeira é o cobalto da marca, então um gráfico de série
    única sai na cor do console em vez de introduzir uma sétima cor na tela.

    A quarta é púrpura e não violeta. Violeta é o vizinho de hue do cobalto, e duas séries
    adjacentes num gráfico de barras é onde a paleta falha primeiro.
  */
  --c1:#2563eb; --c2:#16794a; --c3:#a15c00; --c4:#9333ea; --c5:#0e7490; --c6:#b42318;
}
/*
  Três estados, não dois: claro, escuro, e "o que o sistema disser" — que é o
  padrão e não carimba nada. Por isso o bloco de mídia e o de atributo repetem os
  mesmos tokens: a escolha manual precisa vencer o sistema NOS DOIS sentidos, e uma
  cor definida só dentro de um deles não existe no estado sem carimbo.
*/
@media (prefers-color-scheme:dark){:root:not([data-theme=light]){
  color-scheme:dark;
  --paper:#0b0d10; --surface:#11151a; --warm:#171c23;
  --mist:#29313b; --mist-soft:#202731;
  --slate:#c0c7d1; --slate-dim:#8b95a4; --graphite:#f9fafb;
  /* O preenchimento não clareia; a tinta sobre ele continua branca nos dois temas. */
  --accent:#60a5fa; --accent-hover:#93c5fd;
  --accent-solid:#2563eb; --accent-solid-hover:#1d4ed8;
  --accent-soft:#122341; --accent-border:#315b9e;
  --positive:#4ade80; --danger:#fca5a5; --danger-soft:#321616;
  --warning:#fbbf24; --warning-soft:#2b220f;
  --shadow:0 20px 48px rgb(0 0 0 / .38);
  --shadow-sm:0 1px 2px rgb(0 0 0 / .24);
  /* Os mesmos seis papéis, com luminância que funciona sobre fundo escuro. */
  --c1:#60a5fa; --c2:#4ade80; --c3:#fbbf24; --c4:#c084fc; --c5:#22d3ee; --c6:#fca5a5;
}}
:root[data-theme=dark]{
  color-scheme:dark;
  --paper:#0b0d10; --surface:#11151a; --warm:#171c23;
  --mist:#29313b; --mist-soft:#202731;
  --slate:#c0c7d1; --slate-dim:#8b95a4; --graphite:#f9fafb;
  --accent:#60a5fa; --accent-hover:#93c5fd;
  --accent-solid:#2563eb; --accent-solid-hover:#1d4ed8;
  --accent-soft:#122341; --accent-border:#315b9e;
  --positive:#4ade80; --danger:#fca5a5; --danger-soft:#321616;
  --warning:#fbbf24; --warning-soft:#2b220f;
  --shadow:0 20px 48px rgb(0 0 0 / .38);
  --shadow-sm:0 1px 2px rgb(0 0 0 / .24);
  /* Os mesmos seis papéis, com luminância que funciona sobre fundo escuro. */
  --c1:#60a5fa; --c2:#4ade80; --c3:#fbbf24; --c4:#c084fc; --c5:#22d3ee; --c6:#fca5a5;
}

/*
  `hidden` PRECISA vencer, e por padrão ele perde.

  O atributo `hidden` vale `display:none` pela folha do navegador — que é a de MENOR
  precedência. Qualquer regra nossa que declare `display` ganha dela, e as duas telas do
  console do cliente declaram: `#app{display:flex}` e `.entrada{display:grid}`. O
  resultado, visto num navegador de verdade: depois de entrar, o formulário de login
  continuava na página, com o console inteiro logo abaixo.

  Não é um caso exótico — é o padrão de qualquer página que troque de tela sem framework.
  A regra fica aqui, uma vez, em vez de cada `display` novo ter de lembrar do `hidden`.
*/
[hidden]{display:none!important}

*{box-sizing:border-box}
html,body{height:100%}
body{
  margin:0;background:var(--paper);color:var(--graphite);
  font:15px/1.6 ui-sans-serif,-apple-system,"Segoe UI",system-ui,sans-serif;
  letter-spacing:-.003em;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
}
:focus-visible{outline:3px solid color-mix(in srgb,var(--accent) 45%,transparent);outline-offset:3px}
@media (prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}

/* h-screen + flex-col, não min-h-screen: com altura mínima a faixa de ambiente
   soma aos 100vh do miolo e empurra o pé da coluna para fora da tela. */
#app{display:flex;flex-direction:column;height:100vh;overflow:hidden}

/* A faixa é permanente, não só quando algo está errado: as telas são idênticas
   em todos os ambientes e a mesa alterna entre eles no mesmo navegador. */
.env-banner{
  display:flex;align-items:center;gap:8px;padding:5px 16px;
  font-size:12px;font-weight:500;background:var(--warning-soft);color:var(--warning);
  border-bottom:1px solid var(--mist);
}
.env-banner[data-env=prod]{background:var(--danger-soft);color:var(--danger)}
.env-banner .dot{width:6px;height:6px;border-radius:99px;background:currentColor}

.frame{display:flex;min-height:0;flex:1}

aside{
  display:flex;flex-direction:column;width:260px;flex-shrink:0;
  border-right:1px solid var(--mist);background:var(--surface);
}
.brand{display:flex;align-items:center;gap:9px;padding:16px 16px 14px}
.brand .logo{display:inline-flex}
.brand img{height:17px;width:auto}
/*
  Duas imagens, uma escondida: a logo nao e monocromatica, e `filter: invert`
  transformaria o cobalto num laranja que nao existe na marca.

  Toda regra de exibicao passa por `.brand` de proposito. Antes, esconder era
  `.logo-dark{display:none}` (0,1,0) contra `.brand img{display:block}` (0,1,1):
  a mais especifica ganhava sempre, a ordem no arquivo nao decidia nada, e no tema
  claro as duas logos apareciam sobrepostas — a branca invisivel sobre o fundo
  branco, empurrando o resto da linha. Com o mesmo peso dos dois lados, quem
  decide volta a ser o tema.
*/
/*
  A regra é do LOGO, e não do lugar onde ele está.

  Ela estava presa a `.brand`, que é a marca da coluna lateral. A tela de entrada desenha
  a mesma marca noutro contêiner, então nenhuma das duas regras a alcançava e as DUAS
  imagens apareciam lado a lado — que é o que se via no login.

  O peso continua igual dos dois lados (`.logo-light` contra `.logo-light` sob o tema), que
  é o que faz o tema decidir em vez da ordem no arquivo.
*/
.logo-light{display:block}
.logo-dark{display:none}
@media (prefers-color-scheme:dark){
  :root:not([data-theme=light]) .logo-light{display:none}
  :root:not([data-theme=light]) .logo-dark{display:block}}
:root[data-theme=dark] .logo-light{display:none}
:root[data-theme=dark] .logo-dark{display:block}
/*
  O NOME DO PRODUTO SAIU DAQUI PORQUE ELE ESTÁ NA MARCA.

  A marca anterior era um símbolo, então o rótulo ao lado carregava o nome. A nova é um
  logotipo: a palavra CoreQA está desenhada nela. Manter o `span` escrevia o nome duas
  vezes lado a lado, separado por um filete, e um nome repetido lê-se como erro de
  montagem e não como reforço.

  O nome acessível continua no `aria-label` do contêiner da marca, então quem usa leitor
  de tela não perdeu nada: a `img` tem `alt` vazio de propósito, para o nome não ser
  anunciado em dobro pelo mesmo motivo visual.
*/

nav{flex:1;overflow-y:auto;padding:0 8px 8px}
nav .group{margin-bottom:16px}
nav .group>p{
  margin:0;padding:0 12px 6px;font-size:11px;font-weight:600;
  text-transform:uppercase;letter-spacing:.06em;color:var(--slate-dim);
}
nav a{
  position:relative;
  display:flex;align-items:center;gap:10px;width:100%;margin-bottom:2px;
  padding:8px 12px;border-radius:7px;text-decoration:none;
  font-size:14px;color:var(--slate);cursor:pointer;
  transition:background-color .12s,color .12s;
}
/*
  O filete do item ativo é desenhado por `::before` e não por `border-left`: uma borda
  empurraria o conteúdo dois pixels só no item aceso, e a fila de ícones deixaria de estar
  alinhada. Ele existe transparente em todo item, para não nascer no clique.
*/
nav a::before{
  content:"";position:absolute;left:0;top:8px;bottom:8px;width:2px;
  border-radius:2px;background:transparent;
}
nav a:hover{background:var(--warm);color:var(--graphite)}
nav a[aria-current=page]{background:var(--accent-soft);color:var(--accent);font-weight:600}
nav a[aria-current=page]::before{background:var(--accent)}
nav a svg{width:16px;height:16px;flex-shrink:0}
/*
  O link que SAI do console.

  A seta à direita não é enfeite: sem ela, um item que abre outra aba é indistinguível dos
  sete que trocam a tela, e o salto surpreende. É a convenção do manual para o mesmo caso.
*/
nav a.externo{color:var(--slate)}
nav a.externo .fora{margin-left:auto;color:var(--slate-dim);width:14px;height:14px}
nav a.externo:hover .fora{color:var(--accent)}

nav .count{margin-left:auto;font-size:11px;font-variant-numeric:tabular-nums;
  background:var(--warm);color:var(--slate);border-radius:99px;padding:1px 7px}
nav a[aria-current=page] .count{background:var(--surface)}

.who{border-top:1px solid var(--mist);padding:12px 16px;display:flex;align-items:center;gap:10px}
/*
  A regra é da PEÇA e não do contêiner: os dois consoles desenham o avatar em lugares
  diferentes — `.who` no de operação, `button.quem` no do cliente — e uma regra presa a um
  deles não alcança o outro.

  `flex:none` porque ele é o item que não cede: quem cede é o nome ao lado, que tem
  reticências para isso.
*/
.avatar{
  width:28px;height:28px;flex:none;border-radius:99px;background:var(--accent-soft);
  color:var(--accent);display:grid;place-items:center;
  font-size:12px;font-weight:650;line-height:1;
}
.who .id{min-width:0}
.who .id strong{display:block;font-size:13px;font-weight:500;color:var(--graphite);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.who .id span{font-size:11px;color:var(--slate)}
.who .icons{margin-left:auto;display:flex;gap:2px}
.who .icons button{border:0;background:none;color:var(--slate);cursor:pointer;padding:4px;
  border-radius:5px;display:inline-flex}
.who .icons button:hover{background:var(--warm);color:var(--graphite)}
.who .icons button.out:hover{color:var(--danger)}
.who svg{width:16px;height:16px}

main{flex:1;min-width:0;overflow-y:auto}
/*
  A margem cresce com a largura, com teto: numa tela larga uma folga fixa deixa a página
  colada na coluna lateral, e sem teto ela vira uma coluna de texto no meio do vazio.
*/
.page{padding:30px clamp(28px,3.2vw,52px) 64px}

/* ── cabeçalhos ─────────────────────────────────────────────────────────── */
/* Um só componente de cabeçalho para lista e para ficha. Duas variações do
   mesmo bloco é como as telas começam a divergir uma da outra. */
.head{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;
  gap:12px;margin-bottom:24px}
.head .titles{min-width:0}
.head h2{margin:0;font-size:23px;font-weight:650;letter-spacing:-.02em;line-height:1.25;
  display:flex;align-items:center;gap:8px;flex-wrap:wrap}
/*
  A MEDIDA DOS BLOCOS DE TEXTO, e por que ela existe.  (2026-09-06)

  Numa tela de 1600px um parágrafo de 70ch termina no meio e a metade direita fica vazia
  — foi assim que o problema chegou, e a leitura estava certa: parecia texto cortado.

  A resposta NÃO é tirar o limite. Linha muito longa quebra a volta do olho de uma linha
  para a outra, e o efeito é reler a mesma frase sem perceber; por isso a medida subiu até
  perto do teto do que ainda se lê bem, e não até a borda da janela.

  O espaço que sobra é resolvido do outro lado, onde há conteúdo para pôr nele: as seções
  com `.explicada` põem a lista de fatos AO LADO da explicação em vez de embaixo. Onde o
  conteúdo é tabela ou gráfico, que já ocupam a largura inteira, a margem de respiro à
  direita do parágrafo é intencional.
*/
.head p{margin:6px 0 0;color:var(--slate);font-size:14.5px;line-height:1.55;max-width:96ch}

/*
  A abertura é uma classe A MAIS sobre `.head`, e não um segundo componente: as ações e o
  comportamento em tela estreita continuam sendo os mesmos para todas as telas.

  Ela existe porque na primeira tela o título é o NOME DA EMPRESA, e não o rótulo do menu:
  sem sobrancelha, a única coisa que diria qual tela está aberta seria o item aceso na
  coluna lateral.
*/
.head.abertura{margin-bottom:30px;padding-bottom:26px;border-bottom:1px solid var(--mist)}
.head.abertura .olho{margin:0 0 8px;font-size:10px;font-weight:700;letter-spacing:.19em;
  text-transform:uppercase;color:var(--accent)}
.head.abertura h2{font-size:clamp(28px,3vw,34px);font-weight:700;letter-spacing:-.03em;
  line-height:1.15}
/*
  A medida da lede: larga o bastante para a linha não terminar com espaço vazio à direita —
  o que se lê como texto truncado —, e limitada, porque uma linha que atravessa a tela
  inteira faz o olho perder o começo da seguinte.
*/
.head.abertura p{margin-top:10px;font-size:17px;line-height:1.55;max-width:88ch}
.head .actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap}

.back{display:inline-flex;align-items:center;gap:6px;margin-bottom:14px;
  font-size:13px;color:var(--slate);text-decoration:none;cursor:pointer}
.back:hover{color:var(--accent-hover)}
.back svg{width:15px;height:15px}

/* ── abas ───────────────────────────────────────────────────────────────── */
.tabs{display:flex;gap:2px;overflow-x:auto;border-bottom:1px solid var(--mist);margin-bottom:22px}
.tabs a{
  flex-shrink:0;white-space:nowrap;padding:9px 14px;margin-bottom:-1px;
  border-bottom:2px solid transparent;font-size:14px;color:var(--slate);
  text-decoration:none;cursor:pointer;transition:color .12s,border-color .12s;
}
.tabs a:hover{color:var(--graphite)}
.tabs a[aria-current=page]{border-bottom-color:var(--accent);color:var(--accent);font-weight:500}
.tabs .n{margin-left:6px;font-size:12px;opacity:.7;font-variant-numeric:tabular-nums}

/* ── barra de filtros ───────────────────────────────────────────────────── */
.bar{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-bottom:16px}
.bar .spacer{flex:1}

/* ── campos ─────────────────────────────────────────────────────────────── */
input,textarea{
  height:36px;padding:0 10px;border:1px solid var(--mist);border-radius:7px;
  background:var(--surface);color:var(--graphite);font:inherit;font-size:14px;
  min-width:0;width:100%;transition:border-color .12s,box-shadow .12s;
}
textarea{height:auto;padding:8px 10px;resize:vertical;line-height:1.5}
/*
  O campo em foco troca a borda e ganha um halo, em vez do contorno geral: o anel de
  `:focus-visible` é desenhado por fora com afastamento, e num campo encostado no botão de
  uma `.row` ele invade o vizinho.
*/
input:focus-visible,textarea:focus-visible{
  outline:none;border-color:var(--accent);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 13%,transparent);
}
input::placeholder{color:var(--slate-dim)}
input:disabled{background:var(--warm);color:var(--slate);cursor:not-allowed}
/*
  Caixa de marcar e botão de opção têm dimensão própria: a regra de campo acima alcança todo
  `<input>`, e `width:100%` numa caixa dentro de um flex faz o quadradinho comer a linha.

  `accent-color` porque a caixa marcada é desenhada pelo sistema operacional, e sem isto ela
  sai no azul dele.
*/
input[type=checkbox],input[type=radio]{
  width:16px;height:16px;min-width:0;padding:0;margin:0;
  accent-color:var(--accent-solid);
}

input[type=search]{width:240px}
/*
  O botão de mostrar fica DENTRO da caixa do campo, e o recuo à direita no `input` é o que
  abre o espaço: ao lado, ele encolheria o campo em quarenta pixels em toda tela onde
  aparece, e são três campos seguidos no diálogo de trocar a senha.
*/
.senha{position:relative;display:grid;min-width:0}
.senha>input{padding-right:40px}
.senha>.olho{
  position:absolute;right:4px;top:50%;transform:translateY(-50%);
  display:inline-flex;align-items:center;justify-content:center;
  width:30px;height:30px;padding:0;border:0;border-radius:6px;
  background:none;color:var(--slate-dim);cursor:pointer;
  transition:color .12s,background-color .12s;
}
.senha>.olho:hover{background:var(--warm);color:var(--graphite)}
.senha>.olho[aria-pressed=true]{color:var(--accent)}
.senha>.olho svg{width:16px;height:16px}

/*
  O CAMPO NÃO ESTICA POR DENTRO, e era isso que desalinhava a página Empresa.  (2026-09-06)

  `label.field` é uma grade de três linhas: rótulo, controle e dica. Numa grade de duas
  colunas, a célula mais baixa é esticada até a altura da mais alta — e uma grade com
  `align-content` normal DISTRIBUI essa sobra entre as próprias linhas. Resultado: no
  campo cuja dica tem uma linha a menos, o controle desce alguns pixels e deixa de estar
  na mesma reta do vizinho.

  O espaçamento entre linhas de um campo é decisão do desenho, não sobra de layout. Com
  `align-content:start` as três linhas ficam coladas no topo, os controles das duas
  colunas nascem no mesmo y, e a diferença de altura sobra embaixo, onde ninguém a vê.
*/
label.field{display:grid;align-content:start;gap:5px;min-width:0}
label.field>.lbl{font-size:13px;font-weight:500;color:var(--graphite);
  display:flex;align-items:center;gap:6px;flex-wrap:wrap}
label.field>.hint{font-size:12px;color:var(--slate);line-height:1.45}
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:16px}
/*
  Duas grades seguidas encostavam: a `gap` vale DENTRO de uma grade e não entre duas, e o
  formulário da Empresa é feito de duas — o rótulo da segunda linha nascia colado na dica
  da primeira, e a coluna da direita, com dica de uma linha só, ficava com um respiro que
  a da esquerda não tinha. O olho lê isso como campo desalinhado, que foi como chegou.
*/
.grid+.grid{margin-top:16px}
.grid.wide{grid-template-columns:repeat(auto-fit,minmax(320px,1fr))}

/*
  O seletor, desenhado aqui.

  Substitui o `<select>` nativo pela mesma razão do console: o menu aberto é
  desenhado pelo sistema operacional, ignora o tema da página e aparece branco no
  tema escuro, com a fonte do sistema. Num painel escuro isso lê como defeito.
  O campo fechado dava para estilizar; o menu, não.
*/
.sel{position:relative;min-width:0}
.sel>button{
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  width:100%;height:36px;padding:0 10px;border:1px solid var(--mist);border-radius:7px;
  background:var(--surface);color:var(--graphite);font:inherit;font-size:14px;
  text-align:left;cursor:pointer;transition:border-color .12s,box-shadow .12s;
}
.sel>button:hover:not(:disabled){border-color:var(--accent-border)}
.sel>button:disabled{background:var(--warm);color:var(--slate);cursor:not-allowed}
.sel>button[aria-expanded=true]{border-color:var(--accent);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 13%,transparent)}
/* Reticências no valor: um rótulo longo quebrava em duas linhas dentro de um
   campo de altura fixa e desalinhava a barra inteira. */
.sel>button>.val{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sel>button>svg{width:15px;height:15px;flex-shrink:0;color:var(--slate);transition:transform .12s}
.sel>button[aria-expanded=true]>svg{transform:rotate(180deg)}
/* Posição fixa e não absoluta: o seletor aparece dentro de tabelas com rolagem
   própria, e um menu absoluto fica cortado pela borda delas. */
.sel-menu{
  position:fixed;z-index:60;max-height:280px;overflow-y:auto;padding:4px;
  border:1px solid var(--mist);border-radius:var(--radius);background:var(--surface);
  box-shadow:var(--shadow);
}
.sel-menu [role=option]{
  display:flex;align-items:center;gap:8px;padding:7px 9px;border-radius:6px;
  font-size:14px;color:var(--graphite);cursor:pointer;white-space:nowrap;
}
.sel-menu [role=option] .tick{width:15px;flex-shrink:0;color:var(--accent);display:inline-flex}
.sel-menu [role=option] .tick svg{width:15px;height:15px}
.sel-menu [role=option][data-active=true]{background:var(--warm)}
.sel-menu [role=option][aria-selected=true]{color:var(--accent);font-weight:600}
.sel-menu [role=option] .sub{color:var(--slate);font-size:12px;margin-left:auto;padding-left:16px}

/* ── botões ─────────────────────────────────────────────────────────────── */
/*
  `.btn` e não `button.btn`.

  Dois botões desta interface são LINKS de verdade — "abrir fatura", que sai para o
  provedor, e "ver a assinatura", que muda de tela. Um link precisa ser um `<a>`: é o que
  o meio do botão do mouse abre em outra aba, o que o leitor de tela anuncia como link, e
  o que funciona sem JavaScript.

  Com o seletor preso a `button`, o `<a class="btn">` não recebia estilo nenhum — e o
  sintoma, visto num navegador de verdade, era o ícone do link renderizado no tamanho
  natural do SVG: uma seta azul gigante dentro da tabela de cobranças.
*/
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;height:36px;padding:0 16px;
  border-radius:7px;border:1px solid transparent;font:inherit;font-size:14px;font-weight:600;
  cursor:pointer;text-decoration:none;white-space:nowrap;
  transition:background-color .12s,border-color .12s,color .12s,transform .12s;
}
.btn svg{width:15px;height:15px;flex-shrink:0}
.btn:disabled,.btn[disabled]{opacity:.5;cursor:not-allowed}
/*
  O primário usa `--accent-solid`, que não muda entre os temas: branco sobre ele vale nos
  dois, a 5,17:1 — o mesmo número que a marca declara. Com o acento de texto, que clareia no
  escuro, a tinta teria de inverter e a peça teria dois desenhos.

  O levantar de um pixel no hover é suprimido junto com as outras transições sob
  `prefers-reduced-motion`.
*/
.btn.primary{background:var(--accent-solid);border-color:var(--accent-solid);color:#fff}
.btn.primary:hover:not(:disabled){background:var(--accent-solid-hover);
  border-color:var(--accent-solid-hover);transform:translateY(-1px)}
.btn.secondary{border-color:var(--mist);background:var(--surface);color:var(--graphite)}
.btn.secondary:hover:not(:disabled){border-color:var(--accent-border);
  background:var(--accent-soft);color:var(--accent)}
.btn.ghost{background:none;color:var(--slate);padding:0 10px;height:32px;font-size:13px}
.btn.ghost:hover:not(:disabled){background:var(--warm);color:var(--graphite)}
.btn.danger{border-color:color-mix(in srgb,var(--danger) 40%,transparent);
  background:var(--danger-soft);color:var(--danger)}
.btn.danger:hover:not(:disabled){border-color:var(--danger)}
.btn.sm{height:32px;padding:0 12px;font-size:13px}

/* ── tabelas ────────────────────────────────────────────────────────────── */
/* Sempre com rolagem própria: uma tabela de operação tem colunas demais para
   caber em tela estreita, e sem isto a página inteira ganha barra horizontal. */
/* Com margem inferior, como cartão, gráfico, seção e aviso: sem ela a seção seguinte
   encosta na tabela. */
.table{overflow-x:auto;border:1px solid var(--mist);border-radius:9px;background:var(--surface);
  margin-bottom:16px;box-shadow:var(--shadow-sm)}
/* Dentro de uma seção, o padding dela já dá o espaço; a margem sobraria. */
.section>.table:last-child{margin-bottom:0}
/*
  A TABELA NÃO ACOMPANHA A ESCALA DO CORPO, e isso é deliberado.

  O corpo subiu para 15px porque o texto que se LÊ ganha com isso. Uma tabela não se lê,
  se varre: a mesma subida em vinte linhas de dados empurra a última para fora da tela e
  troca uma leitura mais confortável por uma rolagem a mais. O manual faz o mesmo — o
  texto dele é 16px e as tabelas são 14px.
*/
table{width:100%;border-collapse:collapse;font-size:14px}
/*
  O cabeçalho vive no acento suave, e a linha em hover num azul mais fraco. Com os dois em
  cinza, passar o mouse na primeira linha a fazia parecer parte do cabeçalho.
*/
thead{background:var(--accent-soft)}
th{padding:11px 16px;text-align:left;font-size:12px;font-weight:600;
  text-transform:uppercase;letter-spacing:.035em;color:var(--graphite);white-space:nowrap}
/*
  O FILETE ENTRE LINHAS É MAIS FRACO QUE O DA MOLDURA.

  É a hierarquia do manual: `--mist` delimita a peça, `--mist-soft` separa o que está
  dentro dela. Com o mesmo tom nos dois papéis, uma tabela de dez linhas lê como dez
  caixas empilhadas em vez de uma peça com dez linhas.
*/
td{padding:12px 16px;border-top:1px solid var(--mist-soft);vertical-align:middle}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums}
tbody tr{transition:background-color .12s}
tbody tr:hover{background:color-mix(in srgb,var(--accent-soft) 45%,transparent)}
/* A linha inteira abre a ficha: a coluna de ações some, e com ela a fileira de
   botões que fazia cada tela parecer outra. */
tbody tr.link{cursor:pointer}
td .chev{color:var(--slate);display:inline-flex}
td .chev svg{width:15px;height:15px}

/* ── paginação ──────────────────────────────────────────────────────────── */
/* Fora da tabela e não dentro: a tabela tem rolagem horizontal própria, e um rodapé
   dentro dela sairia da tela junto com a última coluna. */
.pager{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;
  gap:10px;margin:-8px 0 16px}
.pager:empty{display:none}
.pager .conta{font-size:12px;color:var(--slate);font-variant-numeric:tabular-nums}

/* ── selos ──────────────────────────────────────────────────────────────── */
/*
  Etiqueta quadrada com borda: com o canto quase reto, o fundo sozinho não delimita mais
  nada sobre a faixa morna do cabeçalho.

  SEM `text-transform`: estes selos carregam frases — "há mais de um dia", "em avaliação" —
  e uma frase em caixa alta fica mais larga e mais lenta de ler.
*/
.badge{display:inline-flex;align-items:center;gap:5px;border-radius:5px;padding:2px 8px;
  font-size:12px;font-weight:600;background:var(--warm);color:var(--slate);white-space:nowrap;
  border:1px solid var(--mist)}
.badge.accent{background:var(--accent-soft);color:var(--accent);border-color:var(--accent-border)}
.badge.positive{background:color-mix(in srgb,var(--positive) 12%,transparent);color:var(--positive);
  border-color:color-mix(in srgb,var(--positive) 30%,transparent)}
.badge.warning{background:var(--warning-soft);color:var(--warning);
  border-color:color-mix(in srgb,var(--warning) 30%,transparent)}
.badge.danger{background:var(--danger-soft);color:var(--danger);
  border-color:color-mix(in srgb,var(--danger) 30%,transparent)}
.badge .dot{width:6px;height:6px;border-radius:99px;background:currentColor}

.mono{font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace}
/* Data e hora não quebram no meio: "03/09/2026," numa linha e "08:18" na outra é a
   coisa que faz uma tabela parecer mal montada. O nome de um projeto quebra à vontade. */
.nowrap{white-space:nowrap}
.muted{color:var(--slate)}
.stack{display:grid;gap:2px}
/* Um selo dentro de uma pilha não estica.
   `.stack` é grid, e um `inline-flex` como item de grid é esticado até a largura da
   coluna: o selo "você" virava uma faixa cinza atravessando a célula inteira. Só o
   alinhamento, para não mexer no que mais vive dentro de uma pilha. */
.stack>.badge{justify-self:start}
.actions{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
.tags{display:flex;gap:6px;flex-wrap:wrap}

/*
  O vazio é uma caixa tracejada, e para isso a moldura de fora sai da frente: `.empty` só
  existe dentro de `.table`, e as duas juntas dariam molduras concêntricas.
*/
.table:has(>.empty){border:0;background:none;box-shadow:none}
.empty{padding:40px 16px;text-align:center;color:var(--slate);
  border:1px dashed var(--mist);border-radius:9px;background:var(--surface)}
.empty strong{display:block;color:var(--graphite);font-weight:600;margin-bottom:4px}

/* ── cartões e medidores ────────────────────────────────────────────────── */
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px;margin-bottom:22px}
.card{border:1px solid var(--mist);border-radius:9px;background:var(--surface);padding:16px 18px}
.card .label{font-size:11px;font-weight:600;text-transform:uppercase;
  letter-spacing:.05em;color:var(--slate-dim)}
.card .value{font-size:27px;font-weight:650;letter-spacing:-.025em;line-height:1.2;
  font-variant-numeric:tabular-nums;margin-top:6px}
.card .foot{font-size:12px;color:var(--slate);margin-top:3px}

/* O consumo é uma barra, não um número: 1.847/2.000 exige que a pessoa faça a
   conta; a barra cheia diz sozinha que a cota vai estourar. */
.meter{margin-top:12px}
.meter .track{height:6px;border-radius:99px;background:var(--mist);overflow:hidden}
.meter .fill{height:100%;border-radius:99px;background:var(--accent);transition:width .2s}
.meter[data-pressure=high] .fill{background:var(--warning)}
.meter[data-pressure=over] .fill{background:var(--danger)}

/* ── seções de conteúdo ─────────────────────────────────────────────────── */
.section{border:1px solid var(--mist);border-radius:9px;background:var(--surface);
  padding:20px 22px;margin-bottom:18px}
.section>header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;
  gap:12px;margin-bottom:16px}
.section h3{margin:0;font-size:16px;font-weight:650;letter-spacing:-.01em}
.section header p{margin:4px 0 0;font-size:13.5px;line-height:1.55;color:var(--slate);max-width:92ch}
/* Filete à esquerda, como o recado grave do manual: a borda inteira avermelhada fazia a
   seção parecer um erro que acabou de acontecer, e não uma zona onde se age com cuidado. */
/*
  A SEÇÃO EXPLICADA: o texto de um lado, o que ele explica do outro.

  Um parágrafo tem medida — 70ch, e ela não é para ser esticada — mas numa tela de 1500px
  a seção ficava com metade vazia à direita e o cartão jogado lá embaixo. Em duas colunas
  a explicação mantém a medida e o conteúdo sobe para o lado dela.

  Só em tela larga: abaixo disso é uma coluna só, que já era o certo.
*/
@media (min-width:1180px){
  .section.explicada{display:grid;grid-template-columns:minmax(280px,40ch) 1fr;
    gap:24px;align-items:start}
  .section.explicada>header{grid-column:1;grid-row:1;margin-bottom:0}
  .section.explicada>header p{max-width:none}
  /* Tudo o que não é o cabeçalho vai para a coluna da direita e empilha lá: uma seção com
     uma nota extra depois do conteúdo — a da retenção, em Uso — teria a nota caindo
     embaixo da explicação, longe do número que ela explica. */
  .section.explicada>:not(header){grid-column:2}
}
.section.perigo{border-left:4px solid var(--danger)}
.section.perigo h3{color:var(--danger)}
/* O rodapé de um formulário fica sempre no mesmo canto, em toda tela: é o que
   faz a segunda ficha parecer a primeira. */
.section>footer{display:flex;justify-content:flex-end;align-items:center;gap:10px;
  margin-top:18px;padding-top:14px;border-top:1px solid var(--mist)}
.section>footer .note{margin-right:auto;font-size:12px;color:var(--slate)}

.rows{display:grid;gap:0}
.rows>div{display:flex;flex-wrap:wrap;gap:12px;justify-content:space-between;
  padding:9px 0;border-top:1px solid var(--mist-soft)}
.rows>div:first-child{border-top:0;padding-top:0}
.rows dt{color:var(--slate);font-size:13px;margin:0}
.rows dd{margin:0;text-align:right;min-width:0}

/* ── diálogo ────────────────────────────────────────────────────────────── */
dialog{border:1px solid var(--mist);border-radius:var(--radius);background:var(--surface);
  color:var(--graphite);padding:0;min-width:min(460px,92vw);max-width:min(460px,92vw);
  box-shadow:var(--shadow)}
/* A cortina é a tinta neutra da marca: um véu de outra família tinge a página inteira de
   uma cor que não existe nela. */
dialog::backdrop{background:rgb(17 24 39 / .45)}
dialog .body{padding:22px}
dialog h3{margin:0;font-size:16px;font-weight:600}
dialog .lede{margin:6px 0 0;color:var(--slate);font-size:13px}
dialog .top{display:flex;gap:12px;align-items:flex-start}
dialog .warn{flex-shrink:0;width:32px;height:32px;border-radius:99px;display:grid;
  place-items:center;background:var(--danger-soft);color:var(--danger);margin-top:1px}
dialog .warn svg{width:17px;height:17px}
dialog .extra{margin-top:16px;display:grid;gap:12px}
dialog footer{display:flex;justify-content:flex-end;gap:8px;margin-top:20px}
.err{color:var(--danger);font-size:13px;margin:10px 0 0}

/* ── avisos ─────────────────────────────────────────────────────────────── */
/* Confirmar é a pergunta; o aviso é a resposta. Sem ele um "Salvar" que deu
   certo é indistinguível de um que não fez nada. */
.toasts{position:fixed;z-index:80;right:16px;bottom:16px;display:grid;gap:8px;
  max-width:min(380px,calc(100vw - 32px))}
.toast{display:flex;gap:9px;align-items:flex-start;padding:12px 14px;border-radius:var(--radius);
  border:1px solid var(--mist);background:var(--surface);box-shadow:var(--shadow);
  font-size:13px;animation:rise .16s ease-out}
.toast svg{width:16px;height:16px;flex-shrink:0;margin-top:1px}
.toast.ok svg{color:var(--positive)}
.toast.bad{border-color:color-mix(in srgb,var(--danger) 40%,transparent)}
.toast.bad svg{color:var(--danger)}
@keyframes rise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

/* ── linha de campo + botão ─────────────────────────────────────────────── */
/* Um campo e a ação dele lado a lado, com o campo comendo a sobra. É a forma de
   "cole aqui e confirme", que aparece no segredo de uso único e na versão fixada. */
.row{display:flex;gap:8px;align-items:center;min-width:0}
.row>input{flex:1;min-width:0}
.row .btn{flex-shrink:0}
dialog .note{margin:0;font-size:12px;color:var(--slate);line-height:1.45}

/* ── aviso de estado ────────────────────────────────────────────────────── */
/*
  Diferente do toast de propósito: o toast é o RESULTADO de uma ação e some sozinho;
  isto é um ESTADO e fica. Quem abriu a tela depois do toast nunca soube que a
  empresa está a três dias de ser cortada.
*/
/*
  Superfície branca com filete de quatro pixels, e não bloco colorido: o fundo inteiro
  tingido lê-se como "alguma coisa quebrou" mesmo quando o recado é um prazo se aproximando,
  e dois avisos empilhados deixam a página inteira amarela.

  A cor vive no filete e no disco do ícone, que bastam.
*/
.notice{display:flex;gap:12px;align-items:flex-start;padding:15px 17px;border-radius:9px;
  border:1px solid var(--mist);border-left:4px solid var(--mist);
  background:var(--surface);margin-bottom:16px}
.notice .ico{flex-shrink:0;width:30px;height:30px;border-radius:99px;display:grid;
  place-items:center;background:var(--warm);color:var(--slate)}
.notice .ico svg{width:16px;height:16px}
.notice .txt{min-width:0;flex:1}
.notice .txt strong{display:block;font-size:14px;font-weight:600}
.notice .txt p{margin:3px 0 0;font-size:13px;color:var(--slate);max-width:92ch}
.notice .btn{flex-shrink:0;align-self:center}
.notice.warning{border-left-color:var(--warning)}
.notice.warning .ico{background:var(--warning-soft);color:var(--warning)}
.notice.danger{border-left-color:var(--danger)}
.notice.danger .ico{background:var(--danger-soft);color:var(--danger)}
.notice.positive{border-left-color:var(--positive)}
.notice.positive .ico{background:color-mix(in srgb,var(--positive) 15%,transparent);color:var(--positive)}
.notice.accent{border-left-color:var(--accent)}
.notice.accent .ico{background:var(--accent-soft);color:var(--accent)}

/* ── gráficos ───────────────────────────────────────────────────────────── */
.chart{border:1px solid var(--mist);border-radius:9px;background:var(--surface);padding:16px 18px 12px}
.chart>header{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;
  gap:10px;margin-bottom:12px}
.chart h4{margin:0;font-size:13px;font-weight:600}
.chart header p{margin:2px 0 0;font-size:12px;color:var(--slate);max-width:84ch}
.chart-empty{margin:0;padding:26px 0;text-align:center;font-size:13px;color:var(--slate)}
/*
  O SVG NÃO é esticado pelo CSS.

  Ele é desenhado na largura medida do contêiner, 1:1, e traz `width`/`height` próprios.
  Forçar `width:100%` sobre um viewBox menor era o que achatava as letras do eixo.
*/
.plot-wrap{width:100%;min-height:60px}
svg.plot{display:block}
svg.plot .axis{font-size:10px;fill:var(--slate);font-variant-numeric:tabular-nums}
/*
  A DICA DE VALOR sobre um gráfico.

  `fixed` e não `absolute`: ela precisa escapar do `overflow` do cartão em que o gráfico
  mora, senão fica cortada pela borda exatamente nas colunas das pontas. `pointer-events`
  desligado para ela nunca ficar por baixo do ponteiro e matar o próprio hover.
*/
.dica{
  position:fixed;z-index:90;pointer-events:none;
  display:grid;gap:3px;min-width:120px;max-width:260px;
  padding:9px 11px;border:1px solid var(--mist);border-radius:8px;
  background:var(--surface);box-shadow:var(--shadow);
  font-size:12.5px;line-height:1.45;color:var(--graphite);
}
.dica strong{font-size:12px;font-weight:650;color:var(--slate)}
.dica span{display:flex;align-items:center;gap:7px}
.dica i{width:9px;height:9px;border-radius:2px;flex:none}
.dica em{font-style:normal;color:var(--slate);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dica b{margin-left:auto;font-weight:650;font-variant-numeric:tabular-nums}

/* A faixa sensível de cada coluna acende de leve, para o número mostrado ter um dono. */
svg.plot .alvo,svg.spark .alvo{fill:transparent;cursor:default}
/*
  A FAIXA DE HOVER É TRANSLÚCIDA, e não uma cor cheia.

  Ela é desenhada por último — precisa ser, ou as barras roubariam o ponteiro e a dica
  não apareceria — e `--accent-soft` é opaco: a coluna inteira SUMIA embaixo do realce,
  exatamente no gesto que existe para examiná-la. Com alfa, a barra continua visível
  através do realce.
*/
svg.plot .alvo:hover{fill:var(--accent);fill-opacity:.13}
.hbar{cursor:default}
.hbar:hover .b{background:var(--mist)}

.legend{display:flex;gap:12px;flex-wrap:wrap;font-size:12px;color:var(--slate)}
.legend span{display:inline-flex;align-items:center;gap:5px}
.legend i{width:9px;height:9px;border-radius:2px;display:inline-block}

/* Barras horizontais: o nome da categoria cabe deitado, e é onde a vertical falha. */
.hbars{display:grid;gap:7px}
.hbar{display:grid;grid-template-columns:minmax(80px,32%) 1fr auto;gap:10px;align-items:center}
.hbar .k{font-size:12px;color:var(--graphite);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hbar .b{height:9px;border-radius:99px;background:var(--warm);overflow:hidden}
.hbar .b i{display:block;height:100%;border-radius:99px}
.hbar .v{font-size:12px;color:var(--slate);font-variant-numeric:tabular-nums;min-width:36px;text-align:right}

.donut-wrap{display:grid;place-items:center}
svg.donut{width:150px;height:150px}
svg.donut .donut-n{font-size:22px;font-weight:600;fill:var(--graphite);font-variant-numeric:tabular-nums}
svg.donut .donut-l{font-size:9px;fill:var(--slate);text-transform:uppercase;letter-spacing:.06em}

svg.spark{display:block;width:100%;height:28px;margin-top:8px}

/* A régua até o corte: quanto da tolerância já passou, com a cor mudando quando a
   decisão vira urgente. */
.prazo{margin-top:10px}
.prazo .track{height:6px;border-radius:99px;background:var(--mist);overflow:hidden}
.prazo .fill{height:100%;border-radius:99px;background:var(--accent);transition:width .2s}
.prazo[data-pressure=high] .fill{background:var(--warning)}
.prazo[data-pressure=over] .fill{background:var(--danger)}
.prazo .ends{display:flex;justify-content:space-between;margin-top:5px;font-size:11px;color:var(--slate)}

/* ── grade de gráficos ──────────────────────────────────────────────────── */
.charts{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:14px;margin-bottom:18px}
.charts.wide{grid-template-columns:1fr}

/* ── entrada do console do cliente ──────────────────────────────────────── */
/*
  A tela de entrada não usa o quadro: quem chega aqui ainda não tem sessão, e mostrar
  o menu com as telas atrás de um diálogo ensina que existe alguma coisa alcançável ali.
*/
.entrada{min-height:100vh;display:grid;place-items:center;padding:24px;background:var(--paper);
  position:relative;isolation:isolate;overflow:hidden}
/*
  O FUNDO DA ENTRADA: nós em losango ligados por linha, que é a forma de um pipeline.

  Esta é a única tela do produto sem quadro e sem conteúdo, e papel liso com uma caixa no
  meio não diz que produto é este. A malha diz, e diz baixo: ela é textura, não ilustração.

  DESENHADA COMO MÁSCARA, e não como imagem colorida. Um SVG embutido não enxerga
  `var(--accent)` — a cor teria de ser escrita à mão dentro do data URI, uma vez por tema,
  e a segunda cópia é a que sai de sincronia na próxima mudança de marca. Aqui o SVG só
  recorta a forma e a tinta vem do token, então a malha acompanha o tema sem repetir cor
  nenhuma. É o mesmo motivo pelo qual o teste de identidade não precisa conhecer esta regra.

  A MÁSCARA É UM ARQUIVO, E NÃO UM `data:` — E FOI ISSO QUE QUEBROU DUAS VEZES.
  (2026-09-06)

  O desenho vivia num data URI aqui dentro. No navegador ele nunca chegou a existir: a
  política de conteúdo do painel diz `img-src 'self'`, uma máscara é buscada COMO IMAGEM,
  e o `data:` foi barrado — sem erro na tela, sem quadro quebrado, só um fundo liso. Eu
  conferi no Quick Look, que não aplica CSP, e concluí que era composição de máscara. Era
  a política, e ela estava certa; o errado era pedir imagem de um lugar que ela não
  permite. O ladrilho agora é `brand/malha.svg`, servido pelo mesmo painel, mesma origem.

  O caminho é RELATIVO de propósito: esta folha é servida em `/console.css` para o
  cliente e em `/console/console.css` para a operação, e um caminho absoluto faria o
  console de operação buscar um asset fora do prefixo que o SSO protege.

  Duas camadas, cada uma com uma coisa só: `::before` é a malha, com UMA máscara — a
  primeira tentativa compunha duas com `mask-composite`, que é onde os motores discordam
  —, e `::after` é um véu da cor do papel que apaga a textura no centro, onde ela
  competiria com o formulário. Se o véu falhar, a malha continua inteira: degradar é ficar
  uniforme, nunca ficar em branco.

  `isolation:isolate` prende os dois z-index negativos a esta tela; sem ele passariam por
  trás do papel, onde não aparecem.
*/
/*
  E SÓ QUANDO HÁ MÁSCARA. Sem ela, `::before` seria um retângulo azul chapado por cima da
  tela inteira — o modo de falhar mais feio que este efeito tem, e o que o navegador de
  quem pediu quase mostrou. Um fundo decorativo não vale esse risco: onde não houver
  máscara, a entrada volta a ser papel liso, que já era aceitável ontem.
*/
@supports ((-webkit-mask-image:url(#m)) or (mask-image:url(#m))){
.entrada::before{
  /* A folga além da borda é o que permite a malha DERIVAR sem descobrir um canto: ela
     anda 72px, que é exatamente um ladrilho, e volta ao começo sem emenda visível. */
  content:"";position:absolute;inset:-80px;z-index:-3;pointer-events:none;
  background:var(--accent);opacity:.16;
  --malha:url("brand/malha.svg");
  -webkit-mask-image:var(--malha);
          mask-image:var(--malha);
  -webkit-mask-size:72px 72px;
          mask-size:72px 72px;
  -webkit-mask-repeat:repeat;
          mask-repeat:repeat;
}
.entrada::after{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:radial-gradient(ellipse 56% 52% at 50% 48%,var(--paper) 0,transparent 76%);
}

/*
  O QUE ANDA SOBRE A MALHA.

  Losangos percorrendo as mesmas retas que a malha desenha — poucos, devagar, e com
  durações diferentes para nunca formarem fila.

  A GEOMETRIA É O QUE FAZ ISSO FUNCIONAR, e ela é toda em múltiplos de 72:

    o ladrilho tem 72px, e as retas da malha são `x - y` e `x + y` múltiplos de 72;
    cada losango começa num múltiplo de 72 nos dois eixos, logo está sobre as duas
    famílias; andar em diagonal, (±1,±1), mantém a soma ou a diferença constante, e
    portanto o losango em cima da reta o percurso inteiro.

  O CONTÊINER TEM A MESMA DERIVA DA MALHA, e a mesma origem (`inset:-80px`). Sem isso a
  malha andaria por baixo dos losangos e o encaixe se desfaria em segundos — que é
  exatamente o que acontecia quando este efeito era um SVG com viewBox próprio, escalado
  pela janela: as diagonais dele não tinham como coincidir com as da malha.

  O percurso é 576px, oito ladrilhos: o desenho se repete a cada 72, então o fim é
  idêntico ao começo. A opacidade nasce e morre em zero para o retorno não aparecer.
*/
.entrada .tecido{position:absolute;inset:-80px;z-index:-2;pointer-events:none;overflow:hidden}
.entrada .tecido i{position:absolute;left:var(--x);top:var(--y);width:11px;height:11px;
  margin:-5.5px 0 0 -5.5px;background:var(--accent);border-radius:1.5px;opacity:0;
  box-shadow:0 0 12px color-mix(in srgb,var(--accent) 45%,transparent);
  transform:rotate(45deg)}

/*
  O BRILHO E A MARCA, acima do véu e abaixo do formulário.

  O brilho é a cor da marca respirando atrás do cartão — é o que tira da tela a impressão
  de imagem congelada quando nenhum ponto está passando por perto. A marca-d'água é a
  mesma logo do cartão, grande e quase apagada: a tela de entrada é a única do produto sem
  quadro nem menu, e é onde a marca pode ocupar espaço sem disputar com conteúdo.
*/
.entrada .brilho{position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(ellipse 40% 36% at 50% 50%,
    color-mix(in srgb,var(--accent) 16%,transparent),transparent 70%)}

/*
  A ANIMAÇÃO É OPCIONAL, e a regra geral desta folha já desliga tudo sob
  `prefers-reduced-motion:reduce`. Declarar sob `no-preference` diz a mesma coisa duas
  vezes de propósito: aqui é fundo de tela cheia, o caso em que a preferência mais importa,
  e um `!important` distante num arquivo de mil linhas não é uma garantia que se leia daqui.
*/
@media (prefers-reduced-motion:no-preference){
  /* A malha e o contêiner dos losangos derivam JUNTOS: mesma duração, mesmo início, e
     por isso o encaixe entre os dois não escorrega com o tempo. */
  .entrada::before,.entrada .tecido{animation:deriva 72s linear infinite}
  .entrada .tecido i{animation:navegar var(--t,20s) linear var(--d,0s) infinite,
    surgir var(--t,20s) linear var(--d,0s) infinite}
  .entrada .brilho{animation:respirar 11s ease-in-out infinite}
}
@keyframes deriva{to{transform:translate3d(72px,72px,0)}}
@keyframes navegar{
  from{transform:translate(0,0) rotate(45deg)}
  to{transform:translate(calc(var(--vx,1) * 576px),calc(var(--vy,1) * 576px)) rotate(45deg)}
}
@keyframes surgir{0%,100%{opacity:0}14%,86%{opacity:.62}}
@keyframes respirar{0%,100%{opacity:.55}50%{opacity:1}}
}
/* No escuro a mesma tinta rende menos: o acento clareia, mas o papel afunda junto. */
@media (prefers-color-scheme:dark){:root:not([data-theme=light]) .entrada::before{opacity:.26}}
:root[data-theme=dark] .entrada::before{opacity:.26}
.entrada .caixa{position:relative;z-index:1;width:min(420px,100%);border:1px solid var(--mist);border-radius:var(--radius);
  background:var(--surface);padding:30px;box-shadow:var(--shadow)}
.entrada .marca{display:flex;align-items:center;gap:9px;margin-bottom:20px}
.entrada .marca img{height:18px;width:auto}
.entrada h1{margin:0 0 6px;font-size:19px;font-weight:600;letter-spacing:-.01em}
.entrada .lede{margin:0 0 20px;font-size:13px;color:var(--slate);line-height:1.5}
.entrada .campos{display:grid;gap:14px}
.entrada footer{margin-top:20px;display:grid;gap:10px}
.entrada .ajuda{font-size:12px;color:var(--slate);line-height:1.5}
.entrada .err{margin:14px 0 0}
.entrada .alternar{background:none;border:0;padding:0;font:inherit;font-size:12px;
  color:var(--accent);cursor:pointer;text-align:left}
.entrada .alternar:hover{color:var(--accent-hover);text-decoration:underline}
.entrada .ok{margin:14px 0 0;font-size:13px;color:var(--positive)}

/* ── o menu de quem está usando ─────────────────────────────────────────── */
/*
  O rodapé da coluna vira um botão, e não ganha mais ícones ao lado.
  
  Tema, perfil, senha e sair somavam quatro alvos de clique de dezesseis pixels espremidos
  num rodapé de 240px — e cada item novo apertava os outros. Um menu tem espaço para
  rótulos por extenso, que é o que separa "trocar a senha" de um cadeado desenhado.
*/
button.quem{display:flex;align-items:center;gap:10px;width:100%;padding:12px 16px;border:0;
  background:none;font:inherit;text-align:left;cursor:pointer;color:inherit;
  border-top:1px solid var(--mist)}
button.quem:hover{background:var(--warm)}
button.quem .id{min-width:0;flex:1}
button.quem .id strong{display:block;font-size:13px;font-weight:500;color:var(--graphite);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
button.quem .id span{font-size:11px;color:var(--slate)}
button.quem>svg{width:15px;height:15px;color:var(--slate);flex-shrink:0}

.menu{position:fixed;z-index:70;min-width:240px;padding:6px;border:1px solid var(--mist);
  border-radius:var(--radius);background:var(--surface);box-shadow:var(--shadow)}
.menu .cabeca{padding:8px 10px 10px;border-bottom:1px solid var(--mist);margin-bottom:6px}
.menu .cabeca strong{display:block;font-size:13px}
.menu .cabeca span{font-size:11px;color:var(--slate)}
.menu button{display:flex;align-items:center;gap:10px;width:100%;padding:8px 10px;border:0;
  border-radius:6px;background:none;font:inherit;font-size:14px;color:var(--graphite);
  text-align:left;cursor:pointer}
.menu button:hover{background:var(--warm)}
.menu button svg{width:16px;height:16px;color:var(--slate);flex-shrink:0}
.menu button[aria-pressed=true]{color:var(--accent);font-weight:500}
.menu button[aria-pressed=true] svg{color:var(--accent)}
.menu button.saida{color:var(--danger)}
.menu button.saida svg{color:var(--danger)}
.menu .grupo{padding:8px 10px 4px;font-size:11px;font-weight:600;text-transform:uppercase;
  letter-spacing:.06em;color:var(--slate-dim)}
.menu hr{border:0;border-top:1px solid var(--mist);margin:6px 0}

/* ── ficha em duas colunas ──────────────────────────────────────────────── */
.split{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:16px;margin-bottom:16px}
.kv{display:flex;justify-content:space-between;gap:12px;padding:8px 0;border-top:1px solid var(--mist);font-size:13px}
.kv:first-child{border-top:0;padding-top:0}
.kv .k{color:var(--slate)}
.kv .v{text-align:right;min-width:0}

/* ── tela estreita ──────────────────────────────────────────────────────── */
/*
  O QUADRO DE DUAS COLUNAS NÃO CABE NUM CELULAR, e o console do cliente vai ser
  aberto num.

  A coluna da esquerda tem 240px fixos. Numa tela de 390 ela come dois terços, e o
  conteúdo fica espremido num terço que não mostra um cartão inteiro — foi exatamente
  isso que o navegador de teste registrou. Não é um detalhe estético: o valor que este
  console entrega mais rápido é aprovar um portão de onde a pessoa estiver, e "de onde
  estiver" quase sempre é o telefone.

  Abaixo de 860px o quadro empilha: a marca e a pessoa numa faixa, o menu numa fita
  rolável logo abaixo, e a página rolando como página — e não dentro de um contêiner de
  altura fixa, que num celular briga com a barra de endereço que aparece e some.
*/
@media (max-width:860px){
  #app{height:auto;min-height:100vh;overflow:visible}
  .frame{flex-direction:column;min-height:0}
  aside{width:100%;flex-shrink:0;border-right:0;border-bottom:1px solid var(--mist);
    position:sticky;top:0;z-index:20}
  .brand{padding:10px 14px 8px}
  /* A marca e a pessoa dividem a primeira linha: duas faixas gastariam metade da
     altura útil de um celular só com cabeçalho. */
  aside{display:grid;grid-template-columns:1fr auto;grid-template-areas:"marca quem" "nav nav"}
  .brand{grid-area:marca}
  .who{grid-area:quem;border-top:0;padding:8px 14px}
  .who .id{display:none}
  nav{grid-area:nav;display:flex;gap:4px;overflow-x:auto;overflow-y:hidden;
    padding:0 10px 8px;-webkit-overflow-scrolling:touch}
  nav .group{display:flex;align-items:center;gap:4px;margin-bottom:0}
  nav .group>p{display:none}
  nav a{margin-bottom:0;white-space:nowrap;padding:7px 11px}
  main{overflow:visible}
  /*
    OS NÚMEROS DAQUI SÃO RECALIBRADOS A CADA MUDANÇA DE MEDIDA LÁ EM CIMA.

    Eles não são "o de cima menos um tanto": são o que cabe em 390px. O respiro que faz a
    página larga parecer o manual é exatamente o que, num telefone, come a largura de uma
    coluna inteira de cartão.
  */
  .page{padding:18px 16px 44px}
  .head{margin-bottom:18px}
  .head h2{font-size:20px}
  .head.abertura{margin-bottom:22px;padding-bottom:18px}
  .head.abertura h2{font-size:26px}
  .head.abertura p{font-size:15px;margin-top:8px}
  .cards{grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px}
  .card{padding:14px 15px}
  .card .value{font-size:24px}
  .charts{grid-template-columns:1fr}
  .section{padding:16px 15px;margin-bottom:14px}
  .section>footer{flex-wrap:wrap}
  .section>footer .note{margin-right:0;width:100%}
  input[type=search]{width:100%}
  /* Um diálogo em tela cheia no celular: 460px de largura mínima estourava a tela. */
  dialog{min-width:auto;max-width:calc(100vw - 24px)}
  .hbar{grid-template-columns:minmax(70px,40%) 1fr auto}
}

/*
  O aceite de termos, num diálogo que muda o valor da fatura.

  Alinhado ao topo e não ao centro: o texto tem três linhas e uma caixa centralizada
  contra um parágrafo fica no meio da segunda, longe da primeira palavra que ela governa.
  A área clicável é o rótulo inteiro — uma caixa de 13px é um alvo que erra, e errar aqui
  significa não conseguir aceitar sem saber por quê.
*/
.aceite {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin-top: 14px;
  padding: 12px;
  border: 1px solid var(--mist);
  border-radius: 9px;
  background: var(--surface);
  cursor: pointer;
  font-size: 13px;
  line-height: 1.5;
}
.aceite input { margin-top: 2px; flex: none; cursor: pointer; }
.aceite span { color: var(--graphite); }
