/* =============================================================================
   Distribuidor — folha de estilo
   -----------------------------------------------------------------------------
   A direção é a FICHA TÉCNICA, não a app de chat. O assunto é um armazém de
   materiais de construção com vinte anos de histórico, e a paleta sai dos
   próprios materiais: betão, aço, e o laranja de sinalização de obra. Nada de
   balões coloridos.

   Tipos, e porquê estes: a Bahnschrift é derivada da DIN, a letra dos desenhos
   técnicos e da sinalização industrial — é o registo certo para etiquetas e
   números, e já vem instalada no Windows, por isso não se carrega nada da rede
   (uma ferramenta local não deve depender de estar online). A Cascadia Mono
   trata dos dados, e a Segoe do texto corrido.

   O elemento assinatura é a CALHA da esquerda: uma linha contínua a percorrer a
   conversa toda, com quem falou e o número de cada consulta pendurados nela.
   É a margem de um livro de registo — e a numeração não é decorativa, é a
   ordem por que as queries correram, que é o que permite auditá-las.
   ========================================================================== */

/* --- As fontes ------------------------------------------------------------
   Auto-alojadas, e não por gosto: a CSP do servidor declara `default-src
   'self'` e não declara `font-src`, portanto o `font-src` herda o `'self'` e
   um pedido ao Google Fonts é bloqueado antes de sair. Alojá-las mantém de pé o
   argumento original desta folha — uma ferramenta local não deve depender de
   estar online.

   Subconjunto `latin` apenas. Confirmado que `ã õ ç á é í ó ú â ê ô à º ª €`
   cabem todos em U+0000–00FF: o latin-ext não acrescenta nada ao português e
   duplicava os ficheiros.

   `font-display: swap` de propósito: com `block` a página ficava muda durante
   o carregamento, e o que aqui interessa é o texto a chegar.
   ------------------------------------------------------------------------- */

/* Substitui a Bahnschrift, e herda-lhe o argumento: a Archivo é um grotesco de
   sinalização, do mesmo registo do desenho técnico. O eixo de LARGURA é o que
   dispensa uma segunda família — condensada nas etiquetas, normal nos títulos. */
@font-face {
  font-family: "Archivo";
  src: url("/fontes/archivo-var-latin.woff2") format("woff2-variations");
  font-weight: 400 800;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
}

/* Substitui a Segoe UI Variable. Desenhada para escrita técnica e com a
   acentuação portuguesa bem resolvida, que é onde muitas faces se estragam. */
@font-face {
  font-family: "IBM Plex Sans VF";
  src: url("/fontes/plex-sans-var-latin.woff2") format("woff2-variations");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

/* Substitui a Cascadia Mono. Mesmo esqueleto da de texto: o SQL e as colunas de
   euros ficam da mesma família que a prosa à volta deles. Esta não é variável no
   upstream, por isso são dois pesos e não um ficheiro. */
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fontes/plex-mono-400-latin.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fontes/plex-mono-600-latin.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Sem isto os controlos nativos — o <select> do modelo, as barras de scroll,
     o calendário de um input de data — ficam com o tema do sistema e não com o
     da página: no tema claro apareciam pretos no meio de tudo o resto. */
  color-scheme: light dark;

  --calha: 5.5rem;
  --raio: 3px;

  --fonte-display: "Archivo", Bahnschrift, "Archivo Narrow", "Arial Narrow", sans-serif;
  --fonte-texto: "IBM Plex Sans VF", "IBM Plex Sans", "Segoe UI Variable Text", "Segoe UI", system-ui, sans-serif;
  --fonte-dados: "IBM Plex Mono", "Cascadia Mono", Consolas, ui-monospace, monospace;

  /* Betão escuro. Neutro frio, nunca preto puro — preto puro não existe em
     obra e vibra contra o laranja. */
  --betao: #17191a;
  --betao-2: #1f2325;
  --betao-3: #2b3033;
  --aco: #4d5c66;
  --cal: #e9e7e2;
  --cal-2: #979d9f;
  --sinal: #f2621a;
  --sinal-fundo: rgba(242, 98, 26, 0.12);
  --verdete: #57b083;
  --sombra: 0 1px 2px rgba(0, 0, 0, 0.4);

  /* --- Os estados, que são um conjunto à parte do laranja ------------------
     O `--sinal` significa UMA coisa e só uma: o sistema a agir — a acção
     principal e a consulta a correr. Não é o erro, não é a etiqueta do papel.
     Foi essa a confusão que se desfez aqui.

     Os quatro estados vêm da sinalização de obra, e cada um traz uma FORMA
     além da cor (ver .selo mais abaixo): o disco é a regra, o triângulo é o
     aviso, o octógono é a paragem. É o que os torna legíveis sem cor nenhuma.

     O --limite é o mais importante desta lista: uma consulta recusada por
     falta de permissão NÃO é uma avaria, é o sistema a fazer o que devia, e
     nunca pode ser vermelha.

     Os valores não são escolhidos a olho. O verdete era #62a189 e ficava a
     ΔE 9.5 do azul do limite — abaixo do limiar em que duas cores se
     distinguem mesmo com visão normal, e estas duas aparecem na MESMA posição
     em talões consecutivos. Empurrou-se o verde até o par passar. */
  /* A tinta dos valores no SQL. Areia, e nao uma das cores de estado: um
     literal nao e um estado, e reaproveitar o verde ou o azul aqui punha o
     realce a competir com o selo, que e o que tem de saltar a vista. */
  --sql-valor: #c9b99a;

  --limite: #6a8fe0;
  --limite-fundo: rgba(106, 143, 224, 0.12);
  --aviso: #dfa73c;
  --aviso-fundo: rgba(223, 167, 60, 0.12);
  --falha: #e0574f;
  --falha-fundo: rgba(224, 87, 79, 0.12);

  /* --- O ritmo -------------------------------------------------------------
     Um degrau de 4px. Antes eram 3, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 22 e
     28 espalhados por 41 declarações, o que é o mesmo que não haver ritmo. */
  --e-1: 4px;
  --e-2: 8px;
  --e-3: 12px;
  --e-4: 16px;
  --e-5: 24px;
  --e-6: 32px;
  --e-7: 48px;

  /* A largura da coluna de conteúdo estava escrita três vezes, em três regras
     que TÊM de concordar — a conversa, o ecrã vazio e a barra de escrita. */
  --largura-conteudo: 62rem;

  /* A gestão precisa de mais: a tabela de contas tem seis colunas e a matriz de
     permissões tem cinco acções. Mas NÃO precisa de tudo — sem tecto, num
     monitor largo um campo "nome de utilizador" ficava com dois mil pixels. */
  --largura-gestao: 90rem;

  /* O recuo do conteúdo face à calha, idem: estava em três sítios (o corpo do
     turno, o índice do talão e o ecrã vazio) e mexer num partia o alinhamento
     dos outros dois. Era 22px; passou a 24 para assentar no degrau. */
  --recuo-calha: var(--e-5);

  /* --- A escala tipográfica ------------------------------------------------
     Oito degraus, cada um com um papel. Antes eram doze tamanhos literais em
     50 declarações, com o mesmo papel visual reescrito de forma diferente. */
  --t-1: 10px;    /* cabeçalhos da matriz */
  --t-2: 11px;    /* etiqueta em versaletes */
  --t-3: 12px;    /* nota */
  --t-4: 13px;    /* interface: botões, campos, tabelas */
  --t-5: 15px;    /* prosa */
  --t-6: 17px;    /* subtítulo */
  --t-7: 20px;    /* título */
  --t-8: 26px;    /* display */
  /* A monoespaçada corre opticamente mais pequena que a de texto ao mesmo
     tamanho, por isso tem degrau próprio em vez de usar o --t-3. */
  --t-dados: 12.5px;

  --lh-apertada: 1.3;
  --lh-base: 1.6;
  --lh-dados: 1.65;

  --peso-normal: 400;
  --peso-medio: 500;
  --peso-forte: 600;
  --peso-display: 700;

  /* O eixo de largura da Archivo. É o que dispensa uma segunda família: as
     etiquetas saem condensadas, os títulos saem normais, com um ficheiro só. */
  --wdth-etiqueta: 84%;
  --wdth-titulo: 100%;
}

