/* Surface styles. Tokens only — every colour comes from brand/brand.css.
   BRAND.md is normative; validate-brand-tokens.mjs enforces it.

   The template's own palette was removed by BRAND-101 rather than mapped onto
   tokens: the two palettes have no shared meaning, and a mapping would have
   invented equivalences nobody chose. Company panel: Zero brand plus company chrome, applied from GET /me. */

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--z-surface-1);
  color: var(--z-ink-900);
  font-family: var(--z-font-sans);
  font-size: var(--z-text-body);   /* 16px minimum — field use, gloves, sun */
  line-height: var(--z-leading-body);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 {
  font-family: var(--z-font-display);
  letter-spacing: var(--z-tracking-display);
  line-height: var(--z-leading-tight);
  margin: 0 0 var(--z-space-3);
}

h1 { font-size: var(--z-text-h1); }
h2 { font-size: var(--z-text-h2); }
h3 { font-size: var(--z-text-h3); }

a { color: var(--z-info); }

/* Every interactive element: 48px minimum, and a focus ring that is both
   accessibility and brand. */
/**
 * `.ghost-button` entra nestas listas porque nem sempre é um `<button>`.
 *
 * O seletor de arquivo é um `<label for>` — é assim que ele abre o seletor sem
 * JS e mantém o teclado e o leitor de tela. Só que a FORMA de botão morava toda
 * em seletores de elemento (`button, .z-btn`), e um `<label>` não casa com
 * nenhum: ele ficava com 26px de altura, sem recuo, canto reto e cursor de
 * texto, ao lado de um "Cancelar" de 48px com canto pílula. Tinha a cor certa e
 * a forma de nada.
 *
 * Medido antes: `alt=26 pad=0px raio=0px cursor=default` contra
 * `alt=48 pad=0px 24px raio=999px cursor=pointer`.
 *
 * A forma passa a seguir a CLASSE, não a etiqueta. Quem escreve
 * `class="ghost-button"` num `<label>`, num `<a>` ou num `<span>` recebe um
 * botão, que é o que a classe promete.
 */
button, .z-btn, .ghost-button, input, select, textarea {
  font-family: var(--z-font-sans);
  font-size: var(--z-text-body);
  min-height: var(--z-tap-min);
}

button, .z-btn, .ghost-button {
  border: 0;
  border-radius: var(--z-r-pill);
  padding: 0 var(--z-space-5);
  /* Chrome, so it takes the COMPANY's colour — never a category colour.
     See BRAND.md 3.5. */
  background: var(--z-brand-1);
  color: var(--z-brand-1-ink);
  cursor: pointer;
  transition: filter var(--z-dur-fast) var(--z-ease);
}

button:hover, .z-btn:hover, .ghost-button:hover { filter: brightness(1.08); }
button:disabled, .z-btn:disabled { opacity: .55; cursor: not-allowed; }

button:focus-visible, .z-btn:focus-visible, .ghost-button:focus-visible, a:focus-visible,
input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--z-surface-0), 0 0 0 4px var(--z-focus);
}

input, select, textarea {
  background: var(--z-surface-0);
  border: 1px solid var(--z-border);
  border-radius: var(--z-r-sm);
  color: var(--z-ink-900);
  padding: 0 var(--z-space-3);
  width: 100%;
}

.z-eyebrow {
  font-size: var(--z-text-eyebrow);
  font-weight: 600;
  letter-spacing: var(--z-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--z-ink-300);
}

.z-muted { color: var(--z-ink-400); }
.z-surface { background: var(--z-surface-0); border-radius: var(--z-r-md); box-shadow: var(--z-elev-1); }

/* ---------------------------------------------------------------- shell */

body { display: flex; flex-direction: column; min-height: 100vh; }

.app-header {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--z-space-4);
  padding: var(--z-space-3) var(--z-space-6);
  /**
   * A cor da empresa, como `docs/core/DESIGN_SYSTEM.md` §3.5 manda.
   *
   * A tabela de lá põe "Header background" na coluna do que a marca da empresa
   * pinta, e o cabeçalho estava em `--z-surface-0` — branco para todo mundo. Uma
   * empresa escolhia duas cores na Administração e via as duas aparecerem em
   * detalhes de poucos pixels.
   *
   * É também o que explica um defeito anterior: `.icon-button` pintava com
   * `--z-brand-1-ink` e era invisível. Aquele botão foi escrito para ESTE
   * cabeçalho; o cabeçalho é que tinha perdido a cor.
   *
   * `.z-glass` continua sendo daqui e de nenhum outro lugar (BRAND.md 6), agora
   * sobre a cor da empresa em vez de sobre o branco.
   */
  background: color-mix(in srgb, var(--z-brand-1) 92%, transparent);
  backdrop-filter: blur(14px) saturate(1.4);
  border-bottom: 1px solid color-mix(in srgb, var(--z-brand-1-ink) 18%, transparent);
  /* Derivada da luminância da cor escolhida, nunca branca por suposição: uma
     empresa que escolhe amarelo-claro tem de continuar lendo o próprio
     cabeçalho. */
  color: var(--z-brand-1-ink);
}

/* Tudo que vive no cabeçalho herda a tinta calculada. Escrito uma vez aqui em
   vez de em cada elemento, para um controle novo nascer legível. */
.app-header a,
.app-header .brand-name,
.app-header .company-name,
.app-header .date-time,
.app-header .user-name,
.app-header .brand-divider,
.app-header .material-symbols-outlined { color: var(--z-brand-1-ink); }

.app-header .company-name,
.app-header .date-time,
.app-header .brand-divider { opacity: .78; }

.app-header .user-button { color: var(--z-brand-1-ink); }

.app-header .user-button:hover {
  background: color-mix(in srgb, var(--z-brand-1-ink) 14%, transparent);
  filter: none;
}

/* A bolacha de iniciais é `--z-brand-1` sobre `--z-brand-1-ink` no resto do
   produto. Sobre o cabeçalho, que agora É `--z-brand-1`, isso a apagaria: mesma
   cor sobre a mesma cor. Aqui ela se inverte. */
.app-header .user-initials {
  background: color-mix(in srgb, var(--z-brand-1-ink) 22%, transparent);
  color: var(--z-brand-1-ink);
}

.brand { display: inline-flex; align-items: center; }
.brand img { width: 40px; height: 40px; display: block; }

.header-actions {
  display: flex;
  align-items: center;
  gap: var(--z-space-4);
}

/* Timestamps are data. BRAND.md 1.1. */
.date-time {
  font-family: var(--z-font-mono);
  font-size: var(--z-text-sm);
  color: var(--z-ink-400);
}

.app-main { flex: 1; padding: var(--z-space-6); }

/**
 * Fino e preso ao pé da janela.
 *
 * Existia só no painel: quem estava no programa — que é onde se passa o dia —
 * não tinha como dizer que versão estava usando, e "qual build?" é a primeira
 * pergunta de qualquer suporte. Agora está nas duas páginas.
 *
 * `fixed` porque ele não é conteúdo: é a etiqueta do produto. Rolando junto, ou
 * some no fim de uma lista longa, ou empurra o conteúdo numa lista curta. Preso,
 * está sempre no mesmo lugar e ocupa 28px, que é o que uma etiqueta merece.
 *
 * O `padding-bottom` no `body` reserva a faixa: sem isso a última linha de um
 * grid termina debaixo do rodapé, legível pela metade.
 */
.app-footer {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 9;
  display: flex;
  align-items: center;
  height: 28px;
  padding: 0 var(--z-space-6);
  border-top: 1px solid var(--z-border);
  background: color-mix(in srgb, var(--z-surface-1) 88%, transparent);
  backdrop-filter: blur(6px);
  font-size: var(--z-text-xs);
  color: var(--z-ink-300);
}

