/* ===== modais, definições e assistente =====
   O que vive dentro dos modais: editar dispositivo, o painel de definições e o assistente de
   adicionar. Com eles ficam as peças que lhes cresceram ao lado -- o medidor de sinal, a
   tira da fralda, o menu de notificações e a pastilha de estado de um bloco.

   É o último `<link>` da página e não o primeiro: `/main.css` é uma rota fixa do servidor e
   há testes que lêem este ficheiro pelo nome, por isso ficou com a cauda da folha original
   em vez de mudar de nome. O resto está em `assets/css/`, carregado antes deste. */

/* A chapa onde a fotografia do produto assenta.
   As fotografias dos modelos vêm com o fundo branco lá dentro, e por isso no tema escuro
   apareciam como um rectângulo branco a flutuar sobre a superfície escura -- que se lê como
   um erro e não como uma fotografia. A chapa é clara nos dois temas de propósito: assim o
   branco da imagem encosta a um branco que ali devia estar, e o que se vê é uma fotografia
   numa moldura. Não é `bg-body-tertiary` porque essa vira com o tema, que é exactamente o
   que aqui não pode acontecer. */
.showcase-preview {
    min-height: 280px;
    background-color: #fff;
}

/* No escuro a chapa não muda de cor -- baixa de brilho com a fotografia em cima dela. Os dois
   descem juntos, e por isso o rebordo branco da imagem continua a não se ver; o que muda é
   deixar de ser um farol no meio de uma página escura. Uma chapa acinzentada em vez desta
   fazia reaparecer o rectângulo, que é o que se queria tirar. */
[data-bs-theme="dark"] .showcase-preview {
    filter: brightness(.84);
}

.showcase-preview img {
    max-width: 100%;
    max-height: 260px;
}

/* A identidade do que se esta a editar, no cabecalho do modal. */
.modal-device-identity {
    display: flex;
    align-items: center;
    gap: .75rem;
    min-width: 0;
    flex: 1;
}

.modal-device-thumb {
    width: 40px;
    height: 40px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: .625rem;
    background: var(--bs-tertiary-bg);
}

.modal-device-thumb img,
.modal-device-thumb i {
    max-width: 26px;
    max-height: 26px;
}


.selected-device-preview {
    width: 72px;
    height: 72px;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 1rem;
    background: var(--bs-tertiary-bg);
    flex-shrink: 0;
}

.selected-device-preview img {
    max-width: 56px;
    max-height: 56px;
}

.gateway-picker {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
    gap: .5rem;
    max-height: 18rem;
    overflow-y: auto;
}

/* A mesma lista vazia de gateways aparece no assistente e no modal de edição, e estava
   escrita de duas maneiras: uma preta e normal, a outra cinzenta e pequena. O aspecto passa
   a viver aqui, e os dois sítios escrevem só a classe. */
.gateway-picker-empty {
    grid-column: 1 / -1;
    margin-bottom: 0;
    color: var(--bs-secondary-color);
    font-size: .875em;
}

.gateway-card {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin: 0;
    padding: .5rem .75rem;
    border: 1px solid var(--bs-border-color);
    border-radius: .75rem;
    background: var(--bs-body-bg);
    cursor: pointer;
    transition: border-color .15s ease-in-out, background-color .15s ease-in-out;
}

.gateway-card:hover {
    border-color: var(--bs-primary);
}

.gateway-card:has(.gateway-card-check:focus-visible) {
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
}

.gateway-card:has(.gateway-card-check:checked) {
    border-color: var(--bs-primary);
    background: var(--bs-primary-bg-subtle);
}

.gateway-card:has(.gateway-card-check:disabled) {
    cursor: default;
    opacity: .65;
}

.gateway-card-thumb {
    width: 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: .5rem;
    background: var(--bs-tertiary-bg);
    flex-shrink: 0;
    overflow: hidden;
}

/* As fotografias dos modelos já vêm sobre branco; o tom só existe para dar superfície ao
   ícone que aparece quando não há fotografia. */
.gateway-card-thumb:has(img) {
    background: transparent;
}

.gateway-card-thumb img {
    max-width: 44px;
    max-height: 44px;
    object-fit: contain;
    mix-blend-mode: multiply;
}

.gateway-card-thumb-icon {
    width: 24px;
    height: 24px;
    color: var(--bs-secondary-color);
}

.gateway-card-text {
    min-width: 0;
}