@media (prefers-color-scheme: light) {
  :root {
    /* Papel de saco de cimento: cinzento quente, não creme. */
    --betao: #e3e2dd;
    --betao-2: #efeeea;
    --betao-3: #cfcdc6;
    --aco: #5c6a72;
    --cal: #1a1c1d;
    --cal-2: #5d6366;
    --sinal: #bf3d0c;
    --sinal-fundo: rgba(191, 61, 12, 0.09);
    --verdete: #227a56;
    --sql-valor: #6b5b3f;
    --limite: #2f5aa8;
    --limite-fundo: rgba(47, 90, 168, 0.1);
    --aviso: #9a6a00;
    --aviso-fundo: rgba(154, 106, 0, 0.1);
    --falha: #a01f3c;
    --falha-fundo: rgba(160, 31, 60, 0.1);
    --sombra: 0 1px 2px rgba(0, 0, 0, 0.08);
  }
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  /* Coluna flexível e não grelha de linhas fixas: as faixas do topo (sessão
     expirada, mudança de palavra-passe, aviso do modelo) aparecem e desaparecem,
     e com linhas contadas à mão a área de trabalho caía na linha errada assim
     que uma delas estivesse escondida. Aqui o número de faixas não importa. */
  display: flex;
  flex-direction: column;
  height: 100dvh;
  font-family: var(--fonte-texto);
  font-size: var(--t-5);
  line-height: var(--lh-base);
  color: var(--cal);
  background: var(--betao);
  -webkit-font-smoothing: antialiased;
}

/* --- Cabeçalho ------------------------------------------------------------ */

.cabecalho {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-4);
  align-items: center;
  justify-content: space-between;
  padding: var(--e-3) var(--e-5);
  background: var(--betao-2);
  border-bottom: 1px solid var(--betao-3);
}

.cabecalho__marca {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  min-width: 0;
}

/* A sigla é a chapa de identificação da ficha técnica. */
.cabecalho__sigla {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-titulo);
  font-size: var(--t-5);
  font-weight: var(--peso-display);
  letter-spacing: 0.04em;
  color: var(--betao);
  background: var(--sinal);
  border-radius: var(--raio);
}

.cabecalho h1 {
  margin: 0;
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-7);
  font-weight: var(--peso-forte);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1.15;
}

.cabecalho__ficha {
  margin: 1px 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-3);
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-3);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--cal-2);
}

.cabecalho__ficha > span + span::before {
  content: "·";
  margin-right: var(--e-3);
  color: var(--betao-3);
}

.etiqueta--leitura {
  color: var(--verdete);
}

.cabecalho__controlos {
  display: flex;
  align-items: center;
  gap: var(--e-3);
}

/* --- Seletor de modelo ---------------------------------------------------- */

.campo-modelo {
  display: flex;
  align-items: center;
  gap: var(--e-2);
}

.campo-modelo__etiqueta {
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-2);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--cal-2);
}

select {
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-titulo);
  font-size: var(--t-4);
  letter-spacing: 0.04em;
  color: var(--cal);
  background: var(--betao);
  border: 1px solid var(--betao-3);
  border-radius: var(--raio);
  padding: var(--e-2) var(--e-3);
  cursor: pointer;
}

select:hover {
  border-color: var(--aco);
}

/* Nota do modelo — só aparece quando o modelo escolhido tem uma condição. */
.nota-modelo {
  margin: 0;
  padding: var(--e-2) var(--e-5);
  font-size: var(--t-4);
  color: var(--cal);
  background: var(--aviso-fundo);
  border-bottom: 1px solid var(--betao-3);
}

.nota-modelo[hidden] {
  display: none;
}

/* --- Botões --------------------------------------------------------------- */

.botao {
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-4);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: var(--e-2) var(--e-4);
  border-radius: var(--raio);
  cursor: pointer;
  border: 1px solid transparent;
  transition: background-color 0.12s ease, border-color 0.12s ease;
}

.botao--discreto {
  color: var(--cal-2);
  background: transparent;
  border-color: var(--betao-3);
}

.botao--discreto:hover {
  color: var(--cal);
  border-color: var(--aco);
}

.botao--principal {
  color: #fff;
  background: var(--sinal);
}

.botao--principal:hover:not(:disabled) {
  background: color-mix(in srgb, var(--sinal) 85%, #000);
}

.botao:disabled {
  opacity: 0.45;
  cursor: default;
}

:focus-visible {
  outline: 2px solid var(--sinal);
  outline-offset: 2px;
}

/* --- A área: calha à esquerda, conversa à direita ------------------------- */

.area {
  flex: 1;
  display: grid;
  grid-template-columns: 15rem minmax(0, 1fr);
  min-height: 0;
  overflow: hidden;
}

/* As conversas rolam; o alcance fica preso em baixo.
   A ordem importa: com as duas a rolar juntas, meia dúzia de conversas
   empurrava o painel de alcance para fora do ecrã — e o painel é o que tem de
   estar à vista ANTES de alguém perguntar, que é o ponto todo dele. */
.calha-lateral {
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--betao-3);
  background: color-mix(in srgb, var(--betao-2) 60%, transparent);
  min-height: 0;
  overflow-y: auto;
}

.conversas {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: var(--e-5) var(--e-4);
  min-height: 0;
}