body { padding-bottom: 28px; }

/* ------------------------------------------------------------ typography */

.eyebrow {
  margin: 0 0 var(--z-space-1);
  font-size: var(--z-text-eyebrow);
  font-weight: 600;
  letter-spacing: var(--z-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--z-ink-300);
}

/* ------------------------------------------------------------ user menu */

.user-menu { position: relative; }

.user-button {
  display: inline-flex;
  align-items: center;
  gap: var(--z-space-2);
  padding: 0 var(--z-space-3);
  background: transparent;
  color: var(--z-ink-900);
  font-weight: 500;
}

.user-button:hover { background: var(--z-surface-2); filter: none; }

.user-initials {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--z-r-pill);
  background: var(--z-brand-1);
  color: var(--z-brand-1-ink);
  font-size: var(--z-text-sm);
  font-weight: 600;
}

.user-name { max-width: 12rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.chevron { transition: transform var(--z-dur-fast) var(--z-ease); }
.user-button[aria-expanded='true'] .chevron { transform: rotate(180deg); }

.user-dropdown {
  position: absolute;
  right: 0;
  top: calc(100% + var(--z-space-2));
  min-width: 17rem;
  display: flex;
  flex-direction: column;
  gap: var(--z-space-4);
  padding: var(--z-space-4);
  background: var(--z-surface-0);
  border: 1px solid var(--z-border);
  border-radius: var(--z-r-md);
  box-shadow: var(--z-elev-2);
}

/* The markup uses the `hidden` attribute; without this the flex display above
   would override it and the menu would never close. */
.user-dropdown[hidden] { display: none; }

.menu-section { border-bottom: 1px solid var(--z-border); padding-bottom: var(--z-space-3); }
.user-email { margin: 0; font-size: var(--z-text-sm); color: var(--z-ink-400); }

/* -------------------------------------------------------- theme/language */

.choice-group { border: 0; margin: 0; padding: 0; }

.choice-group legend {
  padding: 0 0 var(--z-space-2);
  font-size: var(--z-text-eyebrow);
  font-weight: 600;
  letter-spacing: var(--z-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--z-ink-300);
}

.segmented-control, .flag-control {
  display: flex;
  gap: var(--z-space-1);
  padding: var(--z-space-1);
  background: var(--z-surface-2);
  border-radius: var(--z-r-sm);
}

.flag-control { flex-direction: column; }

.choice-button, .flag-button {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--z-space-2);
  border-radius: var(--z-r-xs);
  background: transparent;
  color: var(--z-ink-500);
  font-size: var(--z-text-sm);
  font-weight: 500;
}

.flag-button { justify-content: flex-start; padding: 0 var(--z-space-3); }

.choice-button:hover, .flag-button:hover { background: var(--z-surface-0); filter: none; }

/**
 * O estado escolhido, com a cor da empresa.
 *
 * Era `--z-surface-0` sobre um trilho `--z-surface-2`: dois cinzas de diferença
 * mínima, e no tema claro o ícone do próprio tema claro quase não aparecia —
 * uma opção marcada que não se via marcada. Agora o preenchimento e o ícone
 * carregam `--z-brand-2`, que é a cor secundária da empresa, e a borda vem da
 * mesma cor em vez de um cinza genérico.
 *
 * A borda continua junto com o preenchimento, pela razão de sempre: quem não
 * separa dois tons próximos ainda vê o contorno.
 */
.choice-button.active, .flag-button.active {
  background: color-mix(in srgb, var(--z-brand-2) 16%, var(--z-surface-0));
  color: var(--z-ink-900);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--z-brand-2) 55%, transparent);
}

.choice-button.active .material-symbols-outlined { color: var(--z-brand-2); }

.flag-icon { width: 20px; height: 14px; border-radius: 2px; flex: 0 0 auto; }

/**
 * O foco do seletor de arquivo aparece no BOTÃO, não no input invisível.
 *
 * O `<input type="file">` é `sr-only` — fora da vista, mas focável, porque tirá-lo
 * da ordem de tabulação tiraria o controle de quem usa teclado. Sem esta regra o
 * foco existia e não se via: a pessoa tabulava e nada acontecia na tela.
 */
.sr-only:focus-visible + .ghost-button,
.ghost-button:has(+ .sr-only:focus-visible) {
  outline: 2px solid var(--z-brand-2);
  outline-offset: 2px;
}

.ghost-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--z-space-2);
  background: transparent;
  color: var(--z-ink-500);
  box-shadow: inset 0 0 0 1px var(--z-border);
}

.ghost-button:hover { background: var(--z-surface-2); filter: none; }

/**
 * O botão secundário: a SEGUNDA cor da empresa.
 *
 * O produto tinha duas demãos e nada entre elas — o cheio, em `--z-brand-1`, e o
 * fantasma, que é contorno sobre nada. Operações como "Responder" e "Transferir
 * de local" não são nenhuma das duas: pesam mais que um fantasma e não são a
 * ação principal da janela, que é ler o informe.
 *
 * `--z-brand-2` é a cor que a empresa escolheu no cadastro para exatamente isso,
 * e `--z-brand-2-ink` vem da luminância dela — nunca presumida branca, porque
 * uma empresa que escolhe amarelo claro precisa continuar lendo o próprio botão.
 * BRAND.md §3.5: a marca da empresa pinta o cromo, e um botão de operação é
 * cromo. Nunca a semântica: categoria e severidade continuam nos `--z-cat-*` e
 * `--z-sev-*`, que nenhuma empresa muda.
 */
.secondary-button {
  background: var(--z-brand-2);
  color: var(--z-brand-2-ink);
}

/* --------------------------------------------------------------- surface */

/**
 * A superfície ocupa a janela, com uma folga nas laterais.
 *
 * Eram 68rem — 1088px — centralizados. Numa tela de 2000px isso deixava quase
 * metade do navegador vazia enquanto o grid de informes, que tem nove colunas,
 * espremia "Registrado em" e "Situação" em duas linhas cada. O limite fazia
 * sentido para um formulário e nenhum para uma tabela, e as duas coisas usam
 * esta classe.
 *
 * O teto de 120rem existe para telas muito largas: uma linha de texto de dois
 * metros não se lê. Quem precisa de medida curta é o CONTEÚDO — ver
 * `.form-column` — e não a superfície inteira.
 */
.module-surface {
  width: 100%;
  max-width: 120rem;
  margin: 0 auto;
  padding: var(--z-space-6);
  background: var(--z-surface-0);
  border: 1px solid var(--z-border);
  border-radius: var(--z-r-lg);
}

/**
 * Formulário dentro de uma superfície larga.
 *
 * Campo de texto tem largura útil: um `input` de 1700px não ajuda ninguém a
 * digitar uma razão social. As telas de Empresa e Usuários limitam o próprio
 * conteúdo em vez de limitar a superfície, para o grid poder respirar na mesma
 * página.
 */
.form-column { max-width: 56rem; }

/* Título à esquerda, a saída para Administração à direita, na mesma linha. */
.surface-heading {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--z-space-3);
  margin-bottom: var(--z-space-5);
}

.surface-heading > .eyebrow { flex-basis: 100%; margin: 0; }
.surface-heading a[hidden] { display: none; }
.surface-heading h1 { margin: 0; }

.status-banner {
  padding: var(--z-space-3) var(--z-space-4);
  margin-bottom: var(--z-space-5);
  border-radius: var(--z-r-sm);
  background: var(--z-surface-2);
  color: var(--z-ink-500);
  font-size: var(--z-text-sm);
}

/* ------------------------------------------------------- module launcher */

.module-launcher, .module-launcher-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: var(--z-space-4);
}

