/* ===== Design tokens — extraídos do Brandbook (aquastatus-brandbook.html) ===== */
:root{
  --bg:#FAFCFD;
  --panel:#F2F6F9;
  --panel-strong:#E8F1F8;
  --ink:#101B26;
  --ink-2:#4A5C6B;
  --ink-3:#8296A6;
  --line:#D7E2EA;
  --line-strong:#B9CBD8;
  --signal:#1768AC;
  --signal-ink:#0B2338;
  --flow:#4A90C4;

  --ok:#1C9C79;       --ok-bg:#E3F5EE;
  --warn:#B8842A;     --warn-bg:#FBF1DE;
  --crit:#C1442E;     --crit-bg:#FBE7E3;
  --unk:#6B7E8D;      --unk-bg:#EEF1F3;

  --sw-mist:#E8F1F8;
  --sw-paper:#FAFCFD;

  --font-display:'Space Grotesk', 'Segoe UI', Arial, sans-serif;
  --font-body:'IBM Plex Sans', 'Segoe UI', Arial, sans-serif;
  --font-mono:'IBM Plex Mono', 'SFMono-Regular', Consolas, monospace;

  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-5:24px;
  --sp-6:32px; --sp-7:48px; --sp-8:64px; --sp-9:96px;
}

@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --bg:#0A1F33;
    --panel:#0E2A45;
    --panel-strong:#123253;
    --ink:#DFEBF6;
    --ink-2:#A9C4DB;
    --ink-3:#6E8CA6;
    --line:#234863;
    --line-strong:#31597A;
    --signal:#6FB5E8;
    --signal-ink:#DFEBF6;
    --flow:#4FA3D9;

    --ok:#3FD9A9;       --ok-bg:rgba(63,217,169,0.12);
    --warn:#F0C066;     --warn-bg:rgba(240,192,102,0.12);
    --crit:#F0796A;     --crit-bg:rgba(240,121,106,0.13);
    --unk:#93A9BD;      --unk-bg:rgba(147,169,189,0.12);
  }
}

*{box-sizing:border-box;}
html,body{height:100%;}
body{
  margin:0;
  background:var(--bg);
  color:var(--ink);
  font-family:var(--font-body);
  font-size:16px;
  line-height:1.6;
}
h1,h2{font-family:var(--font-display); font-weight:600; margin:0; letter-spacing:-0.01em;}
h3{font-family:var(--font-body); font-weight:600; font-size:1.15rem; margin:0;}
p{margin:0 0 var(--sp-4);}
a{color:var(--signal); text-decoration:none;}
a:hover{text-decoration:underline;}
button{font-family:inherit;}

/* ===== Layout de página ===== */
.page-header{
  display:flex; align-items:center; justify-content:space-between; gap:var(--sp-4);
  margin-bottom:var(--sp-6);
  /* Revisão mobile 2026-10-02: título/texto + botão passam para linhas separadas em vez de
     se espremerem ou empurrarem o botão para fora do ecrã. */
  flex-wrap:wrap;
}
.page-header > h2, .page-header > p{min-width:0; overflow-wrap:anywhere;}

