/* NEXUS · sistema visual — papel claro com cor rara (DECISÃO do PO 20260921-2330).
 * Base osso/tinta, sem gradientes nem sombras; a separação é uma linha de 1px.
 * A cor de acção é uma só (petróleo); os estados aparecem uma vez por ecrã.
 * Instrument Serif nos títulos e números grandes; Instrument Sans no resto.
 */

/* O atributo HTML `hidden` tem de esconder SEMPRE, mesmo quando um selector de
 * classe do autor define `display`. Sem isto, `.x[flex] + hidden` mostra na
 * mesma (a folha do browser perde para a classe). Armadilha que já mordeu na
 * vista de infraestrutura; global para não voltar a morder. */
[hidden] { display: none !important; }

:root {
  /* ---- A linguagem nova (DECISÃO 2330) ---- */
  --papel: #FFFFFF;
  --fundo: #F4F2ED;
  --fundo-2: #EDEAE1;
  --linha: #E2DFD6;
  --linha-forte: #DCD8CD;

  --tinta: #1C1B18;
  --tinta-2: #46433C;
  --tinta-3: #5A574F;
  --tinta-4: #6E6A60;
  /* 0800 §4: era #8A857A (3,67:1 sobre --papel, falhava AA). Escurecido até
     passar 4,5:1 — #726D63 dá 5,14:1, distinto do --tinta-4. Toca 24 usos via
     --txt-muted. */
  --tinta-fraca: #726D63;

  --accao: #2F5E5A;
  --accao-escura: #1F433F;

  --erro: #B4451F;
  --erro-fundo: #FBEDE8;
  --erro-tinta: #8E3818;

  --aviso: #C08A2E;
  --aviso-fundo: #F7F1E4;
  --aviso-tinta: #7A5A22;

  --bom: #4A6741;
  --bom-fundo: #EAF0EE;

  /* Crachás de cliente e de caixa — mesma luminosidade, dessaturados de propósito */
  --cracha-1: #2F5E5A;
  --cracha-2: #3A4E7A;
  --cracha-3: #6B4269;
  --cracha-4: #4A6741;
  --cracha-5: #8A5A2B;

  /* Selecção — item escolhido numa lista (FASE 2, ADENDA 1330). Único token
     novo aprovado pelo PO. Par escuro em :root[data-tema="escuro"]. */
  --seleccao: #EFF3F2;

  --raio: 10px;
  --raio-pequeno: 7px;

  /* ---- Nomes antigos, A CAMINHO DE SAIR: apontam para os novos para não deixar
   * nenhuma página com variável indefinida enquanto o CSS espalhado migra. ---- */
  --bg-0: var(--fundo);
  --bg-1: var(--papel);
  --bg-2: var(--papel);
  --bg-3: var(--fundo-2);
  --line: var(--linha);
  --line-strong: var(--linha-forte);
  --txt: var(--tinta);
  --txt-dim: var(--tinta-3);
  --txt-muted: var(--tinta-fraca);
  --azul: var(--accao);
  --ciano: var(--accao);
  --violeta: var(--accao);
  --violeta-forte: var(--accao-escura);
  --sucesso: var(--bom);
  --nucleo-glow: none;
  --card-shadow: none;
}

/* ═══════════════════════════════════════════════════════════════
   TEMA ESCURO (pedido 20260922-0800 §3). O PO quer poder voltar ao
   escuro pela lua; logo os valores não desaparecem — voltam.

   Os valores vêm do HISTÓRICO deste ficheiro, do :root anterior à
   troca para o tema claro: commit 159a405 (pai de 779ea43, o pedido
   2330 que trouxe o claro). Só se sobrescrevem os SEMÂNTICOS; a
   camada de compatibilidade (--bg-*, --txt*, --ciano…) aponta para
   eles e passa a funcionar nos dois temas de graça.

   Especificidade: :root[data-tema] > :root, por isso ganha sempre,
   independente da ordem no ficheiro.

   Regra «nada se inventa» (arranque de turno 0922): TODO o hex daqui é do
   histórico 159a405. O tema escuro do histórico só tinha 3 níveis de texto
   (--txt/--txt-dim/--txt-muted); os 5 nomes de tinta do tema claro colapsam
   sobre esses 3 — fiel ao histórico, sem hex interpolado. Os únicos valores
   sem antepassado directo são os FUNDOS de estado (o tema claro é que os criou;
   o escuro nunca teve --erro-fundo/--aviso-fundo/--bom-fundo): em vez de cor
   nova, uso a própria cor de estado do histórico ESBATIDA a 14% — não é cor
   nova, é a mesma cor a servir de fundo. Listados na RESPOSTA para o PO decidir.
═══════════════════════════════════════════════════════════════ */
:root[data-tema="escuro"] {
  --papel: #131a30;                       /* 159a405 --bg-2 */
  --fundo: #05070f;                       /* 159a405 --bg-0 */
  --fundo-2: #1a2242;                     /* 159a405 --bg-3 (mantém alias --bg-3) */
  --linha: rgba(120, 140, 200, 0.15);     /* 159a405 --line */
  --linha-forte: rgba(120, 140, 200, 0.3);/* 159a405 --line-strong */

  --tinta: #e6edff;                       /* 159a405 --txt */
  --tinta-2: #8b98c9;                     /* 159a405 --txt-dim (o escuro só tinha 3 greys) */
  --tinta-3: #8b98c9;                     /* 159a405 --txt-dim (mantém alias --txt-dim) */
  --tinta-4: #808fbf;                     /* 159a405 --txt-muted (idem: colapsa no histórico) */
  --tinta-fraca: #808fbf;                 /* 159a405 --txt-muted, 5,42:1 sobre --papel (mantém alias --txt-muted) */

  --accao: #22d3ee;                       /* 159a405 --ciano (a cor de link do escuro) */
  --accao-escura: #7c3aed;                /* 159a405 --violeta-forte (mantém alias --violeta-forte) */

  --erro: #f87171;                        /* 159a405 --erro */
  --erro-fundo: rgba(248, 113, 113, 0.14);/* --erro (159a405) esbatida — o escuro não tinha fundo de erro */
  --erro-tinta: #f87171;                  /* 159a405 --erro (texto de erro legível sobre escuro) */

  --aviso: #facc15;                       /* 159a405 --aviso */
  --aviso-fundo: rgba(250, 204, 21, 0.14);/* --aviso (159a405) esbatida — idem */
  --aviso-tinta: #facc15;                 /* 159a405 --aviso, 11,26:1 sobre --papel */

  --bom: #34d399;                         /* 159a405 --sucesso (mantém alias --sucesso) */
  --bom-fundo: rgba(52, 211, 153, 0.14);  /* --sucesso (159a405) esbatida — idem */

  /* Crachás — família de acento do histórico (todos 159a405). */
  --cracha-1: #22d3ee;                    /* 159a405 --ciano */
  --cracha-2: #3b82f6;                    /* 159a405 --azul */
  --cracha-3: #a78bfa;                    /* 159a405 --violeta */
  --cracha-4: #34d399;                    /* 159a405 --sucesso */
  --cracha-5: #facc15;                    /* 159a405 --aviso */

  /* Selecção — o --accao do escuro (#22d3ee = rgb 34,211,238) esbatido a 14%,
     mesmo método dos fundos de estado do escuro (--erro-fundo, etc.). */
  --seleccao: rgba(34, 211, 238, 0.14);

  /* Glow e sombra do núcleo — restaurados do histórico. */
  --nucleo-glow: 0 0 40px rgba(124, 58, 237, 0.55), 0 0 80px rgba(34, 211, 238, 0.25);
  --card-shadow: 0 6px 24px rgba(0, 0, 0, 0.45);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--fundo);
  color: var(--tinta);
  font-family: 'Instrument Sans', system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 14px;
  line-height: 1.55;
  min-height: 100vh;
}

a { color: var(--accao); text-decoration: none; }
a:hover { color: var(--accao-escura); }

/* ============================================================= */
/* Shell — sidebar + topo + palco                                 */
/* ============================================================= */
.shell {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: 56px 1fr;
  grid-template-areas:
    "brand topo"
    "nav   palco";
  min-height: 100vh;
}

/* Zona 1 — Marca (0800 §2): a área do grid passa a envolver o logótipo E o botão
   de colapsar. O .brand deixa de ser a célula do grid; passa a ser um filho. */
.marca-zona {
  grid-area: brand;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding-right: 0.5rem;
  border-right: 1px solid var(--linha);
  border-bottom: 1px solid var(--linha);
  background: var(--papel);
}
.brand {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.75rem 1rem;
  color: var(--tinta);
  text-decoration: none;
  transition: background 0.15s;
}
.brand:hover { background: var(--fundo-2); color: var(--tinta); }
.brand .marca, .brand .sufixo { display: block; }

