﻿/* =============================================================
   Correções ao tema Alina.

   Vive aqui e não dentro do `assets/css/style.css` porque esse é
   ficheiro de fornecedor: uma atualização do tema apagaria as
   alterações sem aviso. Carregado DEPOIS do style.css.
   ============================================================= */

/* -------------------------------------------------------------
   Texto secundário ilegível no modo escuro com a paleta vermelha

   A paleta `theme-gradient-5` define `--secondary: 34, 22, 25` — quase
   preto, pensado para fundos claros. O seu seletor no tema é
   `:root .theme-gradient-5`, que **vence o `body.dark` em
   especificidade** (0,2,0 contra 0,1,1). Resultado: no modo escuro todo
   o `.text-secondary` fica preto sobre um cartão escuro.

   Medido antes da correção: contraste de **1.14** contra o mínimo de 4.5
   das WCAG para texto normal. Ilegível, não "difícil de ler".

   O valor abaixo é o que o próprio tema usa no seu bloco de modo escuro
   (`_variables.scss`, `.sidebar-dark .app-navbar, body.dark`). Só se
   repõe o que a paleta pisou.

   Especificidade 0,2,1 — ganha à regra da paleta sem `!important`.
   Aplica-se a todas as paletas porque todas redefinem `--secondary`.
   ------------------------------------------------------------- */

body.dark.theme-gradient-1,
body.dark.theme-gradient-2,
body.dark.theme-gradient-3,
body.dark.theme-gradient-4,
body.dark.theme-gradient-5,
body.dark.theme-gradient-6 {
    --secondary: 185, 179, 166;
}

/* -------------------------------------------------------------
   Logótipo do CdoMeio: um por tema

   A `.main-side-nav` do tema é branca no modo claro
   (medido: rgb(255,255,255)) e escura no modo escuro
   (rgb(34,37,44)). Um único ficheiro não serve os dois — daí os dois
   logótipos.

   A tira estreita não precisa de par: o `--dark-color-gradient` mantém-na
   em carmim escuro (#221619 → #50142D) nos dois temas, por isso a marca
   branca lê-se sempre.

   Sem clarão na troca: a classe `dark` é posta no <body> pelo script
   inline do App.razor, antes de a página pintar.
   ------------------------------------------------------------- */

.logo-cdomeio--escuro {
    display: none;
}

body.dark .logo-cdomeio--claro {
    display: none;
}

body.dark .logo-cdomeio--escuro {
    display: inline-block;
}

/* A marca recortada no quadrado da tira estreita. O lockup é largo:
   entra sobredimensionado e o quadrado corta-o. */
.marca-tira {
    position: relative;
    overflow: hidden;
}

.marca-tira img {
    width: 30px;
    max-width: none;
}

/* -------------------------------------------------------------
   O tema recolore o logótipo. Nós não queremos isso.

   Cada paleta traz uma regra como esta:

     .theme-gradient-5 .main-side-nav .logo img {
       filter: brightness(0) saturate(100%) invert(20%) sepia(85%)
               saturate(2000%) hue-rotate(...) ...
     }

   O `brightness(0)` achata a imagem a PRETO e o resto recolore-a numa
   cor única. Funciona para o logótipo do tema, que é uma silhueta de uma
   só cor. Aplicado ao lockup do CdoMeio destrói o desenho a duas cores
   (seta magenta + texto) e achata os dois ficheiros na mesma mancha
   vermelha — o que tornava o par claro/escuro inútil.

   Alternativa que NÃO foi escolhida: deixar o filtro. O logótipo passaria
   a acompanhar automaticamente a cor da paleta, mas deixaria de ser o
   logótipo da marca e um dos dois ficheiros seria redundante.
   ------------------------------------------------------------- */

.main-side-nav .logo img.logo-cdomeio {
    filter: none;
}

/* -------------------------------------------------------------
   Cartao de resumo que tambem e botao

   Na listagem de clientes, os quatro `ticket-card` do template do tema
   filtram a lista. Por isso sao <button> e nao <div>: assim ganham
   teclado, foco e sao anunciados como controlo.

   Sendo <button>, trazem o padding, a fonte e o alinhamento por
   omissao do browser, que empurrariam o `.card-body` para dentro. Aqui
   repoem-se os valores herdados. O tema nao previa este caso, por isso
   o ajuste vive neste ficheiro e nao no style.css.
   ------------------------------------------------------------- */

button.ticket-card {
    padding: 0;
    font: inherit;
    color: inherit;
    text-align: inherit;
    -webkit-appearance: none;
    appearance: none;
}

/* O anel do cartao ativo e um `b-2-light` de 2px. Sem compensar, o
   cartao ativo fica 4px mais alto que os vizinhos e a fila desalinha. */
button.ticket-card:not(.b-2-light) {
    border: 2px solid transparent;
}

button.ticket-card:focus-visible {
    outline: 2px solid rgba(var(--white), 0.9);
    outline-offset: 2px;
}

/* -------------------------------------------------------------
   Separador desativado não parecia desativado

   O `/clientes/novo` mostra a mesma barra da ficha, com Contactos,
   Saúde, Medições e Fotos desativados — precisam de um cliente já
   gravado. Os botões têm `disabled` a sério: não recebem clique
   nem foco.

   Mas viam-se exatamente iguais aos ativos. A causa é do tema:

     .app-tabs-primary .nav-item .nav-link {
       color: rgba(var(--primary), 1) !important;
     }

   Esse `!important` (especificidade 0,3,0) anula o
   `--bs-nav-link-disabled-color` que o Bootstrap aplica em
   `.nav-tabs .nav-link:disabled`. Resultado: um botão morto
   pintado de rosa vivo, indistinguível de um que funciona.

   A regra abaixo tem especificidade 0,4,0 e ganha-lhe.

   Usa-se `--secondary` e não uma cor fixa porque essa variável já
   é corrigida acima para o modo escuro — assim o separador
   desativado lê-se nos dois temas sem uma segunda regra.

   As WCAG isentam controlos inativos do mínimo de contraste
   (1.4.3), mas 0.75 de alfa mantém-no confortavelmente legível:
   o objetivo é dizer "ainda não", não esconder.
   ------------------------------------------------------------- */

.nav-tabs .nav-item .nav-link:disabled {
    color: rgba(var(--secondary), 0.75) !important;
    cursor: not-allowed;
}

/* -------------------------------------------------------------
   A etiqueta de uma checkbox fica colada à caixa.

   O Bootstrap reserva o espaço da caixa com `padding-left: 1.5em`
   no `.form-check` e puxa o input para lá com uma margem negativa
   igual. Com a fonte a 13px isso são 19,5px. Mas o tema redefine
   `.form-check:not(.form-switch) .form-check-input` para
   `width: 1.25rem` — 20px — e a caixa passa a ser MAIS LARGA do
   que o espaço reservado: a etiqueta começa exatamente onde a
   caixa acaba, sem folga nenhuma.

   Medido: input.right 1248,759 / label.left 1248,759.

   Corrige-se com um recuo na etiqueta e não mexendo na largura
   da caixa: o tamanho é escolha do tema, o encosto é que não.
   ------------------------------------------------------------- */