/* Colado em baixo, e não numa faixa de grelha própria: numa janela baixa o
   alcance sozinho é mais alto do que a calha inteira, e uma faixa rígida
   transbordava por cima das conversas. Assim a calha rola como um todo e o
   alcance fica sempre à vista, que é o que dele se quer. */
.alcance {
  flex: 0 0 auto;
  position: sticky;
  bottom: 0;
  padding: var(--e-5) var(--e-4);
  border-top: 1px solid var(--betao-3);
  background: var(--betao-2);
}

.coluna {
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  min-height: 0;
}

/* --- As conversas --------------------------------------------------------- */

.conversas__lista {
  margin: var(--e-3) 0 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 1px;
}

.conversas__item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  border-radius: var(--raio);
}

.conversas__item:hover { background: var(--betao-3); }

/* A conversa aberta leva o filete do lado, que é a mesma marca que o talão usa
   para o estado: a aresta esquerda diz onde se está. */
.conversas__item--aberta {
  background: var(--betao-3);
  box-shadow: inset 2px 0 0 var(--sinal);
}

.conversas__abrir {
  display: grid;
  gap: 1px;
  min-width: 0;
  text-align: left;
  padding: var(--e-2);
  background: none;
  border: none;
  cursor: pointer;
  font: inherit;
  color: inherit;
}

.conversas__titulo {
  font-size: var(--t-4);
  color: var(--cal);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.conversas__item--aberta .conversas__titulo { font-weight: var(--peso-medio); }

.conversas__quando {
  font-family: var(--fonte-dados);
  font-size: var(--t-1);
  font-variant-numeric: tabular-nums;
  color: var(--aco);
}

/* Só aparece com o rato ou com o foco: uma coluna de cruzes ao lado de cada
   conversa convida a enganos, e apagar não tem desfazer. */
.conversas__apagar {
  flex: none;
  padding: 0 var(--e-2);
  align-self: stretch;
  font-size: var(--t-6);
  line-height: 1;
  color: var(--cal-2);
  background: none;
  border: none;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s ease;
}

.conversas__item:hover .conversas__apagar,
.conversas__apagar:focus-visible { opacity: 1; }
.conversas__apagar:hover { color: var(--falha); }
.conversas__apagar:disabled { cursor: wait; }

.conversas__vazio {
  padding: var(--e-2) 0;
  font-size: var(--t-2);
  line-height: 1.45;
  color: var(--aco);
}

/* --- O alcance desta sessão -----------------------------------------------
   As quatro contas desta aplicação NÃO se contêm umas às outras, e disso a
   página mostrava uma etiqueta de três palavras. Este painel mostra as seis
   áreas, incluindo as que a sessão não alcança — que são metade do que há a
   dizer: sem elas, a primeira recusa parece uma avaria.

   As formas são as do talão de propósito. O disco que aqui marca uma área
   fora de alcance é o mesmo que lá marca a consulta recusada, e é assim que
   uma coisa explica a outra sem uma linha de texto a fazer a ligação.
   ------------------------------------------------------------------------- */

.alcance[hidden] { display: none; }

.alcance__titulo {
  margin: 0;
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-2);
  font-weight: var(--peso-forte);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cal-2);
}

.alcance__quem {
  margin: var(--e-1) 0 var(--e-4);
  font-family: var(--fonte-dados);
  font-size: var(--t-2);
  color: var(--aco);
}

.alcance__lista {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: var(--e-3);
}

.alcance__item {
  display: grid;
  grid-template-columns: 9px minmax(0, 1fr);
  gap: 0 var(--e-2);
  align-items: baseline;
}

.alcance__item .selo__forma {
  align-self: center;
  margin-top: 1px;
}

.alcance__nome {
  font-size: var(--t-4);
  font-weight: var(--peso-medio);
  color: var(--cal);
}

.alcance__cobre {
  grid-column: 2;
  font-size: var(--t-2);
  line-height: 1.45;
  color: var(--aco);
}

/* Dentro: quadrado cheio, a mesma forma do selo "devolvido". */
.alcance__item--dentro .selo__forma {
  color: var(--verdete);
  background: currentColor;
  border-radius: 1px;
}

/* Fora: disco, a mesma forma do selo do limite. Não é vermelho e não é uma
   falta — é o desenho do papel. */
.alcance__item--fora .selo__forma {
  color: var(--limite);
  background: transparent;
  border: 1.5px solid currentColor;
  border-radius: 50%;
}

.alcance__item--fora .alcance__nome { color: var(--cal-2); }
.alcance__item--fora .alcance__cobre { color: var(--limite); }

/* A escrita é uma capacidade à parte das áreas: um employee alcança as seis e
   não escreve em nenhuma, e isso não se lê na lista. */
.alcance__escrita {
  margin: var(--e-4) 0 0;
  padding-top: var(--e-3);
  border-top: 1px solid var(--betao-3);
  font-size: var(--t-2);
  line-height: 1.45;
  color: var(--aco);
}

.alcance__escrita--escreve {
  color: var(--sinal);
  font-weight: var(--peso-medio);
}

/* --- Conversa ------------------------------------------------------------- */

.conversa {
  overflow-y: auto;
  padding: var(--e-5) var(--e-5) var(--e-7);
  scrollbar-gutter: stable;
}

/* O turno é a linha do registo: calha à esquerda, conteúdo à direita.
   A borda esquerda do conteúdo é a linha contínua que atravessa a página. */
.turno {
  display: grid;
  grid-template-columns: var(--calha) minmax(0, 1fr);
  max-width: var(--largura-conteudo);
  margin: 0 auto;
}

.turno__quem {
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-2);
  font-weight: var(--peso-forte);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--cal-2);
  text-align: right;
  padding: var(--e-3) var(--e-3) 0 0;
}

.turno--utilizador .turno__quem {
  color: var(--cal-2);
}

.turno__corpo {
  border-left: 1px solid var(--betao-3);
  padding: var(--e-3) 0 var(--e-3) var(--recuo-calha);
  min-width: 0;
}

/* A pergunta é o cabeçalho da secção, não um balão. */
.turno--utilizador .turno__corpo {
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-titulo);
  font-size: var(--t-7);
  letter-spacing: 0.01em;
  line-height: var(--lh-apertada);
  padding-top: var(--e-3);
}

/* --- O talão: o elemento assinatura --------------------------------------
   Um talão de pesagem responde a quatro perguntas — o que foi medido, contra
   quê, quanto deu e quando. São exactamente as quatro que este bloco tem de
   responder de relance, e é de lá que vem a forma: cabeça, corpo, leitura.
   ------------------------------------------------------------------------- */