/* Botão de colapsar a Nav (0800 §2). Ícone de painel lateral. Escolha: colapsada
   a Nav DESAPARECE e o Palco alarga — não vira rail de ícones sem rótulo (o
   pedido 0900 já rejeitara esse padrão «de telemóvel»). Fica um gume de 56px com
   o cérebro + este botão, para dar sempre para reabrir. Justificado na RESPOSTA. */
.nav-colapsar {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0;
  background: none;
  border: 1px solid var(--linha);
  border-radius: 7px;
  color: var(--tinta-fraca);
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.nav-colapsar:hover { background: var(--fundo-2); color: var(--tinta); border-color: var(--linha-forte); }
.nav-colapsar:focus-visible { outline: 2px solid var(--accao); outline-offset: 2px; }
.nav-colapsar svg { width: 17px; height: 17px; }

/* Estado colapsado — só no largo (≥1024). No estreito a Nav é gaveta e o gume
   não faz sentido. */
@media (min-width: 1024px) {
  .shell.nav-rail {
    grid-template-columns: 56px 1fr;
    grid-template-areas:
      "brand topo"
      "brand palco";
  }
  .shell.nav-rail .nav { display: none; }
  .shell.nav-rail .marca-zona {
    flex-direction: column;
    align-items: center;
    gap: 0.6rem;
    padding: 0.7rem 0;
    border-bottom: none;
  }
  .shell.nav-rail .brand { padding: 0; justify-content: center; }
  .shell.nav-rail .brand .rotulo { display: none; }
}

/* O número à direita de uma entrada da Nav (0800 §1: «quando tiver»). Discreto e
   legível nos dois temas (não usa a cor de acção como fundo — no escuro o ciano
   com texto branco falharia). */
.nav-count {
  margin-left: auto;
  min-width: 1.2rem;
  padding: 0.02rem 0.42rem;
  border-radius: 999px;
  background: var(--fundo-2);
  border: 1px solid var(--linha-forte);
  color: var(--tinta-3);
  font-size: 0.7rem;
  font-weight: 600;
  text-align: center;
  line-height: 1.5;
}

/* Roda dentada como menu (0800 §1) + a lua do tema (0800 §2). */
.tb-painel-lista { padding: 0.4rem; min-width: 190px; display: flex; flex-direction: column; }
.tb-item {
  display: block;
  padding: 0.45rem 0.6rem;
  border-radius: 7px;
  color: var(--tinta-2);
  text-decoration: none;
  font-size: 0.85rem;
}
.tb-item:hover { background: var(--fundo-2); color: var(--tinta); }
.tb-item.activo { background: var(--fundo-2); color: var(--tinta); font-weight: 600; }
/* Separador no menu da roda dentada — divide as soluções das ferramentas de
   fábrica (NetBox, Consola), que entraram aqui na FASE 2 (ADENDA 1330). */
.tb-sep { height: 1px; background: var(--linha); margin: 0.35rem 0.3rem; }
.tb-tema { display: inline-flex; margin: 0; }
button.tb-ico { background: none; border: 0; font: inherit; }
.tema-ico { font-size: 0.95rem; line-height: 1; }

/* ============================================================= */
/* Cérebro NEXUS — identidade do brand. DECISÃO 2330: parado e sem */
/* brilho (sem animação, sem drop-shadow, sem filter), em tinta.   */
/* ============================================================= */
.nx-cerebro {
  display: inline-block;
  width: var(--nx-size, 32px);
  height: var(--nx-size, 32px);
  flex-shrink: 0;
  line-height: 0;
  color: var(--tinta);
}

.nx-cerebro svg {
  width: 100%;
  height: 100%;
}

.brand .marca {
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--tinta);
  font-size: 1.05rem;
}

.brand .sufixo {
  color: var(--tinta-fraca);
  font-size: 0.7rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
}

.topo {
  grid-area: topo;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.6rem 1.2rem;
  border-bottom: 1px solid var(--linha);
  background: var(--papel);
}

.topo .breadcrumb {
  color: var(--tinta-3);
  font-size: 0.85rem;
  letter-spacing: 0.02em;
}

.topo .breadcrumb strong { color: var(--tinta); }

.topo .direita {
  display: flex;
  align-items: center;
  gap: 0.8rem;
}

.busca {
  display: flex;
  align-items: center;
  background: var(--fundo-2);
  border: 1px solid var(--linha-forte);
  border-radius: 999px;
  padding: 0.28rem 0.9rem;
  min-width: 280px;
}
.busca input {
  background: none;
  border: none;
  border-radius: 0;
  color: var(--tinta);
  outline: none;
  width: 100%;
  font-size: 0.85rem;
}
.busca .lupa {
  color: var(--tinta-fraca);
  margin-right: 0.4rem;
  font-size: 0.85rem;
}

.utilizador {
  color: var(--tinta-3);
  font-size: 0.8rem;
  padding: 0.35rem 0.65rem;
  border: 1px solid var(--linha);
  border-radius: 999px;
}
.utilizador strong { color: var(--tinta); }

/* ============================================================= */
/* Navegação lateral                                              */
/* ============================================================= */
.nav {
  grid-area: nav;
  background: var(--papel);
  border-right: 1px solid var(--linha);
  padding: 0.8rem 0;
  overflow-y: auto;
}

.nav-secao {
  padding: 0.5rem 1.1rem 0.25rem;
  color: var(--tinta-fraca);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* 1830 — cabeçalho de ZONA (uma acima da secção): «O meu trabalho» e
   «Clientes» são as duas zonas de topo; leem-se mais fortes que as sub-secções
   e separam-se por um traço fino. `summary.nav-zona` mantém o cursor/marcador. */
.nav-zona {
  color: var(--tinta-fraca);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  margin-top: 0.35rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--linha);
}
.nav-zona:first-child { margin-top: 0; padding-top: 0.4rem; border-top: none; }

.nav-link {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.55rem 1.1rem;
  color: var(--tinta-3);
  font-size: 0.87rem;
  transition: background 0.15s, color 0.15s;
}

.nav-link:hover {
  background: var(--fundo-2);
  color: var(--tinta);
}

.nav-link.activo {
  background: var(--fundo-2);
  color: var(--tinta);
  font-weight: 600;
}

.nav-link .icon {
  width: 18px;
  text-align: center;
  color: var(--tinta-fraca);
  font-size: 0.9rem;
}
.nav-link.activo .icon { color: var(--accao); }

/* ============================================================= */
/* Palco (conteúdo principal)                                     */
/* ============================================================= */
.palco {
  grid-area: palco;
  padding: 1.5rem 2rem 2.5rem;
  overflow-y: auto;
  /* Base de palco consistente em TODAS as páginas (antes só as que carregavam
     consola.css eram grid → "salto" entre páginas). align-content:start é
     essencial: o palco está na row 1fr do shell (altura do viewport) e sem isto
     o grid esticaria o conteúdo verticalmente em todas as páginas. */
  display: grid;
  gap: 1.2rem;
  align-content: start;
}

.palco h1 {
  font-family: 'Instrument Serif', Georgia, serif;
  font-size: 1.7rem;
  font-weight: 400;
  margin: 0 0 0.4rem;
  letter-spacing: 0;
  color: var(--tinta);
}

.palco h2 {
  font-size: 1.05rem;
  font-weight: 600;
  margin: 1.4rem 0 0.5rem;
  color: var(--tinta);
}

.palco .lead {
  color: var(--tinta-3);
  margin: 0 0 1.3rem;
  font-size: 0.9rem;
}

/* ============================================================= */
/* Painéis / cards                                                */
/* ============================================================= */
.painel {
  background: var(--papel);
  border: 1px solid var(--linha);
  border-radius: var(--raio);
  padding: 1.1rem 1.2rem;
}

.painel + .painel { margin-top: 1rem; }

.painel-cabeca {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.7rem;
}
.painel-cabeca h3 {
  margin: 0;
  font-size: 0.92rem;
  color: var(--tinta);
  letter-spacing: 0.01em;
}

