/* =====================================================================================
   EFICÁCIA CRM — mod-artigos.css · SÓ o que o design system (ds-) não cobre
   Prefixo próprio: ma-   ·   Mobile-first (base <768px), tal como o design-system.css
   ===================================================================================== */

/* ---------- Caixa de pesquisa (vista de Famílias / Sub-Famílias) --------------
   A listagem de artigos deixou de a usar: passou para o painel de filtros da
   moldura `ds-lst` (`.ds-filter--search`). Fica para as famílias, que são duas
   tabelas simples sem filtros. */
.ma-procurar-wrap { position: relative; flex: 1 1 auto; min-width: 0; }
.ma-procurar-wrap > svg {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--neutral-400);
    pointer-events: none;
}
.ma-procurar-wrap > .ds-input { padding-left: 38px; padding-right: 40px; }
/* Botão de limpar a pesquisa (10.13 — o original não tinha) */
.ma-procurar-limpar {
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border: none;
    background: transparent;
    border-radius: var(--radius-sm);
    color: var(--neutral-400);
    cursor: pointer;
}
.ma-procurar-limpar:hover { color: var(--neutral-700); background: var(--neutral-100); }
.ma-procurar-limpar[hidden] { display: none; }
/* esconder o "x" nativo do input[type=search] (temos o nosso, com aria-label) */
.ma-procurar-wrap input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; }

@media (min-width: 768px) {
    .ma-procurar-wrap { max-width: 420px; }
}