/* Module tile: chrome, so the company's colour lands here. */
.module-button {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--z-space-3);
  min-height: 128px;
  padding: var(--z-space-4);
  border-radius: var(--z-r-md);
  background: var(--z-surface-0);
  color: var(--z-ink-900);
  box-shadow: inset 0 0 0 1px var(--z-border);
  text-align: left;
  text-decoration: none;
}

.module-button:hover {
  filter: none;
  box-shadow: inset 0 0 0 1px var(--z-brand-1), var(--z-elev-1);
}

.module-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--z-r-sm);
  background: color-mix(in srgb, var(--z-brand-1) 12%, transparent);
  color: var(--z-brand-1);
}

.module-name { font-weight: 600; }

/* An empty launcher states the fact. It never congratulates: BRAND.md 5. */
.empty-state {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--z-space-3);
  padding: var(--z-space-8);
  color: var(--z-ink-400);
}

.material-symbols-outlined {
  font-family: 'Material Symbols Outlined';
  font-size: 20px;
  line-height: 1;
  font-variation-settings: 'FILL' 0, 'wght' 400, 'GRAD' 0, 'opsz' 24;
}

@media (max-width: 40rem) {
  .app-header, .app-main, .app-footer { padding-left: var(--z-space-4); padding-right: var(--z-space-4); }
  .user-name { display: none; }
  .module-surface { padding: var(--z-space-4); }
}

/* ------------------------------------------------------- panel-only screens */

/* The boot, maintenance and sign-in screens. One document, three states: the
   panel decides which is visible before rendering, because showing the shell
   and hiding it flashes somebody else's company. */

.boot-screen,
.notice-screen {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--z-space-4);
}

.notice-card {
  width: 100%;
  /* 32rem. Estava em 26rem, estreito demais para um e-mail inteiro no campo de
     entrada e para o nome de uma empresa na lista de escolha. */
  max-width: 32rem;
  display: flex;
  flex-direction: column;
  gap: var(--z-space-3);
  /* Menos respiro lateral do que vertical. Com 64px dos dois lados num cartão de
     512px, 128px iam para a margem e sobrava pouco para o campo — alargar o
     cartão não teria adiantado nada. */
  padding: var(--z-space-8) var(--z-space-6);
  background: var(--z-surface-0);
  border: 1px solid var(--z-border);
  border-radius: var(--z-r-lg);
}

.notice-card h1 { margin: 0; }
.notice-card p { margin: 0; color: var(--z-ink-500); }

.field { display: flex; flex-direction: column; gap: var(--z-space-2); }

.field > span {
  font-size: var(--z-text-sm);
  font-weight: 600;
  color: var(--z-ink-500);
}

.field-error {
  color: var(--z-sev-critico);
  font-size: var(--z-text-sm);
}

.field-error[hidden] { display: none; }

.brand-name {
  font-family: var(--z-font-display);
  font-weight: 600;
  font-size: var(--z-text-h3);
}

.module-icon img { width: 28px; height: 28px; }

/* The shell itself: header on top, launcher in the middle, footer at the
   bottom, and the footer stays at the bottom on a short page. */
.app-shell {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.brand-logo { width: 40px; height: 40px; flex: 0 0 auto; }

/* The sign-in card is a form, so its fields need the gap the notice card's
   prose does not. */
.sign-in { gap: var(--z-space-4); }

.handle-echo {
  margin: 0;
  padding: var(--z-space-2) var(--z-space-3);
  border-radius: var(--z-r-sm);
  background: var(--z-surface-2);
  font-family: var(--z-font-mono);
  color: var(--z-ink-700);
}

.field-help {
  margin: 0;
  font-size: var(--z-text-sm);
  color: var(--z-ink-400);
}

.field-help[hidden] { display: none; }

/* SEC-104. Cloudflare Turnstile on Entrar, Esqueci minha senha and the code
   resend. The widget is Cloudflare's iframe (size "flexible": the width of the
   card); its message line reads like the other help lines. */
.turnstile {
  display: flex;
  flex-direction: column;
  gap: var(--z-space-2);
  min-height: 65px;
}

.turnstile-widget { width: 100%; }

.turnstile-message {
  margin: 0;
  font-size: var(--z-text-sm);
  color: var(--z-ink-500);
}

.checkbox-field {
  display: flex;
  align-items: center;
  gap: var(--z-space-2);
  font-size: var(--z-text-sm);
  color: var(--z-ink-500);
}

.checkbox-field input {
  width: auto;
  min-height: 0;
  accent-color: var(--z-brand-1);
}

/* A button that reads as a link, for the secondary way out of a screen. */
.link-button {
  background: transparent;
  color: var(--z-info);
  min-height: 0;
  padding: 0;
  font-size: var(--z-text-sm);
  font-weight: 500;
  text-decoration: underline;
}

.link-button:hover { filter: none; background: transparent; }

/* In-button activity. Immediate on purpose: the user pressed something and is
   owed an acknowledgement. The 400ms rule governs waits they did not start. */
/* ------------------------------------------------------- the welcome dialog */

/* The first thing a customer does inside the product. It is modal because the
   panel is not usable in a meaningful way until the programme has a name — the
   module tile would read "PIS" to somebody who has never heard the acronym. */
.welcome-dialog {
  width: min(30rem, calc(100vw - 2rem));
  padding: 0;
  border: 1px solid var(--z-border);
  border-radius: var(--z-r-lg);
  background: var(--z-surface-0);
  color: var(--z-ink-900);

  /* Âncora do `×` de fechar, que fica no canto do DIÁLOGO e não do corpo: o
     corpo rola, e um fechar que rola junto some quando o conteúdo é longo. */
  position: relative;

  /* Nunca mais alto que a tela. `dvh` e não `vh` porque no Safari do iPad a
     barra do navegador recolhe: com `vh` a janela é medida contra a altura sem
     barra, e com a barra aberta o rodapé — que é onde fica o botão de fechar —
     some para fora da vista. O conteúdo rola dentro do corpo, logo abaixo, e não
     no diálogo, para a rolagem não passar por cima dos cantos arredondados. */
  max-height: calc(100dvh - 4rem);
}

/* The backdrop is the product's darkest ink, dimmed — not a colour of its
   own, so it follows the brand rather than sitting beside it. */
.welcome-dialog::backdrop {
  background: color-mix(in srgb, var(--z-ink-900) 55%, transparent);
}

/**
 * O corpo do diálogo.
 *
 * Treze das catorze janelas do produto são um `<form>`, e por isso esta regra
 * nascia presa a `form`. A décima quarta — ver um informe — não é formulário
 * nenhum: é leitura, e o seu corpo é uma `<div>`. O seletor não a alcançava, e
 * ela abria sem recuo, sem espaçamento e sem coluna: o título encostado no canto,
 * os botões espremidos contra a borda direita e o "Fechar" cortado embaixo.
 *
 * Então a regra passa a nomear as duas, e `.dialog-body` existe para o caso em
 * que envolver o conteúdo num `<form>` só para herdar espaçamento seria mentir
 * sobre o que a janela faz.
 */
.welcome-dialog form,
.welcome-dialog > .dialog-body {
  display: flex;
  flex-direction: column;
  gap: var(--z-space-4);
  padding: var(--z-space-6);

  /* A rolagem mora aqui, e não no `<dialog>`: o diálogo tem `padding: 0` e
     cantos arredondados, e uma barra de rolagem nele passaria por cima deles. */
  overflow-y: auto;
}

/* Espaço para o `×` não pousar em cima do título. Só à direita, e só o
   suficiente: o título é um código curto e não precisa de mais. */
/**
 * Aberto, o diálogo é uma coluna: corpo que rola, rodapé que fica.
 *
 * `[open]` e não `.welcome-dialog` sozinho, e isto não é preciosismo: a regra do
 * navegador que esconde um diálogo fechado é `dialog:not([open]) { display:
 * none }`, e QUALQUER `display` escrito aqui a vence — folha de autor ganha da
 * folha do navegador, independentemente de especificidade. Sem o `[open]`, as
 * catorze janelas do painel apareceriam todas, sempre, empilhadas na página.
 */
.welcome-dialog[open] {
  display: flex;
  flex-direction: column;
}

/* `min-height: 0` porque um item de flex não encolhe abaixo do próprio conteúdo
   sem isso — e sem encolher ele não rola: empurra o rodapé para fora. */
.welcome-dialog > form,
.welcome-dialog > .dialog-body {
  flex: 1 1 auto;
  min-height: 0;
}

/**
 * O rodapé que não rola.
 *
 * Ficava no fim do corpo, e num informe longo saía da vista junto com ele:
 * "Responder" existia, mas só para quem rolasse até o fim para descobrir. Fora
 * do corpo rolável ele é o que a janela oferece, visível desde o primeiro
 * instante — que é o que uma barra de operações precisa ser.
 *
 * A linha em cima não é enfeite: sem ela o conteúdo rolando passa por baixo dos
 * botões e parece que eles flutuam sobre texto cortado.
 */
.dialog-footer {
  flex: 0 0 auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--z-space-3);
  justify-content: flex-end;
  padding: var(--z-space-4) var(--z-space-6);
  border-top: 1px solid var(--z-border);
  background: var(--z-surface-0);
}

