/* =========================================================
   ZERO — DESIGN TOKENS
   Informe de segurança · Saúde, Segurança, Meio Ambiente, Qualidade

   Fonte única de verdade. Não hardcode cor, raio, sombra ou duração
   fora deste arquivo. Ver BRAND.md para as regras normativas.
   ========================================================= */

/* ---------------------------------------------------------
   AS FONTES SÃO DAQUI. Nada é pedido ao Google em execução.

   Antes isto era um `@import` para `fonts.googleapis.com`, e cada pessoa que
   abria qualquer tela do Zero fazia o navegador contar ao Google que estava
   ali — endereço IP, página, horário. Para um produto que fala de LGPD na
   própria política de privacidade, mandar o IP de todo usuário a um terceiro
   para buscar tipografia é difícil de defender.

   Também deixou de ser um ponto de falha: numa corrida do simulador a rede
   oscilou, o pedido morreu com `ERR_NETWORK_CHANGED` e a página reprovou por
   uma coisa que ninguém pode corrigir no código.

   Só `latin` e `latin-ext`, que é o que o português usa — cirílico, grego e
   vietnamita eram 29 dos 51 arquivos que o Google entregava. Os ícones são um
   subconjunto dos 20 que o produto realmente desenha: 24 KB contra 3.874 KB da
   família inteira, e `validate-fonts.mjs` recusa um ícone que não esteja nele,
   para que a economia nunca vire uma caixinha vazia na tela.

   Licenças: Sora e IBM Plex sob SIL Open Font License 1.1; Material Symbols
   sob Apache License 2.0. As três permitem redistribuição. Ver fonts/LICENSES.md.
   --------------------------------------------------------- */

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/ibm-plex-mono-400-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/ibm-plex-mono-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/ibm-plex-mono-500-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/ibm-plex-mono-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/ibm-plex-mono-600-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "IBM Plex Mono";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/ibm-plex-mono-600-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Sans";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-400-italic-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "IBM Plex Sans";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-400-italic-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-400-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-500-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-600-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-600-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-700-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "IBM Plex Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/ibm-plex-sans-700-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Sora";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/sora-400-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Sora";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/sora-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Sora";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/sora-600-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Sora";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("fonts/sora-600-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Sora";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/sora-700-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Sora";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/sora-700-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Material Symbols Outlined";
  font-style: normal;
  font-weight: 300 700;
  /* block, e não swap: um ícone trocado por texto durante o carregamento mostra
     a palavra "logout" no lugar do desenho, o que é pior do que nada aparecer
     por um instante. */
  font-display: block;
  src: url("fonts/material-symbols-outlined.woff2") format("woff2");
}

.material-symbols-outlined {
  font-family: "Material Symbols Outlined";
  font-weight: normal;
  font-style: normal;
  font-size: 24px;
  line-height: 1;
  letter-spacing: normal;
  text-transform: none;
  display: inline-block;
  white-space: nowrap;
  word-wrap: normal;
  direction: ltr;
  -webkit-font-feature-settings: "liga";
  -webkit-font-smoothing: antialiased;
}

/* ---------------------------------------------------------
   `hidden` PRECISA esconder.

   A folha do próprio navegador diz `[hidden] { display: none }`, e essa regra
   tem o menor peso possível: QUALQUER regra de autor que defina `display` numa
   classe ganha dela. Foi assim que `.boot-screen { display: flex }` fez
   `node.hidden = true` não fazer nada — o painel chamava `show("signIn")`
   depois de um 401, o código estava certo, e o usuário via um spinner para
   sempre.

   `painel/styles.css` acumulou seis remendos `X[hidden] { display: none }`,
   um de cada vez, e nunca esta linha. Fica aqui, no arquivo que as quatro
   superfícies carregam, porque o problema não era de nenhuma delas em
   particular.

   `validate-web-surfaces.mjs` verifica que esta regra continua existindo.
   --------------------------------------------------------- */
[hidden] {
  display: none !important;
}