.gateway-card-mac {
    display: block;
    font-weight: 600;
    font-size: var(--fs-body);
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.gateway-card-model {
    display: block;
    font-size: var(--fs-sm);
    line-height: 1.3;
    color: var(--bs-secondary-color);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/*
 * A intensidade de sinal em quatro barras crescentes. A contagem de barras cheias diz a
 * leitura tão bem como a cor, para o medidor continuar legível sem percepção de tom, e o
 * dBm exacto vive na tooltip.
 */
.signal-meter {
    display: inline-flex;
    align-items: flex-end;
    gap: 2px;
    height: 1rem;
    flex-shrink: 0;
    cursor: help;
}

.signal-meter-bar {
    width: 3px;
    border-radius: 1px;
    background-color: currentColor;
    opacity: .2;
}

.signal-meter-bar-on {
    opacity: 1;
}

.signal-meter-bar:nth-child(1) { height: 25%; }
.signal-meter-bar:nth-child(2) { height: 50%; }
.signal-meter-bar:nth-child(3) { height: 75%; }
.signal-meter-bar:nth-child(4) { height: 100%; }

/* Os três estados de humidade têm cor própria porque nenhuma das do Bootstrap os diz: seco,
   húmido e molhado é uma escala do domínio, não um `info`/`warning`/`danger`. Ficam em
   tokens e não escritas nas cinco regras que as usam, para o azul da barra e o azul do
   número não poderem passar a dizer coisas diferentes. */
:root {
    --moisture-dry: #cbd5e1;
    --moisture-damp: #93c5fd;
    --moisture-wet: #3b82f6;
    --moisture-damp-text: #1d4ed8;
    --moisture-wet-text: #1e3a8a;
}

/* No escuro a escala inverte-se de direcção mas não de sentido: no claro, mais humidade é
   azul mais carregado; aqui é azul mais aceso. O que se lê continua a ser "quanto mais
   forte, mais molhado", que é o que a barra tem de dizer. O seco deixa de ser um cinzento
   claro e passa a ser um degrau acima do fundo da barra, senão lê-se como cheio. */
[data-bs-theme="dark"] {
    --moisture-dry: #2c3850;
    --moisture-damp: #3b82f6;
    --moisture-wet: #93c5fd;
    --moisture-damp-text: #60a5fa;
    --moisture-wet-text: #93c5fd;
}

.diaper-strip {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: .35rem;
    align-items: end;
}

.diaper-channel {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: .2rem;
    min-width: 0;
}

.diaper-channel-value {
    text-align: center;
    font-size: var(--fs-sm);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    line-height: 1.2;
    color: var(--bs-secondary-color);
}

.diaper-channel-value--damp {
    color: var(--moisture-damp-text);
}

.diaper-channel-value--wet {
    color: var(--moisture-wet-text);
}

.diaper-channel-track {
    position: relative;
    height: 64px;
    border-radius: .35rem;
    background: var(--bs-tertiary-bg);
    display: flex;
    align-items: flex-end;
    overflow: hidden;
}

/* O limiar de "precisa de muda", para se ver quais as barras que o passaram. */
.diaper-channel-track::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: var(--diaper-threshold, 50%);
    border-top: 1px dashed var(--bs-border-color);
    opacity: .9;
    pointer-events: none;
}

/* No min-height: a dry channel reading 0 must paint nothing at all, otherwise
   an empty strip still looks faintly wet. */
.diaper-channel-fill {
    width: 100%;
    border-radius: .35rem .35rem 0 0;
    background: var(--moisture-dry);
    transition: height .2s ease-in-out;
}

.diaper-channel-fill--damp {
    background: var(--moisture-damp);
}

.diaper-channel-fill--wet {
    background: var(--moisture-wet);
}

.diaper-channel-index {
    text-align: center;
    font-size: var(--fs-label);
    line-height: 1.2;
    color: var(--bs-secondary-color);
    font-variant-numeric: tabular-nums;
}

.navbar-brand img {
    height: 30px;
    width: auto;
    display: block;
}

.dashboard-notifications-menu {
    width: min(24rem, calc(100vw - 2rem));
}

.dashboard-notifications-list {
    max-height: min(28rem, calc(100vh - 8rem));
}

/* O encaixe de 1rem é para ecrã largo, onde a moldura separa o modal do que está por trás.
   Num telefone não há "por trás" nenhum que valha 16px de cada lado, e o
   `.modal-fullscreen` do Bootstrap já põe o modal de bordo a bordo -- por isso a regra
   começa em `sm` em vez de existir e ser anulada logo a seguir. */
@media (min-width: 576px) {
    #deviceModal .modal-dialog.modal-fullscreen,
    #settingsModal .modal-dialog.modal-fullscreen {
        margin: 1rem;
        width: calc(100vw - 2rem);
        max-width: none;
        height: calc(100% - 2rem);
    }
}

/* O modal de definições é de ecrã inteiro: é um painel de administração com cinco listas, e
   não um formulário. */