.welcome-dialog h2 { margin: 0; padding-right: var(--z-space-7); }

/**
 * O `×` de fechar.
 *
 * Fora do fluxo, no canto, e com uma área de toque de 44px — o mínimo que a
 * Apple e o WCAG pedem para um alvo tocável, e este é o alvo mais tocado da
 * janela. O glifo em si é menor; a área é maior que ele.
 */
.dialog-dismiss {
  position: absolute;
  top: var(--z-space-3);
  right: var(--z-space-3);
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  padding: 0;
  border: 0;
  border-radius: var(--z-r-sm);
  background: transparent;
  color: var(--z-ink-500);
  cursor: pointer;
}

.dialog-dismiss:hover { background: var(--z-surface-1); color: var(--z-ink-900); }

/* O foco é o do resto do produto, não um contorno próprio desta janela. */
.dialog-dismiss:focus-visible {
  outline: 2px solid var(--z-focus);
  outline-offset: 2px;
}

/**
 * O diálogo largo, para quem tem formulário de verdade.
 *
 * `.welcome-dialog` são 30rem e serve às catorze janelas do produto — inclusive
 * a de boas-vindas, que pede duas coisas. Alargar a classe alargaria todas, e um
 * diálogo de dois campos com 45rem é um retângulo com um formulário perdido no
 * canto.
 *
 * Aqui entram os que passam de meia dúzia de campos: o informe tem dez. A 30rem
 * eles empilhavam um por linha e a janela virava uma coluna estreita e alta, com
 * metade do formulário fora da vista. A 45rem os pares cabem lado a lado.
 */
.dialog-wide { width: min(45rem, calc(100vw - 2rem)); }

/**
 * Mais larga ainda, para a janela que só LÊ.
 *
 * As de 45rem são formulários: alargar mais espalha os campos e a pessoa
 * atravessa a tela entre o rótulo e o que digita. A de detalhe não tem esse
 * custo — são treze pares de rótulo e valor, e cada rem a mais é uma linha a
 * menos de rolagem. 56rem põe os pares em duas colunas com folga e ainda cabe
 * num laptop de 13 polegadas.
 */
.dialog-xwide { width: min(56rem, calc(100vw - 2rem)); }

/**
 * Os pares voltam a uma coluna sozinhos quando não cabem.
 *
 * `.colour-row` — que o formulário já usava para tipo/categoria e unidade/local
 * — era `1fr 1fr` fixo, e num diálogo estreito isso espremia dois selects a
 * menos de 200px cada. `auto-fit` decide pela largura disponível, sem uma
 * segunda regra de telefone para manter em sincronia.
 */
.dialog-wide .colour-row {
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

.step-lead { margin: 0; color: var(--z-ink-500); }

/* A sigla do programa: curta, exata, e por isso em fonte de dado. */
.short-input {
  font-family: var(--z-font-mono);
  text-transform: uppercase;
  max-width: 10rem;
}

/* O aviso de contraste da marca. Não bloqueia — a marca é da empresa — mas não
   passa despercebido: o produto avisa uma vez e guarda assim mesmo. */
.brand-warning {
  margin: 0;
  padding: var(--z-space-3) var(--z-space-4);
  border-radius: var(--z-r-sm);
  background: var(--z-sev-alto-soft);
  color: var(--z-ink-700);
  font-size: var(--z-text-sm);
}

.brand-warning[hidden] { display: none; }

/* As ações de um formulário, à direita e na mesma linha. */
.wizard-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--z-space-3);
  justify-content: flex-end;
}

/* O nome da empresa e a engrenagem andam juntos. */
.brand-group {
  display: flex;
  align-items: center;
  gap: var(--z-space-2);
  min-width: 0;
}

/* O indicador dentro de um botão: a MESMA marca, na cor do texto do botão.

   O arquivo é o mesmo `zero-loading.svg` da marca, usado como
   MÁSCARA em vez de imagem. Como imagem ele traria as quatro cores de categoria,
   e a 16px quatro cores viram borrão — dentro de um botão primário, um borrão
   que ainda briga com a cor do botão. Como máscara, o desenho recorta
   `currentColor`: o mesmo movimento, na cor que aquele botão já usa para o
   texto.

   Confirmado no navegador que uma máscara SVG anima: dois quadros capturados com
   600ms de intervalo saíram diferentes.

   Aparece na HORA, sem os 400ms de atraso das esperas em geral — quem apertou
   algo merece confirmação imediata (`BRAND.md` §6.2). */
.spinner {
  display: inline-block;
  width: 18px;
  height: 18px;
  vertical-align: -4px;
  flex: 0 0 auto;
  background-color: currentColor;
  -webkit-mask: url("../brand/animations/zero-loading.svg") center / contain no-repeat;
  mask: url("../brand/animations/zero-loading.svg") center / contain no-repeat;
}

/* Disabled inputs read as information rather than as broken controls. */
input:disabled {
  background: var(--z-surface-2);
  color: var(--z-ink-500);
  cursor: default;
}

@media (max-width: 40rem) {
  .colour-row { grid-template-columns: 1fr; }
  /* On a phone the header keeps the icon and drops the word. */
  .icon-button span:last-child { display: none; }
}

/* --------------------------------------------------------- users and roles */

.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--z-space-3);
  margin-top: var(--z-space-4);
}

.pager button:disabled { opacity: .45; cursor: not-allowed; }

/* Row actions are icon-only, with the label carried for a screen reader. The
   top bar and forms carry icon plus text — a row of fifteen labelled buttons
   is a wall, and a lone icon in a toolbar is a guess. */
.row-actions {
  display: flex;
  gap: var(--z-space-1);
  white-space: nowrap;
}

.row-actions .row-action {
  min-width: 36px;
  padding: 0 var(--z-space-2);
}

.role-list {
  display: flex;
  flex-direction: column;
  gap: var(--z-space-3);
  max-height: 16rem;
  overflow-y: auto;
}

.role-choice {
  display: flex;
  align-items: flex-start;
  gap: var(--z-space-3);
  padding: var(--z-space-3);
  border-radius: var(--z-r-sm);
  background: var(--z-surface-2);
  cursor: pointer;
}