/* KPI cards */
.grid-kpi {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.9rem;
  margin-bottom: 1.4rem;
}
.kpi {
  background: var(--papel);
  border: 1px solid var(--linha);
  border-radius: var(--raio);
  padding: 0.9rem 1rem;
}
.kpi .rotulo {
  color: var(--tinta-fraca);
  font-size: 0.72rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.kpi .valor {
  font-family: 'Instrument Serif', Georgia, serif;
  color: var(--tinta);
  font-size: 2.1rem;
  font-weight: 400;
  margin-top: 0.15rem;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}
.kpi .sub {
  color: var(--tinta-3);
  font-size: 0.78rem;
  margin-top: 0.2rem;
}
/* KPI clicável: cada total abre a lista que o compõe (régua do clicável). */
a.kpi {
  text-decoration: none;
  color: inherit;
  display: block;
  transition: border-color 0.12s ease, transform 0.12s ease;
}
a.kpi:hover,
a.kpi:focus-visible {
  border-color: var(--ciano);
  transform: translateY(-1px);
}
a.kpi .abrir {
  color: var(--txt-dim);
  font-size: 0.72rem;
  margin-top: 0.35rem;
}
a.kpi:hover .abrir,
a.kpi:focus-visible .abrir { color: var(--ciano); }

/* ------------------------------------------------------------------ */
/* Hierarquia do Painel (só /dashboard): o resumo é uma faixa          */
/* secundária; os dois painéis é que são o foco. Classes próprias      */
/* (`--resumo`, `.secao-*`) — `.grid-kpi`/`.kpi` servem 8 ecrãs e não  */
/* podem mudar aqui. Ver pedido 20260921-0645 §5.                      */
/* ------------------------------------------------------------------ */
/* Rótulo-sobrelinha que nomeia cada zona (lê-se em 3 segundos). */
.secao-rotulo {
  color: var(--txt-muted);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin: 0 0 0.55rem;
}
/* Título da zona primária: entre o h1 (1.5rem) e os h3 dos painéis
   (0.92rem). Herda `.palco h2`; aqui só o filete de acento que o marca
   como o foco do ecrã. */
.palco h2.secao-titulo {
  margin: 1.6rem 0 0.7rem;
  padding-left: 0.6rem;
  border-left: 3px solid var(--ciano);
  line-height: 1.1;
}
/* A faixa de resumo: cartões compactos, números menores. Deixa de
   competir com os painéis — é «num relance», não o trabalho. */
.grid-kpi--resumo {
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.6rem;
  margin-bottom: 0.4rem;
}
.grid-kpi--resumo .kpi { padding: 0.6rem 0.75rem; }
.grid-kpi--resumo .kpi .valor { font-size: 1.35rem; margin-top: 0.05rem; }
.grid-kpi--resumo .kpi .sub { display: none; }          /* o rótulo + o «abrir» chegam na faixa compacta */
.grid-kpi--resumo .kpi .abrir { margin-top: 0.2rem; }

/* Nome do cliente na timeline do painel: discreto, mas é caminho para a ficha. */
.tl-empresa { display: inline-block; font-size: 0.78rem; }

/* ------------------------------------------------------------------ */
/* Ficha de cliente (pedido 20260921-0900): grupo clicável, faixa da   */
/* cronologia (reservada), separadores com contagem e formulários que  */
/* saem da vista. Só forma; sem JS (CSP: script-src 'self').           */
/* ------------------------------------------------------------------ */
.grupo-irmas a { white-space: nowrap; }

/* Faixa 2 — o lugar reservado da cronologia (ainda por ligar). */
.faixa-cronologia { margin-top: 1rem; border-left: 3px solid var(--ciano); }

/* Rótulo de faixa, para nomear as zonas da ficha (lê-se em 3 segundos). */
.faixa-rotulo {
  color: var(--txt-muted);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  margin: 1.4rem 0 0.55rem;
}

/* Separadores sem JS: rádios escondidos + rótulos. O painel do rádio marcado
   aparece; os outros ficam escondidos. Contagem no rótulo. */
.ficha-tabs > .tab-radio {
  position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none;
}
.ficha-tabs .tabs-barra {
  display: flex; flex-wrap: wrap; gap: 0.2rem;
  border-bottom: 1px solid var(--line);
}
.ficha-tabs .tabs-barra label {
  padding: 0.5rem 0.9rem; cursor: pointer; color: var(--txt-dim);
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  font-size: 0.9rem; white-space: nowrap;
}
.ficha-tabs .tabs-barra label:hover { color: var(--txt); }
.ficha-tabs .tab-painel { display: none; padding-top: 0.9rem; }
/* radio marcado → painel visível + rótulo activo (um par por separador) */
#ftab-contactos:checked  ~ #fp-contactos,
#ftab-ativos:checked     ~ #fp-ativos,
#ftab-alertas:checked    ~ #fp-alertas,
#ftab-documentos:checked ~ #fp-documentos { display: block; }
#ftab-contactos:checked  ~ .tabs-barra label[for="ftab-contactos"],
#ftab-ativos:checked     ~ .tabs-barra label[for="ftab-ativos"],
#ftab-alertas:checked    ~ .tabs-barra label[for="ftab-alertas"],
#ftab-documentos:checked ~ .tabs-barra label[for="ftab-documentos"] {
  color: var(--txt); border-bottom-color: var(--ciano);
}
/* teclado: o rádio escondido continua focável — o rótulo mostra o foco */
#ftab-contactos:focus-visible  ~ .tabs-barra label[for="ftab-contactos"],
#ftab-ativos:focus-visible     ~ .tabs-barra label[for="ftab-ativos"],
#ftab-alertas:focus-visible    ~ .tabs-barra label[for="ftab-alertas"],
#ftab-documentos:focus-visible ~ .tabs-barra label[for="ftab-documentos"] {
  outline: 2px solid var(--ciano); outline-offset: 2px; border-radius: 4px;
}

/* Formulário que sai da vista: um botão (o <summary>) que o abre. Nenhum
   formulário ocupa espaço permanente (0900 §2.1). */
details.form-escondido { margin-top: 0.8rem; }
details.form-escondido > summary {
  display: inline-flex; align-items: center; gap: 0.3rem;
  padding: 0.35rem 0.7rem; cursor: pointer; list-style: none;
  border: 1px solid var(--line-strong); border-radius: 8px;
  color: var(--txt-dim); font-size: 0.85rem; width: max-content;
}
details.form-escondido > summary::-webkit-details-marker { display: none; }
details.form-escondido > summary:hover { color: var(--txt); border-color: var(--ciano); }
details.form-escondido[open] > summary { color: var(--txt); border-color: var(--ciano); margin-bottom: 0.6rem; }

/* Barra de acções + filtro da fila de pedidos (sem estilo à mão no template). */
.barra-accoes {
  display: flex;
  gap: 0.5rem;
  margin-bottom: 1rem;
  align-items: center;
  flex-wrap: wrap;
}
.barra-accoes .rotulo-filtro { margin-left: 0.8rem; }
.empty-accao { margin-top: 0.6rem; }

/* Tabelas */
.tabela {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.86rem;
}
.tabela th,
.tabela td {
  padding: 0.55rem 0.6rem;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}
.tabela th {
  color: var(--txt-muted);
  font-weight: 500;
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.tabela tr:hover td {
  background: rgba(59, 130, 246, 0.05);
}

/* Chips e badges */
.chip {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  background: rgba(124, 58, 237, 0.18);
  color: var(--violeta);
  font-size: 0.72rem;
  letter-spacing: 0.03em;
}
.chip.ok       { background: rgba(52, 211, 153, 0.14); color: var(--sucesso); }
.chip.aviso    { background: rgba(250, 204, 21, 0.14); color: var(--aviso-tinta); }
.chip.erro     { background: rgba(248, 113, 113, 0.14); color: var(--erro); }
.chip.info     { background: rgba(34, 211, 238, 0.14); color: var(--ciano); }
.chip.neutro   { background: rgba(139, 152, 201, 0.14); color: var(--txt-dim); }

/* ============================================================= */
/* Células de cliente no Palco (pedido 1150). Só tokens que já    */
/* existem; a borda é ESTADO, o ponto é IDENTIDADE.               */
/* ============================================================= */
.empresa-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}
@media (max-width: 1100px) { .empresa-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 720px)  { .empresa-grid { grid-template-columns: 1fr; } }

.empresa-cel {
  display: flex;
  flex-direction: column;
  gap: 0.55rem;
  padding: 0.9rem 1rem;
  background: var(--papel);
  border: 1.5px solid var(--linha);
  border-left-width: 4px;
  border-radius: var(--raio);
  text-decoration: none;
  color: var(--tinta);
  transition: background 0.15s, box-shadow 0.15s;
}
.empresa-cel:hover { background: var(--fundo-2); box-shadow: 0 1px 6px rgba(0,0,0,0.06); }
/* A borda ESQUERDA carrega o estado (§2.4): verde em dia · âmbar parado · vermelho
   crítico. O --aviso como borda passa os 3:1 e serve (nunca como texto). */
.empresa-cel.estado-em-dia  { border-left-color: var(--bom); }
.empresa-cel.estado-parado  { border-left-color: var(--aviso); }
.empresa-cel.estado-critico { border-left-color: var(--erro); }

.cel-topo { display: flex; align-items: flex-start; gap: 0.5rem; }
.cel-ponto {
  flex: 0 0 auto;
  width: 10px; height: 10px;
  margin-top: 0.28rem;
  border-radius: 50%;
}
.cel-ponto.cracha-1 { background: var(--cracha-1); }
.cel-ponto.cracha-2 { background: var(--cracha-2); }
.cel-ponto.cracha-3 { background: var(--cracha-3); }
.cel-ponto.cracha-4 { background: var(--cracha-4); }
.cel-ponto.cracha-5 { background: var(--cracha-5); }
.cel-nome { font-weight: 600; line-height: 1.25; }         /* pode quebrar em 2 linhas */
.cel-nif { color: var(--tinta-fraca); font-size: 0.78rem; letter-spacing: 0.03em; }