.form-check .form-check-label {
    padding-left: 0.4rem;
}

/* -------------------------------------------------------------
   Uma folga lateral no conteúdo das páginas, sem mexer no
   breadcrumb.

   O MainLayout envolve o @Body num `.container-fluid px-0`, e o
   `px-0` deixa os cartões encostados às margens da coluna de
   conteúdo. Medido: contentor, breadcrumb e primeiro cartão todos
   a começar em x=352.

   Porquê aqui e não um `px-2` no próprio contentor: o breadcrumb
   é renderizado PELA PÁGINA, dentro do mesmo contentor, e já tem
   um recuo de 40px que lhe vem do `.app-breadcrumbs` do tema.
   Um padding no contentor empurrava-o também, e ele já está no
   sítio.

   Daí o `:not(nav)` — o componente Breadcrumb renderiza sempre um
   <nav>, e é o único filho deste contentor que o é. Se algum dia
   ele passar a envolver-se noutra coisa, esta regra deixa de o
   poupar.
   ------------------------------------------------------------- */
main > .container-fluid > :not(nav) {
    padding-left: 0.5rem;
    padding-right: 0.5rem;
}

/* -------------------------------------------------------------
   Dizer ao browser em que esquema a página está.

   O modo escuro do tema é só um conjunto de classes CSS: o browser
   continua a achar que a página é clara e desenha os controlos que
   ELE controla — e que a página não pode pintar — em claro. Daí a
   lista de um <select> abrir branca com a barra de seleção no azul
   do sistema, no meio de uma app escura.

   Medido: `color-scheme` estava `normal` em toda a árvore, com o
   `body.dark` ativo.

   Isto não é decoração: o `color-scheme` é a única forma
   normalizada de o dizer. Apanha de uma vez a lista dos <select>,
   o calendário dos <input type=date>, as barras de deslocamento e
   o resto dos widgets nativos. Herda, por isso basta no <body>.

   O que continua fora do nosso alcance: a COR da barra de seleção
   dentro da lista, que vem do acento do sistema operativo. Para a
   controlar era preciso trocar o <select> nativo por um widget
   próprio (`appearance: base-select`, só no Chrome) — e isso muda
   o comportamento no teclado e no telemóvel. Não compensa.
   ------------------------------------------------------------- */
:root {
    color-scheme: light;
}

body.dark {
    color-scheme: dark;
}

/* -------------------------------------------------------------
   E NAO CHEGA, porque o TEMA escreve branco sobre branco.

   Relatado pelo autor em 22/09/2026 com o seletor de tipo de
   acompanhamento aberto: a lista abria branca no meio da app
   escura, e os titulos dos grupos ("Plano online", "Treino
   personalizado") estavam quase invisiveis.

   O `color-scheme: dark` acima ESTAVA a ser computado no <select>
   -- medido, nao suposto. O que o venceu foi isto, que vem do
   `style.css` do fornecedor:

     body.dark .app-form select option {
         background-color: rgba(var(--white), 1);
         color: rgb(255, 255, 255);
     }

   Branco sobre branco, na regra que existe SO para o modo escuro.
   E o `optgroup` nao tem regra nenhuma, portanto herda a cor do
   <select> -- medida em `rgba(234, 234, 236, .4)`, um branco a 40%
   -- que sobre o fundo branco da lista da exactamente o fantasma
   que se ve no ecra.

   Porque e que o `color-scheme` nao salva isto: no Chrome, a cor
   do popup de um <select> sai do `background-color` do PROPRIO
   elemento quando o autor lho da. O do tema e
   `rgba(155, 155, 190, .1)` -- translucido -- e o Chrome compoe-o
   sobre branco. Dai o fundo claro mesmo com o esquema escuro
   declarado. Por isso o fundo passa aqui a OPACO.

   O valor `rgb(48, 51, 60)` nao e escolhido a olho: e a composicao
   do translucido do tema sobre o fundo de um cartao
   (`rgb(36, 39, 45)`), medida no browser. Ou seja, o campo fechado
   continua a ter exactamente o aspeto de hoje -- o que muda e so o
   que o browser desenha por cima.

   ATENCAO: o popup de um <select> e uma janela do sistema
   operativo. NAO aparece numa captura de ecra da pagina, portanto
   isto nao e verificavel a partir daqui -- quem confirma e quem
   esta a olhar. A cor da barra de selecao continua a ser o acento
   do sistema, e isso fica fora do nosso alcance.
   ------------------------------------------------------------- */
body.dark .app-form select,
body.dark .app-form .form-select {
    background-color: rgb(48, 51, 60);
}

body.dark .app-form select option,
body.dark .app-form select optgroup,
body.dark .app-form .form-select option,
body.dark .app-form .form-select optgroup {
    background-color: rgb(36, 39, 45);
    color: rgba(234, 234, 236, .92);
}

/* O titulo de um grupo nao e escolhivel, e tem de se ler como tal
   -- mas LER-SE. Mais fraco do que as opcoes, nunca invisivel. */
body.dark .app-form select optgroup,
body.dark .app-form .form-select optgroup {
    color: rgba(234, 234, 236, .62);
}

/* -------------------------------------------------------------
   A zona de upload do tema tem cores fixas.

   O `.custom-upload` do `file_upload.html` é a única zona de
   upload do Alina que funciona sem plugin — as outras precisam
   do FilePond. Mas traz `border: 2px dashed #d0d5dd` e
   `background: #fafafa` em hexadecimal fixo, e não em variáveis
   da paleta: sobre um cartão escuro fica uma caixa branca com
   texto claro por cima.

   Aqui redefine-se com as variáveis do tema, que trocam sozinhas
   entre claro e escuro — a mesma disciplina do ReconnectModal.
   ------------------------------------------------------------- */
.custom-upload {
    /* 0.65 e nao os 0.4 iniciais: a moldura tracejada e a UNICA coisa que
       delimita a zona de upload, portanto e um limite de componente e cai no
       criterio 1.4.11 das WCAG -- minimo 3:1. Medido no ecra com 0.4: 2.51 em
       claro e 2.16 em escuro. */
    border-color: rgba(var(--secondary), 0.65);
    background: rgba(var(--secondary), 0.06);
    color: rgba(var(--dark), 1);
}

.custom-upload:hover {
    border-color: rgba(var(--primary), 0.6);
    background: rgba(var(--primary), 0.06);
}