/* A chave crua ao lado do nome da tela: quem lê a linha entende o que está
   concedendo, e quem abre um chamado tem o identificador que o backend usa. */
.role-action-key {
  margin-left: auto;
  padding-left: var(--z-space-3);
  color: var(--z-ink-500);
  font-size: var(--z-text-xs);
  white-space: nowrap;
}

.role-choice input {
  width: auto;
  min-height: 0;
  margin-top: 3px;
  accent-color: var(--z-brand-1);
}

/* What a role grants, in the mono face: it is data, not prose. */
.role-grants {
  font-family: var(--z-font-mono);
  font-size: var(--z-text-xs);
  color: var(--z-ink-400);
}

button.danger { background: var(--z-sev-critico); color: var(--z-surface-0); }

/* ------------------------------------------------------- grids and tabbars */

/* Restored in tokens. These lived in the template's operator console and went
   with it in WEB-101; the shapes are the same because the job is the same —
   a searchable, sortable, server-paged list. */

/**
 * Uma linha, sempre.
 *
 * `flex-wrap: wrap` quebrava as sete abas em duas fileiras e a segunda ficava
 * parecendo um segundo nível de navegação que não existe — "Matriz de
 * responsáveis" e "Locais de Ocorrência" são irmãs de "Meus Informes", não
 * filhas. Com a superfície ocupando a janela elas cabem; quando não couberem, a
 * barra rola na horizontal, que é honesto sobre haver mais à direita.
 *
 * `scrollbar-width: none` esconde a barra de rolagem e não o conteúdo: a última
 * aba fica meio visível na borda, que é o sinal de que há mais.
 */
.tabbar {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--z-space-1);
  margin-bottom: var(--z-space-4);
  border-bottom: 1px solid var(--z-border);
  overflow-x: auto;
  scrollbar-width: none;
}

.tabbar::-webkit-scrollbar { display: none; }

/**
 * As abas encolhem antes de sumir.
 *
 * Com oito abas e rótulos em português — "Administração de Informes", "Locais de
 * Ocorrência" — a barra pedia 1731px numa janela de 1434. Como eu tinha tirado a
 * quebra de linha E escondido a barra de rolagem, duas abas saíram da vista sem
 * nenhum sinal de que existiam: a pessoa não achou a Administração porque ela
 * estava 363px à direita do fim da tela.
 *
 * O recuo menor recupera cerca de metade disso; o resto é resolvido fixando a
 * Administração à direita, logo abaixo.
 */
/**
 * Uma faixa de botões: ícone grande em cima, nome pequeno embaixo.
 *
 * Eu tinha escondido os ícones para as oito abas caberem numa linha. Isso
 * resolveu a largura e custou o reconhecimento: uma barra de oito rótulos em
 * português é lida palavra por palavra toda vez.
 *
 * Empilhar devolve as duas coisas. O ícone deixa de somar largura — ele fica
 * ACIMA do rótulo em vez de ao lado — então a barra ocupa quase o mesmo espaço
 * de quando não tinha ícone nenhum, e volta a ter uma forma para reconhecer
 * antes de ler.
 */
.tab-button {
  /* Ocupam a barra inteira, repartindo o que sobra em proporção ao rótulo.
     Antes se agrupavam à esquerda e deixavam um terço da barra vazio numa tela
     larga — oito botões apertados de um lado e nada do outro. `auto` e não `0`
     porque repartir em partes iguais faria "Dashboards" ficar do tamanho de
     "Administração de Informes" e quebrar o rótulo longo. */
  flex: 1 1 auto;
  flex-direction: column;
  justify-content: center;
  gap: var(--z-space-1);
  height: auto;
  min-height: 0;
  padding: var(--z-space-2) var(--z-space-3);
  line-height: 1.15;
  text-align: center;
}

.tab-button .material-symbols-outlined { font-size: 26px; }

/* O nome é legenda do ícone, não título: menor e sem peso disputando com ele. */
.tab-button > span:last-child {
  font-size: var(--z-text-xs);
  font-weight: 500;
}

.tab-button {
  display: inline-flex;
  align-items: center;
  gap: var(--z-space-2);
  border-radius: var(--z-r-sm) var(--z-r-sm) 0 0;
  background: transparent;
  color: var(--z-ink-400);
  font-weight: 500;
  /* The active tab is marked by a bar as well as by colour, so it survives a
     brand pair that happens to sit close to the ink. */
  border-bottom: 3px solid transparent;
}

.tab-button:hover { background: var(--z-surface-2); filter: none; }

.tab-button.active {
  color: var(--z-ink-900);
  /* A cor SECUNDÁRIA da empresa. A principal já é o cabeçalho inteiro logo
     acima, e a mesma cor duas vezes em dois centímetros não destaca nada — a
     linha some dentro da faixa. A secundária separa a aba escolhida da barra
     que a contém, que é o trabalho desta linha. */
  border-bottom-color: var(--z-brand-2);
  background: transparent;
}

.tab-button[hidden] { display: none; }

/**
 * Uma linha, os campos lado a lado.
 *
 * Já era `flex` com `flex-wrap`, e mesmo assim cada filtro ocupava uma linha
 * inteira: a regra global `input, select, textarea { width: 100% }` faz de cada
 * controle um item que reivindica a largura toda, então o `wrap` quebrava depois
 * de cada um. Sete filtros viravam sete linhas, e o grid só começava meia tela
 * abaixo.
 *
 * Aqui eles voltam a se dimensionar pelo conteúdo, com uma base pequena e teto
 * para nenhum filtro sozinho tomar a barra. `flex-wrap` continua: numa janela
 * estreita quebrar é melhor do que espremer sete campos ilegíveis.
 */
.filters-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--z-space-2);
  align-items: center;
  margin-bottom: var(--z-space-4);
}

.filters-row > select,
.filters-row > input,
.filters-row > label {
  width: auto;
  flex: 1 1 8rem;
  min-width: 7rem;
  max-width: 13rem;
}

/* Os botões de ação não são filtros: mantêm o tamanho do rótulo e vão para o
   fim da barra, separados do que se ajusta. */
.filters-row > button {
  flex: 0 0 auto;
  margin-left: auto;
}

.filters-row > button ~ button { margin-left: 0; }

/* Full width at the top, as the design system asks: search is the primary way
   into a list of fifty people. */
.search-input { flex: 1; min-width: 14rem; }

.grid-frame {
  background: var(--z-surface-0);
  border: 1px solid var(--z-border);
  border-radius: var(--z-r-md);
  overflow-x: auto;
}

.grid-frame table { width: 100%; border-collapse: collapse; }

.grid-frame th,
.grid-frame td {
  padding: var(--z-space-3) var(--z-space-4);
  text-align: left;
  border-bottom: 1px solid var(--z-border);
  vertical-align: top;
}

.grid-frame th {
  font-size: var(--z-text-sm);
  font-weight: 600;
  color: var(--z-ink-400);
  background: var(--z-surface-2);
  white-space: nowrap;
}

.grid-frame tr:last-child td { border-bottom: 0; }

/* Handles and identifiers are data. */
.grid-frame td code {
  font-family: var(--z-font-mono);
  font-size: var(--z-text-sm);
  color: var(--z-ink-700);
}

.sort-button {
  background: transparent;
  color: inherit;
  padding: 0;
  min-height: 0;
  font: inherit;
  font-weight: 600;
}

.sort-button:hover { filter: none; text-decoration: underline; }

.state-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--z-space-2);
  padding: var(--z-space-1) var(--z-space-3);
  border-radius: var(--z-r-pill);
  background: var(--z-surface-2);
  color: var(--z-ink-500);
  font-size: var(--z-text-sm);
  font-weight: 600;
  white-space: nowrap;
}