.talao {
  position: relative;
  margin: var(--e-3) 0;
  background: var(--betao-2);
  border: 1px solid var(--betao-3);
  border-left: 2px solid var(--betao-3);
  border-radius: var(--raio);
}

/* O estado pinta a aresta esquerda e mais nada. É o que permite ler uma coluna
   de talões de lado e ver logo qual foi o que não passou. */
.talao--correr { border-left-color: var(--sinal); }
.talao--devolvido { border-left-color: var(--verdete); }
.talao--limite { border-left-color: var(--limite); }
.talao--aviso { border-left-color: var(--aviso); }
.talao--falha { border-left-color: var(--falha); }

/* O índice vive na margem, alinhado com a calha. É a ordem por que as
   consultas correram — informação, não ornamento. */
.talao__indice {
  position: absolute;
  left: calc(var(--recuo-calha) * -1);
  top: var(--e-2);
  width: var(--recuo-calha);
  transform: translateX(-100%);
  padding-right: var(--e-3);
  text-align: right;
  font-family: var(--fonte-dados);
  font-size: var(--t-2);
  font-variant-numeric: tabular-nums;
  color: var(--aco);
}

.talao__cabeca {
  display: flex;
  align-items: baseline;
  gap: var(--e-3);
  padding: var(--e-2) var(--e-3);
  border-bottom: 1px solid var(--betao-3);
}

.talao__nome {
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-3);
  font-weight: var(--peso-forte);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--cal);
  flex: none;
}

/* Contra que tabelas. É a etiqueta, não a prova — a prova é o SQL logo abaixo. */
.talao__alvo {
  font-family: var(--fonte-dados);
  font-size: var(--t-2);
  color: var(--cal-2);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.talao__alvo[hidden] { display: none; }

/* O tempo conta desde a chamada, não desde a resposta: o intervalo é real e é
   o único momento em que se vê que está a acontecer alguma coisa do outro lado. */
.talao__tempo {
  font-family: var(--fonte-dados);
  font-size: var(--t-2);
  font-variant-numeric: tabular-nums;
  color: var(--cal-2);
  flex: none;
}


.talao__tempo[hidden] { display: none; }

.talao--correr .talao__tempo { color: var(--sinal); }

.talao__sql {
  margin: 0;
  padding: var(--e-3);
  overflow-x: auto;
  font-family: var(--fonte-dados);
  font-size: var(--t-dados);
  font-weight: var(--peso-normal);
  line-height: var(--lh-dados);
  white-space: pre;
  color: var(--cal-2);
  tab-size: 2;
}

/* Três tintas e não mais: as palavras-chave a cheio, os valores em areia, o
   resto quieto. Um arco-íris aqui competia com os estados, que são o que tem
   mesmo de saltar à vista. */
.sql-chave {
  color: var(--cal);
  font-weight: var(--peso-forte);
}

.sql-valor { color: var(--sql-valor); }

.sql-quieto { color: var(--aco); }

/* --- A leitura ------------------------------------------------------------ */

.talao__leitura {
  display: flex;
  align-items: center;
  gap: var(--e-3);
  padding: var(--e-2) var(--e-3);
  border-top: 1px solid var(--betao-3);
  background: color-mix(in srgb, var(--betao-3) 30%, transparent);
  border-radius: 0 0 var(--raio) var(--raio);
}

/* A régua mede contra 200, que é o LIMIT que a Camada 3 do MCP aplica a uma
   query sem LIMIT explícito. A escala não é inventada: é uma verdade do
   sistema, e é ela que faz 5 linhas e 200 linhas deixarem de parecer iguais. */
.talao__regua {
  display: flex;
  align-items: center;
  gap: var(--e-2);
  flex: 1;
  min-width: 0;
}

.talao__regua[hidden] { display: none; }

.talao__regua-barra {
  flex: 1;
  min-width: 3rem;
  max-width: 14rem;
  height: 3px;
  background: var(--betao-3);
  border-radius: 2px;
  overflow: hidden;
}

.talao__regua-barra::before {
  content: "";
  display: block;
  width: var(--preenchido, 0%);
  height: 100%;
  background: var(--verdete);
  border-radius: 2px;
  transition: width 0.3s ease-out;
}

/* 200 linhas quase nunca são "as 200 que existem" — são "as primeiras 200 de
   um número que não sabemos". A marca no tecto diz isso. */
.talao__regua--tecto .talao__regua-barra::before { background: var(--aviso); }
.talao__regua--tecto .talao__regua-escala { color: var(--aviso); }

.talao__regua-escala {
  font-family: var(--fonte-dados);
  font-size: var(--t-2);
  font-variant-numeric: tabular-nums;
  color: var(--aco);
  flex: none;
}

/* A explicação só aparece quando acrescenta alguma coisa ao selo. */
/* A recusa por permissão leva o fundo do limite, como o erro leva o da falha:
   o bloco inteiro diz de que família é, e não só o selo. */
.talao--limite .talao__leitura { background: var(--limite-fundo); }

.talao__nota {
  margin: 0;
  padding: 0 var(--e-3) var(--e-3);
  font-size: var(--t-3);
  line-height: var(--lh-base);
  color: var(--cal-2);
  max-width: 46rem;
}

.talao__copiar {
  margin-left: auto;
  flex: none;
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--cal-2);
  background: transparent;
  border: 1px solid var(--betao-3);
  border-radius: 2px;
  padding: var(--e-1) var(--e-2);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s ease;
}

.talao:hover .talao__copiar,
.talao__copiar:focus-visible { opacity: 1; }

/* --- O selo: o estado, com forma além da cor -----------------------------
   As formas vêm da sinalização de obra e carregam o significado sozinhas: o
   disco é a regra, o triângulo é o aviso, o octógono é a paragem. É o que
   mantém isto legível para quem não distingue as cores — e o que impede a
   recusa por permissão de se ler como avaria.
   ------------------------------------------------------------------------- */

.selo {
  display: inline-flex;
  align-items: center;
  gap: var(--e-2);
  flex: none;
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-2);
  font-weight: var(--peso-forte);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.selo__forma {
  width: 9px;
  height: 9px;
  flex: none;
  background: currentColor;
}

.selo--espera { color: var(--cal-2); }

/* A espera é um anel aberto, não um disco: ainda não há resposta nenhuma. */
.selo--espera .selo__forma {
  background: transparent;
  border: 1.5px solid currentColor;
  border-radius: 50%;
  border-top-color: transparent;
  animation: rodar 0.9s linear infinite;
}

.selo--devolvido { color: var(--verdete); }
.selo--devolvido .selo__forma { border-radius: 1px; }

/* Disco — a regra. Uma consulta recusada por falta de permissão não é uma
   avaria: é o sistema a fazer o que devia. */
.selo--limite { color: var(--limite); }
.selo--limite .selo__forma { border-radius: 50%; }