/* ===== Botões ===== */
.btn{
  font-family:var(--font-body); font-weight:600; font-size:0.95rem;
  padding:var(--sp-3) var(--sp-5); border:1px solid transparent; border-radius:2px;
  cursor:pointer; display:inline-flex; align-items:center; gap:var(--sp-2);
  transition:opacity .15s ease;
}
.btn:disabled{opacity:0.6; cursor:not-allowed;}
.btn-primary{background:var(--signal); color:#fff;}
.btn-primary:hover{opacity:0.9;}
.btn-ghost{background:transparent; color:var(--ink); border-color:var(--line-strong);}
.btn-ghost:hover{background:var(--panel);}
.btn-link{background:none; border:none; color:var(--signal); padding:0; font-weight:500;}

/* Em mobile, botões "Adicionar X"/"Editar" mostram só um ícone (+ / lápis) em vez do texto —
   poupa espaço em cabeçalhos e cartões estreitos sem perder a ação. */
.btn-icone{display:none;}
@media (max-width:480px){
  .btn-texto{display:none;}
  .btn-icone{display:inline;}
  /* Sem texto, o padding horizontal generoso (var(--sp-5), pensado para rótulos) sobra à volta
     de um único carácter — encolhe para um botão quadrado compacto, importante nas tabelas onde
     vários destes botões ficam lado a lado num espaço estreito. */
  .btn:has(.btn-icone){padding-left:var(--sp-3); padding-right:var(--sp-3);}
}
/* Ações destrutivas (ex. apagar utilizador) — reutiliza a cor --crit já usada em .badge.crit,
   nunca uma cor nova (o brandbook exige que a mesma cor signifique sempre a mesma coisa). */
.btn-danger{background:var(--crit); color:#fff;}
.btn-danger:hover{opacity:0.9;}

/* ===== Inputs ===== */
.field{margin-bottom:var(--sp-4);}
.field label{display:block; font-size:0.85rem; font-weight:600; color:var(--ink-2); margin-bottom:var(--sp-2);}
.field input, .field select{
  width:100%; padding:var(--sp-3); font-size:1rem; font-family:var(--font-body);
  border:1px solid var(--line-strong); border-radius:2px; background:var(--bg); color:var(--ink);
}
.field input:focus, .field select:focus{outline:2px solid var(--signal); outline-offset:1px;}
.field-error{color:var(--crit); font-size:0.82rem; margin-top:var(--sp-2);}
.field-hint{font-size:0.78rem; font-weight:400; color:var(--ink-3); margin-left:var(--sp-2);}
.field-value{margin:0; font-size:0.95rem; color:var(--ink);}

/* Lista de checkboxes (ex. perfis do utilizador) — dentro de .field, mas cada linha não é o
   <label> de campo único que .field label espera (bold, block); .field .checkbox-row (2 classes)
   tem mais especificidade do que .field label (classe+elemento) e ganha por isso. */
.checkbox-list{display:flex; flex-direction:column; gap:var(--sp-2);}

/* Variante para dentro de <Virtualize> (ex. checklists de utilizadores/clientes nos modais de
   associação) — bloco simples com scroll próprio, nunca flex: os espaçadores que o Virtualize
   insere antes/depois do intervalo visível são <div>s com altura fixa, e um pai flex-column não
   os respeita da mesma forma que um bloco normal (o scroll ficava errado/instável). Espaçamento
   entre linhas por margin-bottom em vez de gap, pelo mesmo motivo. */
.checkbox-list-virtualizada{max-height:280px; overflow-y:auto;}
.checkbox-list-virtualizada .checkbox-row{margin-bottom:var(--sp-2);}

.field .checkbox-row{
  display:flex; align-items:center; gap:var(--sp-2); font-size:0.9rem; font-weight:400;
  color:var(--ink); margin-bottom:0; cursor:pointer;
}
.field .checkbox-row input[type=checkbox]{width:auto; flex-shrink:0;}

/* Honeypot anti-bot — fora do ecrã, não display:none/visibility:hidden
   (alguns bots já ignoram esses dois de propósito); tabindex="-1" e aria-hidden garantem que um
   humano nunca lhe chega por Tab nem um leitor de ecrã o anuncia. */
.hp-field{position:absolute; left:-9999px; top:-9999px; width:1px; height:1px; overflow:hidden;}

.subform{
  border-top:1px solid var(--line); border-bottom:1px solid var(--line);
  padding:var(--sp-4) 0; margin-bottom:var(--sp-4);
}
.subform h4{
  font-family:var(--font-mono); font-weight:500; font-size:0.78rem; color:var(--ink-3);
  margin:0 0 var(--sp-4);
}

/* ===== Toggle (switch) — para características booleanas ===== */
.toggle-row{
  display:flex; align-items:center; justify-content:space-between; gap:var(--sp-4);
  padding:var(--sp-2) 0;
}
.toggle-row label{font-size:0.9rem; color:var(--ink); font-weight:500;}
.toggle{
  position:relative; display:inline-block; width:40px; height:22px; flex-shrink:0;
}
.toggle input{position:absolute; opacity:0; width:100%; height:100%; margin:0; cursor:pointer; z-index:1;}
.toggle .track{
  position:absolute; inset:0; background:var(--line-strong);
  transition:background .15s ease; pointer-events:none;
}
.toggle .thumb{
  position:absolute; top:2px; left:2px; width:18px; height:18px;
  background:var(--bg); border:1px solid var(--line-strong);
  transition:transform .15s ease; pointer-events:none;
}
.toggle input:checked ~ .track{background:var(--signal);}
.toggle input:checked ~ .thumb{transform:translateX(18px);}
.toggle input:focus-visible ~ .track{outline:2px solid var(--signal); outline-offset:2px;}
.toggle input:disabled{cursor:not-allowed;}
.toggle:has(input:disabled){opacity:0.45;}

/* ===== Badges de estado ===== */
.badge{display:inline-flex; align-items:center; gap:6px; font-family:var(--font-mono); font-size:0.74rem; padding:3px 8px; border-radius:2px;}
.badge i{width:6px;height:6px;border-radius:50%;display:inline-block;}
.badge.ok{background:var(--ok-bg); color:var(--ok);} .badge.ok i{background:var(--ok);}
.badge.warn{background:var(--warn-bg); color:var(--warn);} .badge.warn i{background:var(--warn);}
.badge.crit{background:var(--crit-bg); color:var(--crit);} .badge.crit i{background:var(--crit);}
.badge.unk{background:var(--unk-bg); color:var(--unk);} .badge.unk i{background:var(--unk);}

/* ===== Spinner (ex. mapa do Dashboard a carregar) ===== */
.spinner{
  width:32px; height:32px; border:3px solid var(--line); border-top-color:var(--signal);
  border-radius:50%; animation:spinner-rodar 0.8s linear infinite;
}
@keyframes spinner-rodar{ to{ transform:rotate(360deg); } }

/* Substitui o "A carregar..." simples de texto em qualquer página/secção que espere dados da Api
   (ver LoadingIndicator.razor) — mesmo espírito do spinner do mapa do Dashboard, generalizado. */
.loading-indicator{
  display:flex; align-items:center; gap:var(--sp-3); color:var(--ink-3); padding:var(--sp-5) 0;
}

/* ===== KPI ===== */
.kpi{border:1px solid var(--line); padding:var(--sp-4); background:var(--panel); position:relative;}
.kpi .label{font-family:var(--font-mono); font-size:0.74rem; color:var(--ink-3); margin-bottom:var(--sp-3);}
.kpi .num{font-family:var(--font-mono); font-size:1.9rem; color:var(--ink); font-weight:500;}

/* ===== Grelha de cartões — entidade genérica (ex. Utilizadores.razor) =====
   Mesma linguagem visual do .cliente-card do Dashboard (plano, sem sombra), mas partilhada em
   app.css em vez de escopada a uma página — já usada por duas páginas independentes. */
.cards-grid{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(min(280px, 100%), 1fr)); gap:var(--sp-5);
  align-items:start;
}
.entity-card{border:1px solid var(--line); background:var(--panel); padding:var(--sp-5); cursor:pointer;}
.entity-card:hover{border-color:var(--line-strong);}
.entity-card-header{
  display:flex; align-items:center; justify-content:space-between; gap:var(--sp-3);
  margin-bottom:var(--sp-4);
}
.entity-card-title{font-weight:600; font-size:1rem; color:var(--ink);}
.entity-card-row{
  display:flex; justify-content:space-between; gap:var(--sp-3); font-size:0.85rem;
  padding:var(--sp-1) 0; color:var(--ink-2);
}
.entity-card-row .label{color:var(--ink-3); flex-shrink:0;}
/* Valores longos (ex. email) quebram em vez de empurrarem o cartão para fora do ecrã. */
.entity-card-row > :not(.label){min-width:0; overflow-wrap:anywhere; text-align:right;}
.entity-card-title{min-width:0; overflow-wrap:anywhere;}

/* ===== Tabela ===== */
/* flex-shrink:0 — sem isto, dentro de um contentor flex em coluna (`.db-main`, `.modal-scroll`)
   este elemento fica com tamanho mínimo automático 0 em vez do tamanho do conteúdo: por regra do
   CSS2.1, se um eixo de overflow não é 'visible' (aqui, overflow-x:auto), o outro eixo
   (overflow-y, mesmo sem o definir) é computado como 'auto' na mesma — e um "scroll container"
   dentro de flex tem tamanho mínimo automático 0, não o tamanho do conteúdo. Resultado: a tabela
   ficava espremida a 0px de altura e ganhava scroll interno próprio mesmo cabendo perfeitamente
   na página (só punha `overflow-y:visible` aqui não chega — o UA ignora-o pela regra acima).
   `flex-shrink:0` corta o problema pela base: nunca encolhe abaixo do tamanho natural do
   conteúdo, deixando o scroll acontecer no nível certo (a página, ou `.modal-scroll` dentro de um
   modal) — overflow-x:auto continua a funcionar para ecrãs estreitos. */
.tbl-wrap{overflow-x:auto; border:1px solid var(--line); flex-shrink:0;}
table{width:100%; border-collapse:collapse; min-width:560px; font-size:0.88rem;}
thead th{text-align:left; font-family:var(--font-mono); font-weight:500; font-size:0.72rem; color:var(--ink-3); padding:var(--sp-3) var(--sp-4); border-bottom:1px solid var(--line-strong); background:var(--panel);}
tbody td{padding:var(--sp-3) var(--sp-4); border-bottom:1px solid var(--line); color:var(--ink-2);}
tbody tr:last-child td{border-bottom:none;}
.mono, td.mono, th.num{font-family:var(--font-mono);}
td.num{font-family:var(--font-mono); text-align:right; color:var(--ink);}
tr.clickable-row{cursor:pointer;}
tr.clickable-row:hover td{background:var(--panel);}

/* ===== Modal ===== */
.modal-backdrop{
  position:fixed; inset:0; background:rgba(11,35,56,0.55); backdrop-filter:blur(2px);
  display:flex; align-items:center; justify-content:center; z-index:100; padding:var(--sp-4);
}
.modal-box{
  background:var(--bg); border:1px solid var(--line); max-width:400px; width:100%;
  padding:var(--sp-6); position:relative;
}
/* Passo de confirmação (com tabela de alterações) — mais largo para não espremer a tabela,
   ajusta-se ao conteúdo dentro deste limite em vez do tamanho fixo do formulário. */
.modal-box.modal-box-confirm{max-width:700px;}
.modal-close{
  position:absolute; top:var(--sp-4); right:var(--sp-4); background:none; border:none;
  font-size:1.4rem; line-height:1; color:var(--ink-3); cursor:pointer; z-index:1;
}
.modal-box h2{font-size:1.4rem; margin-bottom:var(--sp-5);}

/* Modal com muitos campos (ex. EditarClienteModal) — a caixa em si nunca passa da altura do
   ecrã (mesma margem vertical que o .modal-backdrop já reserva com o seu padding); o conteúdo
   é que ganha scroll interno em vez de a caixa crescer para fora do ecrã. Scrollbar escondida
   visualmente (3 propriedades, uma por motor de browser) — só a função de scroll importa, não
   o indicador visual. */
.modal-box-scroll{
  max-height:calc(100vh - 2 * var(--sp-4)); padding:0; display:flex; flex-direction:column;
}
.modal-box-scroll > .modal-scroll{
  overflow-y:auto; overflow-x:hidden; padding:var(--sp-6);
  scrollbar-width:none; -ms-overflow-style:none;
}
.modal-box-scroll > .modal-scroll::-webkit-scrollbar{display:none;}

/* Tabela de confirmação dos modais ("Campo"/"De"/"Para", "Campo"/"Valor", ou só "De"/"Para" —
   ver EditarClienteModal.razor e afins) — em mobile, em vez de ficar com scroll lateral (a
   tabela global tem min-width:560px), cada linha passa a empilhar-se na vertical, uma "mini
   ficha" por campo alterado. Pedido explícito do utilizador. Aplica-se a qualquer
   `.tbl-wrap table` dentro de um modal, só pela posição das colunas — nenhum dos ~19 modais que
   usam este padrão precisa de ser tocado (a 1ª coluna fica como título da linha, sem rótulo
   "Campo:" que seria redundante; a 2ª rotula-se "De" quando há uma 3ª coluna a seguir, ou
   "Valor" quando é a última; a 3ª, quando existe, rotula-se "Para"). */
@media (max-width:480px){
  .modal-box .tbl-wrap{overflow-x:visible;}
  .modal-box .tbl-wrap table{min-width:0;}
  .modal-box .tbl-wrap thead{display:none;}
  .modal-box .tbl-wrap table, .modal-box .tbl-wrap tbody,
  .modal-box .tbl-wrap tr, .modal-box .tbl-wrap td{
    display:block; width:100%;
  }
  .modal-box .tbl-wrap tr{
    border:1px solid var(--line); padding:var(--sp-3); margin-bottom:var(--sp-3);
  }
  .modal-box .tbl-wrap tr:last-child{margin-bottom:0;}
  .modal-box .tbl-wrap td{padding:var(--sp-1) 0; border:none;}
  .modal-box .tbl-wrap td:first-child{
    font-family:var(--font-mono); font-size:0.78rem; font-weight:600; color:var(--ink);
    padding-bottom:var(--sp-2);
  }
  .modal-box .tbl-wrap td:nth-child(2)::before{content:"De: "; font-weight:600; color:var(--ink-3);}
  .modal-box .tbl-wrap td:nth-child(2):last-child::before{content:"Valor: ";}
  .modal-box .tbl-wrap td:nth-child(3)::before{content:"Para: "; font-weight:600; color:var(--ink-3);}

  /* Exceção: tabelas de confirmação só "De"/"Para" sem coluna "Campo" (ex.
     EditarAlertaValidadeDominiosModal/GerirUtilizadoresClienteModal — um único campo implícito,
     já descrito no texto acima da tabela) — aqui a 1ª coluna é já um valor "De", não um título de
     linha, por isso também leva rótulo em vez do estilo de título. */
  .modal-box .tbl-wrap table.tbl-de-para td:first-child{
    font-family:var(--font-body); font-size:0.9rem; font-weight:400; color:var(--ink);
    padding-bottom:var(--sp-1);
  }
  .modal-box .tbl-wrap table.tbl-de-para td:first-child::before{content:"De: "; font-weight:600; color:var(--ink-3);}
  .modal-box .tbl-wrap table.tbl-de-para td:nth-child(2):last-child::before{content:"Para: ";}
}

/* Secção "Acesso Wavecom" encolhível — o cabeçalho é um botão (toda a área clicável), não só
   uma seta pequena, para não obrigar a acertar num alvo minúsculo. */
.subform-header{
  display:flex; align-items:center; justify-content:space-between; width:100%;
  background:none; border:none; padding:0; margin:0 0 var(--sp-4); cursor:pointer;
  font-family:var(--font-mono); font-weight:500; font-size:0.78rem; color:var(--ink-3);
}
.subform-header .chevron{
  display:inline-block; transition:transform 0.15s ease; font-size:0.9rem;
}
.subform-header .chevron.aberto{transform:rotate(90deg);}

/* Separadores (ex. EditarPerfilModal — "Nome"/"Password") — mutuamente exclusivos, ao contrário
   do .subform-header acima (que só encolhe/expande, nunca troca de conteúdo). */
.tabs{
  display:flex; border-bottom:1px solid var(--line); margin-bottom:var(--sp-5); gap:var(--sp-2);
  /* Separadores nunca quebram nem empurram a página: se não couberem (ex. 4 separadores em
     375px), a própria barra faz scroll lateral. */
  overflow-x:auto; scrollbar-width:none; -ms-overflow-style:none;
}
.tabs::-webkit-scrollbar{display:none;}
.tab-btn{
  background:none; border:none; padding:var(--sp-3) var(--sp-4); cursor:pointer;
  font-family:var(--font-body); font-weight:600; font-size:0.9rem; color:var(--ink-3);
  border-bottom:2px solid transparent; margin-bottom:-1px;
}
.tab-btn{white-space:nowrap; flex:0 0 auto;}
.tab-btn.ativo{color:var(--ink); border-bottom-color:var(--signal);}
.tab-btn:hover{color:var(--ink);}

/* Blazor error UI */
#blazor-error-ui{
  background:var(--crit-bg); color:var(--crit); position:fixed; bottom:0; left:0; right:0;
  padding:var(--sp-4) var(--sp-6); display:none; font-size:0.9rem;
}
#blazor-error-ui .dismiss{cursor:pointer; float:right; font-weight:600;}