:root {
  /* ---------- TIPOGRAFIA ---------- */
  --z-font-display: 'Sora', system-ui, sans-serif;
  --z-font-sans: 'IBM Plex Sans', system-ui, -apple-system, sans-serif;
  --z-font-mono: 'IBM Plex Mono', ui-monospace, monospace;

  --z-text-display: 2.75rem;   /* 44px — hero, splash */
  --z-text-h1: 2rem;           /* 32px */
  --z-text-h2: 1.5rem;         /* 24px */
  --z-text-h3: 1.1875rem;      /* 19px */
  --z-text-body: 1rem;         /* 16px — mínimo de corpo no app */
  --z-text-sm: 0.875rem;       /* 14px */
  --z-text-xs: 0.75rem;        /* 12px — só rótulo, nunca frase */
  --z-text-eyebrow: 0.6875rem; /* 11px, maiúsculas, tracking largo */

  --z-leading-tight: 1.1;
  --z-leading-snug: 1.35;
  --z-leading-body: 1.6;
  --z-tracking-display: -0.02em;
  --z-tracking-eyebrow: 0.28em;

  /* ---------- TINTA E SUPERFÍCIE ---------- */
  --z-ink-900: #0B1424;
  --z-ink-800: #14203B;  /* grafite da marca */
  --z-ink-700: #1E2C4A;
  --z-ink-500: #3A465A;
  --z-ink-400: #5B6B7F;
  --z-ink-300: #8792A3;
  --z-ink-200: #9BA5B2;
  --z-ink-100: #C9D1DA;

  --z-surface-0: #FFFFFF;
  --z-surface-1: #F4F7F6;
  --z-surface-2: #EEF2F0;
  --z-border: #DCE4E0;
  --z-border-strong: #C2CCC7;

  /* ---------- PALETA SUGERIDA À EMPRESA ----------
     Seis pares oferecidos no cadastro para a empresa escolher as SUAS cores.
     Não são cores do Zero e não devem ser usadas em nenhuma superfície nossa.

     Existem porque o wizard abria com o grafite da marca — contraste 18,4:1
     contra branco, o extremo da escala — e uma pessoa diante de dois seletores
     já preenchidos com a cor de quem a está cadastrando não entende que a
     escolha é dela. Um campo pré-preenchido não pede decisão nenhuma.

     Cada par foi medido: a cor 1 fica entre 4,4:1 e 5,6:1 sobre branco, ou
     seja, legível com tinta branca e longe do quase-preto; a cor 2 passa de
     5:1 sobre branco, que é onde ela aparece (o ícone do módulo). A empresa
     continua livre para escolher qualquer cor nos seletores — estes são o
     ponto de partida, não uma restrição. */
  --z-suggest-1a: #2E7D6B;  --z-suggest-1b: #1F5F51;  /* verde-mar */
  --z-suggest-2a: #4A6FA5;  --z-suggest-2b: #37527A;  /* azul-sereno */
  --z-suggest-3a: #8A5A83;  --z-suggest-3b: #6B4566;  /* ameixa */
  --z-suggest-4a: #A85C28;  --z-suggest-4b: #83461E;  /* terracota */
  --z-suggest-5a: #4F6D7A;  --z-suggest-5b: #3B535D;  /* ardósia */
  --z-suggest-6a: #6B7A3F;  --z-suggest-6b: #515D2F;  /* oliva */

  /* ---------- CATEGORIA (tipo de informe) ----------
     Uso exclusivo: barra lateral do card, ícone e ponto.
     NUNCA como preenchimento de pílula de severidade. */
  --z-cat-saude: #0E7C86;
  --z-cat-seguranca: #E8722A;
  --z-cat-ambiente: #12A05C;
  --z-cat-qualidade: #7B4DD8;

  --z-cat-saude-soft: #E3F1F2;
  --z-cat-seguranca-soft: #FCEDE3;
  --z-cat-ambiente-soft: #E3F4EB;
  --z-cat-qualidade-soft: #EFE9FC;

  --z-cat-saude-ink: #0A5C64;
  --z-cat-seguranca-ink: #A44D16;
  --z-cat-ambiente-ink: #0B7343;
  --z-cat-qualidade-ink: #5732A8;

  /* ---------- SEVERIDADE ----------
     Uso exclusivo: pílula de status e o centro do alvo.
     NUNCA como barra lateral ou ícone de categoria. */
  --z-sev-critico: #D92D20;
  --z-sev-alto: #F5B301;
  --z-sev-moderado: #5B6B7F;
  --z-sev-baixo: #8792A3;
  --z-sev-critico-soft: #FDECEA;
  --z-sev-alto-soft: #FEF6E0;

  /* ---------- SÉRIE DE GRÁFICO ----------
     Paleta fixa do produto, NUNCA a da empresa. Dois painéis de duas empresas
     precisam ser comparáveis, e uma série que muda de cor por empresa não é.
     DESIGN_SYSTEM.md exige isso; até aqui nenhum token existia para cumprir.

     As oito foram MEDIDAS, não escolhidas de olho — a primeira tentativa tinha
     duas séries a ΔE 18,5 uma da outra e uma delas com contraste 2,68 sobre
     branco. Restrições, todas verificadas por validate-brand-tokens.mjs:

       ΔE76 ≥ 30 entre quaisquer duas séries       (obtido: 30,1)
       ΔE76 ≥ 30 até qualquer cor que já significa
         algo — categoria e severidade             (obtido: 30,3)
       contraste ≥ 3:1 sobre --z-surface-0 nos
         dois temas                                (obtido: 3,02 / 3,01)
       nenhum par com a MESMA luminância           (obtido: 1,045:1)

     A última existe porque duas séries tinham luminância idêntica — 1,00:1 —
     e impressas eram o mesmo cinza. Corrigir isso NÃO resolve a impressão, e é
     importante não fingir que resolve: a regra de ≥3:1 nos dois temas confina a
     luminância à faixa [0,146; 0,300], que é uma janela de 1,786:1. Oito séries
     ali ficam, no melhor caso, a 1,086:1 umas das outras — invisível. Só três
     séries caberiam distinguíveis em cinza por luminância.

     Por isso a distinção na impressão vem de TRAMA, não de tom: module.css dá a
     cada série um padrão próprio dentro de @media print. Quem for "arrumar" a
     paleta para funcionar em cinza sem trama está tentando resolver uma conta
     que não fecha.

     A segunda restrição é a que importa e é fácil de esquecer: uma barra de
     série parecida com --z-sev-critico diz "crítico" para quem olha, e a barra
     não está dizendo isso. Entre os conjuntos que passavam, este é o de menor
     saturação (média 38%) — o menos berrante que ainda satisfaz a medida. */
  --z-chart-1: #526B98;
  --z-chart-2: #8B59A6;
  --z-chart-3: #B3574D;
  --z-chart-4: #BF40B9;
  --z-chart-5: #728B4B;
  --z-chart-6: #B47491;
  --z-chart-7: #AD8A67;
  --z-chart-8: #B1912F;

  /* ---------- ESTADO ---------- */
  --z-ok: #12A05C;
  --z-info: #0E7C86;
  --z-focus: #0E7C86;

  /* ---------- GRADIENTES DA MARCA ---------- */
  /* O ANEL DA MARCA — revisão 2.
     Quatro arcos DISCRETOS com fenda entre eles, e não um degradê contínuo.
     A v2 é explícita: "São sempre quatro arcos, nessa ordem. Nunca degradê,
     nunca um quinto." A ordem, a partir do topo e no sentido horário, é
     Saúde, Segurança, Meio Ambiente, Qualidade — a v1 trocava as duas do meio.
     83 graus de arco e 7 de fenda: é a mesma proporção 23/77 por quarto que
     `zero-logo.svg` desenha com `stroke-dasharray`. */
  --z-ring-saude: #0E7C86;
  --z-ring-seguranca: #E8722A;
  --z-ring-ambiente: #12A05C;
  --z-ring-qualidade: #7B4DD8;

  --z-ring: conic-gradient(from -90deg,
    var(--z-ring-saude) 0deg 83deg, transparent 83deg 90deg,
    var(--z-ring-seguranca) 90deg 173deg, transparent 173deg 180deg,
    var(--z-ring-ambiente) 180deg 263deg, transparent 263deg 270deg,
    var(--z-ring-qualidade) 270deg 353deg, transparent 353deg 360deg);
  /* A versão linear do anel, para barra e texto. Mesma ORDEM da revisão 2:
     saúde, segurança, ambiente, qualidade. Estava com as duas do meio
     trocadas, herdado do anel antigo. */
  --z-ring-linear: linear-gradient(135deg,
    var(--z-ring-saude), var(--z-ring-seguranca) 32%,
    var(--z-ring-ambiente) 66%, var(--z-ring-qualidade));
  --z-aura: radial-gradient(circle at 50% 50%,
      rgba(18,160,92,.20) 0%, rgba(232,114,42,.14) 40%,
      rgba(123,77,216,.10) 62%, transparent 74%);

  /* ---------- MARCA DA EMPRESA ----------
     Preenchidos em runtime a partir de GET /me. Ver BRAND.md secao 3.5:
     a marca da empresa pinta o CROMO, nunca a semantica de categoria ou
     severidade. Os valores abaixo sao so o estado antes do login. */
  --z-brand-1: var(--z-ink-800);
  --z-brand-2: var(--z-ink-700);
  --z-brand-1-ink: #FFFFFF;
  --z-brand-2-ink: #FFFFFF;

  /* ---------- FORMA ---------- */
  --z-delay-loading: 400ms;  /* secao 6.1: abaixo disso, nada aparece */

  --z-r-xs: 8px;
  --z-r-sm: 12px;
  --z-r-md: 16px;
  --z-r-lg: 22px;
  --z-r-xl: 28px;
  --z-r-pill: 999px;
  --z-icon-squircle: 22.5%;  /* raio do ícone do app, sempre % do lado */

  --z-space-1: 4px;
  --z-space-2: 8px;
  --z-space-3: 12px;
  --z-space-4: 16px;
  --z-space-5: 24px;
  --z-space-6: 32px;
  --z-space-7: 48px;
  --z-space-8: 64px;

  --z-tap-min: 48px;  /* alvo de toque mínimo — o app é usado com luva */

  /* ---------- ELEVAÇÃO (sombra fria, nunca preto puro) ---------- */
  --z-elev-1: 0 1px 2px rgba(11,20,36,.06), 0 1px 3px rgba(11,20,36,.07);
  --z-elev-2: 0 2px 4px rgba(11,20,36,.05), 0 8px 16px -6px rgba(11,20,36,.14);
  --z-elev-3: 0 12px 32px -10px rgba(11,20,36,.26);
  --z-inset: inset 0 1px 0 rgba(255,255,255,.6);

  /* ---------- MOVIMENTO ---------- */
  --z-ease: cubic-bezier(.16, 1, .3, 1);
  --z-ease-in-out: cubic-bezier(.4, 0, .2, 1);
  --z-dur-fast: 120ms;
  --z-dur-base: 220ms;
  --z-dur-slow: 340ms;
  --z-dur-ripple: 760ms;
}