.state-badge.active {
  background: color-mix(in srgb, var(--z-ok) 16%, transparent);
  color: var(--z-ok);
}

.empty-state {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--z-space-8);
  color: var(--z-ink-400);
}

.row-action {
  padding: 0 var(--z-space-3);
  min-height: 36px;
  font-size: var(--z-text-sm);
  background: var(--z-surface-2);
  color: var(--z-ink-700);
}

.row-action.danger { background: var(--z-sev-critico); color: var(--z-surface-0); }

@media (max-width: 40rem) {
  /* On a phone the action column comes first and the grid scrolls inside its
     own frame, so a clipped column signals that there is more. */
  .filters-row { flex-direction: column; align-items: stretch; }
  /* Empilhados no telefone, cada um ocupa a largura toda de novo. */
  .filters-row > select,
  .filters-row > input,
  .filters-row > label,
  .filters-row > button { max-width: none; margin-left: 0; }
  .search-input { min-width: 0; }
}


/* --------------------------------------------- seletor de logotipo

   Duplicado de `site/wizard.css` pela razão de sempre neste repositório: o site
   e o painel publicam de raízes separadas e nenhum consegue ligar a folha do
   outro. O mesmo motivo que faz cada superfície carregar sua cópia de brand.css.

   O `<input type="file">` cru desenha o controle do sistema operacional — outra
   tipografia, outra altura, outra ideia de botão — e mostra um nome de arquivo
   onde deveria mostrar o logotipo. A moldura redonda É o botão; o input continua
   existindo, apenas invisível, para não levar junto o teclado e o leitor de tela. */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.logo-picker {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--z-space-3);
}

.logo-frame {
  display: grid;
  place-items: center;
  width: 7.5rem;
  height: 7.5rem;
  padding: var(--z-space-3);
  border: 2px dashed var(--z-border-strong);
  border-radius: var(--z-r-pill);
  background: var(--z-surface-1);
  cursor: pointer;
  overflow: hidden;
}

.logo-frame:hover { border-color: var(--z-ink-300); filter: none; }

.logo-frame[data-empty="false"] {
  border-style: solid;
  border-color: var(--z-border);
  background: var(--z-surface-0);
}

.logo-frame img { max-width: 100%; max-height: 100%; object-fit: contain; }

.logo-frame .material-symbols-outlined { font-size: 32px; color: var(--z-ink-300); }

.logo-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--z-space-2);
  justify-content: center;
}


/* ------------------------------------------------ o cabeçalho, revisto

   Zero em destaque e a empresa ao lado. O produto se apresenta; a empresa
   responde de quem é o painel. A marca da empresa não some — ela pinta o painel
   inteiro por `--z-brand-1`. */

.brand-divider {
  color: var(--z-ink-200);
  font-size: var(--z-text-h3);
  line-height: 1;
}

.company-logo {
  width: 22px;
  height: 22px;
  border-radius: var(--z-r-xs);
  object-fit: contain;
}

.company-logo[hidden] { display: none; }

/* Uma voz mais baixa que a do produto, e a primeira coisa a ser cortada quando
   a janela aperta: o nome de uma empresa pode ter oitenta caracteres. */
.company-name {
  min-width: 0;
  max-width: 22rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--z-ink-400);
  font-size: var(--z-text-sm);
}

/**
 * Administração fica presa à direita, sempre visível.
 *
 * Ela não é irmã das abas do módulo: é outro nível de navegação, e foi posta
 * nesta barra porque é aqui que a navegação desta pessoa mora. Fixá-la à direita
 * diz as duas coisas ao mesmo tempo — pertence à barra e não pertence à
 * sequência — e garante que a única porta para a empresa e os usuários não
 * dependa de a janela ser larga o bastante.
 *
 * A sombra à esquerda é o que revela a rolagem: as abas do módulo passam por
 * baixo dela, e o corte é visível em vez de silencioso.
 */
.tab-link {
  position: sticky;
  right: 0;
  text-decoration: none;
  background: var(--z-surface-0);
  box-shadow: -10px 0 10px -6px color-mix(in srgb, var(--z-ink-900) 14%, transparent);
}

@media (max-width: 60rem) {
  .brand-divider,
  .company-name,
  .company-logo { display: none; }
}


/**
 * Quando a barra não cabe, os ícones saem antes dos rótulos.
 *
 * Sete ícones custam cerca de 220px — quase exatamente o que faltava para as
 * oito abas caberem numa janela de 1434px. E a escolha entre esconder um ícone e
 * esconder uma aba não é difícil: o ícone acompanha um rótulo que continua ali,
 * enquanto a aba escondida é uma tela que a pessoa não encontra. Foi assim que a
 * Administração ficou invisível.
 *
 * O limite é a largura em que a barra passa a não caber, medida e não estimada:
 * 1587px de conteúdo com ícones, 1368px de espaço.
 */
/* A regra que escondia os ícones das abas foi removida: empilhados, eles não
   custam largura e a barra cabe com eles. Ver `.tab-button`. */


/* A barra de baixo é o segundo nível: mesma gramática, menos peso, para não
   competir com a de cima. */
.tabbar-sub {
  border-bottom: 0;
  margin-top: calc(var(--z-space-3) * -1);
  margin-bottom: var(--z-space-5);
}

.tabbar-sub .tab-button { font-size: var(--z-text-sm); }

/* O caminho de volta ao programa, na barra de cima. É um link e parece uma aba
   inativa, porque é isso que ele é: a seção onde você não está agora. */
.tab-link-plain {
  text-decoration: none;
  background: transparent;
}

.tab-link-plain:hover { color: var(--z-ink-700); filter: none; }
.tab-link-plain[hidden] { display: none; }


/* -------------------------------------------- os filtros, com uma cara só

   Altura, fonte, borda e recuo já eram iguais — medidos, 48px nos dois. O que
   destoava era o desenho NATIVO: o `select` traz a seta do sistema operacional e
   o `input[type=date]` traz o botão de calendário, em tamanhos e tons que o
   navegador escolhe. Lado a lado, dois controles do mesmo tamanho pareciam de
   famílias diferentes.

   A seta passa a ser desenhada aqui, com `currentColor` — nada de cor literal,
   que `validate-brand-tokens.mjs` recusaria e que seria uma segunda definição de
   uma cor da marca. O indicador do calendário fica com o mesmo peso visual, no
   mesmo lugar. */

/**
 * Todo `select` do painel, e não só os da barra de filtros.
 *
 * Os controles foram acertados primeiro nos filtros e ficaram diferentes de si
 * mesmos nos diálogos: o mesmo campo tinha uma cara ao filtrar e outra ao criar
 * um informe. As regras subiram do seletor `.filters-row >` para o elemento —
 * uma definição, todas as telas — e a barra de filtros mantém apenas o que é
 * dela, que é começar apagada.
 */
select {
  appearance: none;
  padding-right: calc(var(--z-space-3) + 14px);
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-size: 5px 5px, 5px 5px;
  background-position: right 17px center, right 12px center;
  background-repeat: no-repeat;
  color: var(--z-ink-500);
}

/**
 * Os segmentos da data ficam da cor dos outros campos.
 *
 * O Chrome pinta `::-webkit-datetime-edit-*` com a própria cor de destaque — o
 * azul do sistema — e ignora o `color` do input. Ao lado de cinco selects em
 * cinza, o campo de data aparecia em azul, como se estivesse selecionado ou
 * inválido. Não estava: era a cor do sistema operacional aparecendo dentro do
 * nosso controle.
 */