/* Erros inesperados — mensagem genérica + referência */
.erro-referencia{display:block; margin-top:var(--sp-2); font-size:0.85rem;}
.erro-pagina{
  max-width:34rem; margin:var(--sp-8) auto; padding:var(--sp-6); text-align:center;
  background:var(--crit-bg); color:var(--ink); border-radius:var(--radius, 8px);
}
.erro-pagina h2{color:var(--crit); margin-top:0;}
.aviso-erro-api{
  display:flex; align-items:flex-start; justify-content:space-between; gap:var(--sp-4);
  background:var(--crit-bg); color:var(--crit); padding:var(--sp-3) var(--sp-6); font-size:0.9rem;
}
.aviso-erro-api .dismiss{background:none; border:0; color:inherit; cursor:pointer; font-weight:600;}

/* ===== Revisão mobile (2026-10-02) ===== */

/* Tabelas "normais" (fora de modais) que em mobile passam a lista de mini-fichas — mesmo princípio
   da tabela de confirmação dos modais (ver acima), mas com o rótulo de cada campo vindo do
   atributo data-label da célula (a tabela de confirmação usa rótulos fixos por posição). Uso:
   <table class="tbl-cartoes"> + <td data-label="Nome">. Células sem data-label (ex. coluna de
   ações, class="acoes") ficam sem rótulo, alinhadas à direita. */