/* Tema escuro — inverte superfície, mantém categoria e severidade */
/* O escuro nasce da cor da empresa, não de um azul fixo.

   Era uma paleta única — o grafite do Zero — para toda empresa. Uma empresa
   vermelha punha o próprio cabeçalho vermelho sobre um fundo azul-escuro, duas
   marcas na mesma tela sem relação nenhuma, e o contraste entre elas era sorte.

   As superfícies passam a ser a cor da empresa diluída numa base quase preta:
   pouca saturação, hue da empresa. Um painel de empresa teal fica esverdeado, um
   de empresa vermelha fica quente, e o cabeçalho — que É `--z-brand-1` — assenta
   sobre algo da mesma família em vez de brigar.

   `--z-night` é a âncora e vive aqui, que é onde as cores literais deste produto
   vivem. As proporções são baixas de propósito: acima de ~25% a superfície deixa
   de ser fundo e vira cor.

   `--z-brand-1` é redeclarado porque o valor de :root é `var(--z-ink-800)`, e
   `--z-ink-800` aqui é CLARO — uma empresa sem marca escolhida herdaria um
   "brand" quase branco. Uma empresa com marca sobrescreve os dois pelo estilo
   inline que `applyCompanyBrand` escreve, que vence qualquer seletor. */
[data-theme='dark'] {
  --z-night: #070B14;
  --z-brand-1: #14203B;
  --z-brand-2: #1E2C4A;

  --z-surface-0: color-mix(in srgb, var(--z-brand-1) 16%, var(--z-night));
  --z-surface-1: color-mix(in srgb, var(--z-brand-1) 9%, var(--z-night));
  --z-surface-2: color-mix(in srgb, var(--z-brand-1) 23%, var(--z-night));
  --z-border: color-mix(in srgb, var(--z-brand-1) 34%, var(--z-night));
  --z-border-strong: color-mix(in srgb, var(--z-brand-1) 50%, var(--z-night));
  --z-ink-900: #FFFFFF;
  --z-ink-800: #E8EDF3;
  --z-ink-700: #CBD5E1;
  --z-ink-500: #9BA9BC;
  --z-ink-400: #8492A6;
  --z-elev-1: 0 1px 2px rgba(0,0,0,.32);
  --z-elev-2: 0 8px 20px -8px rgba(0,0,0,.5);
  --z-elev-3: 0 16px 40px -12px rgba(0,0,0,.6);
  --z-inset: inset 0 1px 0 rgba(255,255,255,.06);
}