input[type="date"]::-webkit-datetime-edit,
input[type="date"]::-webkit-datetime-edit-text,
input[type="date"]::-webkit-datetime-edit-day-field,
input[type="date"]::-webkit-datetime-edit-month-field,
input[type="date"]::-webkit-datetime-edit-year-field {
  color: inherit;
}

/* O segmento em edição continua marcado, mas com a cor da empresa em vez do azul
   do sistema. */
input[type="date"]::-webkit-datetime-edit-day-field:focus,
input[type="date"]::-webkit-datetime-edit-month-field:focus,
input[type="date"]::-webkit-datetime-edit-year-field:focus {
  background: color-mix(in srgb, var(--z-brand-2) 22%, transparent);
  color: var(--z-ink-900);
  outline: none;
}

input[type="date"] {
  color: var(--z-ink-900);
  /* Os dígitos não dançam ao trocar de dia: um filtro que muda de largura ao ser
     preenchido empurra os vizinhos. */
  font-variant-numeric: tabular-nums;
}

input[type="date"]::-webkit-calendar-picker-indicator {
  opacity: .45;
  cursor: pointer;
}

input[type="date"]::-webkit-calendar-picker-indicator:hover { opacity: .8; }

/**
 * Só na barra de filtros o controle começa apagado.
 *
 * Um filtro vazio é o estado normal e não deve chamar atenção; um campo de
 * formulário vazio é uma pendência. Mesma aparência, tinta diferente, porque
 * dizem coisas diferentes.
 */
.filters-row > select,
.filters-row > input[type="date"] { color: var(--z-ink-500); }


/* ------------------------------------- onde a cor SECUNDÁRIA da empresa aparece

   Ela existe desde o cadastro, é escolhida com a mesma atenção que a principal, e
   até aqui só pintava o ícone de um azulejo que deixou de existir. Uma empresa
   que escolhe duas cores tem de ver as duas.

   A divisão é a que o `DESIGN_SYSTEM.md` §3.5 já estabelece: a marca pinta o
   cromo e nunca pinta significado. Nenhum destes lugares diz nada sobre um
   informe — são o realce da navegação, o foco e a marca d'água do segundo nível.
   Categoria e severidade continuam intocadas. */

/* O anel de foco em superfície branca: a cor da empresa, não o azul do sistema. */
:focus-visible {
  outline-color: var(--z-brand-2);
}

/* Sobrescritos e etiquetas de seção. */
.eyebrow { color: var(--z-brand-2); }

/* `.chart-bar` NÃO entra aqui, e a tentativa fica registrada: séries de gráfico
   usam a paleta fixa do produto porque dois painéis de duas empresas têm de ser
   comparáveis (DESIGN_SYSTEM.md §3.5). Uma série que muda de cor por empresa não
   é uma série. */


/* ============================================ as telas anteriores à sessão

   Entrada, primeiro acesso, redefinição de senha e manutenção. São as únicas
   telas do painel vistas antes de existir uma empresa na conversa, e por isso
   as únicas que a paleta do Zero pinta inteiras — `DESIGN_SYSTEM.md`, "painel
   antes da sessão resolver: marca Zero".

   Elas eram um cartão branco chapado sobre cinza. Quem vinha da landing pelo
   botão "Já tenho acesso" trocava de mundo no clique: mesma marca, outro
   produto. O que segue traz a mesma moldura — aurora ao fundo, vidro no cartão,
   marca grande e viva. */

.pre-session-aurora {
  position: fixed;
  inset: -20vmax;
  z-index: -1;
  pointer-events: none;
  filter: blur(90px) saturate(1.15);
  opacity: .26;
}

.pre-session-aurora span {
  position: absolute;
  display: block;
  width: 46vmax;
  height: 46vmax;
  border-radius: 50%;
  transform-origin: center;
  animation: painel-aurora 26s ease-in-out infinite alternate;
}

.pre-session-aurora span:nth-child(1) { top: 2%;  left: 8%;   background: var(--z-cat-saude); }
.pre-session-aurora span:nth-child(2) { top: 26%; right: 4%;  background: var(--z-cat-ambiente); animation-delay: -9s; }
.pre-session-aurora span:nth-child(3) { bottom: 4%; left: 32%; background: var(--z-cat-qualidade); animation-delay: -17s; }

@keyframes painel-aurora {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(6vmax, -4vmax, 0) scale(1.18); }
}

/* Vidro sobre a aurora. A opacidade é alta porque há um formulário aqui dentro
   e legibilidade de campo ganha de profundidade. */
.notice-card {
  background: color-mix(in srgb, var(--z-surface-0) 88%, transparent);
  backdrop-filter: blur(14px);
  border-color: color-mix(in srgb, var(--z-border) 70%, transparent);
  box-shadow: 0 28px 70px -44px color-mix(in srgb, var(--z-ink-900) 80%, transparent);
}

/* O título com o degradê das quatro categorias, como no herói do site. A cor
   sólida fica declarada antes: se `background-clip: text` não pegar, o título
   aparece em tinta em vez de sumir. */
.notice-card h1 {
  color: var(--z-ink-900);
  background: linear-gradient(100deg,
    var(--z-cat-saude), var(--z-cat-seguranca) 38%,
    var(--z-cat-ambiente) 68%, var(--z-cat-qualidade));
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

/* -------------------------------------------------- a marca na tela de entrada

   Só tamanho e posição. **Nenhum efeito.**

   A revisão 2 da marca não admite sombra, contorno, brilho nem rotação sobre o
   símbolo. A versão anterior desta folha tinha as três coisas: um `drop-shadow`,
   um giro de 64 segundos escrito aqui e o desenho recomposto à mão no HTML. O
   movimento agora vem de dentro de `zero-orbita.svg`, que é oficial e traz o
   próprio `prefers-reduced-motion`. */
/**
 * A CLASSE de alinhamento fica no `<picture>`, não no `<img>`.
 *
 * O filho do formulário — que é `flex-direction: column` — é o `<picture>`, e é
 * ele que recebe `align-self`. Com a regra na imagem, o `<picture>` esticava na
 * largura toda e a marca ficava encostada à esquerda dentro dele. Era isso que
 * se via na tela: uma marca fora de centro num cartão centrado.
 */
.sign-in-mark-wrap {
  align-self: center;
  display: block;
  margin-bottom: var(--z-space-3);
}

/* Maior: 176px contra 116px. Esta é a única tela do produto vista antes de
   existir uma empresa, e agora que o título saiu ela é o que apresenta o
   produto. Sem efeito nenhum — a revisão 2 não admite sombra, contorno, brilho
   nem rotação sobre o símbolo. */
.sign-in-mark {
  display: block;
  width: clamp(120px, 26vw, 176px);
  height: auto;
  aspect-ratio: 1;
}

/* O olho "ZERO" centrado sob a marca. O `<h1>` do formulário é `.sr-only` desde
   que o título visível saiu, então não há o que centrar nele. */
.sign-in .eyebrow { text-align: center; }

/* Quem pediu menos movimento: a aurora para. A marca não é tratada aqui —
   `zero-orbita.svg` carrega o próprio `prefers-reduced-motion` e para sozinha, e
   regra de fora não alcança o interior de um `<img>`. */
@media (prefers-reduced-motion: reduce) {
  .pre-session-aurora span { animation: none; }
}

/* ------------------------------------------------- a escolha da empresa

   Quem tem acesso a mais de uma empresa escolhe uma depois da senha, e troca
   depois pelo menu da pessoa. Uma linha por empresa, o nome inteiro, alvo de
   48px: é uma lista de destinos, não um formulário. */
.company-choices {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--z-space-2);
}

.company-choice {
  width: 100%;
  justify-content: flex-start;
  padding: var(--z-space-2) var(--z-space-4);
  border-radius: var(--z-r-sm);
  text-align: left;
  color: var(--z-ink-900);
  font-weight: 500;
}