/* -------------------------------------------------------------
   O visualizador de fotos em ecrã inteiro.

   É NOSSO, e não uma correção ao tema: o Alina faz isto com o
   GLightbox, que é JavaScript e nem sequer está copiado para o
   projeto (em `assets/vendor/` só há bootstrap e tabler-icons).

   Fundo quase opaco de propósito. Uma foto de evolução corporal
   vê-se melhor sem o resto da aplicação a competir com ela, e o
   contraste com a pele importa mais aqui do que a coerência com
   a paleta.
   ------------------------------------------------------------- */
.dm-visualizador {
    position: fixed;
    inset: 0;
    z-index: 1080;                 /* acima do modal do Bootstrap (1055) */
    /* 0.97 e nao 0.92: medido no ecra, com 8% de passagem ainda se liam os
       rotulos da pagina por tras, e uma foto de evolucao corporal julga-se
       pela cor da pele -- qualquer coisa a competir por tras estraga a
       leitura. */
    background: rgba(0, 0, 0, 0.97);
    display: flex;
    flex-direction: column;
    /* Sem contorno de foco: o elemento recebe foco por código, só para
       apanhar o Esc. Quem navega por teclado vê o foco nos BOTÕES. */
    outline: none;
}

.dm-visualizador__barra {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.85rem 1.25rem;
    color: #fff;
    background: rgba(0, 0, 0, 0.35);
    flex-shrink: 0;
}

.dm-visualizador__palco {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    /* min-height: 0 é o que permite ao palco ENCOLHER abaixo do seu
       conteúdo. Sem isto, uma imagem alta empurra a barra para fora do
       ecrã — é a mesma armadilha de flexbox já documentada no .dm-shell. */
    min-height: 0;
    padding: 0.5rem;
}

.dm-visualizador__palco img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;           /* contain e não cover: não se corta uma foto de evolução */
    border-radius: 12px;
}

.dm-visualizador__botao,
.dm-visualizador__seta {
    border: 0;
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
    border-radius: 50%;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.25rem;
    cursor: pointer;
    flex-shrink: 0;
}

.dm-visualizador__botao:hover,
.dm-visualizador__seta:hover:not(:disabled) {
    background: rgba(var(--primary), 1);
}

.dm-visualizador__seta:disabled {
    opacity: 0.25;
    cursor: default;
}

.dm-visualizador__botao:focus-visible,
.dm-visualizador__seta:focus-visible {
    outline: 2px solid rgba(var(--primary), 1);
    outline-offset: 2px;
}

/* -------------------------------------------------------------
   A grelha das fotos de evolução.

   O cartão em si é o `.folder-cards` + `.file-image` do
   `file_manager.html` — o único padrão do tema com legenda
   SEMPRE visível, e aqui a legenda é a data, que não pode
   depender de passar o rato.

   O que falta ao tema é o que se segue: o botão de remover no
   canto, a moldura de altura fixa (para as fotos não ficarem
   umas altas e outras baixas na mesma fila) e o par do
   antes-e-depois.
   ------------------------------------------------------------- */
/* O tema desenha uma "aba de pasta" em cada .folder-cards, com um
   ::after posicionado acima do cartão. É decoração de gestor de
   ficheiros; numa foto de evolução não diz nada. Desligada aqui,
   e não no style.css, que é do fornecedor. */
.folder-cards .card-body::after {
    content: none;
}

/* O .card do Bootstrap já é position: relative, por isso o botão
   ancora-se ao cartão sem se acrescentar posicionamento nenhum. */
.dm-foto__remover {
    position: absolute;
    top: 6px;
    right: 6px;
    z-index: 1;
}

/* O botão existe só para a imagem ser clicável e focável pelo teclado.
   Sem `border: 0` e fundo transparente, o browser desenha-lhe uma
   moldura à volta da foto. */
.dm-foto__abrir {
    border: 0;
    padding: 0;
    background: none;
    display: block;
    width: 100%;
    cursor: pointer;
}

.dm-foto__abrir:focus-visible {
    outline: 2px solid rgba(var(--primary), 1);
    outline-offset: 2px;
    border-radius: 12px;
}

/* Altura fixa e `cover`: numa fila, fotos de proporções diferentes
   sem isto dão uma linha aos altos e baixos, e a comparação — que é
   o ponto — fica mais difícil de fazer a olho.

   MEDIDO em 05/09/2026: com `.file-image` do tema à volta, a imagem
   saía a 45×45. Essa regra é `.folder-cards .card-body .file-image img`
   (0,3,1) e existe porque ali a imagem é um ícone de tipo de ficheiro.
   Por isso `.file-image` não se usa aqui — só a moldura `.folder-cards`. */
.dm-foto__abrir img,
.dm-foto__vazia {
    width: 100%;
    height: 150px;
    object-fit: cover;
    border-radius: 12px;
}

.dm-foto__vazia {
    display: flex;
    align-items: center;
    justify-content: center;
}

/* --- antes e depois --- */
.dm-comparar {
    position: relative;
    border-radius: 12px;
    overflow: hidden;
    background: rgba(var(--secondary), 0.1);
    min-height: 220px;
}

.dm-comparar img {
    width: 100%;
    /* `contain` e não `cover`: aqui a imagem é o conteúdo, não uma
       miniatura. Cortar uma foto de evolução ao meio para encher a
       caixa seria esconder precisamente o que se quer comparar. */
    height: 340px;
    object-fit: contain;
    display: block;
}

.dm-comparar__data {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 0.35rem;
    text-align: center;
    font-size: 0.85rem;
    color: #fff;
    background: rgba(0, 0, 0, 0.55);
}

/* -------------------------------------------------------------
   Um badge que não é botão não deve parecer um botão.

   As classes `text-light-*` do tema estão definidas DUAS vezes,
   e a segunda (style.css:20062) acrescenta-lhes um `:hover` que
   muda o fundo e faz aparecer uma borda. A primeira
   (style.css:11197) traz `cursor: pointer`.

   Faz sentido onde o tema as usa — em chips e botões suaves. Nos
   nossos badges de estado ("Ativo") e de modalidade ("PT duo")
   não: não são clicáveis, e o afeto convida a um clique que não
   faz nada. Na faixa da ficha isso nota-se mais, porque o badge
   fica encostado a coisas que são mesmo clicáveis.

   Restringido a `.badge` de propósito: os mesmos nomes de classe
   continuam a comportar-se como o tema quer em todo o resto.

   Corrige-se o CURSOR e a BORDA, e não o fundo. A borda que
   aparece no hover é o que faz o badge parecer um botão, e
   `transparent` não depende da cor. Já o fundo passa de
   `rgba(var(--X), 0.1)` para `0.2`, e repô-lo obrigava a uma
   regra por cada uma das nove cores, com os valores do tema
   copiados à mão -- que passam a mentir na primeira atualização
   do tema. **O tom continua a mudar ao passar o rato**, de
   propósito: é subtil, e não vale uma cópia que apodrece.

   `!important` no cursor porque a regra do tema também o tem.
   ------------------------------------------------------------- */