/* Triângulo — o aviso. */
.selo--aviso { color: var(--aviso); }
.selo--aviso .selo__forma { clip-path: polygon(50% 0, 100% 100%, 0 100%); }

/* Octógono — a paragem. */
.selo--falha { color: var(--falha); }
.selo--falha .selo__forma {
  clip-path: polygon(30% 0, 70% 0, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0 70%, 0 30%);
}

@keyframes rodar {
  to { transform: rotate(360deg); }
}

/* --- Resposta em markdown ------------------------------------------------- */

.resposta > *:first-child {
  margin-top: 0;
}

.resposta > *:last-child {
  margin-bottom: 0;
}

.resposta p {
  margin: 0 0 0.85em;
}

.resposta h1,
.resposta h2,
.resposta h3,
.resposta h4 {
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  letter-spacing: 0.05em;
  text-transform: uppercase;
  margin: 1.4em 0 0.5em;
  font-weight: var(--peso-forte);
}

.resposta h1 { font-size: var(--t-6); }
.resposta h2 { font-size: var(--t-5); }
.resposta h3,
.resposta h4 { font-size: var(--t-4); color: var(--cal-2); }

.resposta ul,
.resposta ol {
  margin: 0 0 0.85em;
  padding-left: 1.3em;
}

.resposta li {
  margin-bottom: 0.3em;
}

.resposta li::marker {
  color: var(--aco);
}

.resposta strong {
  font-weight: var(--peso-forte);
  color: var(--cal);
}

/* Os identificadores da base — no_cli, dt_doc, design — aparecem no meio do
   texto o tempo todo. Ficam em mono para se distinguirem da prosa. */
.resposta code {
  font-family: var(--fonte-dados);
  font-size: 0.88em;
  padding: 1px var(--e-1);
  border-radius: 2px;
  background: color-mix(in srgb, var(--aco) 22%, transparent);
  white-space: nowrap;
}

.resposta pre {
  margin: 0 0 0.85em;
  padding: var(--e-3);
  overflow-x: auto;
  background: var(--betao-2);
  border: 1px solid var(--betao-3);
  border-radius: var(--raio);
}

.resposta pre code {
  background: none;
  padding: 0;
  white-space: pre;
  font-size: var(--t-dados);
}

.resposta blockquote {
  margin: 0 0 0.85em;
  padding-left: var(--e-3);
  border-left: 2px solid var(--aco);
  color: var(--cal-2);
}

/* Tabelas como ficha de dados: filetes finos, cabeçalho em condensada, e os
   números alinhados à direita com algarismos de largura fixa — é o que permite
   comparar duas colunas de euros de relance. */
/* --- As tabelas: uma base, onde havia quatro -----------------------------
   A resposta do agente, as contas, a matriz de permissões e a auditoria eram
   quatro sistemas de tabela sem uma linha em comum — filetes diferentes,
   cabeçalhos diferentes, algarismos diferentes. Passam a partilhar isto, e o
   que cada uma acrescenta por cima é só o que lhe é próprio.

   Os algarismos são de largura fixa em TUDO o que seja valor, contagem ou
   data. Sem isso duas colunas de euros não se comparam de relance, e comparar
   de relance é o objectivo desta página.
   ------------------------------------------------------------------------- */

.tabela-caixa,
.tabela-envolvente,
.matriz-envolvente {
  overflow: auto;
  border: 1px solid var(--betao-3);
  border-radius: var(--raio);
}

.tabela-caixa { margin: 0 0 1em; }

.tabela-base {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: var(--t-4);
}

.tabela-base th {
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-2);
  font-weight: var(--peso-forte);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--cal-2);
  text-align: left;
  padding: var(--e-2) var(--e-3);
  background: var(--betao-2);
  border-bottom: 1px solid var(--betao-3);
  white-space: nowrap;
}

/* O cabeçalho fica colado ao topo: uma tabela de faturação por família passa
   das trinta linhas, e a meio dela já ninguém sabe que coluna é qual. */
.tabela-base thead th {
  position: sticky;
  top: 0;
  z-index: 1;
}

.tabela-base td {
  padding: var(--e-2) var(--e-3);
  border-bottom: 1px solid color-mix(in srgb, var(--betao-3) 55%, transparent);
  vertical-align: top;
}

.tabela-base tbody tr:last-child td { border-bottom: none; }

.tabela-base tbody tr:hover td {
  background: color-mix(in srgb, var(--aco) 10%, transparent);
}

/* A coluna numérica: à direita, monoespaçada, algarismos de largura fixa. */
.tabela-base .num {
  text-align: right;
  font-family: var(--fonte-dados);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Um valor negativo tem tinta própria. Não é decoração: o stock negativo é uma
   das imperfeições propositadas destes dados e uma das cinco perguntas
   sugeridas — num mapa de trinta linhas, o sinal de menos sozinho perde-se. */
.tabela-base .neg { color: var(--falha); }

/* Quantas linhas a tabela tem, por baixo dela. Uma tabela que rola esconde o
   fim: sem isto não se sabe se são doze linhas ou as duzentas do LIMIT. */
.tabela-conta {
  margin: calc(-1em + var(--e-1)) 0 1em;
  font-family: var(--fonte-dados);
  font-size: var(--t-2);
  font-variant-numeric: tabular-nums;
  color: var(--aco);
}

/* --- Estados -------------------------------------------------------------- */

.pensar {
  display: inline-flex;
  align-items: center;
  gap: var(--e-2);
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-3);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--cal-2);
}

.pensar::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--sinal);
  animation: pulsar 1.1s ease-in-out infinite;
}

@keyframes pulsar {
  0%, 100% { opacity: 0.25; }
  50% { opacity: 1; }
}

/* Quem pede menos movimento fica sem movimento nenhum.
   A regra nomeava só o ponto do "a pensar"; qualquer animação acrescentada
   depois — o anel do selo à espera, por exemplo — escapava-lhe em silêncio.
   Passa a apanhar tudo, e os estados continuam legíveis parados: o anel do
   selo tem uma abertura, e é a abertura que diz "ainda não há resposta". */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  .pensar::before { opacity: 0.8; }
}

.erro {
  margin: var(--e-3) 0;
  padding: var(--e-3) var(--e-3);
  border: 1px solid var(--falha);
  border-left-width: 3px;
  border-radius: var(--raio);
  background: var(--falha-fundo);
  font-size: var(--t-4);
}

.erro strong {
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: var(--t-3);
  display: block;
  margin-bottom: var(--e-1);
}

/* Rodapé do turno: o custo da resposta, em registo de ficha técnica. */
.rodape-turno {
  margin-top: var(--e-3);
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-2);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--aco);
  display: flex;
  gap: var(--e-3);
  flex-wrap: wrap;
}