@media (max-width:480px){
  .tbl-wrap:has(> table.tbl-cartoes){overflow-x:visible; border:none;}
  table.tbl-cartoes{min-width:0;}
  table.tbl-cartoes thead{display:none;}
  table.tbl-cartoes, table.tbl-cartoes tbody, table.tbl-cartoes tr, table.tbl-cartoes td{
    display:block; width:100%;
  }
  table.tbl-cartoes tr{
    border:1px solid var(--line); background:var(--panel);
    padding:var(--sp-3); margin-bottom:var(--sp-3);
  }
  table.tbl-cartoes tbody tr:last-child{margin-bottom:0;}
  table.tbl-cartoes td{
    display:flex; align-items:baseline; gap:var(--sp-3);
    padding:var(--sp-1) 0; border:none; overflow-wrap:anywhere; text-align:left;
  }
  table.tbl-cartoes td > *{min-width:0;}
  table.tbl-cartoes td[data-label]::before{
    content:attr(data-label); flex:0 0 6.5rem;
    font-family:var(--font-mono); font-size:0.72rem; color:var(--ink-3);
  }
  table.tbl-cartoes td.acoes{justify-content:flex-end; padding-top:var(--sp-2);}
  table.tbl-cartoes td pre{overflow-wrap:anywhere; max-width:100%; overflow-x:auto;}

  /* Alvo de toque do "×" dos modais: 1.4rem era bem menos do que os ~44px recomendados. */
  .modal-box h2{padding-right:1.5rem;}
  .modal-close{
    top:var(--sp-2); right:var(--sp-2); width:44px; height:44px;
    display:flex; align-items:center; justify-content:center;
  }
}