.badge[class*="text-light-"] {
    cursor: default !important;
}

.badge[class*="text-light-"]:hover {
    border-color: transparent;
}

/* -------------------------------------------------------------
   A fotografia dentro do avatar.

   O círculo já vem do `b-r-50` do tema e o tamanho dos `h-NN`
   / `w-NN`. Falta só uma coisa que o tema não dá, porque nunca
   pôs uma <img> nestas classes: sem `object-fit: cover` uma
   foto que não seja quadrada aparece esticada, e um retrato em
   retrato — que é a esmagadora maioria — fica achatado.

   `cover` corta pelos lados e mantém as proporções. O centro é
   onde está a cara.
   ------------------------------------------------------------- */
.dm-avatar {
    object-fit: cover;
}

/* -------------------------------------------------------------
   O emblema de câmara sobre a fotografia de perfil.

   A própria fotografia é o botão de a trocar — é o padrão que
   toda a gente reconhece —, mas um círculo sem mais nada não
   diz que se pode carregar nele. O emblema di-lo.

   Não vem do tema: o Alina não tem nada parecido, e as classes
   de posição do Bootstrap (`position-absolute`, `bottom-0`)
   davam para o colocar mas não para o dimensionar em função do
   círculo. São seis linhas nossas.
   ------------------------------------------------------------- */
.dm-avatar-editor {
    position: relative;
    display: inline-flex;
    cursor: pointer;
}

.dm-avatar-editor__emblema {
    position: absolute;
    right: -2px;
    bottom: -2px;
    width: 18px;
    height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    font-size: 11px;
    background: rgba(var(--primary), 1);
    color: rgba(var(--white), 1);
    /* O anel separa o emblema da fotografia por baixo, seja ela
       clara ou escura — sem ele, uma foto de fundo rosa engolia-o.

       `--white` e não uma variável de cartão: o tema não tem
       nenhuma para o fundo do cartão. O `.card` é
       `rgba(var(--white), 0.65)` (style.css:16873), e como o
       Alina troca `--white` e `--dark` entre os dois modos, esta
       linha serve claro e escuro sem media query. */
    box-shadow: 0 0 0 2px rgba(var(--white), 1);
}

/* Sem cursor de mão quando está a gravar: o label não fica
   `disabled` (um <label> não tem esse atributo), portanto o
   sinal tem de vir daqui. */
.dm-avatar-editor.opacity-50 {
    cursor: default;
}


/* -------------------------------------------------------------
   A GRELHA SEMANAL DA AGENDA

   Primeira grelha CSS do projeto. Não é preferência: uma semana
   é duas dimensões — dia na horizontal, hora na vertical — e um
   bloco de 90 minutos tem de ocupar três células sem deixar de
   estar alinhado com os vizinhos. Flexbox faria as colunas mas
   não a correspondência entre linhas.

   NÃO SE USA O CALENDÁRIO DO TEMA, e a razão não é só a regra
   do CLAUDE.md contra o JS do Alina. Verificado no
   `template/calendar.html` em 09/09/2026: o markup dele é
   `<div class="app-calendar" id='calendar'></div>` — um div
   VAZIO. Não há uma única classe `fc-` no HTML; o calendário é
   todo construído em runtime pelo FullCalendar (704 KB + 757 KB).
   As 35 regras `.fc-*` que temos no style.css apontam para
   classes que só existem depois de esse JS correr, portanto não
   há nada para copiar — nem markup nem CSS aproveitável.

   O que ele daria e isto não dá: arrastar para mover,
   redimensionar, e vista mensal. Se algum dia forem precisos, é
   essa a conversa a ter — não "o tema já tinha um".

   As unidades:
     - 1 linha = 30 minutos. É o menor passo que faz 30, 60 e 90
       assentarem em números inteiros de células.
     - 07h às 22h = 30 linhas.
   ------------------------------------------------------------- */
/* -------------------------------------------------------------
   QUEM ROLA É A GRELHA, NÃO A PÁGINA.

   QUEM ROLA E A PAGINA, e isto ja foi ao contrario.

   Esta zona teve `max-height: calc(100dvh - 21rem)` e
   `overflow: auto`, e a justificacao escrita era "o shell ocupa
   um ecra e quem rola e a `.dm-tabela`" -- uma regra do
   CLAUDE.md que, quando isto foi escrito, JA ESTAVA
   DESACTUALIZADA: a `.dm-shell` e a `.dm-tabela` foram-se com a
   marca "Do Meio" para o ramo `marca-do-meio`, e a app passou a
   usar o shell do Alina, onde rola a pagina. A agenda era o
   unico ecra com scroll proprio, e por isso parecia errada ao
   lado da lista de clientes.

   O problema original -- o formulario de marcacao a abrir
   centenas de pixels abaixo do clique -- NAO volta, e nao e por
   sorte: quem o resolveu foi por o formulario ACIMA da grelha, e
   ele continua la. O scroll era a segunda metade de uma
   correcao que so precisava da primeira.

   E a janela de horas passou a ser configuravel (014): quem da
   treinos das 9h as 20h tem 22 linhas em vez de 30, e a grelha
   cabe num ecra sem truque nenhum.
   ------------------------------------------------------------- */
.dm-agenda-rolo {
    border-radius: 8px;
}

/* -------------------------------------------------------------
   O CABECALHO DOS DIAS TEM DE CONTINUAR A COLAR-SE.

   Com o scroll interno, o `position: sticky` colava-se a
   `.dm-agenda-rolo`. Sem ele precisa da PAGINA -- e o tema tem
   `overflow: hidden` no `.app-content`, que e exactamente a
   armadilha ja documentada no CLAUDE.md: um antepassado com
   overflow diferente de `visible` passa a ser o scrollport do
   sticky, e o elemento cola-se a nada.

   Medido: sem isto, ao rolar, o cabecalho ia parar a -57px e as
   colunas ficavam sem nome -- numa grelha de 30 linhas, sem
   saber que dia e cada coluna.

   A correcao e destravar esse antepassado. Fica aqui e nao no
   style.css, que e do fornecedor.

   O SELETOR TEM DE SER `.app-wrapper .app-content`, com os dois
   nomes: o do tema (style.css l.11515) e assim, e um
   `.app-content` sozinho perde por especificidade mesmo vindo
   depois. Medido -- a primeira tentativa nao pegou.

   E NAO PODE SER `overflow: visible`, que foi a primeira
   tentativa: o sticky passava a funcionar, mas a pagina ganhava
   SCROLL HORIZONTAL -- o `overflow: hidden` do tema esta la a
   conter alguma coisa que transborda para a direita. Medido.

   `overflow-x: clip` com `overflow-y: visible` da as duas: o
   `clip` corta na horizontal como o `hidden` fazia, mas -- ao
   contrario do `hidden` -- NAO cria um contentor de rolagem,
   portanto o sticky continua a contar com a pagina. E a unica
   combinacao em que o eixo `visible` sobrevive ao lado de um
   eixo cortado; com `hidden` de um lado, o `visible` do outro
   passa a `auto` e o sticky volta a partir-se.
   ------------------------------------------------------------- */