/* --- Ecrã vazio ----------------------------------------------------------- */

/* Alinha com a coluna dos turnos: mesma largura e mesmo recuo da calha, para
   o texto começar exatamente onde as respostas vão começar. */
.vazio {
  max-width: var(--largura-conteudo);
  margin: 6vh auto 0;
  padding-left: calc(var(--calha) + var(--recuo-calha));
}

.vazio h2 {
  margin: 0 0 var(--e-2);
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-titulo);
  font-size: var(--t-8);
  font-weight: var(--peso-forte);
  letter-spacing: 0.02em;
}

.vazio p {
  margin: 0 0 var(--e-5);
  color: var(--cal-2);
  max-width: 34rem;
}

.sugestoes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-2);
}

.sugestoes li[hidden] { display: none; }

.sugestoes button {
  font-family: inherit;
  font-size: var(--t-4);
  color: var(--cal);
  background: var(--betao-2);
  border: 1px solid var(--betao-3);
  border-radius: var(--raio);
  padding: var(--e-2) var(--e-3);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.12s ease;
}

.sugestoes button:hover {
  border-color: var(--sinal);
}

/* --- Barra de escrita ----------------------------------------------------- */

/* A barra ocupa a largura toda (é ela que traz o filete e o fundo), mas os
   campos alinham-se com a coluna da conversa — daí o interior centrado. */
.barra {
  display: grid;
  justify-items: center;
  padding: var(--e-3) var(--e-5) var(--e-4);
  background: var(--betao-2);
  border-top: 1px solid var(--betao-3);
}

.barra__campos {
  display: flex;
  gap: var(--e-3);
  align-items: flex-end;
  width: 100%;
  max-width: var(--largura-conteudo);
}

textarea {
  flex: 1;
  resize: none;
  max-height: 40vh;
  padding: var(--e-3);
  font: inherit;
  line-height: 1.5;
  color: var(--cal);
  background: var(--betao);
  border: 1px solid var(--betao-3);
  border-radius: var(--raio);
}

textarea::placeholder {
  color: var(--cal-2);
}

textarea:focus {
  border-color: var(--aco);
  outline: none;
}

textarea:focus-visible {
  outline: 2px solid var(--sinal);
  outline-offset: 1px;
}

textarea:disabled {
  opacity: 0.55;
}

/* --- Estreito ------------------------------------------------------------- */

/* O único salto estreito da folha. Eram três — 640px duas vezes e 620px —
   para o mesmo momento; em rem acompanha quem aumenta o tamanho de letra. */
@media (max-width: 40rem) {
  :root {
    --calha: 0px;
  }

  /* A calha lateral passa para cima da conversa e deixa de rolar sozinha: numa
     coluna estreita duas zonas de scroll independentes são uma armadilha. */
  .area {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr);
  }

  .calha-lateral {
    grid-template-rows: auto;
    border-right: none;
    border-bottom: 1px solid var(--betao-3);
    max-height: 40vh;
    overflow-y: auto;
  }

  /* O alcance é o que tem de estar à vista; as conversas ficam abaixo dele. */
  .calha-lateral .alcance {
    order: -1;
    border-top: none;
    border-bottom: 1px solid var(--betao-3);
  }

  .alcance__lista {
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  }

  /* A lista fica numa caixa com fim visível. Sem altura própria, o corte da
     calha caía a meio de uma linha e lia-se como avaria em vez de scroll. */
  .conversas__lista {
    max-height: 8rem;
    overflow-y: auto;
  }

  .conversa {
    padding: var(--e-5) var(--e-4) var(--e-6);
  }

  .turno {
    grid-template-columns: 1fr;
  }

  .turno__quem {
    text-align: left;
    padding: var(--e-3) 0 2px;
  }

  .turno__corpo {
    border-left: none;
    padding-left: 0;
  }

  /* Sem calha não há margem onde pendurar o índice — passa a inline. */
  .talao__indice {
    position: static;
    transform: none;
    display: inline-block;
    width: auto;
    padding: var(--e-2) 0 0 var(--e-3);
    text-align: left;
  }

  .vazio {
    padding-left: 0;
  }

  .cabecalho,
  .barra {
    padding-left: var(--e-4);
    padding-right: var(--e-4);
  }
}

/* ===========================================================================
   AUTENTICAÇÃO E GESTÃO
   Acrescentado com os utilizadores e papéis. Reaproveita as variáveis e os
   botões que já existiam; o que faltava mesmo era estilo para <input>.
   =========================================================================== */

/* --- Campos de texto ------------------------------------------------------
   Decalcado do bloco `textarea`, para os formulários novos não destoarem. */
input[type="text"],
input[type="password"] {
  width: 100%;
  padding: var(--e-2) var(--e-3);
  font: inherit;
  line-height: 1.4;
  color: var(--cal);
  background: var(--betao);
  border: 1px solid var(--betao-3);
  border-radius: var(--raio);
}

input[type="text"]:focus,
input[type="password"]:focus {
  border-color: var(--aco);
  outline: none;
}

input[type="text"]:focus-visible,
input[type="password"]:focus-visible {
  outline: 2px solid var(--sinal);
  outline-offset: 1px;
}

input:disabled {
  opacity: 0.55;
}

.campo {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
}

.campo__etiqueta {
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-2);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--cal-2);
}

/* --- A etiqueta -----------------------------------------------------------
   Era escrita no HTML e no JS e não tinha regra nenhuma no CSS: só os
   modificadores pintavam, e uma etiqueta sem modificador não se via. A base
   é a caixa; os modificadores só lhe dão cor.
   ------------------------------------------------------------------------- */

.etiqueta {
  display: inline-block;
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-2);
  font-weight: var(--peso-forte);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--cal-2);
}

.etiqueta[hidden] { display: none; }

/* --- A etiqueta do papel --------------------------------------------------
   O `--leitura` já existia, em verdete. O `--escrita` usa o LARANJA DE SINAL,
   com fundo e caixa: um administrador que julgue estar em só-leitura é o
   cenário perigoso desta aplicação, e a etiqueta tem de o dizer de longe. */
.etiqueta--escrita {
  color: var(--sinal);
  background: var(--sinal-fundo);
  border: 1px solid var(--sinal);
  border-radius: var(--raio);
  padding: 1px var(--e-2);
  font-weight: var(--peso-forte);
}

/* Um filete separa quem está sentado dos controlos. Sem ele o nome colava-se
   ao "Modelo" e liam-se como uma coisa só. */