#settingsModal .modal-dialog.modal-fullscreen .modal-content {
    height: 100%;
}

#settingsModal .modal-body {
    display: flex;
    flex-direction: column;
    overflow: auto;
    min-height: 0;
    padding: 0;
}

#settingsModal .modal-body>.settings-modal-shell {
    min-height: 100%;
}

/* O Bootstrap não tem utilitário de altura por breakpoint -- não existe `h-lg-100` --, por
   isso este é um dos poucos sítios onde a marcação não chega. */
@media (max-width: 575.98px) {

    /* O `h-100` das folhas e do conteúdo estica o separador à altura toda do modal de ecrã
       inteiro, e sete fornecedores deixam meio ecrã em branco por baixo da tabela. Em
       telefone cada folha mede o que o seu conteúdo mede. */
    .settings-modal-shell,
    .settings-modal-shell .tab-content,
    .settings-modal-shell .tab-pane {
        height: auto !important;
    }
}

/* A contagem de cada secção no menu das definições. No separador activo o fundo é do próprio
   branco a 20%, para não abrir um terceiro tom dentro do navy. */
.settings-nav-count {
    flex: none;
    min-width: 1.5rem;
    padding: 0 .375rem;
    border-radius: 20px;
    background: var(--bs-tertiary-bg);
    color: var(--bs-secondary-color);
    font-size: var(--fs-label);
    font-weight: 600;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.nav-pills .nav-link.active .settings-nav-count {
    background: rgba(var(--brand-on-rgb), .2);
    color: var(--brand-on);
}

/* Abaixo do ecrã largo, o menu das definições é uma tira que desliza. O `align-items`
   centrado da linha esticava as pills a altura toda da coluna, o que dava um bloco navy
   de 700px em telefone. */
@media (max-width: 991.98px) {
    .settings-modal-shell>.row {
        align-items: flex-start !important;
        height: auto !important;
    }

    /* Sem isto a coluna do menu ocupa a altura toda e as pills esticam com ela: dava um
       bloco de 700px com o nome do separador centrado no meio do nada. */
    .settings-modal-shell>.row>[class*="col-"] {
        height: auto !important;
    }

    .settings-modal-nav {
        align-items: center;
        overflow-x: auto;
        overflow-y: hidden;
        padding-bottom: .375rem;
        border-bottom: 1px solid var(--bs-border-color);
        scrollbar-width: thin;
    }

    .settings-modal-nav .nav-link {
        flex: none;
        white-space: nowrap;
    }
}

.navbar-brand img {
    filter: invert(100%);
}

/* ===== assistente de adicionar dispositivo ===== */

/* A barra mostra os passos com nome, e não uma percentagem: quem está no primeiro tem de
   conseguir ver o que falta. */
/* A trilha das respostas já dadas, e o passo no fim da linha. Cada badge colapsa uma
   pergunta respondida, o que faz o ecrã nunca acumular controlos -- e cada uma é um botão
   para voltar àquela pergunta. */
.wizard-trail {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .4rem;
    min-height: 1.9rem;
    padding-bottom: .875rem;
    border-bottom: 1px solid var(--bs-border-color);
}

/* A etiqueta por cima do valor, e não ao lado: lado a lado, três respostas com nomes
   compridos não cabem na linha e a terceira cai sozinha para baixo. Empilhadas, cada badge
   mede o mais largo dos seus dois textos e as três cabem. */
.wizard-trail .wizard-badge {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: .05rem;
    min-height: 2.5rem;
    font-size: var(--fs-sm);
    font-weight: 500;
    padding: .25rem .7rem;
    border: 1px solid transparent;
    border-radius: .625rem;
    background: var(--bs-primary-bg-subtle);
    color: var(--bs-emphasis-color);
    animation: wizard-badge-in .32s cubic-bezier(.2, .8, .3, 1) both;
    cursor: pointer;
    text-align: left;
}

.wizard-trail .wizard-badge:hover,
.wizard-trail .wizard-badge:focus-visible {
    border-color: var(--bs-primary-border-subtle);
}

/* A pergunta activa: contornada, sem valor ainda. */
.wizard-trail .wizard-badge-now {
    background: transparent;
    border-color: var(--bs-primary-border-subtle);
    cursor: default;
}

/* As que faltam: esbatidas, para se ver quantas são sem parecerem clicáveis. */
.wizard-trail .wizard-badge-pending {
    background: var(--bs-tertiary-bg);
    cursor: default;
}

.wizard-trail .wizard-badge-pending .wizard-badge-key {
    color: var(--bs-secondary-color);
}

.wizard-trail .wizard-badge-key {
    white-space: nowrap;
    line-height: 1.2;
}

.wizard-trail .wizard-trail-step {
    margin-left: auto;
    font-size: var(--fs-sm);
    color: var(--bs-secondary-color);
    white-space: nowrap;
}

.wizard-trail .wizard-trail-sep {
    color: var(--bs-secondary-color);
    font-size: var(--fs-sm);
}

@keyframes wizard-badge-in {
    from { opacity: 0; transform: translateY(-4px) scale(.96); }
    to { opacity: 1; transform: none; }
}

/* A pergunta activa a esquerda, a imagem do modelo a direita quando ja se sabe qual e. */
.wizard-stage {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 13rem;
    gap: 1.5rem;
    align-items: start;
}

.wizard-stage:has(.wizard-art.d-none) {
    grid-template-columns: minmax(0, 1fr);
}

@media (max-width: 41.75rem) {
    .wizard-stage { grid-template-columns: minmax(0, 1fr); }
}

.wizard-ask {
    display: flex;
    flex-direction: column;
    gap: 1.1rem;
    animation: wizard-ask-in .26s ease both;
}

@keyframes wizard-ask-in {
    from { opacity: 0; transform: translateY(5px); }
    to { opacity: 1; transform: none; }
}

.wizard-art {
    border: 1px solid var(--bs-border-color);
    border-radius: .625rem;
    background: var(--bs-tertiary-bg);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .6rem;
    padding: 1.1rem;
    min-height: 11rem;
    animation: wizard-art-in .48s cubic-bezier(.2, .7, .3, 1) both .1s;
}

.wizard-art img {
    max-width: 100%;
    max-height: 7rem;
}

.wizard-art .wizard-art-name {
    font-size: var(--fs-sm);
    font-weight: 600;
    text-align: center;
}

.wizard-art .wizard-art-sub {
    font-size: var(--fs-label);
    color: var(--bs-secondary-color);
    text-align: center;
}

@keyframes wizard-art-in {
    from { opacity: 0; transform: translateY(6px) scale(.985); }
    to { opacity: 1; transform: none; }
}

/* A grelha de escolhas em cards, partilhada pelo tipo de dispositivo e pelo modelo: um
   leva ícone, o outro leva a fotografia, e o resto da forma é o mesmo. */
.wizard-card-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: .625rem;
}