.app-wrapper .app-content {
    overflow-x: clip;
    overflow-y: visible;
}

.dm-agenda {
    display: grid;
    /* A calha das horas é fixa; os sete dias repartem o resto por
       igual. `minmax(0, 1fr)` e não `1fr`: sem o mínimo a zero,
       um nome comprido dentro de um bloco alarga a coluna e
       desfaz a semana. */
    grid-template-columns: 3.25rem repeat(7, minmax(0, 1fr));
    grid-template-rows: auto repeat(30, 1.35rem);
    gap: 1px;
    background: rgba(var(--secondary), 0.14);
    border: 1px solid rgba(var(--secondary), 0.14);
    border-radius: 8px;
    /* SEM `overflow: hidden`.
       Estava aqui para arredondar os cantos das células de fora, e
       impedia o `position: sticky` do cabeçalho dos dias de
       funcionar dentro da `.dm-agenda-rolo` -- um antepassado com
       overflow diferente de `visible` torna-se o contentor de
       rolagem do sticky, e o cabeçalho colava-se a nada. Os cantos
       passam a ser arredondados pela `.dm-agenda-rolo`. */
}

/* O fundo das células vem daqui: o `gap` de 1px sobre um fundo
   cinzento é o que desenha as linhas da grelha, sem uma única
   border por célula. */
.dm-agenda__celula,
.dm-agenda__hora,
.dm-agenda__dia {
    background: rgba(var(--white), 1);
}

/* O cabeçalho dos dias fica colado ao topo enquanto se rola a
   grelha. Sem isto, rolar até às 19h deixa de dizer que coluna é
   que dia — e num calendário isso é a informação toda.

   z-index 2 e não 1: tem de passar por cima dos blocos das
   sessões, que estão em 1. */
.dm-agenda__dia {
    padding: 0.4rem 0.25rem;
    text-align: center;
    font-size: 12px;
    line-height: 1.3;
    position: sticky;
    /* NAO e 0: por cima ha duas barras FIXAS do tema -- o
       `header-main` (65px) e o `app-breadcrumbs` (ate 109px). Com
       `top: 0` o cabecalho dos dias colava-se por BAIXO delas e
       ficava invisivel, que e o mesmo que nao colar. */
    top: 109px;
    z-index: 2;
}

/* O tom de "hoje" vai por `box-shadow` interior e não por
   `background`.
   Razão: a célula é `sticky`, e uma cor semi-transparente no
   background SUBSTITUÍA o branco opaco — as linhas da grelha
   passavam a ver-se através do cabeçalho ao rolar. Assim a
   camada translúcida assenta por cima do fundo opaco. */
.dm-agenda__dia--hoje {
    box-shadow: inset 0 0 0 999px rgba(var(--primary), 0.10);
    font-weight: 600;
}

/* A etiqueta da hora escreve-se só na hora certa e alinha-se pelo
   topo da célula, que é onde a linha da grelha está. */
.dm-agenda__hora {
    font-size: 11px;
    text-align: right;
    padding-right: 0.35rem;
    color: rgba(var(--secondary), 1);
    line-height: 1;
}

/* Cada célula vazia é um botão: carregar nela marca àquela hora.
   Um <button> e não um <div> com @onclick — teclado e leitores de
   ecrã dependem disso, e é de borla. */
button.dm-agenda__celula {
    border: 0;
    padding: 0;
    width: 100%;
    height: 100%;
    cursor: pointer;
}

button.dm-agenda__celula:hover {
    background: rgba(var(--primary), 0.10);
}

button.dm-agenda__celula:focus-visible {
    outline: 2px solid rgba(var(--primary), 1);
    outline-offset: -2px;
}

/* -------------------------------------------------------------
   FORA DO HORARIO DAQUELE DIA (020)

   Desde que o horario passou a ser por dia da semana, a grelha
   desenha a UNIAO das janelas: com Seg 06-23 e Qua 06-20, sao 17
   linhas de altura e a quarta tem tres horas a mais do que
   trabalha.

   Porque a uniao e nao o menor: a `.dm-agenda` e UM CSS Grid com
   um `grid-template-rows` unico, e colunas com numeros de linhas
   diferentes nao existem nessa estrutura. Encolher ao menor
   escondia as horas em que ele trabalha a segunda.

   CONTINUA CLICAVEL, e isso e deliberado. E a regra do 013
   aplicada as horas: a agenda nunca impede uma marcacao real. O PT
   ha-de querer marcar fora do horario, e recusar obrigava-o a ir
   as definicoes, mudar o horario, marcar, e voltar a muda-lo.

   Riscas e nao um fundo chapado: um fundo mais escuro le-se como
   "ocupado" -- que e o oposto do que isto quer dizer. As riscas
   sao a convencao de "zona inactiva" e nao se confundem com um
   bloco de sessao.
   ------------------------------------------------------------- */
button.dm-agenda__celula--fora {
    background-image: repeating-linear-gradient(
        45deg,
        transparent,
        transparent 4px,
        rgba(var(--secondary), 0.14) 4px,
        rgba(var(--secondary), 0.14) 5px);
}

/* O hover continua a ver-se por cima das riscas -- senao a celula
   fora de horas nao dava sinal nenhum de ser clicavel. */
button.dm-agenda__celula--fora:hover {
    background-color: rgba(var(--primary), 0.10);
}

/* O dia FECHADO (ferias, feriado) marca-se no CABECALHO e nao nas
   celulas: as celulas ja estao todas fora de horas nesse dia, e
   duplicar o sinal so fazia a coluna ficar ilegivel. */
.dm-agenda__dia--fechado {
    opacity: 0.75;
}

/* O motivo por baixo do numero do dia. Sem ele, uma coluna
   sombreada nao explica porque esta sombreada -- e quem olha nao
   sabe se sao ferias ou um defeito. */