.cabecalho__utilizador {
  font-size: var(--t-3);
  color: var(--cal-2);
  padding-right: var(--e-3);
  border-right: 1px solid var(--betao-3);
  max-width: 14rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- Ecrã de entrada ------------------------------------------------------
   O `body` do chat é uma grelha de quatro linhas; esta página precisa da sua
   própria regra, senão o cartão estica-se para preencher a coluna. */
/* --- Ecrã de entrada -----------------------------------------------------
   Duas colunas: a tese à esquerda, a entrada à direita. Dizia só "Consulta à
   base de dados", que descreve mil produtos; o que este tem de próprio é a
   prova, e por isso a prova é o herói — com o mesmo talão que a página usa a
   sério, não um desenho dele.
   ------------------------------------------------------------------------- */

body.pagina-entrar {
  display: grid;
  /* As duas faixas medem-se pelo conteúdo, com tecto — NUNCA `1fr`.
     Com `1fr` a faixa da esquerda engolia todo o espaço livre e o
     `justify-content: center` deixava de ter o que centrar: num monitor
     largo o conjunto encostava à direita com meio ecrã vazio à esquerda.
     Assim é o par que se centra, seja qual for a largura. */
  grid-template-columns: minmax(0, 34rem) minmax(0, 24rem);
  justify-content: center;
  align-content: center;
  gap: var(--e-7);
  height: 100dvh;
  padding: var(--e-6);
  overflow: auto;
}

.tese {
  min-width: 0;
}

.tese__titulo {
  margin: 0 0 var(--e-5);
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-titulo);
  font-size: var(--t-8);
  font-weight: var(--peso-display);
  line-height: var(--lh-apertada);
  letter-spacing: 0.01em;
  color: var(--cal);
}

/* O talão aqui não tem margem na calha nem botão de copiar: é uma amostra. */
.tese__talao { margin: 0; }
.tese__talao .talao__copiar { display: none; }

.tese__texto {
  margin: var(--e-5) 0 0;
  font-size: var(--t-4);
  line-height: var(--lh-base);
  color: var(--cal-2);
}

.tese__ficha {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-3);
  margin: var(--e-4) 0 0;
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-2);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--aco);
}

.tese__ficha > span + span::before {
  content: "·";
  margin-right: var(--e-3);
}

/* Numa janela estreita a tese passa para cima da entrada, e o talão sai: uma
   amostra de SQL a rolar na horizontal num telemóvel não prova nada a
   ninguém. */
/* O par mede 34rem + 24rem + a goteira, ou seja perto de 62rem com o
   preenchimento. O salto tem de ficar ACIMA disso, senão há uma faixa de
   larguras em que as duas colunas se espremem antes de empilhar. */
@media (max-width: 64rem) {
  /* `body.` e não só `.`: a regra de cima é `body.pagina-entrar`, que é mais
     específica, e uma declaração aqui com menos especificidade perdia mesmo
     estando dentro do media query — a página nunca empilhava. */
  body.pagina-entrar {
    /* Faixa com tecto e não `1fr`, pela mesma razão da regra larga: uma faixa
       `1fr` ocupa a largura toda e o `justify-content` fica sem folga para
       centrar — a coluna empilhada encostava à esquerda. */
    grid-template-columns: minmax(0, 26rem);
    justify-items: center;
    align-content: center;
    gap: var(--e-5);
  }

  .tese {
    justify-self: center;
    max-width: 26rem;
  }

  .tese__titulo { font-size: var(--t-7); }
  .tese__talao,
  .tese__ficha { display: none; }
}


.cartao {
  width: min(24rem, 100%);
  display: flex;
  flex-direction: column;
  gap: var(--e-5);
  padding: var(--e-5);
  background: var(--betao-2);
  border: 1px solid var(--betao-3);
  border-radius: var(--raio);
  box-shadow: var(--sombra);
}

.cartao__marca {
  display: flex;
  align-items: center;
  gap: var(--e-3);
}

.cartao__marca h1 {
  margin: 0;
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-titulo);
  font-size: var(--t-7);
  letter-spacing: 0.06em;
}

.cartao__nota {
  margin: 2px 0 0;
  font-size: var(--t-3);
  color: var(--cal-2);
}

.cartao form {
  display: flex;
  flex-direction: column;
  gap: var(--e-4);
}

.erro-entrada {
  margin: 0;
  padding: var(--e-2) var(--e-3);
  font-size: var(--t-4);
  color: var(--falha);
  background: var(--falha-fundo);
  border-left: 2px solid var(--falha);
  border-radius: var(--raio);
}

.erro-entrada[hidden] {
  display: none;
}

/* --- Sessão expirada ------------------------------------------------------ */
.faixa-sessao {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--e-3);
  padding: var(--e-3) var(--e-5);
  font-size: var(--t-4);
  color: var(--aviso);
  background: var(--aviso-fundo);
  border-bottom: 1px solid var(--aviso);
}

.faixa-sessao[hidden] {
  display: none;
}

/* --- Mudança obrigatória de palavra-passe --------------------------------- */
.painel-mudanca {
  margin: 0 auto;
  width: min(26rem, calc(100% - 48px));
  padding: var(--e-5);
  background: var(--betao-2);
  border: 1px solid var(--aviso);
  border-radius: var(--raio);
}

.painel-mudanca[hidden] {
  display: none;
}

.painel-mudanca h2 {
  margin: 0 0 var(--e-2);
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-titulo);
  font-size: var(--t-6);
  letter-spacing: 0.05em;
}

.painel-mudanca > p {
  margin: 0 0 var(--e-4);
  font-size: var(--t-4);
  color: var(--cal-2);
}

.painel-mudanca form {
  display: flex;
  flex-direction: column;
  gap: var(--e-3);
}

/* --- Gestão de utilizadores ----------------------------------------------- */
/* O `grid-template-rows` que aqui estava deixou de fazer nada quando o corpo
   passou a coluna flexível. Quem estica agora é a área, e é ela que rola. */
.gestao {
  flex: 1;
  min-height: 0;
  width: 100%;
  max-width: var(--largura-gestao);
  margin: 0 auto;
  padding: var(--e-5);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: var(--e-5);
}

.gestao__seccao h2 {
  margin: 0 0 var(--e-3);
  font-family: var(--fonte-display);
  font-stretch: var(--wdth-etiqueta);
  font-size: var(--t-5);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--cal-2);
}

.gestao__nota {
  margin: var(--e-3) 0 0;
  font-size: var(--t-3);
  color: var(--cal-2);
  max-width: 46rem;
}

.form-linha {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-3);
  align-items: flex-end;
}

.form-linha .campo {
  min-width: 12rem;
  flex: 1 1 12rem;
}

/* A tabela rola dentro da sua caixa; a página nunca rola na horizontal. */
.tabela-envolvente {
  overflow-x: auto;
  border: 1px solid var(--betao-3);
  border-radius: var(--raio);
}

/* Só o que é próprio das contas — o resto vem da .tabela-base. */
.tabela-utilizadores td { white-space: nowrap; }