/* =========================================================
   EFEITOS DE MARCA
   ========================================================= */

/* O anel. Base do logo, do avatar de categoria e do indicador de meta. */
.z-ring {
  --ring-size: 96px;
  --ring-thickness: 14%;
  width: var(--ring-size);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--z-ring);
  -webkit-mask: radial-gradient(circle, transparent calc(50% - var(--ring-thickness)), #000 calc(50% - var(--ring-thickness) + 1px));
  mask: radial-gradient(circle, transparent calc(50% - var(--ring-thickness)), #000 calc(50% - var(--ring-thickness) + 1px));
}

/* Aura. Só atrás da marca em hero e splash. Nunca atrás de texto corrido. */
.z-aura { position: relative; isolation: isolate; }
.z-aura::before {
  content: '';
  position: absolute;
  inset: -60%;
  z-index: -1;
  background: var(--z-aura);
  filter: blur(28px);
  animation: z-breathe 7s var(--z-ease-in-out) infinite;
}

/* Onda concêntrica. Dispara ao enviar um informe: o registro saindo
   para a base da pirâmide. Este é o gesto assinatura do produto. */
.z-ripple { position: relative; overflow: visible; }
.z-ripple::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  border: 2px solid var(--z-cat-ambiente);
  opacity: 0;
  pointer-events: none;
}
.z-ripple[data-sent='true']::after {
  animation: z-ripple-out var(--z-dur-ripple) var(--z-ease) forwards;
}