.dm-agenda__excecao {
    font-size: 10px;
    line-height: 1.2;
    font-weight: 500;
    color: rgba(var(--warning), 1);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* O bloco da sessão. Fica POR CIMA das células vazias — é por isso
   que elas podem ser desenhadas todas, sempre, sem cálculo de
   quais estão ocupadas. */
.dm-agenda__sessao {
    z-index: 1;
    /* Flex para a unica linha ficar centrada na vertical. Sem
       isto, um bloco de 60 minutos punha as caras encostadas ao
       topo e deixava um vazio por baixo. */
    display: flex;
    align-items: center;
    margin: 1px;
    padding: 0.15rem 0.35rem;
    border: 0;
    border-radius: 5px;

    /* A COR DO SERVICO, escrita no `style` do proprio bloco (019).
       O valor por omissao aqui e o que mantem uma sessao sem tipo
       resolvido exactamente como era antes -- e isso acontece
       sempre que o preco tambem nao resolve, porque a inferencia e
       a mesma. Ver Servicos.Inferir. */
    --dm-sessao-cor: rgba(var(--primary), 1);

    border-left: 3px solid var(--dm-sessao-cor);
    /* 0.2 e nao um valor a olho: e o mesmo que o tema usa no bloco de
       evento do calendario dele (`.app-calendar .fc-event .list-event`,
       style.css:14096). Nao usamos esse calendario -- e FullCalendar por
       JavaScript --, mas o peso visual do bloco vem de la.

       color-mix e nao um rgba() com alfa porque a cor chega em
       hexadecimal e nao ha forma de lhe acrescentar transparencia
       em CSS de outra maneira. Precisa de Chrome 111+, que e o
       caso -- e se faltar, o navegador ignora a declaracao e o
       bloco fica so com a tira da esquerda, que continua a
       distinguir o servico. */
    background: color-mix(in srgb, var(--dm-sessao-cor) 20%, transparent);
    color: rgba(var(--dark), 1);
    font-size: 11px;
    line-height: 1.25;
    text-align: left;
    overflow: hidden;
    cursor: pointer;
}

/* O hover e o focus TEM de usar a mesma variavel. Escritos com
   --primary fixo, passar o rato por cima trocava a cor do servico
   pela do tema -- o defeito era intermitente por desenho, porque
   so se via com o rato em cima. */
.dm-agenda__sessao:hover {
    background: color-mix(in srgb, var(--dm-sessao-cor) 30%, transparent);
}

.dm-agenda__sessao:focus-visible {
    outline: 2px solid var(--dm-sessao-cor);
    outline-offset: 1px;
}

/* O codigo do servico dentro do bloco. Encolhe antes das caras e
   antes da hora: e a informacao mais dispensavel das tres quando
   a coluna e estreita. */
.dm-agenda__codigo {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    opacity: 0.75;
    font-weight: 600;
}

/* O CAMPO DE COR -- um DISCO, como no tema.

   O Alina nao tem componente de seleccao de cor: no base_inputs.html
   e o input nativo com .form-control, uma vez em todo o template. O
   que lhe da a forma e `.app-form [type=color] { padding: 0;
   height: 50px; border-color: transparent }` (style.css:27614), e
   essa regra esta presa a um antepassado `.app-form` que o nosso
   EditForm nao tem -- dai estar repetida aqui.

   O que faz o disco e a largura ser igual a altura mais o
   border-radius: sem largura fixa, o .form-control estica-o de
   ponta a ponta da coluna e fica uma barra. */
.dm-cor-campo[type="color"] {
    -webkit-appearance: none;
    appearance: none;
    width: 44px;
    height: 44px;
    flex: 0 0 auto;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background-color: transparent;
    cursor: pointer;
}

/* O quadrado interno do browser tem margem e cantos proprios. Sem
   estas duas regras fica um quadrado dentro de um circulo. */
.dm-cor-campo::-webkit-color-swatch-wrapper {
    padding: 0;
}

.dm-cor-campo::-webkit-color-swatch {
    border: 0;
    border-radius: 50%;
}

.dm-cor-campo::-moz-color-swatch {
    border: 0;
    border-radius: 50%;
}

/* SEM COR nao e a mesma coisa que COR PRETA, e o campo nativo nao
   sabe a diferenca: sem value o `input.value` e "#000000" e o
   browser pinta preto. Medido no browser em 18/09/2026, com o
   `value` confirmado por JS. E o mesmo sintoma do campo desativado
   que parecia vazio -- nao se le como "dificil de ver", le-se como
   uma AFIRMACAO ERRADA.

   DUAS TENTATIVAS FALHADAS, registadas para nao se repetirem:

   1. `background-image` so no input: nao se ve. O quadrado da cor
      e um filho do shadow DOM e pinta POR CIMA do fundo do input.
   2. `background-color: transparent` no ::-webkit-color-swatch:
      tambem nao chega. O Chrome IGNORA background-color nesse
      pseudo-elemento -- pinta o `value` e mais nada.

   O que funciona e ESCONDER o swatch: ai o fundo do proprio input
   aparece e a diagonal desenha-se sobre ele. O campo continua
   clicavel e abre o seletor do sistema -- esconder o swatch nao o
   desliga. */
.dm-cor-campo--vazia {
    background-color: rgba(var(--secondary), 0.08);
    box-shadow: inset 0 0 0 1px rgba(var(--secondary), 0.35);
    background-image: linear-gradient(
        to bottom right,
        transparent calc(50% - 1px),
        rgba(var(--secondary), 0.7) calc(50% - 1px),
        rgba(var(--secondary), 0.7) calc(50% + 1px),
        transparent calc(50% + 1px));
}

.dm-cor-campo--vazia::-webkit-color-swatch {
    opacity: 0;
}

/* O Firefox tem o seu proprio nome para a mesma coisa. Nao se
   juntam os dois numa lista separada por virgulas: um seletor
   desconhecido invalida a regra inteira. */
.dm-cor-campo--vazia::-moz-color-swatch {
    opacity: 0;
}

/* A tira de cor na lista do catalogo. *//* A tira de cor na lista do catalogo. *//* A tira de cor na lista do catalogo. *//* A tira de cor na lista do catalogo. *//* A tira de cor na lista do catalogo. */
.dm-cor-tira {
    flex: 0 0 auto;
    width: 4px;
    align-self: stretch;
    min-height: 1.5rem;
    border-radius: 2px;
}

.dm-agenda__nome {
    display: block;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* -------------------------------------------------------------
   O RESUMO DA CONTA: devido / pago / saldo.

   Grelha e nao flexbox porque as tres colunas tem de ter a MESMA
   largura -- com flex, "Em dia" e "Deve 1.250,00 EUR" davam
   colunas diferentes e os numeros deixavam de alinhar entre
   clientes. Abaixo de 480px passa a duas colunas em vez de
   encolher os numeros ate nao se lerem.
   ------------------------------------------------------------- */
.dm-conta-resumo {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.75rem;
    padding: 0.75rem 1rem;
    border-radius: 8px;
    background: rgba(var(--secondary), 0.07);
}

@media (max-width: 479.98px) {
    .dm-conta-resumo {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}


/* -------------------------------------------------------------
   AS CARAS DE UM GRUPO, sobrepostas.

   E o `avatar-group` do ticket.html do Alina, refeito porque o
   dele e para circulos de 45px e aqui ha 21,6px por meia hora.

   O aro NAO e um `border`: um border acrescenta ao tamanho do
   circulo e desalinha-o com a linha do texto ao lado. E um
   box-shadow, que nao ocupa espaco -- e da cor do cartao, para
   parecer um recorte e nao um contorno.

   TENTEI PRIMEIRO com `direction: rtl` mais `row-reverse`, para
   cada circulo ficar POR BAIXO do anterior sem z-index -- que e
   o efeito do tema. Nao serve, e a razao so se ve no ecra: a
   margem negativa passa a ser `margin-right`, encolhe a borda
   DIREITA do contentor, e cancela exactamente o `gap` que
   separa as caras da hora. Ficava "RR13:30", colado.

   Assim, com `margin-left`, a margem negativa come para dentro
   do proprio grupo e a borda direita fica onde deve. O preco e
   a ordem de empilhamento invertida face ao tema -- cada
   circulo por cima do anterior -- que ninguem nota e nao vale
   um z-index por filho.
   ------------------------------------------------------------- */
.dm-avatares {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
}

/* A SOBREPOSICAO E LIMITADA PELAS INICIAIS, nao pelo gosto.

   O tema sobrepoe os circulos em cerca de um terco, o que fica
   bem com CARAS. Aqui o caso comum sao INICIAIS -- nenhum ecra
   desta aplicacao exige fotografia de ninguem -- e duas letras
   tapadas a meio nao dizem nada.

   O tecto e portanto a folga que sobra a volta das letras. A
   30px com f-s-12, as duas letras ocupam ~13px e sobram ~8px de
   cada lado: -0.3rem (4,8px) sobrepoe a olho e nao toca no
   texto. Enquanto o bloco teve 20px o tecto era -0.15rem, e
   passar disso fazia "MG" ler-se "M". Se o tamanho mudar outra
   vez, este numero muda com ele. */
.dm-avatares > * + * {
    margin-left: -0.3rem;
}

.dm-avatares__um,
.dm-avatares__mais {
    display: inline-flex;
    border-radius: 50%;
    box-shadow: 0 0 0 1.5px rgba(var(--white), 1);
}

.dm-avatares__mais {
    align-items: center;
    justify-content: center;
    background: rgba(var(--secondary), 0.9);
    color: rgba(var(--white), 1);
    font-size: 10px;
    font-weight: 600;
    line-height: 1;
}

/* O conteudo do bloco: as caras, a hora e o icone de repeticao,
   tudo na MESMA e UNICA linha.

   Havia uma linha de texto por cima com o nome ou a contagem, e
   saiu -- nao dizia nada que os avatares nao dissessem e ficava
   com metade da altura do bloco. Com uma linha so, as caras
   passaram de 20px para 30px.

   O `gap` e 0.4rem e nao 0.25: o aro dos avatares e um
   box-shadow, que NAO conta para a caixa, e com um gap pequeno
   a hora ficava encostada ao ultimo circulo. Medido no ecra. */
.dm-agenda__rodape {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    min-width: 0;
}

/* A HORA NAO ENCOLHE NUNCA.

   Numa janela estreita, quatro circulos de 30px e a hora nao
   cabem os dois numa coluna de dia. Alguma coisa tem de ceder, e
   nao pode ser a hora: uma sessao sem hora legivel deixa de ser
   uma marcacao. Ficam as caras a serem cortadas a direita, que
   se percebe, em vez de um bloco que nao diz quando e. */
.dm-agenda__hora-bloco {
    flex-shrink: 0;
}


/* -------------------------------------------------------------
   AS FICHAS DOS PARTICIPANTES, no formulario de marcacao.

   Nao sao da grelha -- vivem no painel de cima -- mas sao da
   agenda, e por isso ficam aqui ao lado.

   Existem porque o bloco da grelha nao aguenta tres nomes: com
   1.35rem por meia hora, uma sessao de 60 minutos tem ~43px. A
   grelha mostra "Ana +2"; quem precisa de ver o grupo todo ve-o
   aqui, e a escolha faz-se uma pessoa de cada vez.
   ------------------------------------------------------------- */
.dm-participante {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.3rem 0.2rem 0.6rem;
    border-radius: 999px;
    background: rgba(var(--primary), 0.14);
    color: rgba(var(--dark), 1);
    font-size: 12px;
    line-height: 1.6;
    white-space: nowrap;
}

.dm-participante__tirar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.15rem;
    height: 1.15rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: inherit;
    cursor: pointer;
    opacity: 0.65;
}

.dm-participante__tirar:hover:not(:disabled) {
    background: rgba(var(--primary), 0.28);
    opacity: 1;
}

.dm-participante__tirar:disabled {
    cursor: default;
    opacity: 0.35;
}

.dm-participante__tirar:focus-visible {
    outline: 2px solid rgba(var(--primary), 1);
    outline-offset: 1px;
    opacity: 1;
}


/* -------------------------------------------------------------
   MOBILE: a grelha desaparece e fica a lista por dia.

   Sete colunas num telemóvel dão colunas de 40px, onde não cabe
   um nome. Não se encolhe a grelha — troca-se de forma, com os
   mesmos dados e sem segunda leitura.
   ------------------------------------------------------------- */
.dm-agenda-lista {
    display: none;
}

@media (max-width: 767.98px) {
    .dm-agenda {
        display: none;
    }

    .dm-agenda-lista {
        display: block;
    }
}


/* -------------------------------------------------------------
   MODO ESCURO: um campo DESATIVADO ficava ilegível

   O Bootstrap dá a `:disabled` o fundo `#e9ecef` — um cinzento
   claro pensado para formulários claros. O tema, no modo escuro,
   mantém o texto branco. Resultado medido em 15/09/2026, no
   seletor de cliente do ecrã de pagamentos: `color` a
   rgb(255,255,255) sobre `background-color` rgb(233,236,239).
   Contraste ~1.1, contra o mínimo de 4.5 das WCAG.

   O sintoma é enganador e foi por isso que valeu a pena escrever
   isto: o campo parecia VAZIO. Não estava — o `selectedIndex`
   apontava para a opção certa e o `value` era o id certo. Um
   campo desativado que parece vazio manda procurar um erro nos
   dados, e o erro é de cor.

   É a mesma classe de defeito que o `--secondary` acima: uma
   regra pensada para fundos claros aplicada a um fundo escuro.

   O `opacity: 1` é preciso porque o Bootstrap esbate o campo por
   cima disto, e 0.65 sobre um fundo escuro come o resto do
   contraste. A pista de que está desativado passa a ser o fundo
   mais escuro e o cursor, que chegam.
   ------------------------------------------------------------- */

body.dark .form-control:disabled,
body.dark .form-select:disabled,
body.dark .form-control[readonly] {
    /* Os tokens do PROPRIO tema para o modo escuro, e nao cores
       escolhidas aqui: `--bs-form-control-bg` e o fundo que ele
       ja da a um campo normal, e `--bs-secondary-color` o cinzento
       que ele ja usa para texto de segundo plano. */
    background-color: var(--bs-form-control-bg);
    color: var(--bs-secondary-color);
    border-color: var(--bs-border-color);
    opacity: 1;
    cursor: not-allowed;
}


/* -------------------------------------------------------------
   AGENDA: a falta JUSTIFICADA vê-se na cara

   Das quatro presenças, só esta muda dinheiro — e o sítio onde
   a diferença se procura é a grelha da semana, não o painel,
   que obriga a abrir uma sessão de cada vez.

   `filter: grayscale` e não `opacity`: a opacidade deixava ver
   através da cara o bloco colorido da sessão por baixo, e o
   resultado lia-se como um erro de desenho. O cinzento tira a
   cor sem tirar o contorno, e o aro tracejado diz que a ausência
   é deliberada — um aro cheio mais claro passaria por "ainda a
   carregar".

   O título nativo diz o resto. Ver o `Avatares.razor`.
   ------------------------------------------------------------- */
.dm-avatares__um--isento {
    filter: grayscale(1);
    opacity: 0.75;
}

/* O FILHO DIRECTO, e nao `.avatar` nem `img`.

   Escrito primeiro como `.avatar, img` e verificado no browser
   em 16/09/2026: nao pegava. O <Avatar> sem fotografia e um
   <span> com utilitarios do tema (`h-30 w-30 b-r-50 ...`) e
   NENHUMA classe `.avatar` -- so o caso com foto e um <img>.
   Ou seja: o aro aparecia exactamente nos avatares que ja tem
   uma cara para esbater, e faltava nos que so tem iniciais, que
   e o caso comum nesta app.

   `> *` apanha os dois, e nao precisa de saber qual e. */
.dm-avatares__um--isento > * {
    outline: 1px dashed rgba(var(--white), 0.9);
    outline-offset: -1px;
}


/* =========================================================
   O PAINEL LATERAL (offcanvas do tema, placement right)

   As classes .offcanvas* sao do Bootstrap que ja esta
   carregado; aqui so esta o que o tema NAO cobre. Ver o
   PainelLateral.razor para a razao de nao haver JavaScript.
   ========================================================= */

.dm-painel {
    /* 400px e o valor do Bootstrap, e os nossos formularios
       sao de tres colunas (col-md-4). A 400 os campos passam
       todos a uma coluna e o dos tipos de acompanhamento fica
       com onze empilhados.

       Nao ha media query: o Bootstrap ja traz
       `.offcanvas { max-width: 100% }`, portanto no telemovel
       isto passa a ecra inteiro sozinho. */
    --bs-offcanvas-width: 560px;
}

/* O cabecalho separa-se do corpo, que o Bootstrap nao faz. Sem
   isto o titulo fica colado ao primeiro campo do formulario. */
.dm-painel .offcanvas-header {
    border-bottom: 1px solid var(--bs-border-color);
}

/* O RODAPE DO TEMA VEM BRANCO NO MODO ESCURO.

   O `.canvas-footer` do style.css (l.25150) e
   `background-color: rgba(var(--white), 1)`, e o --white do
   tema NAO muda com o modo -- e branco sempre. Num painel
   escuro ficava uma faixa branca por baixo dos botoes.

   E a terceira vez que o tema faz isto (ver o --secondary da
   paleta e o :disabled do Bootstrap, mais acima). A saida e a
   mesma das outras duas: usar os tokens que SEGUEM o modo. */
.dm-painel .offcanvas-footer {
    background-color: var(--bs-body-bg);
    border-top: 1px solid var(--bs-border-color);
    padding: 1rem;
}

/* O corpo rola; o cabecalho e o rodape ficam. Um formulario de
   vinte campos nao pode empurrar os botoes para fora do ecra --
   e o unico sitio onde eles estao. */
.dm-painel .offcanvas-body {
    overflow-y: auto;
}

/* Os botoes do rodape com espaco entre si. O tema poe-nos
   encostados. */
.dm-painel .offcanvas-footer .btn + .btn {
    margin-left: 0.5rem;
}

/* DENTRO DO PAINEL, UMA COLUNA. E a correccao de um erro de
   raciocinio que so se ve no browser.

   Os formularios sao escritos em `col-md-4`, `col-md-5`... e o
   `md` do Bootstrap e um breakpoint do VIEWPORT, nao do
   contentor. Num ecra de 1568px o `md` aplica-se na mesma, e o
   Bootstrap divide os 560px do painel por tres -- medido: o
   seletor de icone das poses cortava em "Membros i..." e a ajuda
   da ordem partia-se em quatro linhas.

   Container queries resolviam isto sem tocar nas paginas, mas
   seriam um sistema novo so para aqui. Uma coluna e a forma
   normal de um painel lateral, e 560px e uma largura confortavel
   para ela -- e por isso que nao sao os 400 do Bootstrap.

   Os formularios NAO mudam: continuam a ser de tres colunas na
   pagina, se algum dia voltarem la. */
.dm-painel .row > [class*="col-"] {
    flex: 0 0 100%;
    max-width: 100%;
}

/* -------------------------------------------------------------
   As listas de pessoas do painel.

   Usam o padrao do proprio tema -- `.transaction-list-item`, da
   pagina `crypto_dashboard.html` -- porque foi o autor que o
   apontou em 22/09/2026: as listas que estavam ali eram linhas
   soltas de `d-flex`, sem a estrutura de duas linhas nem a
   separacao que o tema da a toda a gente.

   Duas coisas o tema nao da, e sao estas:

   1. O `.transaction-list` do tema tem `height: 204px` com
      `overflow: auto` -- e uma caixa que rola, feita para um
      widget de dashboard. As listas do painel tem OITO linhas e
      um rodape a dizer quantas ficaram de fora; mete-las numa
      caixa que rola escondia esse rodape e punha duas barras de
      deslocamento no mesmo ecra.

   2. Nao existe `.min-w-0` no tema nem neste Bootstrap. Sem ele o
      `txt-ellipsis-1` nao corta nada: um filho de flex nao encolhe
      abaixo do seu min-content, portanto um nome comprido empurrava
      a etiqueta para fora do cartao em vez de ser truncado.
   ------------------------------------------------------------- */
.dm-lista {
    height: auto;
    overflow: visible;
}

/* Uma linha por pessoa, separadas -- e a primeira sem risca em
   cima, que fica colada ao cabecalho do cartao. */
.dm-lista .transaction-list-item {
    padding-left: 0;
    padding-right: 0;
    border-top: 1px solid var(--bs-border-color, rgba(128, 128, 128, .18));
}

.dm-lista .transaction-list-item:first-child {
    border-top: 0;
    padding-top: 0;
}

.min-w-0 {
    min-width: 0;
}