/* Datas e nomes de utilizador com algarismos de largura fixa: uma coluna de
   "último acesso" que não alinha não se lê de cima a baixo. */
.tabela-utilizadores .mono {
  font-variant-numeric: tabular-nums;
  font-family: var(--fonte-dados);
}

.tabela-utilizadores tr.inativo td {
  opacity: 0.5;
}

.tabela-utilizadores .acoes {
  display: flex;
  gap: var(--e-2);
  flex-wrap: wrap;
}

/* --- Botões de role ------------------------------------------------------- */
/* Alternam: com a role, preenchidos; sem ela, contornados. É o estado que
   distingue, e o "+"/"−" diz o que o clique vai fazer. */
.role-botao {
  font-family: var(--fonte-dados);
  font-size: var(--t-2);
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.role-botao--tem {
  background: var(--verdete-fundo);
  border-color: var(--verdete);
  color: var(--verdete);
}

.role-botao:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* --- Registo de autorização ----------------------------------------------- */
.auditoria__nota {
  margin: 0 0 var(--e-4);
  color: var(--cal-2);
  font-size: var(--t-4);
  max-width: 62ch;
}

.auditoria {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1px;
  background: var(--betao-3);
  border: 1px solid var(--betao-3);
  border-radius: var(--raio);
  overflow: hidden;
}

.auditoria__item {
  display: grid;
  grid-template-columns: 8.5rem 1fr;
  gap: var(--e-3);
  align-items: baseline;
  padding: var(--e-2) var(--e-3);
  background: var(--betao-2);
  font-size: var(--t-4);
}

.auditoria__quando {
  font-variant-numeric: tabular-nums;
  font-family: var(--fonte-dados);
  font-size: var(--t-2);
  color: var(--cal-2);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.auditoria__texto strong {
  color: var(--cal);
  font-weight: var(--peso-forte);
}

/* Uma alteração de role mexe no que toda a gente com ela pode fazer; uma
   atribuição mexe numa conta só. A faixa diz qual é qual sem ninguém ler. */
.auditoria__item--role_alterada,
.auditoria__item--role_criada {
  box-shadow: inset 2px 0 0 var(--limite);
}

.auditoria__item--utilizador_roles_alteradas {
  box-shadow: inset 2px 0 0 var(--verdete);
}

.auditoria__vazio {
  margin: var(--e-3) 0 0;
  color: var(--cal-2);
  font-size: var(--t-4);
}

@media (max-width: 40rem) {
  .auditoria__item {
    grid-template-columns: 1fr;
    gap: var(--e-1);
  }
}

/* --- Matriz RBAC ---------------------------------------------------------- */
.permissoes__titulo {
  display: flex;
  justify-content: space-between;
  gap: var(--e-5);
  align-items: flex-start;
  margin-bottom: var(--e-4);
}

.permissoes__sobretitulo {
  margin: 0 0 var(--e-1);
  color: var(--aco);
  font-family: var(--fonte-dados);
  font-size: var(--t-1);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.permissoes__selo {
  padding: var(--e-2) var(--e-2);
  border: 1px solid var(--limite);
  color: var(--limite);
  font-family: var(--fonte-dados);
  font-size: var(--t-1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

.permissoes__layout {
  display: grid;
  grid-template-columns: minmax(190px, 0.3fr) minmax(0, 1fr);
  gap: var(--e-4);
  align-items: start;
}

.role-navegacao,
.role-editor {
  border: 1px solid var(--betao-3);
  background: var(--betao-2);
  border-radius: var(--raio);
}

.role-navegacao {
  padding: var(--e-3);
  display: flex;
  flex-direction: column;
  gap: var(--e-5);
}

.role-nova {
  border-top: 1px solid var(--betao-3);
  padding-top: var(--e-4);
}

.role-nova .campo__etiqueta {
  display: block;
  margin-bottom: var(--e-2);
}

.role-nova__form {
  display: flex;
  flex-direction: column;
  gap: var(--e-2);
}

.role-editor {
  min-width: 0;
  padding: var(--e-4);
}

.role-editor__cabecalho {
  display: flex;
  flex-wrap: wrap;
  gap: var(--e-3);
  align-items: flex-end;
  margin-bottom: var(--e-4);
}

.role-editor__cabecalho .campo {
  min-width: 12rem;
  flex: 1 1 12rem;
}

.role-editor__cabecalho .role-editor__descricao {
  flex-basis: 18rem;
}

.interruptor {
  display: inline-flex;
  align-items: center;
  gap: var(--e-2);
  min-height: 34px;
  color: var(--cal-2);
  font-family: var(--fonte-dados);
  font-size: var(--t-2);
  text-transform: uppercase;
}

.interruptor input,
.matriz__controlo input {
  accent-color: var(--verdete);
}

.matriz-envolvente {
  overflow-x: auto;
  border: 1px solid var(--betao-3);
  border-radius: var(--raio);
}

/* Só o que é próprio da matriz — o resto vem da .tabela-base.
   Uma matriz de 34 permissions lê-se por cruzamento e não por linha, por isso
   as células vão ao centro e não à esquerda. */
.matriz__tabela {
  min-width: 560px;
  font-family: var(--fonte-dados);
}

.matriz__tabela th,
.matriz__tabela td {
  text-align: center;
}

.matriz__tabela tbody th {
  width: 34%;
  text-align: left;
  color: var(--cal);
  font-family: var(--fonte-dados);
  font-size: var(--t-3);
  letter-spacing: 0;
  text-transform: none;
  border-bottom: 1px solid color-mix(in srgb, var(--betao-3) 55%, transparent);
}

.matriz__tabela thead th { font-size: var(--t-1); }

.matriz__tabela tbody tr:last-child th { border-bottom: none; }

.matriz__controlo {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  min-height: 26px;
  cursor: pointer;
}

.matriz__controlo:focus-within {
  outline: 2px solid var(--sinal);
  outline-offset: 2px;
}

.matriz__vazio {
  color: var(--aco);
}

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

.permissoes__estado {
  min-height: 18px;
  margin: 0;
  color: var(--cal-2);
  font-family: var(--fonte-dados);
  font-size: var(--t-3);
}

.visualmente-oculto {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

@media (max-width: 40rem) {
  /* O cabeçalho passou a ter mais três elementos com a autenticação. */
  .cabecalho__controlos {
    flex-wrap: wrap;
    gap: var(--e-2);
  }

  .cabecalho__utilizador {
    max-width: 100%;
  }

  .gestao {
    padding: var(--e-4);
  }

  .permissoes__titulo,
  .role-editor__rodape {
    align-items: stretch;
    flex-direction: column;
  }

  .permissoes__layout {
    grid-template-columns: 1fr;
  }
}