/* Anel de foco. Acessibilidade e marca no mesmo elemento. */
.z-focus-ring:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--z-surface-0), 0 0 0 4px var(--z-focus);
}

/* Indicador de carregamento.
 *
 * RULE (secao 6.1): o loading so entra depois de 400ms de espera. Isso e feito
 * em CSS, com atraso na animacao, e nao em JavaScript: um setTimeout por tela e
 * um lugar por tela onde a regra pode ser esquecida. Marque o elemento com
 * .z-loading e ele se revela sozinho, ou nunca aparece se a espera terminar
 * antes — que e o caso da maioria das requisicoes.
 *
 * Sob prefers-reduced-motion o anel para de girar mas o atraso permanece: o
 * usuario pediu menos movimento, nao mais espera. */
.z-loading {
  opacity: 0;
  animation: z-loading-reveal var(--z-dur-fast) var(--z-ease) var(--z-delay-loading) forwards;
}

/* O indicador de espera É a marca: `animations/zero-loading.svg`.

   `BRAND.md` recusa o player Lottie no web e a razão continua de pé — um player
   custa ~250KB em toda navegação. Mas a razão sempre foi o PLAYER, não o
   desenho: a revisão 2 da marca entrega o SVG animado por CSS pronto, ao lado do
   Lottie que o app usa. Os dois saem da mesma fonte, então o web e o app mostram
   o mesmo movimento sem ninguém converter nada.

   Havia um conversor aqui (`scripts/lottie-to-svg.mjs`) que gerava o SVG a
   partir do JSON. **Foi removido na revisão 2**, porque o SVG passou a ser
   entregue: um conversor que traduz um arquivo que já existe é uma segunda
   chance de a marca sair errada, e saiu — cinco vezes.

   O arquivo traz o próprio `prefers-reduced-motion` e para sozinho.

   A cor é do ZERO e não da empresa: este é o alvo do produto, não o cromo do
   cliente. Dentro de um botão vale o contrário — ver `.spinner` em
   `painel/styles.css`, que usa `currentColor` porque um alvo de quatro cores em
   16px vira borrão e brigaria com a cor do próprio botão. */