/* ---------- Realce do termo pesquisado ---------------------------------------- */
.ma-realce {
    background: var(--warning-100, #fef3c7);
    color: inherit;
    border-radius: 3px;
    padding: 0 1px;
}

/* =====================================================================================
   LISTAGEM DE ARTIGOS — a MOLDURA é o `ds-listagem.css` (família `ds-lst-*`):
   cartões até 1023px, tabela `table-layout:fixed` a partir daí. Aqui ficam só
   as três coisas que a folha partilhada não pode saber:

     1. as LARGURAS das colunas deste ecrã (a folha traz as do contrato);
     2. a coluna extra `--stock`, que a folha não tem (é só nossa);
     3. o par de reticências da referência, que é mono e longa.

   Tudo scoped por `[data-lista="artigos"]` — não toca em mais nenhuma
   listagem. Mobile-first: a base é o cartão, o `min-width` é a tabela.
   ===================================================================================== */

/* Cartão (<1024px): o Stock viaja na mesma linha da Unidade (célula própria
   escondida) para o cartão não ganhar uma linha só para um número. */
[data-lista="artigos"] .ds-lst-c--stock { display: none; }
[data-lista="artigos"] .ma-cel-stock-mob {
    display: inline;
    margin-left: 8px;
    color: var(--text-3, #94a3b8);
}
/* A referência manda no cartão: mono, sem quebrar a meio de uma palavra. */
[data-lista="artigos"] .ds-lst-cod { overflow-wrap: anywhere; }

/* No cartão o badge de margem está sozinho no canto superior direito, sem
   cabeçalho de coluna a dizer o que é. A moldura apaga o eyebrow da célula
   de estado (lá é o estado do contrato, que se lê sozinho); aqui é um
   número, e um número sem rótulo não se lê. */
[data-lista="artigos"] .ds-lst-c--estado[data-rot]::before { content: attr(data-rot); }

@media (min-width: 1024px) {
    /* Larguras somadas (sem a `cliente`, que é a elástica):
       132+112+52+60+88+88+136+124 = 792px. O contentor mais estreito com
       sidebar é ~935px → sobram ~143px para a descrição, que corta com
       reticências; a 1440 sobram ~350px e lê-se inteira.
       Os 124px das ações são MEDIDOS: três `ds-icon-btn` de 34px + folgas
       + o padding da célula. Com 100px o botão de apagar ficava cortado
       ao passar o rato — e um botão meio visível é um botão perdido. */
    [data-lista="artigos"] .ds-lst-h--codigo { width: 132px; }
    [data-lista="artigos"] .ds-lst-h--cliente { width: auto; }
    [data-lista="artigos"] .ds-lst-h--marca { width: 112px; min-width: 0; }
    [data-lista="artigos"] .ds-lst-h--proposta { width: 52px; min-width: 0; text-align: center; }
    [data-lista="artigos"] .ds-lst-h--stock { width: 60px; text-align: right; }
    [data-lista="artigos"] .ds-lst-h--inicio { width: 88px; min-width: 0; text-align: right; }
    [data-lista="artigos"] .ds-lst-h--fim { width: 88px; min-width: 0; text-align: right; }
    /* 136px são MEDIDOS: a pílula da margem chega a "140,00 € (100,0 %)",
       que pede 107px de pílula + 24px de padding da célula. Com 96px a
       pílula era cortada a meio do próprio contorno arredondado. */
    [data-lista="artigos"] .ds-lst-h--estado { width: 136px; }
    [data-lista="artigos"] .ds-lst-h--acoes { width: 124px; }
    [data-lista="artigos"] .ds-lst-c--acoes { padding-left: 0; }

    [data-lista="artigos"] .ds-lst-c--proposta { text-align: center; }
    /* Na tabela o cabeçalho já diz «Margem»: o eyebrow do cartão sai. */
    [data-lista="artigos"] .ds-lst-c--estado[data-rot]::before { content: none; }
    /* Descrições longas ("VINIL MONOMÉRICO IMPRESSO COM LAMINAÇÃO"): o corte
       tem de ser com reticências, e o `display:block` do `.ds-lst-forte`
       tira-o à célula que as traz. Devolve-se ao próprio span. */
    [data-lista="artigos"] .ds-lst-c--cliente .ds-lst-forte,
    [data-lista="artigos"] .ds-lst-c--marca {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
    }
    [data-lista="artigos"] .ds-lst-c--stock {
        display: table-cell;
        text-align: right;
        font-variant-numeric: var(--num-tabular, tabular-nums);
    }
    /* O Stock já tem coluna própria: some da linha da Unidade. */
    [data-lista="artigos"] .ma-cel-stock-mob { display: none; }
}

/* O Stock é a coluna de MENOR prioridade (sub-sistema dormente —
   inventário §20 nota 10): é a primeira a sair quando o espaço aperta.
   Nunca desaparece do sistema: continua no cartão, na ficha e no CSV. */
@media (min-width: 1024px) and (max-width: 1199px) {
    [data-lista="artigos"] .ds-lst-h--stock,
    [data-lista="artigos"] .ds-lst-c--stock { display: none; }
    /* …e volta para junto da Unidade, como no cartão: sai da GRELHA, não do ECRÃ. */
    [data-lista="artigos"] .ma-cel-stock-mob { display: inline; }
}

/* Aviso de margem negativa nas células/detalhe (10.30) */
.ma-aviso-margem {
    display: inline-flex;
    vertical-align: -2px;
    color: var(--error-600, #dc2626);
}

/* Coluna de ações: largura mínima e sem quebra */
.ma-th-acoes { width: 1%; }

/* Alvos de toque ≥44px em ecrãs de toque (critério de aceitação §11.4):
   em modo cartão os ícones de ação são os alvos primários; a regra também
   cobre telemóveis em paisagem (≥768px de largura mas ponteiro grosso). */
@media (max-width: 767px), (pointer: coarse) {
    .ma-page .ds-icon-btn {
        width: 44px;
        height: 44px;
        min-width: 44px;
        min-height: 44px;
    }
    .ma-modal-overlay .ds-modal-close { width: 44px; height: 44px; }
    .ma-modal-overlay .ds-combobox-clear,
    .ma-page .ds-combobox-clear {
        width: 40px;
        height: 40px;
    }
}

/* ---------- FAB mobile (Adicionar Artigo) — §11.4 ----------------------------- */
.ma-fab {
    position: fixed;
    right: 16px;
    bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    z-index: var(--ds-z-sticky, 30);
    width: 56px;
    height: 56px;
    min-height: 56px;
    padding: 0;
    border-radius: 50%;
    box-shadow: var(--shadow-lg, 0 10px 24px -6px rgba(15, 23, 42, 0.35));
}
.ma-fab > svg { margin: 0; }
@media (min-width: 768px) {
    .ma-fab { display: none; }
}

/* ---------- Formulário de artigo ---------------------------------------------- */
/* Indicador de unicidade da referência (✓ / ✗ / spinner) dentro do sufixo */
.ma-ref-estado {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
}
.ma-ref-estado.is-livre { color: var(--success-600, #16a34a); }
.ma-ref-estado.is-ocupada { color: var(--error-600, #dc2626); }
.ma-ref-spinner { width: 14px; height: 14px; border-width: 2px; }

/* Faixa da margem calculada em tempo real (§11.2) */
.ma-margem-box {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 12px;
    padding: 10px 12px;
    background: var(--neutral-25, #fafafa);
    border: 1px dashed var(--neutral-200);
    border-radius: var(--radius-md);
    min-height: 44px;
}
.ma-margem-rotulo {
    font-size: var(--text-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--neutral-500);
}
.ma-alerta-margem { margin-top: 10px; }
.ma-alerta-margem .ds-alert-body { display: flex; align-items: center; gap: 8px; }

/* ---------- Detalhe ------------------------------------------------------------ */
.ma-det-auditoria {
    margin-top: 16px;
    padding-top: 12px;
    border-top: 1px dashed var(--neutral-100);
    font-size: var(--text-xs);
    color: var(--neutral-400);
    display: flex;
    flex-wrap: wrap;
    gap: 4px 6px;
}

/* Painel "Onde é usado" */
.ma-uso-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 16px;
    min-width: 0;
}
@media (min-width: 640px) {
    .ma-uso-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.ma-uso-bloco { min-width: 0; }
.ma-uso-titulo {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 8px;
    font-size: var(--text-sm);
    font-weight: 700;
    color: var(--neutral-700);
}
.ma-uso-lista {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
}
.ma-uso-lista li {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 2px;
    min-height: 36px;
    border-bottom: 1px dashed var(--neutral-100);
    min-width: 0;
}
.ma-uso-lista li:last-child { border-bottom: none; }
/* Alvo de toque ≥44px nos links da lista (auditoria responsiva, check 4):
   o link cresce em altura sem alterar a métrica visual do texto. */
.ma-uso-lista li a.ds-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    padding: 0 4px;
    margin: -8px 0;      /* absorve o padding do li — a linha não engorda */
}
.ma-uso-lista .ds-cell-muted {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}
.ma-uso-nada { margin: 2px 0 0; font-size: var(--text-xs); }

/* ---------- Famílias / Sub-Famílias ------------------------------------------- */
/* Duas tabelas lado a lado em desktop (paridade §4.5); empilhadas em mobile */
.ma-fam-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--ds-page-gap, 16px);
    align-items: start;
    min-width: 0;
}
@media (min-width: 1024px) {
    .ma-fam-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.ma-fam-grid .ma-procurar-wrap { margin-bottom: 12px; }
.ma-fam-metas { display: inline-flex; gap: 6px; flex-wrap: wrap; }

/* Nos cartões mobile, a célula-hero da família alinha nome + contadores */
@media (max-width: 767px) {
    .ma-fam-grid .ds-table td.ds-td-hero { flex-wrap: wrap; gap: 6px; }
}

/* =====================================================================================
   DASHBOARD DO CATÁLOGO  (mod-artigos.js §11.A · spec-frontend/dashboards-artigos.md)
   -------------------------------------------------------------------------------------
   Mobile-first e por esta ordem: faixa de mosaicos (uma linha que rola) → botão que
   abre a análise → gráficos → listas accionáveis. Em mobile o painel nasce FECHADO:
   quem abre a listagem no telemóvel quer a lista, e o dashboard não lhe pode roubar
   o ecrã. Em desktop nasce aberto.

   A faixa reutiliza `.ds-lst-kpis`/`.ds-lst-kpi` da moldura (`ds-listagem.css`, dentro
   de `@layer listagem` — por isso estas regras sem camada ganham-lhe sempre, seja qual
   for a especificidade). É o MESMO componente do dashboard das Propostas: só se alarga
   o mosaico, porque «a margem destes lê-se como 100 %» não cabe nos 96 px pensados
   para uma contagem.
   ===================================================================================== */

.ma-dash {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
}

/* `display:flex` ganha ao `[hidden]{display:none}` do agente do utilizador — sem
   isto o painel «fechado» continuava a ocupar o ecrã todo em mobile. */
.ma-dash[hidden],
.ma-dash-corpo[hidden] { display: none; }


.ma-dash-kpis { align-items: stretch; }

.ma-dash .ma-kpi {
    min-width: 172px;
    max-width: 264px;
    gap: 3px;
    text-align: left;
}
.ma-dash .ma-kpi-n { font-variant-numeric: var(--num-tabular); white-space: nowrap; }

/* A micro-legenda é o que impede o número de mentir: diz a base («sobre 17 artigos
   com PVP e custo») ou o que não foi apurado. Quebra de linha à vontade — nunca
   truncar, porque truncada muda de significado.

   13 px no telemóvel e 11 px só a partir do desktop: é a mesma regra que o
   `.ds-lst-kpi-rot` da moldura já aplica («nada de texto abaixo de 12 px no
   telemóvel»). E vale a dobrar aqui, porque é NESTA linha que está a ressalva
   que impede a leitura errada do número grande. */
.ma-kpi-nota {
    font-size: var(--txt-sm);
    line-height: 1.35;
    color: var(--text-3);
    white-space: normal;
    font-weight: var(--fw-medium, 500);
}
@media (min-width: 1024px) {
    .ma-kpi-nota { font-size: var(--txt-xs); }
}

/* O botão que abre/fecha a análise deixou de viver aqui: é
   `.ds-analise-toggle` no ds-listagem.css, igual nos dez módulos
   (MOD.listagem.painelAnalise). O que fica é só a GRELHA do interior,
   que é do catálogo e de mais nenhum módulo. */
.ma-dash-corpo {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--sp-3);
    align-items: start;
    min-width: 0;
}

/* ---------- Blocos (gráfico ou lista) ---------- */
.ma-dash-bloco {
    display: flex;
    flex-direction: column;
    gap: var(--sp-2);
    min-width: 0;
    padding: var(--sp-3);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
}
.ma-dash-bloco-cab {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-2);
    flex-wrap: wrap;
}
.ma-dash-bloco-tit {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    font-size: var(--txt-sm);
    font-weight: var(--fw-bold);
    text-transform: uppercase;
    letter-spacing: var(--track-caps);
    color: var(--text-2);
}
.ma-dash-cont { font-variant-numeric: var(--num-tabular); }

/* Quando o título ocupa duas linhas o «Ver todas» passa para baixo — e aí
   encostado à esquerda parecia um item da lista, não uma ação do cabeçalho.
   `margin-left:auto` mantém-no à direita nas duas situações. */
.ma-dash-bloco-cab > .ds-btn { margin-left: auto; }

/* Legenda acima do gráfico e nota abaixo da lista. É aqui que vivem as bases de
   cálculo e as trocas assumidas — e por isso não encolhem abaixo dos 11 px do
   token nem ficam em cinzento-fantasma. */
.ma-dash-legenda,
.ma-dash-nota {
    margin: 0;
    font-size: var(--txt-sm);
    line-height: 1.45;
    color: var(--text-3);
}
@media (min-width: 1024px) {
    .ma-dash-legenda,
    .ma-dash-nota { font-size: var(--txt-xs); }
}
.ma-dash-nota { padding-top: 2px; }
.ma-dash-legenda strong,
.ma-dash-nota strong { color: var(--text-2); font-weight: var(--fw-bold); }
/* `font-size: inherit` e não `.95em`: a 11 px do desktop, 0,95 dava 10,45 px —
   abaixo do mínimo legível da auditoria, e num nome de coluna (`artigo_id`) que
   é precisamente o que o leitor tem de conseguir ler para perceber a ressalva. */
.ma-dash-nota code {
    font-size: inherit;
    padding: 0 3px;
    border-radius: 4px;
    background: var(--surface-alt);
}

/* Altura CONTIDA: a lista é que manda. Sem `maintainAspectRatio:false` do lado do
   Chart.js estas alturas não pegam. */
.ma-graf-caixa { position: relative; min-width: 0; }
.ma-graf-caixa--faixas { height: 232px; }
.ma-graf-caixa--forn { height: 320px; }
@media (min-width: 1024px) {
    .ma-graf-caixa--faixas { height: 252px; }
    .ma-graf-caixa--forn { height: 356px; }
}
.ma-graf-caixa canvas { max-width: 100%; }

/* A tabela equivalente do gráfico. Fica escondida (`ds-sr-only` no DIV que a
   embrulha) para leitores de ecrã; só se revela quando o Chart.js não carrega,
   e aí tem de ser legível. O `overflow-x` é do embrulho: uma tabela revelada
   não pode ser ela a dar scroll horizontal ao body. */
.ma-tab-wrap:not(.ds-sr-only) { overflow-x: auto; max-width: 100%; }
.ma-tab-dados { width: 100%; border-collapse: collapse; font-size: var(--txt-xs); }
.ma-tab-dados caption {
    text-align: left;
    padding-bottom: var(--sp-1);
    color: var(--text-3);
    font-weight: var(--fw-bold);
}
.ma-tab-dados th,
.ma-tab-dados td {
    padding: 6px 8px;
    border-bottom: 1px solid var(--border);
    text-align: left;
    white-space: nowrap;
}
.ma-tab-dados td { font-variant-numeric: var(--num-tabular); }

/* ---------- Listas accionáveis ---------- */
/* GRID com `grid-auto-rows: 1fr` e não uma coluna flex: em mobile os números de
   uma linha cabem numa linha de texto e os da seguinte passam para duas, e as
   linhas ficavam com alturas diferentes — o que num bloco de cinco se lê como
   desalinhamento, não como conteúdo diferente. Assim todas as linhas tomam a
   altura da mais alta. */
.ma-mini-lista { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-rows: 1fr; }
.ma-mini-linha {
    display: flex;
    align-items: stretch;
    gap: var(--sp-2);
    min-width: 0;
    border-bottom: 1px solid var(--border);
}
.ma-mini-linha:last-child { border-bottom: none; }

.ma-mini-abrir {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-content: center;
    gap: 2px;
    flex: 1 1 auto;
    min-width: 0;
    min-height: var(--ds-touch, 44px);
    padding: var(--sp-2) 0;
    border: 0;
    background: none;
    text-align: left;
    cursor: pointer;
    color: inherit;
    font: inherit;
}
.ma-mini-abrir:hover .ma-mini-nome { color: var(--text-1); }
.ma-mini-ref {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: var(--txt-sm);
    font-weight: var(--fw-bold);
    color: var(--text-3);
    overflow-wrap: anywhere;
}
.ma-mini-nome {
    font-size: var(--txt-sm);
    font-weight: var(--fw-medium, 500);
    color: var(--text-2);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* `nowrap`: com wrap, uma linha cujo fornecedor fosse comprido passava os
   números para uma segunda linha e a linha crescia para 112 px em mobile —
   e, por `grid-auto-rows: 1fr`, arrastava as outras quatro com ela. O nome do
   fornecedor tem reticências; os números, que são o que importa, ficam sempre
   à vista. */
.ma-mini-nums {
    display: flex;
    align-items: baseline;
    gap: var(--sp-2);
    flex-wrap: nowrap;
    min-width: 0;
    font-size: var(--txt-sm);
    font-variant-numeric: var(--num-tabular);
    color: var(--text-3);
}
.ma-mini-num { flex: 0 0 auto; }
.ma-mini-num:not(.ma-mini-num--sec) { font-weight: var(--fw-bold); color: var(--text-2); }
.ma-mini-num--sec { font-weight: var(--fw-medium, 500); color: var(--text-3); }
.ma-mini-num--mau { color: var(--danger-600, #b80a0c); }
.ma-mini-vazio { font-style: italic; color: var(--text-3); }
.ma-mini-forn {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* A mesma altura do botão que abre a linha (44 px). Com o `ds-btn--sm` a 32 px
   ficavam dois botões de alturas diferentes lado a lado — e o mais pequeno era
   justamente a ação («Corrigir preços»), abaixo do alvo de toque mínimo. */
/* Ocupa a linha toda, como o botão que a abre. Com `align-self:center` ficavam
   44 px ao lado de 82 px — dois botões irmãos de alturas diferentes, que é o que
   a auditoria apanha (check 9) e o que o olho lê como desalinhado. A altura
   inteira também dá à ação uma zona de toque a sério em mobile. */
.ma-mini-accao {
    flex: 0 0 auto;
    align-self: stretch;
    /* `.ds-btn--sm` fixa `height` — e uma altura explícita ganha sempre ao
       `align-self: stretch`. Sem este `auto`, o botão continuava a 32/44 px. */
    height: auto;
    white-space: nowrap;
    min-height: var(--ds-touch, 44px);
}

/* ---------- Erro da faixa ---------- */
.ma-dash-erro {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex-wrap: wrap;
    width: 100%;
    padding: var(--sp-2) var(--sp-3);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    background: var(--surface);
    font-size: var(--txt-sm);
    color: var(--text-3);
}

/* ---------- Desktop: dois gráficos por linha ----------
   Os gráficos lado a lado e as listas por baixo em largura inteira: uma lista de
   trabalho lê-se em linha, não em coluna estreita. */
@media (min-width: 1024px) {
    .ma-dash { gap: var(--sp-3); }
    .ma-dash-corpo { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .ma-dash-bloco { padding: var(--sp-4); }
    .ma-dash-corpo > [data-ma-bloco] { grid-column: 1 / -1; }
    .ma-mini-abrir {
        grid-template-columns: 128px minmax(0, 1fr) auto;
        align-items: baseline;
        gap: var(--sp-3);
    }
    .ma-mini-nums { justify-content: flex-end; flex-wrap: nowrap; }
}

/* A partir daqui há largura para os seis mosaicos de uma vez. A faixa que
   rola (o comportamento da moldura) resolve o telemóvel, mas em desktop
   um KPI atrás de um scroll horizontal é um KPI que ninguém vê — e o que
   está escondido costuma ser o último, que aqui é o que explica porque é
   que a utilização está a zero. */
@media (min-width: 1024px) {
    /* GRID e não `flex-wrap`: o flex estica os itens LINHA A LINHA, e com 6
       mosaicos em 4+2 a segunda fila ficava 15 px mais baixa do que a primeira.
       `grid-auto-rows: 1fr` dá a mesma altura a todas as filas.

       Três colunas fixas e não `auto-fit`: com `auto-fit` cabiam 5 numa fila e
       o sexto ficava sozinho com quatro quintos da linha vazios ao lado — e o
       sexto é justamente o que explica porque é que a utilização está a zero.
       3×2 fecha a grelha e dá largura à micro-legenda, que aqui é texto a
       sério e não um subtítulo. */
    .ma-dash-kpis {
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        grid-auto-rows: 1fr;
        overflow-x: visible;
    }
    .ma-dash .ma-kpi { max-width: none; min-width: 0; }
}

/* Ecrã largo: os seis cabem numa fila só. */
@media (min-width: 1700px) {
    .ma-dash-kpis { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

@media print {
    .ma-dash { display: none; }
}