.cel-selos { display: flex; gap: 0.3rem; flex-wrap: wrap; }
.cel-selos .selo {
  font-size: 0.66rem; font-weight: 600; letter-spacing: 0.06em;
  padding: 0.08rem 0.4rem; border-radius: 999px;
  background: var(--fundo-2); border: 1px solid var(--linha-forte); color: var(--tinta-3);
}

.cel-sinais { display: flex; gap: 0.35rem; flex-wrap: wrap; margin-top: auto; }
.sinal {
  font-size: 0.7rem;
  padding: 0.1rem 0.5rem; border-radius: 999px;
  background: var(--fundo-2); border: 1px solid var(--linha-forte); color: var(--tinta-3);
}
/* Ausência não se pinta (§2.3): contorno tracejado, sem preenchimento. */
.sinal.vazio { background: none; border-style: dashed; color: var(--tinta-fraca); }
/* O tom aquece com a espera do mais antigo, nunca com a quantidade. */
.sinal.tom-frio   { color: var(--tinta-3); }
.sinal.tom-morno  { color: var(--aviso-tinta); border-color: var(--aviso); }
.sinal.tom-quente { color: var(--erro-tinta); border-color: var(--erro); }

/* Botões */
.btn {
  display: inline-block;
  padding: 0.42rem 0.9rem;
  border-radius: 6px;
  border: 1px solid var(--line-strong);
  background: var(--bg-2);
  color: var(--txt);
  font-size: 0.82rem;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.btn:hover { background: var(--bg-3); border-color: var(--ciano); color: var(--txt); }
.btn.primario {
  background: linear-gradient(135deg, var(--azul), var(--violeta));
  color: white;
  border: none;
  font-weight: 500;
}
.btn.primario:hover { filter: brightness(1.1); }
.btn.pequeno { padding: 0.25rem 0.6rem; font-size: 0.75rem; }

/* Formulários */
.form-campo { margin-bottom: 0.9rem; }
.form-campo label {
  display: block;
  color: var(--txt-dim);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: 0.3rem;
}
.form-campo input,
.form-campo select,
.form-campo textarea {
  width: 100%;
  padding: 0.55rem 0.8rem;
  background: var(--bg-2);
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  color: var(--txt);
  font-size: 0.87rem;
  font-family: inherit;
}
.form-campo input:focus,
.form-campo select:focus,
.form-campo textarea:focus {
  outline: none;
  border-color: var(--ciano);
  box-shadow: 0 0 0 3px rgba(34, 211, 238, 0.15);
}
.form-linha { display: flex; gap: 0.9rem; }
.form-linha > .form-campo { flex: 1; }
.form-acoes { display: flex; gap: 0.6rem; margin-top: 1rem; }

/* Timeline */
.timeline {
  list-style: none;
  padding: 0;
  margin: 0;
  border-left: 2px solid var(--line-strong);
}
.tl-item {
  position: relative;
  padding: 0.35rem 0 1rem 1.1rem;
  margin-left: 0.4rem;
}
.tl-item::before {
  content: "";
  position: absolute;
  left: -0.55rem;
  top: 0.55rem;
  width: 0.75rem;
  height: 0.75rem;
  border-radius: 50%;
  background: var(--violeta);
  border: 2px solid var(--bg-0);
  box-shadow: 0 0 10px rgba(167, 139, 250, 0.6);
}
.tl-workshop::before  { background: var(--ciano); box-shadow: 0 0 10px rgba(34, 211, 238, 0.6); }
.tl-auditoria::before { background: #f472b6; box-shadow: 0 0 10px rgba(244, 114, 182, 0.6); }
.tl-incidente::before { background: var(--erro); box-shadow: 0 0 10px rgba(248, 113, 113, 0.6); }
.tl-nomeacao::before  { background: var(--aviso); box-shadow: 0 0 10px rgba(250, 204, 21, 0.6); }
.tl-formacao::before  { background: var(--sucesso); box-shadow: 0 0 10px rgba(52, 211, 153, 0.6); }
.tl-quando { font-size: 0.72rem; color: var(--txt-muted); letter-spacing: 0.05em; }
.tl-corpo strong { color: var(--txt); }
.tl-corpo p { margin: 0.25rem 0 0; color: var(--txt-dim); font-size: 0.83rem; }

/* Login */
.login-caixa {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 2rem;
}
.login-caixa .painel-login {
  width: 100%;
  max-width: 380px;
  padding: 2rem 2.2rem;
  background: linear-gradient(180deg, var(--bg-2), var(--bg-1));
  border: 1px solid var(--line-strong);
  border-radius: 14px;
  box-shadow: var(--card-shadow);
}
.login-caixa .nucleo {
  width: 56px;
  height: 56px;
  margin: 0 auto 1rem;
  border-radius: 50%;
  background:
    radial-gradient(circle at 40% 40%, var(--ciano), var(--violeta) 60%, var(--violeta-forte) 100%);
  box-shadow: var(--nucleo-glow);
  animation: pulsar 3.5s ease-in-out infinite;
}
.login-caixa h1 {
  text-align: center;
  margin: 0 0 0.4rem;
  font-size: 1.4rem;
  letter-spacing: 0.05em;
}
.login-caixa .sub {
  text-align: center;
  color: var(--txt-muted);
  font-size: 0.78rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin-bottom: 1.4rem;
}
.login-caixa .erro-msg {
  background: rgba(248, 113, 113, 0.1);
  color: var(--erro);
  padding: 0.5rem 0.8rem;
  border-radius: 6px;
  font-size: 0.8rem;
  margin-bottom: 0.8rem;
  border: 1px solid rgba(248, 113, 113, 0.3);
}

/* Utilitários */
.mono { font-family: "SFMono-Regular", "JetBrains Mono", ui-monospace, monospace; }
.dim  { color: var(--txt-dim); }
.muted { color: var(--txt-muted); }
.hidden { display: none; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.grid-2col { display: grid; grid-template-columns: 2fr 1fr; gap: 1.2rem; }
.stack > * + * { margin-top: 0.8rem; }

/* Empty state */
/* 1910 §4: a ausência não se pinta. Era um bloco de fundo cinzento-médio
   (rgba escuro herdado do tema antigo) — o mais pesado do ecrã numa página de
   papel claro. Fica só o contorno tracejado + texto esbatido, sem preenchimento;
   uniforme para todos os vazios (é a única regra `.empty`). Sem cor nova. */
.empty {
  padding: 1.4rem 1.2rem;
  text-align: center;
  color: var(--txt-dim);
  border: 1px dashed var(--linha-forte);
  border-radius: 8px;
  background: none;
}

/* Módulo placeholder */
.mvp {
  border-left: 2px solid var(--aviso);
  padding: 0.2rem 0.8rem;
  color: var(--txt-dim);
  font-size: 0.8rem;
  background: rgba(250, 204, 21, 0.05);
  margin-bottom: 1rem;
}

/* Redução de movimento — cérebro fica estático com brilho suave. */
@media (prefers-reduced-motion: reduce) {
  .nx-cerebro svg,
  .brand .nucleo,
  .login-caixa .nucleo {
    animation: none !important;
  }
  .nx-cerebro svg {
    filter: drop-shadow(0 0 5px rgba(124, 58, 237, 0.5));
    transform: none;
    opacity: 0.95;
  }
  * {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}

/* =============================================================
   NAVEGAÇÃO RESPONSIVA (0900) — a barra NUNCA desaparece.
   - largo (>1280): expandida (ou rail, se o utilizador colapsou)
   - médio (901–1280): rail de ícones, sempre visível; expande ao passar o rato
   - estreito (≤900): gaveta por cima do conteúdo, com fundo escurecido
   Sem cores/tokens novos — só estrutura.
============================================================= */

/* Botão que abre/colapsa (no topbar). Escondido no largo por omissão. */
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 36px; height: 36px;
  background: var(--bg-2);
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  color: var(--txt-dim);
  cursor: pointer;
  margin-right: 0.6rem;
}
.nav-toggle:hover { color: var(--txt); border-color: var(--ciano); }
.nav-toggle:focus-visible { outline: 2px solid var(--ciano); outline-offset: 2px; }
.nav-toggle svg { width: 18px; height: 18px; }

/* Fundo escurecido da gaveta (só no estreito, quando aberta). */
.nav-backdrop {
  position: fixed; inset: 0;
  background: rgba(3, 5, 12, 0.6);
  z-index: 35;
  border: 0;
}

/* Foco de teclado visível em toda a navegação. */
.nav-link:focus-visible {
  outline: 2px solid var(--ciano);
  outline-offset: -2px;
  color: var(--txt);
}

/* ---- Regressão do menu corrigida (pedido 20260921-0900) ----
   O `feat(nav)` de 2026-08-29 (b12cebd) forçava um rail de ícones a partir de
   1280px: num ecrã de trabalho (~1180px) a navegação ficava atrás de um
   hambúrguer com ícones sem rótulo — padrão de telemóvel. O DESENHO 3.5 manda
   dois estados só: nav **permanente e visível com rótulos ≥1024px**, gaveta só
   em ecrã estreito (<1024px). O rail de ícones e o colapso manual saem —
   contradiziam «permanente e visível», e eram a origem da regressão. */

/* ---- Estreito (≤1023): gaveta por cima do conteúdo ----
   `.shell .nav` (0,2,0) para VENCER a regra tardia `.nav{position:relative}`
   (grupo do z-index) que, com igual especificidade e mais abaixo no ficheiro,
   anulava o position:fixed e deixava a barra a cair na grelha. */
@media (max-width: 1023px) {
  .shell {
    grid-template-columns: 1fr;
    grid-template-rows: 56px auto 1fr;
    grid-template-areas:
      "brand"
      "topo"
      "palco";
  }
  .nav-toggle { display: inline-flex; }
  .shell .nav {
    position: fixed;
    inset: 0 auto 0 0;            /* top:0 right:auto bottom:0 left:0 */
    width: 260px;
    z-index: 40;
    transform: translateX(-100%);
    transition: transform 0.2s ease;
    /* rótulos completos na gaveta, mesmo se o rail estava activo */
    font-size: 0.87rem;
  }
  .shell .nav .nav-link { justify-content: flex-start; gap: 0.7rem; padding-left: 1.1rem; font-size: 0.87rem; }
  .shell .nav .nav-secao { font-size: 0.68rem; padding: 0.5rem 1.1rem 0.25rem; text-align: left; }
  .shell .nav .nav-secao::before { content: none; }
  .shell.drawer-open .nav { transform: translateX(0); }
  .busca { min-width: 140px; }
  /* A 900px as duas colunas empilham — senão o 2fr/1fr fica ilegível (as 8 do
     desenho, pedido 20260921-0550). */
  .grid-2col { grid-template-columns: 1fr; }
}

/* ── o TOPO em ecrã estreito (`20260930`) ──────────────────────────────────
 *
 * Medido a 375px: a barra de topo precisa de 561px e não encolhe — a `.direita`
 * sozinha pede 399 (busca 143 + utilizador 54 + acções 171), e por isso TODAS as
 * páginas rolavam ao lado, mesmo as que já tinham o conteúdo corrigido. Era o
 * defeito que ficou declarado na !367 e não se corrigiu lá.
 *
 * Das duas saídas previstas no pedido escolheu-se a que MENOS mexe: o topo
 * quebra em duas filas e a busca encolhe. Zero JS, zero markup novo, e o topo
 * do desktop fica exactamente como está — a alternativa (a busca virar ícone
 * que abre o campo) era comportamento novo para resolver um problema de espaço.
 *
 * `min-width:0` é o que faz a diferença: por omissão um item de flex não encolhe
 * abaixo do seu conteúdo, e era isso que empurrava a página para fora do ecrã. */
@media (max-width: 640px) {
  .topo { flex-wrap: wrap; row-gap: 0.4rem; padding-left: 0.7rem; padding-right: 0.7rem; }
  .topo .breadcrumb { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
  /* a segunda fila, a toda a largura, com a busca a ceder o espaço que falta */
  .topo .direita { flex: 1 1 100%; min-width: 0; gap: 0.4rem; }
  .busca { min-width: 0; flex: 1 1 5rem; }
  .topbar-acoes { flex: 0 0 auto; }
}
@media (prefers-reduced-motion: reduce) {
  .shell .nav { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════
   FACELIFT v1 — estrutura/animações mapeadas à PALETA EXISTENTE.
   Não redefine tokens de brand (--txt/--bg-*/--ciano/--violeta*);
   só adiciona aliases dos nomes do v2 + tokens novos.
═══════════════════════════════════════════════════════════════ */
:root {
  --cyan:        var(--ciano);
  --cyan-dim:    rgba(34, 211, 238, .12);
  --cyan-glow:   rgba(34, 211, 238, .35);
  --purple:      var(--violeta-forte);
  --purple-dim:  rgba(124, 58, 237, .15);
  --surface:     var(--bg-1);
  --surface-el:  var(--bg-2);
  --surface-hi:  var(--bg-3);
  --border:      var(--line);
  --border-glow: var(--line-strong);
  --txt-2:       var(--txt-dim);
  --txt-3:       var(--txt-muted);
  --s-nova:       var(--azul);
  --s-curada:     var(--sucesso);
  --s-descartada: var(--txt-muted);
  --r:     10px;
  --r-sm:  6px;
  --nav-w: 240px;   /* igual ao layout existente */
  --top-h: 56px;
  /* família (taxonomia _temas.yaml) → cor — verificar slugs reais */
  --fam-engenharia-social:     #f59e0b;
  --fam-ia-responsavel:        #3b82f6;
  --fam-dados-pessoais:        #8b5cf6;
  --fam-pagamentos-fraudulentos: #ef4444;
  --fam-incidente:             #f97316;
  --fam-conectividade:         #06b6d4;
  --fam-identidade-digital:    #84cc16;
  --fam-diagnostico-awareness: #ec4899;
}

/* família (slugs REAIS de _temas.yaml) → --fam-color (fallback: ciano do brand) */
[data-familia]                         { --fam-color: var(--ciano); }
[data-familia="engenharia-social"]     { --fam-color: var(--fam-engenharia-social); }
[data-familia="ia-responsavel"]        { --fam-color: var(--fam-ia-responsavel); }
[data-familia="dados-pessoais"]        { --fam-color: var(--fam-dados-pessoais); }
[data-familia="pagamentos-fraudulentos"] { --fam-color: var(--fam-pagamentos-fraudulentos); }
[data-familia="incidente"]             { --fam-color: var(--fam-incidente); }
[data-familia="conectividade"]         { --fam-color: var(--fam-conectividade); }
[data-familia="identidade-digital"]    { --fam-color: var(--fam-identidade-digital); }
[data-familia="diagnostico-awareness"] { --fam-color: var(--fam-diagnostico-awareness); }

/* fundo neural — atrás de tudo; o conteúdo fica por cima (z-index) */
#neural-bg { position: fixed; inset: 0; pointer-events: none; z-index: 0; opacity: .30; }
.shell, .brand, .topo, .nav, .palco { position: relative; z-index: 1; }
/* O topbar TEM de ficar acima do palco: .topo e .palco são contextos de
   empilhamento irmãos e, com o mesmo z-index:1, o .palco (mais abaixo no DOM)
   pintava por cima — o H1 do palco apanhava o clique e os painéis 🔔/⏻
   (z-index:50 só válido DENTRO do .topo) não eram clicáveis. Elevar o .topo
   resolve os três painéis do topbar de uma vez, em todas as páginas. As áreas
   do grid não se sobrepõem no fluxo normal, portanto sem efeito visual lateral. */
.topo { z-index: 20; }

/* ── SIDEBAR: icons SVG animados (sobre .nav-link .icon existente) ── */
.nav-link .icon {
  width: 20px; height: 20px; font-size: 0; /* anula o glyph antigo */
  display: flex; align-items: center; justify-content: center;
}
.nav-link .icon svg { width: 18px; height: 18px; display: block; }
.nav-link:hover .icon,
.nav-link.activo .icon { color: var(--ciano); }
.nav-link.activo .icon { filter: drop-shadow(0 0 4px var(--cyan-glow)); }

/* icons SEMPRE com vida: respiração idle no wrapper + animações internas a correr;
   o hover intensifica (brilho ciano). */
.nav-link .icon { animation: nav-icon-idle 3.6s ease-in-out infinite; }
.nav-link:nth-child(3n) .icon { animation-delay: .6s; }
.nav-link:nth-child(3n+1) .icon { animation-delay: 1.2s; }
@keyframes nav-icon-idle { 0%,100% { opacity: .78; } 50% { opacity: 1; } }
.nav-link:hover .icon { filter: drop-shadow(0 0 5px var(--cyan-glow)); }
/* as animações internas dos SVG correm sempre (não pausadas) */

/* sinapse a atravessar o item no hover */
.nav-link { position: relative; overflow: hidden; }
.nav-link::after {
  content: ''; position: absolute; bottom: 0; left: -50%;
  width: 50%; height: 1px;
  background: linear-gradient(90deg, transparent, var(--ciano), transparent);
  opacity: 0;
}
.nav-link:hover::after { animation: nl-syn .6s ease forwards; }
@keyframes nl-syn { from { left: -50%; opacity: .8; } to { left: 150%; opacity: 0; } }

/* radar */
.ico-radar .rs { transform-origin: 9px 9px; animation: rs 2s linear infinite; }
@keyframes rs { from { transform: rotate(0); } to { transform: rotate(360deg); } }
.ico-radar .rp  { animation: rp 2s ease-out infinite; opacity: 0; }
.ico-radar .rp2 { animation: rp 2s ease-out .8s infinite; opacity: 0; }
@keyframes rp { 0% { r: 0; opacity: .8; } 100% { r: 8; opacity: 0; } }
/* eye */
.ico-eye .iris { animation: eis 3s ease-in-out infinite; transform-origin: 9px 9px; }
@keyframes eis { 0%,100% { transform: translateX(-2px); } 50% { transform: translateX(2px); } }
.ico-eye .eb { animation: ebk 4s ease-in-out infinite; transform-origin: 9px 9px; }
@keyframes ebk { 0%,85%,95%,100% { transform: scaleY(1); } 90% { transform: scaleY(.1); } }
/* net */
.ico-net .nn { animation: nnp 2s ease-in-out infinite; }
.ico-net .nn:nth-child(2) { animation-delay: .4s; }
@keyframes nnp { 0%,100% { r: 2; fill-opacity: .6; } 50% { r: 3; fill-opacity: 1; } }
/* user */
.ico-user .ur { animation: urp 3s ease-in-out infinite; }
@keyframes urp { 0%,100% { r: 5; stroke-opacity: 0; } 50% { r: 8; stroke-opacity: .5; } }
/* bell */
.ico-bell .bb { animation: bsw 3s ease-in-out infinite; transform-origin: 9px 4px; }
@keyframes bsw { 0%,70%,100% { transform: rotate(0); } 75% { transform: rotate(-16deg); } 80% { transform: rotate(14deg); } 85% { transform: rotate(-10deg); } 90% { transform: rotate(8deg); } }
.ico-bell .bd { animation: bdb 3s ease-in-out infinite; transform-origin: 13px 4.5px; }
@keyframes bdb { 0%,100% { transform: scale(1); } 80% { transform: scale(.6); } 85% { transform: scale(1.3); } }
/* bolt */
.ico-bolt .bg { animation: bfl 1.6s ease-in-out infinite; transform-origin: 9px 9px; }
@keyframes bfl { 0%,60%,100% { opacity: 0; transform: scale(.8); } 20%,40% { opacity: .5; transform: scale(1.2); } }
.ico-bolt .bm { animation: bst 1.6s ease-in-out infinite; }
@keyframes bst { 0%,100% { fill: #facc15; } 20%,40% { fill: #fde68a; } }
/* gear */
.ico-gear .go { animation: gt 4s linear infinite; transform-origin: 9px 9px; }
.ico-gear .gi { animation: gt 4s linear infinite reverse; transform-origin: 9px 9px; }
@keyframes gt { from { transform: rotate(0); } to { transform: rotate(360deg); } }
/* chip */
.ico-chip .cp { animation: cgw 2s ease-in-out infinite; }
@keyframes cgw { 0%,100% { opacity: .5; } 50% { opacity: 1; } }
.ico-chip .df  { stroke-dasharray: 3 2; animation: dft 1.2s linear infinite; }
.ico-chip .df2 { animation-delay: .4s; }
@keyframes dft { from { stroke-dashoffset: 8; } to { stroke-dashoffset: 0; } }
/* wifi */
.ico-wifi .w1,.ico-wifi .w2,.ico-wifi .w3 { stroke-dasharray: 14; stroke-dashoffset: 14; animation: wd 2s ease-in-out infinite; }
.ico-wifi .w2 { animation-delay: .3s; } .ico-wifi .w3 { animation-delay: .6s; }
@keyframes wd { 0%,80%,100% { stroke-dashoffset: 14; opacity: 0; } 30%,60% { stroke-dashoffset: 0; opacity: 1; } }
.ico-wifi .wd { animation: wdot 2s ease-in-out infinite; }
@keyframes wdot { 0%,100% { opacity: .4; } 70% { opacity: 1; } }
/* docs */
.ico-docs .dl { stroke-dasharray: 8; animation: dlt 3s ease-in-out infinite; }
.ico-docs .dl:nth-child(2) { animation-delay: .3s; }
@keyframes dlt { 0%,100% { stroke-dashoffset: 8; } 50% { stroke-dashoffset: 0; } }
/* book */
.ico-book .page { transform-origin: left center; transform-box: fill-box; animation: pf 2.5s ease-in-out infinite; }
.ico-book .page2 { animation-delay: .6s; }
@keyframes pf { 0%,60%,100% { transform: rotateY(0); } 30% { transform: rotateY(-50deg); } }
/* synapse */
.ico-synapse .sn { animation: snp 2s ease-in-out infinite; }
.ico-synapse .sn:nth-child(2) { animation-delay: .4s; } .ico-synapse .sn:nth-child(3) { animation-delay: .8s; }
@keyframes snp { 0%,100% { r: 1.5; opacity: .6; } 50% { r: 2.5; opacity: 1; } }
.ico-synapse .sl { stroke-dasharray: 12; stroke-dashoffset: 12; animation: sld 2s ease-in-out infinite; }
.ico-synapse .sl:nth-child(6) { animation-delay: .4s; }
@keyframes sld { 0% { stroke-dashoffset: 12; opacity: 0; } 40% { opacity: 1; } 80% { stroke-dashoffset: 0; opacity: 0; } 100% { stroke-dashoffset: -12; opacity: 0; } }
/* calendar */
.ico-cal .cr { animation: crk 3s ease-in-out infinite; transform-origin: 9px 6px; }
@keyframes crk { 0%,70%,100% { transform: rotate(0); } 75% { transform: rotate(-15deg); } 80% { transform: rotate(14deg); } 85% { transform: rotate(-9deg); } 90% { transform: rotate(7deg); } }
.ico-cal .ct2 { animation: ctp 3s ease-in-out infinite; }
@keyframes ctp { 0%,100% { fill: rgba(34,211,238,.2); } 60% { fill: rgba(34,211,238,.5); } }
/* chart */
.ico-chart .b1 { animation: cbar 2s ease-in-out infinite; transform-origin: 9px 15px; transform-box: fill-box; }
.ico-chart .b2 { animation: cbar 2s ease-in-out .2s infinite; transform-origin: 9px 15px; transform-box: fill-box; }
.ico-chart .b3 { animation: cbar 2s ease-in-out .4s infinite; transform-origin: 9px 15px; transform-box: fill-box; }
@keyframes cbar { 0%,100% { transform: scaleY(.4); } 50% { transform: scaleY(1); } }
/* lock */
.ico-lock .sh { animation: lsh 3s ease-in-out infinite; transform-origin: 9px 7px; transform-box: fill-box; }
@keyframes lsh { 0%,20%,100% { transform: translateY(-2px); } 40%,80% { transform: translateY(0); } }
.ico-lock .lg { animation: lgw 3s ease-in-out infinite; }
@keyframes lgw { 0%,30% { opacity: 0; } 60%,80% { opacity: .6; } 100% { opacity: 0; } }

/* ── FACELIFT v1 — forms escuros por defeito (tema escuro consistente) ──
   Base de baixa especificidade: campos não estilizados deixam de ser brancos;
   .form-campo/.busca (mais específicos) continuam a mandar onde já existem. */
input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]):not([type=file]),
select,
textarea {
  background-color: var(--bg-2);
  color: var(--txt);
  border: 1px solid var(--line);
  border-radius: 6px;
  font-family: inherit;
}
input:not([type=checkbox]):not([type=radio]):focus,
select:focus,
textarea:focus {
  border-color: var(--ciano);
  outline: none;
  box-shadow: 0 0 0 2px rgba(34, 211, 238, .15);
}
select option { background-color: var(--bg-1); color: var(--txt); }

/* ── FACELIFT v1 — link "↗ NetBox" nas linhas da tabela de tenants ── */
.btn-netbox-link {
  font-size: 0.7rem;
  color: var(--ciano);
  border: 1px solid var(--ciano);
  border-radius: 4px;
  padding: 1px 6px;
  margin-left: 0.4rem;
  text-decoration: none;
  opacity: .7;
  white-space: nowrap;
  transition: opacity .2s, box-shadow .2s;
}
.btn-netbox-link:hover { opacity: 1; box-shadow: 0 0 8px var(--cyan-dim); }

/* ── ico-biblioteca (dois livros) ── */
.ico-biblioteca svg rect { animation: bib-glow 3s ease-in-out infinite; }
.ico-biblioteca svg rect:nth-child(2) { animation-delay: .6s; }
@keyframes bib-glow { 0%,100% { opacity: .6; } 50% { opacity: 1; } }
.ico-biblioteca svg line { stroke-dasharray: 3; animation: bib-line 2.5s ease-in-out infinite; }
.ico-biblioteca svg line:nth-child(4) { animation-delay: .5s; }
@keyframes bib-line { 0%,100% { stroke-dashoffset: 3; opacity: .4; } 50% { stroke-dashoffset: 0; opacity: 1; } }

/* ── ico-aware (globo/cérebro) ── */
.ico-aware svg ellipse { animation: aw-spin 7s linear infinite; transform-origin: 9px 9px; transform-box: fill-box; }
@keyframes aw-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.ico-aware svg path:first-of-type { animation: aw-path 3s ease-in-out infinite; }
.ico-aware svg path:last-of-type  { animation: aw-path 3s ease-in-out .6s infinite; }
@keyframes aw-path { 0%,100% { opacity: .5; } 50% { opacity: 1; } }
.ico-aware svg circle { animation: aw-dot 3s ease-in-out infinite; transform-origin: 9px 9px; transform-box: fill-box; }
@keyframes aw-dot { 0%,100% { transform: scale(1); opacity: .5; } 50% { transform: scale(1.6); opacity: 1; } }

/* ── ico-shield (administração) ── */
.ico-shield svg path:first-child { animation: sh-pulse 2.5s ease-in-out infinite; }
@keyframes sh-pulse { 0%,100% { fill: rgba(34,211,238,.1); } 50% { fill: rgba(34,211,238,.28); } }
.ico-shield svg path:last-child { animation: sh-check 2.5s ease-in-out .4s infinite; }
@keyframes sh-check { 0%,100% { opacity: .6; } 50% { opacity: 1; } }

/* MFA — QR escala ao contentor (o SVG gerado já vem sem width/height em mm;
   ver app/services/mfa.py). Sem isto, um SVG inline sem dimensões não enche a
   caixa de forma fiável. */
.qr-box svg { width: 100%; height: auto; display: block; }

/* ── Sidebar colapsável (<details>) + topbar (acções) — feat/shell ── */
.nav-grupo { margin: 0; }
/* O <summary> é agora um CONTROLO (colapsa/expande), não um rótulo passivo:
   ≥11px, contraste ≥4.5:1 (--txt-dim ~6.6:1, acima do antigo --txt-muted ~3:1 mas
   abaixo do link a branco), peso 600 e seta visível — sem competir com os links. */
.nav-grupo > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: center; gap: 0.4rem;
  padding: 0.4rem 1.1rem 0.3rem;
  color: var(--txt-dim);
  font-size: 0.8rem;          /* ~11.2px (era 0.68rem/9.52px) */
  font-weight: 600;           /* distingue do link (400) */
  letter-spacing: 0.06em;
  border-radius: 6px;
  transition: color 0.12s ease, background 0.12s ease;
}
.nav-grupo > summary::-webkit-details-marker { display: none; }
.nav-grupo > summary::after {
  content: "▸"; margin-left: auto; font-size: 0.95rem; opacity: 0.85;
  transition: transform 0.15s ease;
}
.nav-grupo[open] > summary::after { transform: rotate(90deg); }
/* estados: um controlo tem de responder ao hover e ao teclado */
.nav-grupo > summary:hover {
  color: var(--txt); background: rgba(120, 140, 200, 0.08);
}
.nav-grupo > summary:focus-visible {
  outline: 2px solid var(--txt-dim); outline-offset: -2px; color: var(--txt);
}
.nav-sub { margin-left: 0.4rem; }

.topbar-acoes { display: inline-flex; align-items: center; gap: 0.2rem; margin-left: 0.6rem; }
.tb-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 8px; cursor: pointer;
  text-decoration: none; color: inherit; font-size: 1rem; line-height: 1;
}
.tb-ico:hover { background: var(--fundo-2); }
.tb-menu { position: relative; display: inline-block; }
.tb-menu > summary { list-style: none; }
.tb-menu > summary::-webkit-details-marker { display: none; }
.tb-painel {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 50;
  min-width: 200px; padding: 0.8rem 0.9rem; border-radius: 10px;
  background: var(--bg-1, #0f1420); border: 1px solid var(--line, rgba(255,255,255,0.1));
  box-shadow: 0 8px 24px rgba(0,0,0,0.4);
}

/* ── KB · Markdown renderizado (âmbito mínimo: código, tabelas, títulos, listas) ── */
.kb-conteudo { font-size: 0.9rem; line-height: 1.7; color: var(--txt-dim); }
.kb-conteudo h1, .kb-conteudo h2, .kb-conteudo h3, .kb-conteudo h4 { color: var(--txt); margin: 1.3rem 0 0.5rem; line-height: 1.3; }
.kb-conteudo h2 { font-size: 1.1rem; } .kb-conteudo h3 { font-size: 0.98rem; }
.kb-conteudo p, .kb-conteudo li { color: var(--txt-dim); }
.kb-conteudo strong { color: var(--txt); }
.kb-conteudo a { color: var(--ciano, #22d3ee); }
.kb-conteudo code { font-family: "JetBrains Mono", ui-monospace, monospace; font-size: 0.85em; background: rgba(120,140,200,0.12); padding: 0.1rem 0.35rem; border-radius: 4px; }
.kb-conteudo pre { position: relative; background: var(--bg-0, #05070f); border: 1px solid var(--line); border-radius: 8px; padding: 0.85rem 1rem; overflow-x: auto; margin: 0.85rem 0; }
.kb-conteudo pre code { background: none; padding: 0; font-size: 0.82rem; color: var(--txt); }
.kb-conteudo table { border-collapse: collapse; margin: 0.85rem 0; font-size: 0.85rem; }
.kb-conteudo th, .kb-conteudo td { border: 1px solid var(--line); padding: 0.3rem 0.6rem; text-align: left; }
.kb-conteudo th { color: var(--txt); background: rgba(120,140,200,0.06); }
.kb-conteudo blockquote { border-left: 3px solid var(--line-strong); margin: 0.85rem 0; padding: 0.2rem 0 0.2rem 1rem; color: var(--txt-muted); }
.kb-copy { position: absolute; top: 0.4rem; right: 0.4rem; font-size: 0.7rem; padding: 0.15rem 0.5rem; border-radius: 5px; border: 1px solid var(--line); background: var(--bg-2, #131a30); color: var(--txt-dim); cursor: pointer; }
.kb-copy:hover { color: var(--txt); border-color: var(--line-strong); }

/* ─── Ficha de cliente (pedido 1915) — secções visíveis ─── */
/* 20260924-2315 §1: as regras `.ficha-ambito`, `.ficha-ambito-rot` e
   `.ficha-ambito-nome` saíram com a faixa que as usava. Varrimento feito antes
   de apagar: não restava nenhum outro uso das três em todo o repo. */
/* Cada família é uma secção VISÍVEL (deixou de ser separador escondido): quem
   chega vê o conjunto sem clicar. */
.ficha-secao { margin: 0 0 1rem; }
.ficha-secao > .painel-cabeca h2 { font-size: 1.02rem; margin: 0; }
/* O «· Nome» ao lado de cada título repete o âmbito dentro da secção. */
.ficha-de-quem { color: var(--txt-muted); font-weight: 400; font-size: 0.85rem; }

/* ===================================================================== *
 * FASE 2 — a ficha do cliente em OITO abas horizontais (pedido 1545 +
 * DESTRAVADO 2000 + ADENDA 1330). Sem cor nova além de --seleccao. Todas as
 * cores por token; nenhum hex aqui.
 * ===================================================================== */

/* ---- Cabeça: identidade que fica no topo (a barra de âmbito, já sticky, é que
   garante «que cliente é este» ao rolar). ---- */
.ficha-cabeca { margin: 0 0 1rem; }
.fc-topo { display: flex; align-items: flex-start; gap: 0.7rem; }
.fc-topo .cel-ponto { margin-top: 0.5rem; flex: 0 0 auto; }
.fc-id { flex: 1 1 auto; min-width: 0; }
.fc-nome {
  font-family: "Instrument Serif", Georgia, "Times New Roman", serif;
  font-size: 2rem; line-height: 1.1; margin: 0; color: var(--tinta);
}
.fc-meta { margin: 0.2rem 0 0; color: var(--tinta-3); font-size: 0.9rem; }
.fc-meta .mono { color: var(--tinta-2); }
.fc-accoes { flex: 0 0 auto; display: flex; gap: 0.4rem; align-items: center; }

/* O ⋯ recolhe as acções secundárias (uma só primária fica à vista). */
.fc-mais { position: relative; }
.fc-mais > summary {
  list-style: none; cursor: pointer; user-select: none;
  padding: 0.4rem 0.7rem; line-height: 1;
}
.fc-mais > summary::-webkit-details-marker { display: none; }
.fc-mais-lista {
  position: absolute; right: 0; top: calc(100% + 0.3rem); z-index: 30;
  min-width: 210px; padding: 0.4rem;
  background: var(--papel); border: 1px solid var(--linha-forte);
  border-radius: var(--raio-pequeno); box-shadow: var(--card-shadow, 0 6px 24px rgba(0,0,0,0.12));
  display: flex; flex-direction: column;
}

/* Faixa: equipa (iniciais em círculo) + serviços (cheio/tracejado) + o (i). */
.fc-faixa {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  margin: 0.8rem 0 0; padding-top: 0.7rem; border-top: 1px solid var(--linha);
}
.fc-equipa { display: flex; align-items: center; gap: 0.35rem; flex-wrap: wrap; }
.fc-inicial {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.7rem; height: 1.7rem; border-radius: 50%;
  background: var(--fundo-2); border: 1px solid var(--linha-forte);
  color: var(--tinta-2); font-size: 0.72rem; font-weight: 600; letter-spacing: 0.02em;
}
.fc-inicial.primario { border-color: var(--accao); color: var(--accao); }
.fc-primario-nome { font-size: 0.85rem; color: var(--tinta-2); margin-left: 0.2rem; }
.fc-servicos { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.fc-svc {
  font-size: 0.72rem; padding: 0.15rem 0.55rem; border-radius: 999px;
  border: 1px solid var(--linha-forte); color: var(--tinta-2);
}
.fc-svc.tracejado { border-style: dashed; color: var(--tinta-fraca); }
.fc-info { margin-left: auto; position: relative; }
.fc-info > summary {
  list-style: none; cursor: pointer; user-select: none;
  color: var(--tinta-fraca); font-size: 1.05rem; line-height: 1;
}
.fc-info > summary::-webkit-details-marker { display: none; }
.fc-info > summary:hover { color: var(--accao); }
.fc-info-painel {
  position: absolute; right: 0; top: calc(100% + 0.4rem); z-index: 30;
  width: min(320px, 80vw); margin: 0;
}

/* ---- As abas ---- */
.ficha-abas {
  display: flex; gap: 0.2rem; flex-wrap: wrap;
  margin: 0 0 0.2rem; border-bottom: 1px solid var(--linha-forte);
}
.fa-aba {
  background: none; border: 0; border-bottom: 2px solid transparent;
  font: inherit; cursor: pointer; color: var(--tinta-2);
  padding: 0.5rem 0.8rem; margin-bottom: -1px;
  display: inline-flex; align-items: center; gap: 0.35rem;
}
.fa-aba:hover { color: var(--tinta); }
.fa-aba.activo { color: var(--tinta); border-bottom-color: var(--accao); font-weight: 600; }
.fa-aba:focus-visible { outline: 2px solid var(--accao); outline-offset: 2px; border-radius: 4px; }
/* Aba a zero: esbatida com --tinta-fraca (ADENDA 1330). */
.fa-aba.fa-zero { color: var(--tinta-fraca); }
.fa-conta {
  font-size: 0.72rem; color: var(--tinta-fraca);
  background: var(--fundo-2); border-radius: 999px; padding: 0.05rem 0.4rem;
}
.fa-aba.activo .fa-conta { color: var(--tinta-2); }
/* Ponto de atenção — vermelho, o mesmo do estado. */
.fa-atencao {
  width: 0.5rem; height: 0.5rem; border-radius: 50%;
  background: var(--erro); display: inline-block;
}

/* ---- «O que precisa de ti» ---- */
.ficha-precisa {
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
  margin: 0.8rem 0 1rem;
}
.fp-rot { font-size: 0.66rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--tinta-fraca); }
.fp-item { background: none; border: 0; padding: 0; font: inherit; cursor: pointer; }
.fp-nada {
  color: var(--tinta-fraca); font-size: 0.85rem;
  border: 1px dashed var(--linha-forte); border-radius: var(--raio-pequeno);
  padding: 0.3rem 0.7rem;
}

/* ---- O Palco: grelha nascida com a coluna do objecto colapsada (previsão 1) ---- */
.ficha-palco {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 0;
  gap: 1.4rem; align-items: start;
}
.fa-corpo { min-width: 0; }
.fa-objecto { overflow: hidden; }

/* ---- Item seleccionado numa lista (previsão 2) — realce com --seleccao ---- */
.fa-selecionavel .fa-item { cursor: pointer; }
.fa-selecionavel .fa-item.selecionado,
.fa-selecionavel tr.fa-item.selecionado > td { background: var(--seleccao); }

/* ---- Filtro por instalação (aba Documentos) ---- */
.fa-filtro { display: flex; gap: 0.35rem; flex-wrap: wrap; margin: 0 0 0.7rem; }
.fa-chip {
  background: none; border: 1px solid var(--linha-forte); border-radius: 999px;
  font: inherit; font-size: 0.78rem; cursor: pointer; color: var(--tinta-3);
  padding: 0.2rem 0.7rem;
}
.fa-chip:hover { color: var(--tinta); border-color: var(--tinta-fraca); }
.fa-chip.activo { background: var(--accao); border-color: var(--accao); color: var(--papel); }

/* Projectos na aba Documentos (pedido 1515): um grupo por projecto (instalação),
   com cabeçalho próprio; e o formulário de registo, agora aberto. */
.fa-projecto { margin: 0 0 1.1rem; }
.fa-projecto-cab { padding: 0.35rem 0; border-bottom: 2px solid var(--linha-forte); margin-bottom: 0.3rem; }
.fa-registar { margin-top: 0.6rem; padding-top: 0.9rem; border-top: 1px solid var(--linha); }
/* Arrastar-e-largar um ficheiro (pedido 1640). */
.fa-dropzone { display: block; border: 1px dashed var(--linha-forte); border-radius: var(--raio-pequeno); padding: 0.9rem; text-align: center; cursor: pointer; color: var(--tinta-3); }
.fa-dropzone:hover { border-color: var(--tinta-fraca); }
.fa-dropzone.a-largar { border-color: var(--accao); background: var(--seleccao); color: var(--tinta); }
.fa-dropzone.tem-ficheiro { border-style: solid; border-color: var(--accao); }
.fa-dropzone input[type="file"] { display: block; margin: 0.5rem auto 0; }
.fa-dropzone-nome { display: block; margin-top: 0.3rem; font-size: 0.8rem; }

/* ---- Módulo de documentos, FASE 1 (pedido 20260926-0215) ---- */
/* A linha do documento: título abre, etiquetas dizem o que é, linha mono com
   extensão·tamanho·data; descarregar/ligação são acção secundária. */
.doc-linha { padding: 0.45rem 0; border-bottom: 1px solid var(--linha); }
.doc-topo { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; }
.doc-titulo { font-weight: 600; color: var(--tinta); text-decoration: none; }
.doc-titulo:hover { text-decoration: underline; }
.doc-etq { font-size: 0.7rem; padding: 0.05rem 0.4rem; border-radius: 999px; background: var(--seleccao); color: var(--tinta-2); white-space: nowrap; }
.doc-etq.neutro { background: transparent; border: 1px solid var(--linha); }
.doc-etq-cliente { background: var(--seleccao); color: var(--accao); border: 1px solid var(--accao); }
.doc-etq-interno { background: transparent; color: var(--tinta-3); border: 1px solid var(--linha); }
.doc-etq-aviso { background: transparent; color: var(--aviso, #b45309); border: 1px dashed var(--aviso, #b45309); }
.doc-accao { margin-left: auto; font-size: 0.78rem; color: var(--tinta-3); text-decoration: none; }
.doc-accao:hover { color: var(--tinta); text-decoration: underline; }
.doc-meta { display: flex; gap: 0.75rem; margin-top: 0.15rem; font-size: 0.72rem; color: var(--tinta-3); font-family: "SFMono-Regular", "JetBrains Mono", ui-monospace, monospace; }
.doc-resumo { font-size: 0.78rem; margin-top: 0.15rem; }
.doc-vazio-linha { font-size: 0.78rem; padding: 0.2rem 0 0.2rem 0.2rem; }
/* `20260928-0845` (parte B): a linha do documento passou a ser a LINHA EXPANSÍVEL
   do /kb (`linha-expansivel.css`, carregada por este ecrã). O padding vertical
   passa a ser o da `.kb-cabeca` — senão somavam-se os dois e a lista abria. */
.doc-linha.kb-linha { padding: 0; }
.doc-lote-resumo { background: var(--seleccao); border: 1px solid var(--linha); border-radius: var(--raio-pequeno); padding: 0.5rem 0.7rem; margin: 0 0 0.7rem; font-size: 0.85rem; }
.doc-lote-rej { color: var(--aviso, #b45309); font-size: 0.78rem; margin-top: 0.25rem; }

/* Fila de preparação do carregamento em lote: uma linha por ficheiro. */
.fa-fila-prep { margin: 0.6rem 0; display: flex; flex-direction: column; gap: 0.35rem; }
.fila-linha { display: flex; gap: 0.4rem; align-items: center; flex-wrap: wrap; }
.fila-nome { flex: 0 0 auto; max-width: 14rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.72rem; color: var(--tinta-3); }
.fila-titulo { flex: 1 1 12rem; }
.fila-tipo { flex: 0 0 auto; }
.fa-ligacao { margin-top: 0.8rem; }
.fa-ligacao summary { cursor: pointer; font-size: 0.82rem; }

@media (max-width: 760px) {
  .fc-nome { font-size: 1.6rem; }
  .fc-accoes { flex-wrap: wrap; }
  .doc-accao { margin-left: 0; }
  .fila-nome { max-width: 100%; }
}