.z-loading-ring {
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
  background: url("animations/zero-loading.svg") center / contain no-repeat;
}

/* Cabeçalho fixo translúcido. Só no topo. */
.z-glass {
  background: color-mix(in srgb, var(--z-surface-0) 78%, transparent);
  backdrop-filter: blur(14px) saturate(1.4);
  border-bottom: 1px solid var(--z-border);
}

/* Card de informe. A barra lateral carrega a categoria. */
.z-card {
  background: var(--z-surface-0);
  border: 1px solid var(--z-border);
  border-left: 4px solid var(--cat, var(--z-ink-300));
  border-radius: var(--z-r-md);
  box-shadow: var(--z-elev-1);
  padding: var(--z-space-4);
  transition: box-shadow var(--z-dur-base) var(--z-ease),
              transform var(--z-dur-base) var(--z-ease);
}
.z-card:hover { box-shadow: var(--z-elev-2); transform: translateY(-1px); }

/* Pílula de severidade. Único lugar onde vermelho e âmbar aparecem. */
.z-sev {
  font: 600 var(--z-text-xs)/1 var(--z-font-sans);
  letter-spacing: .04em;
  text-transform: uppercase;
  padding: 6px 10px;
  border-radius: var(--z-r-pill);
}
.z-sev--critico { background: var(--z-sev-critico); color: #fff; }
.z-sev--alto { background: var(--z-sev-alto-soft); color: #7A5800; }
.z-sev--moderado { background: var(--z-surface-2); color: var(--z-ink-400); }
.z-sev--baixo { background: var(--z-surface-2); color: var(--z-ink-400); }

/* Números de dashboard sempre alinham em coluna. */
.z-num {
  font-family: var(--z-font-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

@keyframes z-ripple-out {
  0%   { opacity: .9; transform: scale(1); }
  100% { opacity: 0; transform: scale(2.6); }
}
@keyframes z-breathe {
  0%, 100% { opacity: .75; transform: scale(1); }
  50%      { opacity: 1; transform: scale(1.06); }
}
@keyframes z-ring-in {
  from { opacity: 0; transform: scale(.9) rotate(-14deg); }
  to   { opacity: 1; transform: scale(1) rotate(0); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
}

@keyframes z-loading-reveal {
  to { opacity: 1; }
}

@keyframes z-spin {
  to { transform: rotate(360deg); }
}