.company-choice .material-symbols-outlined { color: var(--z-ink-300); }

.company-switch-list {
  display: flex;
  flex-direction: column;
  gap: var(--z-space-1);
}

.menu-label {
  margin: 0 0 var(--z-space-2);
  font-size: var(--z-text-eyebrow);
  font-weight: 600;
  letter-spacing: var(--z-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--z-ink-300);
}

.menu-section[hidden] { display: none; }

/* ------------------------------------------------ senha, código e convite */

/* A tela que define a senha: o mesmo ritmo do cartão de entrada. `display`
   só quando visível — o `[hidden]` do navegador tem de continuar valendo. */
.password-flow:not([hidden]),
.otp-block:not([hidden]) {
  display: flex;
  flex-direction: column;
  gap: var(--z-space-4);
}

.otp-block p { margin: 0; }

/* O botão de pedir o código não estica: é uma ação ao lado do campo, não o
   envio do formulário. */
.otp-block .ghost-button { align-self: flex-start; }

/**
 * O QR do convite é SEMPRE escuro sobre claro.
 *
 * `site/qrcode.js` pinta com `--z-surface-0` e `--z-ink-900`, e no tema
 * escuro do painel esses dois se invertem — o código sairia claro sobre
 * escuro, que nem todo leitor lê. O próprio gerador avisa disso. Aqui os dois
 * são redefinidos DENTRO do SVG a partir de valores lidos no quadro, e no
 * escuro o quadro lê o par ao contrário: a tinta do tema escuro é branca, e a
 * noite é quase preta. Nenhuma cor nova: as mesmas quatro do `brand.css`.
 */
.invite-qr {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--z-space-2);
  --qr-light: var(--z-surface-0);
  --qr-dark: var(--z-ink-900);
}

.invite-qr[hidden] { display: none; }

[data-theme='dark'] .invite-qr {
  --qr-light: var(--z-ink-900);
  --qr-dark: var(--z-night);
}

.invite-qr-frame {
  width: 220px;
  max-width: 100%;
  line-height: 0;
}

.invite-qr-frame svg {
  width: 100%;
  height: auto;
  --z-surface-0: var(--qr-light);
  --z-ink-900: var(--qr-dark);
}

.invite-message {
  margin: 0;
  padding: var(--z-space-3);
  border-radius: var(--z-r-sm);
  background: var(--z-surface-2);
  color: var(--z-ink-700);
  white-space: pre-wrap;
}

.invite-message[hidden] { display: none; }

.invite-actions { flex-wrap: wrap; }

/* Um link com a forma do botão principal: abre o WhatsApp de quem convida
   numa aba nova, com a mensagem já escrita. */
.invite-whatsapp {
  display: inline-flex;
  align-items: center;
  gap: var(--z-space-2);
  text-decoration: none;
}

/* ------------------------------------------- WEB-106: Acesso e pedidos */

/**
 * Empresa › Acesso: três cartões empilhados, cada um com a medida de um
 * formulário (`.form-column`) — um campo de URL de 1700px não ajuda ninguém.
 */
.access-card {
  max-width: 56rem;
  display: flex;
  flex-direction: column;
  gap: var(--z-space-3);
  padding: var(--z-space-5) 0;
  border-top: 1px solid var(--z-border);
}

.access-card:first-of-type { border-top: 0; padding-top: 0; }
.access-card[hidden] { display: none; }
.access-card h2 { margin: 0; }
.access-card .field-help { margin: 0; }

.access-form {
  display: flex;
  flex-direction: column;
  gap: var(--z-space-3);
}

/* "Expira depois de [180] dias sem entrar", numa linha só. */
.access-choice {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--z-space-2);
}

.access-choice .role-choice { margin: 0; }
.access-choice input[type="number"] { width: 7rem; }

/* Um valor para copiar e o botão ao lado dele. */
.copy-row {
  display: flex;
  gap: var(--z-space-2);
  align-items: center;
}

.copy-row input { flex: 1; min-width: 0; }

/* O segredo configurado: o selo e "Substituir", nunca o valor. */
.sso-secret-state {
  display: flex;
  align-items: center;
  gap: var(--z-space-3);
}

.sso-secret-state[hidden] { display: none; }

/* Todos / Pedidos de acesso, acima da busca. */
.users-filter {
  display: inline-flex;
  margin-bottom: var(--z-space-3);
}

.users-filter .choice-button { flex: 0 0 auto; padding: 0 var(--z-space-4); }

/* O número de pedidos esperando: pequeno, e na cor que pede atenção. */
.count-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.5rem;
  height: 1.5rem;
  padding: 0 var(--z-space-2);
  border-radius: var(--z-r-pill);
  background: var(--z-sev-critico);
  color: var(--z-surface-0);
  font-size: var(--z-text-sm);
  font-weight: 600;
}

.count-badge[hidden] { display: none; }

/* A situação que pede uma decisão de alguém. */
.state-badge.pending {
  background: var(--z-sev-alto-soft);
  color: var(--z-ink-900);
}

/* "Sair desta empresa" é um fim de vínculo, não um "Sair" comum. */
.leave-company { color: var(--z-sev-critico); }

/**
 * A folha A4 do QR de entrada.
 *
 * Na tela ela nunca aparece (`hidden`). Ao imprimir, `body.printing-join`
 * esconde tudo o que não é ela e a mostra centrada numa página A4 — sem
 * cabeçalho, sem menu, sem a aurora. Preto no branco, de propósito: é papel.
 */
.print-sheet {
  display: none;
  /* O mesmo par do QR do convite: escuro sobre claro nos dois temas. */
  --qr-light: var(--z-surface-0);
  --qr-dark: var(--z-ink-900);
}

[data-theme='dark'] .print-sheet {
  --qr-light: var(--z-ink-900);
  --qr-dark: var(--z-night);
}

@media print {
  @page { size: A4; margin: 20mm; }

  body.printing-join > :not(.print-sheet) { display: none !important; }

  body.printing-join > .print-sheet {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10mm;
    min-height: 240mm;
    text-align: center;
    color: var(--qr-dark);
  }

  .print-sheet h1 { margin: 0; font-size: 28pt; }

  .print-sheet-qr { width: 120mm; line-height: 0; }

  .print-sheet-qr svg {
    width: 100%;
    height: auto;
    --z-surface-0: var(--qr-light);
    --z-ink-900: var(--qr-dark);
  }

  .print-sheet-lead { margin: 0; font-size: 18pt; font-weight: 600; }
  .print-sheet-url { margin: 0; font-size: 10pt; word-break: break-all; }
}

/* ------------------------------------------------ excluir minha conta (PRIV-102)

   O que acontece, em lista curta: a pessoa lê antes de decidir. O bloco das
   empresas que faltam sair fica destacado, porque é o que impede o pedido. */
.deletion-intro,
.deletion-form {
  display: flex;
  flex-direction: column;
  gap: var(--z-space-3);
}

.deletion-form[hidden],
.deletion-intro[hidden],
.deletion-memberships[hidden] { display: none; }

.deletion-points {
  margin: 0;
  padding-left: var(--z-space-5);
  display: flex;
  flex-direction: column;
  gap: var(--z-space-2);
  color: var(--z-ink-500);
  font-size: var(--z-text-sm);
}

.deletion-memberships {
  display: flex;
  flex-direction: column;
  gap: var(--z-space-2);
  padding: var(--z-space-3);
  border: 1px solid var(--z-sev-alto);
  border-radius: var(--z-r-sm);
  background: var(--z-sev-alto-soft);
}

.deletion-memberships p { color: var(--z-ink-900); }