@media (max-width: 34rem) {
    .wizard-card-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.wizard-card {
    border: 1px solid var(--bs-border-color);
    border-radius: .625rem;
    background: var(--bs-body-bg);
    padding: .9rem .7rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .45rem;
    text-align: center;
    cursor: pointer;
    transition: border-color .15s ease, background-color .15s ease, transform .15s ease;
}

.wizard-card:hover {
    border-color: var(--bs-primary);
    transform: translateY(-1px);
}

.wizard-card:focus-visible {
    outline: 2px solid var(--bs-primary);
    outline-offset: 2px;
}

/* O que ja esta escolhido. So o modal de edicao o usa: no assistente responder colapsa a
   pergunta numa badge, e não há grelha por onde ver a escolha. */
.wizard-card.selected {
    border-color: var(--bs-primary);
    background: var(--bs-primary-bg-subtle);
}

.wizard-card-icon {
    font-size: var(--fs-xl);
    color: var(--bs-secondary-color);
}

/* A miniatura tem altura fixa para os cards de uma linha ficarem alinhados mesmo com
   fotografias de proporcoes diferentes. */
.wizard-card-thumb {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 3.75rem;
}

.wizard-card-thumb img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}

.wizard-card-label {
    font-size: var(--fs-sm);
    font-weight: 500;
    line-height: 1.3;
}

/* O modelo interno, ou a contagem de modelos de um tipo. */
.wizard-card-sub {
    font-size: var(--fs-label);
    color: var(--bs-secondary-color);
}

/* ===== pastilha de estado ===== */

/* O estado vive no bloco e não no separador: umas configurações viajam para o
   dispositivo e podem ficar pendentes, outras valem de imediato. Nomear separadores por essa
   diferença era nomear pela implementação.

   A pastilha é o `badge` do Bootstrap com as utilitárias `bg-*-subtle` e `text-*-emphasis`,
   montada no `components/state-badge.js`. Sobra aqui o ponto, para que o Bootstrap não tem
   medida. A leitura não pode depender da cor, e por isso o rótulo diz sempre o estado. */
.state-badge-dot {
    width: 6px;
    height: 6px;
    background: currentcolor;
}

@media (prefers-reduced-motion: reduce) {
    .wizard-trail .wizard-badge,
    .wizard-ask,
    .wizard-art {
        animation: none;
    }
    .wizard-card { transition: none; }
    .wizard-card:hover { transform: none; }
}
