/* Terminal (quiosque) — protótipo exclusivamente visual. Tela cheia, alvos de toque grandes,
   baixa densidade de informação. Reaproveita as variáveis --tm-* definidas em durin-tokens.css. */

html:has(.terminal-bare),
html:has(.terminal-app) {
    overflow-x: hidden;
}

/* =====================================================================================
   CONTRATO DO CANAL — tokens e alvos de toque
   (§4.1 e §4.3 de docs/terminal-full-visual-review-plan.md; medições em
   docs/terminal-visual-baseline.md)

   Existe porque a medição renderizada mostrou que declarar tamanho botão a botão não
   funciona: dos 186 MudButton do terminal, os 143 sem Size ficavam em 36,5 px e os 43 com
   Size.Large paravam em 42,25 px — nenhum alcançava os 48 px, em nenhuma viewport. Um piso
   declarado uma vez vale mais que 186 decisões individuais.
   ===================================================================================== */

/* Reatribuição de tokens DENTRO do canal. Não são aliases novos: são os mesmos --tm-* de
   durin-tokens.css, reapontados só aqui, para os portais não mudarem de aparência. */
.terminal-app,
.terminal-bare {
    /* O laranja da marca (#F15A24) dá 3,37:1 com texto branco — reprova nos 4,5:1 do §11.3.
       Este tom é o mesmo laranja escurecido até passar (~4,6:1), e vale SÓ no papel de
       superfície/rótulo de botão: ícones, selos e destaques continuam usando --tm-primary. */
    --tm-primary-action: #CE4716;
    --tm-primary-action-hover: #B23C11;

    /* #747A80 dava 4,34:1 sobre branco em quinze papéis diferentes (código de SKU, "Etapa X de
       Y", metadados, rodapé). O degrau resolve o conjunto inteiro — e foi escolhido para passar
       também sobre as superfícies TINGIDAS (cartão destacado #FFF4EE, cartão selecionado), onde
       o branco puro não é o fundo real: 5,0:1 sobre branco e 4,6:1 sobre o tinto. */
    --tm-text-muted: #6A7076;

    /* Trava explícita da família. O canal do quiosque é quase todo HTML nativo (div, span,
       button próprio) e por isso herdava direto do `body`; quando o `body` era 'Helvetica Neue',
       o terminal inteiro renderizava em Helvetica enquanto os poucos MudText vizinhos vinham em
       Montserrat. Hoje o `body` já resolve para --font-body, mas repetir aqui deixa o canal
       imune a qualquer folha futura que volte a mexer no `body` do portal. */
    font-family: var(--font-body);
}

/* Piso tátil. `:where()` zera a especificidade do ancestral de propósito: assim a regra vale
   0,1,0 e qualquer contrato MAIOR declarado adiante neste arquivo (teclado de 56 px, cartão de
   128 px, operador de 72 px) continua ganhando. O piso nunca encolhe ninguém.

   Seletores de data e adornos de campo ficam de fora: lá dentro o `.mud-button-root` é dia de
   calendário ou ícone de campo denso, e 48 px destruiria a grade.

   O MudSwitch também fica de fora: a base dele (`.mud-switch-base`) é um `.mud-icon-button`
   posicionado em absoluto, com 38 px (polegar de 20 + padding de 9) calculados para o trilho.
   Com 48 px o polegar descia 5 px e saía do trilho. O alvo de toque do switch é o `<label>`
   inteiro, com o texto — o piso dele está em `.terminal-settings-toggle-row`. */
:where(.terminal-app, .terminal-bare) .mud-button-root:not(:where(.mud-picker *, .mud-input-adornment *, .mud-switch *)) {
    min-height: 48px;
}

/* Botão só de ícone precisa dos DOIS eixos. O segundo seletor existe para vencer o
   `.mud-icon-button.mud-button { min-width: unset }` do MudBlazor (0,2,0) — era ele que fazia
   os controles +/- de quantidade renderizarem 42 px de largura apesar do `min-width: 48px`
   declarado no componente. */
:where(.terminal-app, .terminal-bare) .mud-icon-button:not(:where(.mud-picker *, .mud-input-adornment *, .mud-switch *)),
:where(.terminal-app, .terminal-bare) .mud-icon-button.mud-button:not(:where(.mud-picker *, .mud-input-adornment *, .mud-switch *)) {
    min-width: 48px;
    min-height: 48px;
}

/* Campo de formulário também é alvo de toque (§4.5). O `Margin.Dense` do painel de filtros
   entregava 40 px de altura — abaixo do piso, e é justamente o campo que se usa com o teclado
   virtual aberto. O piso não desfaz a densidade: só impede que ela caia abaixo do contrato.

   O piso vai na CAIXA do campo (`.mud-input`) e NUNCA no `<input>` de dentro (`.mud-input-root`).
   O input outlined do MudBlazor já carrega o próprio padding vertical, então um min-height ali
   soma em vez de substituir: medido, um MudSelect que nasce com 56px ia para 85px. A caixa é
   também o que a pessoa realmente toca — clicar na borda do campo já foca o input. */
:where(.terminal-app, .terminal-bare) .mud-input {
    min-height: 48px;
}

/* Foco visível dos cartões que agora são controles de verdade (role="button" + tabindex). Sem
   isto, a navegação por teclado que acabou de ser habilitada seria invisível. Mesma anatomia do
   `.terminal-position-option:focus-visible`, que já era o padrão correto do canal. */
:where(.terminal-app, .terminal-bare) .terminal-action-card:focus-visible,
:where(.terminal-app, .terminal-bare) .terminal-sku-card:focus-visible,
:where(.terminal-app, .terminal-bare) .terminal-withdrawal-card:focus-visible,
:where(.terminal-app, .terminal-bare) .terminal-card-selected:focus-visible,
:where(.terminal-app, .terminal-bare) .terminal-withdrawal-list > .mud-paper:focus-visible {
    outline: 2px solid var(--tm-primary, #F15A24);
    outline-offset: 2px;
}

/* Cor do botão primário no canal. Filled usa o tom escurecido como FUNDO; Outlined e Text o usam
   como TEXTO — nos dois casos o rótulo é o que precisava passar no contraste.

   Os seletores repetem o par de classes do MudBlazor (`.mud-button-filled.mud-button-filled-primary`,
   0,2,0) porque é dele que precisam ganhar; um seletor de classe única perderia e o botão
   continuaria laranja de marca. A borda do Outlined fica como está: borda não é texto, e os 3,37:1
   do laranja da marca já passam no mínimo de 3:1 de elemento não textual. */
:where(.terminal-app, .terminal-bare) .mud-button-filled.mud-button-filled-primary {
    background-color: var(--tm-primary-action);
}

:where(.terminal-app, .terminal-bare) .mud-button-filled.mud-button-filled-primary:hover,
:where(.terminal-app, .terminal-bare) .mud-button-filled.mud-button-filled-primary:focus-visible,
:where(.terminal-app, .terminal-bare) .mud-button-filled.mud-button-filled-primary:active {
    background-color: var(--tm-primary-action-hover);
}

:where(.terminal-app, .terminal-bare) .mud-button-outlined.mud-button-outlined-primary,
:where(.terminal-app, .terminal-bare) .mud-button-text.mud-button-text-primary {
    color: var(--tm-primary-action);
}

/* O azul de Info do MudBlazor dá 3,62:1 sobre o próprio fundo tingido do alerta. As outras três
   severidades já passam; só esta precisava de um degrau. Não é cor de marca — é paleta de
   componente —, então o ajuste fica aqui e não vira decisão de identidade. */
:where(.terminal-app, .terminal-bare) .mud-alert-text-info {
    color: #0A6FBF;
}

/* ---------- Ativação (/terminal) ---------- */

.terminal-activation {
    width: 100%;
    max-width: 420px;
    display: flex;
    flex-direction: column;
    align-items: center;
}

.terminal-activation-brand {
    margin-bottom: 24px;
}

.terminal-activation-card {
    width: 100%;
    padding: 32px;
    box-sizing: border-box;
}

.terminal-activation-subtitle {
    color: var(--tm-text-muted, #747A80);
    margin-top: 8px;
}

.terminal-activation-form {
    display: flex;
    flex-direction: column;
}

/* Campo do serial + botão de leitura por QR Code, lado a lado.

   O botão é irmão do campo (e não adorno interno do MudTextField) porque o adorno renderiza com
   tabindex="-1" e ficaria inalcançável por teclado.

   `align-items: flex-start` alinha pelo TOPO: alinhar pelo centro deslocaria o botão para baixo
   assim que a mensagem de validação aparecesse embaixo do input, e alinhar pela base o deslocaria
   junto com ela.

   O detalhe que faz o alinhamento fechar de verdade é a margem. O MudTextField traz
   `margin: 8px 0 4px` no próprio `.mud-input-control`, então a caixa desenhada do campo começa
   8 px ABAIXO do topo da linha — e o botão, sem margem nenhuma, ficava 8 px acima dela. A margem
   de cima é transferida para a LINHA e zerada no campo: assim os dois filhos partem exatamente do
   mesmo ponto, o espaçamento em relação ao que vem acima não muda, e nada aqui repete o valor que
   o MudBlazor usa internamente. */
.terminal-activation-serial-row {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin-top: 8px;
}

.terminal-activation-serial-row .terminal-activation-serial-field {
    flex: 1 1 auto;
    min-width: 0;
    margin-top: 0;
}

/* 56 px: a altura da caixa do campo com Variant.Outlined, e bem acima do alvo mínimo de toque
   de 48 px de um tablet operado com luva. */
.terminal-activation-scan-btn.mud-icon-button {
    width: 56px;
    height: 56px;
    flex: 0 0 auto;
}

.terminal-activation-hint {
    display: block;
    margin-top: 16px;
    color: var(--tm-text-muted, #747A80);
    text-align: center;
}

.terminal-activation-support {
    margin-top: 24px;
    color: var(--tm-text-muted, #747A80);
}

.terminal-activation-success,
.terminal-activation-offline {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 24px 0;
    gap: 4px;
}

/* ---------- Identificação (/terminal/app) ---------- */

.terminal-login {
    width: 100%;
    display: flex;
    justify-content: center;
}

.terminal-login-card {
    width: 100%;
    max-width: 420px;
    padding: 32px;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

/* O tamanho vem do parâmetro Size do LogoMarkIcon, que já vira width/height no <img> e reserva o
   espaço antes do download. Aqui fica só o espaçamento e o alinhamento no card. */
.terminal-login-avatar {
    margin-bottom: 12px;
    display: flex;
    justify-content: center;
}

.terminal-login-title {
    margin-bottom: 4px;
}

.terminal-login-subtitle {
    color: var(--tm-text-muted, #747A80);
    margin-bottom: 8px;
}

/* O card é flex column com align-items:center, então um filho em bloco encolheria até o conteúdo.
   Estas larguras explícitas são o que mantém as duas etapas com a MESMA caixa — sem elas a tela
   "pula" de largura ao trocar o campo de matrícula pelo teclado do PIN. */
.terminal-login-step,
.terminal-login-form,
.terminal-login-alert {
    width: 100%;
}

/* A matrícula usa o mesmo teclado da tela que o PIN, mas com valor legível. Como não existe input
   focável, tocar nesta etapa nunca abre o teclado completo do sistema no quiosque. */
.terminal-registration-keypad {
    width: 100%;
    margin-top: 16px;
}

.terminal-registration-label {
    display: block;
    margin-bottom: 8px;
    text-align: left;
    color: var(--tm-text-muted, #747A80);
}

.terminal-registration-keypad .terminal-keypad {
    margin-top: 0;
}

.terminal-registration-keypad .terminal-keypad-display-value {
    min-height: 56px;
    margin-bottom: 12px;
    padding: 8px 12px;
    align-items: center;
    border: 1px solid var(--tm-border, #D8DADD);
    border-radius: 8px;
    box-sizing: border-box;
    font-size: clamp(1.25rem, 6vw, 2rem);
    line-height: 1.15;
    overflow-wrap: anywhere;
    word-break: break-all;
}

/* Etapa 2: a matrícula já informada, discreta. É confirmação visual, não um campo — o valor que
   vai para o servidor é o input hidden dentro do formulário. */
.terminal-login-identity {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 4px;
    color: var(--tm-text-muted, #747A80);
    font-size: 0.875rem;
}

.terminal-login-identity-value {
    font-weight: 600;
    color: var(--tm-text, #111111);
    /* Matrícula é texto livre de até 30 caracteres: sem isto, uma matrícula longa estoura a
       largura do card em vez de quebrar. */
    overflow-wrap: anywhere;
}

.terminal-login-help {
    margin-top: 16px;
}

.terminal-login-submitting {
    width: 100%;
    margin-top: 16px;
    display: grid;
    gap: 8px;
    color: var(--tm-text-muted, #747A80);
}

.terminal-login-submitting[hidden] {
    display: none;
}

/* A barra ocupa o lugar do botão durante o POST, preservando a altura do cartão em telas baixas. */
.terminal-login-form[aria-busy="true"] .terminal-login-submit {
    display: none;
}

/* ---------- Cartão RFID (identificação e /terminal/app/cartao) ----------
   docs/terminal-rfid-authentication-plan.md. O leitor em modo teclado não tem estado observável:
   o desenho diz "aguardando leitura", nunca "leitor conectado". */

/* Captor: focável e acessível (rótulo próprio), mas fora da vista. Não é display:none nem
   visibility:hidden — os dois tirariam o foco, e o foco "vazio" é o que mantém a rajada do leitor
   longe dos botões. O contêiner relativo impede que o absoluto role a página ao focar. */
.terminal-card-login-form,
.terminal-card-capture {
    position: relative;
}

.terminal-card-captor {
    position: absolute;
    top: 0;
    left: 0;
    width: 1px;
    height: 1px;
    margin: 0;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    opacity: 0;
}

.terminal-card-reader-visual {
    position: relative;
    width: 112px;
    height: 112px;
    margin: 20px auto 4px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background-color: var(--tm-primary-tint, #FDEAE1);
    color: var(--tm-primary, #F15A24);
}

.terminal-card-reader-visual .mud-icon-root {
    width: 56px;
    height: 56px;
}

/* Pulso discreto de "pronto para ler". Some durante o envio e para quem pede menos movimento. */
.terminal-card-reader-visual::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 2px solid currentColor;
    opacity: 0;
    animation: terminal-card-reader-pulse 2.4s ease-out infinite;
}

@keyframes terminal-card-reader-pulse {
    0% {
        transform: scale(1);
        opacity: 0.35;
    }

    100% {
        transform: scale(1.35);
        opacity: 0;
    }
}

.terminal-card-login-form[aria-busy="true"] .terminal-card-reader-visual::after {
    animation: none;
}

@media (prefers-reduced-motion: reduce) {
    .terminal-card-reader-visual::after {
        animation: none;
    }
}

.terminal-login-mode-switch {
    min-height: 48px;
}

/* Enquanto a preferência local do método inicial é lida: estado neutro, sem formulário. */
.terminal-login-preparing {
    width: 100%;
    margin-top: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    color: var(--tm-text-muted, #747A80);
}

/* /terminal/app/cartao */
.terminal-card-loading {
    display: flex;
    justify-content: center;
    padding: 32px 0;
}

.terminal-card-status-head {
    display: flex;
    align-items: flex-start;
    gap: 16px;
}

.terminal-card-status-icon {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    color: var(--tm-primary, #F15A24);
}

.terminal-card-status-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

/* Sufixo mascarado: tabular para "•••• 4225" não dançar de largura entre cartões. */
.terminal-card-masked {
    font-size: 1.25rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    font-variant-numeric: tabular-nums;
    color: var(--tm-text, #111111);
}

.terminal-card-status-date,
.terminal-card-status-hint,
.terminal-card-capture-hint,
.terminal-card-unavailable {
    color: var(--tm-text-muted, #747A80);
}

.terminal-card-session-hint {
    padding: 10px 14px;
    border-radius: 10px;
    border: 1px solid var(--tm-border, #D8DADD);
    background-color: var(--tm-primary-tint, #FDEAE1);
    color: var(--tm-text, #111111);
}

.terminal-card-form {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.terminal-card-actions,
.terminal-card-capture,
.terminal-card-confirm {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.terminal-card-actions > .mud-button-root {
    min-height: 48px;
}

.terminal-card-capture {
    align-items: stretch;
    text-align: center;
}

.terminal-card-candidate {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px;
}

.terminal-card-confirm .terminal-keypad {
    margin-top: 4px;
}

/* ---------- Teclado numérico ---------- */

.terminal-keypad {
    width: 100%;
    margin-top: 20px;
}

.terminal-keypad-display {
    display: flex;
    justify-content: center;
    gap: 10px;
    margin-bottom: 16px;
}

.terminal-keypad-dot {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    border: 2px solid var(--tm-border, #D8DADD);
    box-sizing: border-box;
}

.terminal-keypad-dot-filled {
    background-color: #F15A24;
    border-color: #F15A24;
}

.terminal-keypad-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 10px;
}

.terminal-keypad-key {
    min-height: 56px;
    font-size: 1.25rem !important;
}

.terminal-keypad-key-action {
    font-size: 0.875rem !important;
}

.terminal-keypad-display-value {
    font-size: 2.25rem;
    font-weight: 700;
    min-height: 1.2em;
}

/* Variante compacta OPT-IN (parâmetro Compact do componente), usada só no inventário: mesmas
   quatro linhas e três colunas, menos gaps e margens, teclas de 2.75rem (= 44px, o piso de alvo
   de toque — nunca abaixo). Sem o parâmetro, PIN e perfil seguem exatamente como estavam. */
.terminal-keypad-compact {
    margin-top: 0;
}

.terminal-keypad-compact .terminal-keypad-grid {
    gap: 8px;
}

.terminal-keypad-compact .terminal-keypad-key {
    /* max(): 48px e o piso do canal (§12 do plano pede que a variante compacta não fique
       abaixo dele), 2.75rem o que continua crescendo com a preferência "Texto grande". */
    min-height: max(48px, 2.75rem);
    font-size: 1.125rem !important;
}

/* ---------- Cabeçalho do terminal (TerminalAppLayout) ---------- */

/* Composição determinística em DUAS LINHAS — logo à esquerda e operador à direita na primeira,
   máquina inteira na segunda — como padrão, com a linha única entrando só a partir de 760px
   (bloco @media no fim desta seção).

   Este é o padrão, e não o contrário, porque a linha única não cabe em tela estreita: abaixo de
   760px ela espremia a coluna do operador para menos que a largura da palavra "Administrador",
   que não tem onde quebrar e vazava por cima do botão de perfil. Dar um piso àquela coluna
   apenas trocava a sobreposição por rolagem horizontal do cabeçalho — não havia espaço para
   logo + máquina + operador + dois botões numa linha só.

   Vale para os três estados: só máquina (a célula do operador fica vazia), operador comum e
   administrador. */
.terminal-header {
    display: grid;
    /* A marca NÃO cede largura; quem cede é o bloco do operador, cujo nome já trunca.
       Era o contrário — `minmax(0, 1fr) auto` — e a coluna da marca chegava a 24 px em 320 px
       enquanto a imagem, com width fixo no atributo, continuava com 120 px e caía POR CIMA do
       avatar. Medido: 84 px de sobreposição em 320 px, 57 px em 360 px, 10 px em 430 px, com
       nome de operador curto ou longo. */
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    row-gap: 8px;
    column-gap: 12px;
    /* Região fixa do shell (.terminal-app é height:100dvh com só o <main> rolando): o cabeçalho
       nunca cede altura para o conteúdo nem sai da viewport. */
    flex-shrink: 0;
    padding: 12px 16px;
    /* A PWA do terminal declara viewport-fit=cover (TerminalPwaHead), então em standalone o
       cabeçalho fica por baixo da barra de status/recorte. Os insets valem 0 em qualquer
       navegador ou aparelho sem recorte, então o layout de desktop não muda. */
    padding-top: calc(12px + env(safe-area-inset-top));
    padding-left: calc(16px + env(safe-area-inset-left));
    padding-right: calc(16px + env(safe-area-inset-right));
    background-color: #FFFFFF;
    border-bottom: 1px solid var(--tm-border, #D8DADD);
    min-height: 64px;
    box-sizing: border-box;
}

/* O espaçador só faz sentido no flex de uma linha; na grade ele viraria uma célula fantasma. */
.terminal-header .mud-spacer {
    display: none;
}

.terminal-header-brand {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    grid-row: 1;
    grid-column: 1;
}

/* Rede de segurança do mesmo defeito: a imagem da marca declara width/height em atributo, então
   sem isto ela ignora a caixa que a recebe. Com `height: auto` ela encolhe mantendo proporção em
   vez de transbordar. */
.terminal-header-brand .logo-mark {
    max-width: 100%;
    height: auto;
}

/* Em celular a conta de largura não fecha com a marca em 120px: perfil e bloqueio ocupam 48px cada
   pelo contrato tátil, e ainda precisam caber avatar e nome do operador. Quem cede é a marca — ela
   continua legível menor, enquanto um alvo de toque menor e um nome de operador oculto não são
   negociáveis. Medido em 320px: 72px de marca deixam 204px para o bloco do operador, que precisa
   de ~194px. */
@media (max-width: 379px) {
    .terminal-header-brand .logo-mark {
        width: 72px;
    }
}

@media (min-width: 380px) and (max-width: 599px) {
    .terminal-header-brand .logo-mark {
        width: 96px;
    }
}

.terminal-header-machine {
    display: flex;
    flex-direction: column;
    gap: 2px;
    /* Nome de máquina é texto livre: sem min-width:0 um nome longo empurra o bloco do operador
       para fora da viewport em vez de truncar. */
    min-width: 0;
    grid-row: 2;
    grid-column: 1 / -1;
}

.terminal-header-machine-name {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.terminal-header-machine-title {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.terminal-header-serial {
    color: var(--tm-text-muted, #747A80);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.terminal-header-user {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
    /* Com `justify-self: end` o item é dimensionado pelo max-content e simplesmente VAZA para a
       esquerda da própria célula — foi assim que ele passou a cobrir a marca. O max-width prende o
       bloco à célula e obriga o nome do operador (que já trunca) a ceder, que é o comportamento
       pretendido desde sempre. */
    max-width: 100%;
    grid-row: 1;
    grid-column: 2;
    justify-self: end;
}

.terminal-header-user-info {
    display: flex;
    flex-direction: column;
    line-height: 1.1;
    min-width: 0;
}

/* Perfil e bloqueio ficam SEMPRE visíveis: quem cede espaço é o nome do operador. */
.terminal-header-user-name {
    max-width: 32vw;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* "Administrador" é uma palavra só: sem onde quebrar, ela transbordava a caixa da coluna (que
   tem min-width:0 para o nome poder truncar) e ia parar por baixo do botão de perfil. A grade de
   duas linhas é o que devolve espaço; estas quatro linhas são a rede de segurança, para o rótulo
   nunca mais vazar — com qualquer largura, qualquer perfil e o "Texto grande" ligado, que escala
   tudo em rem. O title do elemento mantém o texto completo acessível quando truncar. */
.terminal-header-admin-badge {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.7rem;
    font-weight: 600;
    color: #F15A24;
}

/* A partir de 760px sobra largura para tudo numa linha só — o visual histórico do desktop.

   760 e não 700: o limiar é a largura em que "Administrador" ainda cabe INTEIRO na linha, e quem
   manda no pior caso é a preferência "Texto grande" (html { font-size: 18px }), que engorda o
   rótulo para ~86px. Medido: em 700px falta 24px e em 730px ainda faltam 11px; em 760px cabe com
   folga. Abaixo disso a rede de segurança salvaria da sobreposição, mas às custas de exibir
   "Administrad…" — e um indicador de perfil cortado não serve para o que ele existe.

   min-width (e não um max-width no bloco acima) de propósito: assim não existe faixa fracionária
   descoberta entre os dois layouts. Com `max-width: 759px`, uma janela de 759,5px cairia na linha
   única, que é justamente onde a sobreposição acontecia. */
@media (min-width: 760px) {
    .terminal-header {
        display: flex;
        gap: 20px;
        padding: 12px 24px;
        /* Repetidos porque o shorthand acima zera os insets herdados da regra base. */
        padding-top: calc(12px + env(safe-area-inset-top));
        padding-left: calc(24px + env(safe-area-inset-left));
        padding-right: calc(24px + env(safe-area-inset-right));
    }

    /* Volta a empurrar o bloco do operador para a direita — na grade quem fazia isso era o
       justify-self, que o flex ignora. */
    .terminal-header .mud-spacer {
        display: block;
    }

    /* Quem cede largura é o nome da MÁQUINA, que já trunca com reticências e guarda o valor
       inteiro no title. Sem isto o bloco da máquina vencia a disputa de flex e espremia o do
       operador: medido em 28 px no 768x1024 e 42 px no 800x1280 — nome do operador e selo
       "Administrador" ilegíveis justamente no formato de tablet retrato. */
    .terminal-header-user {
        flex-shrink: 0;
    }

    .terminal-header-user-name {
        max-width: clamp(96px, 22vw, 240px);
    }
}

/* ---------- Badges de máquina ---------- */

.machine-type-badge {
    display: inline-flex;
    align-items: center;
    padding: 2px 10px;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.machine-type-badge-fisica {
    background-color: #E8EAF6;
    color: #303236;
}

.machine-type-badge-virtual {
    background-color: #E3F2FD;
    color: #1565C0;
}

.machine-type-badge-unknown {
    background-color: #ECEFF1;
    color: #4A4F55;
}

.machine-status-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 2px 10px;
    border-radius: 999px;
    font-size: 0.7rem;
    font-weight: 600;
}

.machine-status-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
}

.machine-status-badge-ok {
    background-color: #E8F5E9;
    color: #2E7D32;
}

.machine-status-badge-ok .machine-status-dot {
    background-color: #2E7D32;
}

.machine-status-badge-warning {
    background-color: #FFF3E0;
    color: #C77700;
}

.machine-status-badge-warning .machine-status-dot {
    background-color: #C77700;
}

.machine-status-badge-error {
    background-color: #FDECEA;
    color: #B3261E;
}

.machine-status-badge-error .machine-status-dot {
    background-color: #B3261E;
}

.machine-status-badge-neutral {
    background-color: #ECEFF1;
    color: #747A80;
}

.machine-status-badge-neutral .machine-status-dot {
    background-color: #747A80;
}

/* ---------- Cartões de ação (página inicial) ---------- */

.terminal-home-greeting {
    margin-bottom: 2px;
}

.terminal-home-subtitle {
    color: var(--tm-text-muted, #747A80);
    margin-bottom: 24px;
}

/* minmax(0, 1fr) e não 1fr: com o selo de perfil no fluxo (nowrap), o min-content do card passa
   a incluir a largura do selo, e um `1fr` — que é minmax(auto, 1fr) — deixaria um selo longo
   esticar a coluna e estourar a grade. Com o mínimo zerado, quem cede é o selo (max-width +
   reticências), nunca a grade. */
.terminal-home-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px;
}

.terminal-home-secondary {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 16px;
}

/* Par de opções IRMÃS — duas ações que são a mesma decisão vista dos dois lados (retirar aqui /
   receber aqui, no submenu de movimentação entre estoques; a gaveta que já tem o item / a gaveta
   vazia, na escolha de alocação).

   Classe própria, e NÃO um modificador da grade do menu do início, por dois motivos que se
   somam:

     * o cartão destacado daquela grade tem `grid-column: span 2` de propósito — lá ele é a ação
       principal ENTRE VÁRIAS, e ocupar o dobro é a hierarquia. Aqui as duas ações têm o mesmo
       peso, e o destaque diz apenas por onde a maioria começa: é pintura, não tamanho;
     * as regras de paisagem levam aquela grade para 3 e 4 colunas. Com dois cartões só, isso
       deixaria metade da linha vazia.

   `grid-auto-rows: 1fr` cuida do empilhamento do celular: as linhas ficam do mesmo tamanho, em
   vez de um cartão encolher por ter a descrição mais curta. */
.terminal-option-pair {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    grid-auto-rows: 1fr;
    gap: 16px;
}

/* Sem isto o span 2 herdado jogaria o cartão destacado para a linha inteira e empurraria o irmão
   para baixo — exatamente a diferença de tamanho que esta grade existe para não ter. */
.terminal-option-pair > .terminal-action-card-highlighted {
    grid-column: auto;
}

.terminal-action-card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
    padding: 20px;
    border: 1px solid var(--tm-border, #D8DADD);
    border-radius: 12px;
    cursor: pointer;
    min-height: 128px;
    box-sizing: border-box;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.terminal-action-card:hover {
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
}

.terminal-action-card:active {
    transform: scale(0.99);
}

.terminal-action-card-highlighted {
    grid-column: span 2;
    background-color: #FFF4EE;
    border-color: #F15A24;
}

.terminal-action-card-disabled {
    cursor: not-allowed;
    opacity: 0.6;
}

/* Linha do topo do card: ícone à esquerda, selo de perfil à direita. Ela existe para RESERVAR
   espaço para os dois — ver os dois selos logo abaixo. */
.terminal-action-card-top {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
}

.terminal-action-card-icon {
    color: #F15A24;
    flex-shrink: 0;
}

.terminal-action-card-title {
    margin: 0;
}

.terminal-action-card-description {
    color: var(--tm-text-muted, #747A80);
}

/* Os dois selos do card — perfil exigido ("Administrador") no topo e motivo do bloqueio
   ("Inventário em andamento") na base — ficam NO FLUXO, em QUALQUER largura.

   Eram absolutos, e um elemento absoluto não empurra nada: ele apenas passa por cima quando o
   conteúdo cresce até a posição dele. O caso mais visível era a grade de duas colunas entre 601
   e 699px, onde o card cai para ~269px e a descrição quebra em linhas suficientes para alcançar
   o selo da base — mas o mesmo acontece em 700, 900 e 1100px, porque quem determina a colisão é
   o número de linhas da descrição dentro do card, não a largura da tela.

   No fluxo o card simplesmente cresce, e nenhuma das duas coisas pode se sobrepor em largura
   nenhuma. É por isso que aqui não existe @media: um breakpoint só reintroduziria a sobreposição
   de um dos lados da fronteira. */
.terminal-action-card-badge {
    margin-left: auto;
    /* Não encolhe: o texto do selo é o dado, quem cede espaço é o resto da linha. O teto + reticências
       impedem que um selo longo estoure a largura do card. */
    flex-shrink: 0;
    max-width: 60%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.65rem;
    font-weight: 700;
    text-transform: uppercase;
    color: #303236;
    background-color: #ECEFF1;
    padding: 2px 8px;
    border-radius: 999px;
}

.terminal-action-card-soon {
    /* margin-top:auto encosta o selo na base sempre que sobra altura (o min-height do card),
       reproduzindo o canto inferior direito — só que empurrando o card em vez de flutuar sobre
       a descrição quando ela cresce. */
    align-self: flex-end;
    margin-top: auto;
    max-width: 100%;
    font-size: 0.65rem;
    font-weight: 600;
    color: var(--tm-text-muted, #747A80);
}

/* ---------- Fluxos operacionais (Selecionar → Informar → Revisar → Executar → Resultado) ---------- */

.terminal-flow {
    padding-bottom: 24px;
}

.terminal-flow-title {
    margin-bottom: 20px;
}

.terminal-flow-title-row {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 20px;
}

.terminal-flow-title-row .terminal-flow-title {
    margin-bottom: 0;
}

.terminal-flow-card {
    padding: 24px;
    display: flex;
    flex-direction: column;
    gap: 16px;
}

/* Cola no fundo da ÁREA ROLÁVEL (.terminal-app-content é o scroll container do shell), nunca
   da página — o que o mantém sempre acima do rodapé global, que vive fora do scroll. */
.terminal-step-footer-wrapper {
    position: sticky;
    bottom: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-top: 8px;
    z-index: 2;
}

.terminal-step-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    background-color: #FFFFFF;
    border: 1px solid var(--tm-border, #D8DADD);
    border-radius: 12px;
    padding: 12px 20px;
}

.terminal-step-indicator {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--tm-text-muted, #747A80);
    text-align: center;
}

.terminal-cancel-row {
    display: flex;
    justify-content: center;
}

.terminal-cancel-row-button {
    width: 100%;
}

/* ---------- Seleção de SKU ---------- */

.terminal-sku-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 16px;
}

.terminal-sku-card {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--tm-border, #D8DADD);
    border-radius: 12px;
    cursor: pointer;
    overflow: hidden;
    box-sizing: border-box;
    background-color: #FFFFFF;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.terminal-sku-card:hover {
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
}

.terminal-sku-card:active {
    transform: scale(0.99);
}

.terminal-sku-card-selected {
    border-color: #F15A24;
    border-width: 2px;
    background-color: #FFF4EE;
}

.terminal-sku-card-disabled {
    cursor: not-allowed;
    opacity: 0.55;
}

.terminal-sku-card-photo {
    position: relative;
    width: 100%;
    height: 140px;
    background-color: #ECEFF1;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    flex-shrink: 0;
    color: #747A80;
}

.terminal-sku-card-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* Modificador ligado pelo TerminalSkuCard via ShowWholePhoto — hoje só /terminal/app/retirada,
   o único fluxo que exibe o catálogo REAL do cliente.

   O quadro vira 1:1 para casar com o contrato de cadastro da foto, que já é quadrado ponta a
   ponta: o recorte em /skus mostra um quadro 1:1 (skus.css), o canvas de recorte é 300x300 e a
   exportação sai em 512x512 (ImageCropDialog.razor + image-crop.js). Exibir esse arquivo
   quadrado dentro do retângulo 100%x140px do estilo base era o que produzia o "quadradinho
   flutuante" com faixas cinza dos dois lados — a imagem estava correta, o quadro é que tinha
   outra proporção.

   Sem padding de propósito: a margem do produto tem que vir do enquadramento feito no diálogo
   de cadastro, não de uma moldura cinza fixa entre o arquivo e o contêiner.

   `contain` continua sendo a regra (não `cover`) como rede de segurança: para os 512x512 do
   fluxo atual ele preenche a área inteira sem sobra, e para fotos legadas ou vindas de outro
   caminho, fora do 1:1, ele garante que nada seja recortado — com o #ECEFF1 herdado do quadro
   preenchendo a sobra.

   O modificador vale para o contêiner inteiro, com ou sem foto, para que todos os cards da
   grade tenham a mesma geometria e as linhas continuem alinhadas. Check de seleção e badge
   "Inativo" não se movem: são position:absolute contra a padding box, que aqui coincide com a
   borda externa do quadro. */
.terminal-sku-card-photo-contain {
    height: auto;
    aspect-ratio: 1 / 1;
    padding: 0;
    box-sizing: border-box;
}

.terminal-sku-card-photo-contain img {
    display: block;
    object-fit: contain;
    object-position: center;
}

/* Placeholder de carregamento da grade de retirada — mesma geometria do card real com
   ShowWholePhoto (mídia 1:1 + faixa de nome/metadados), para não haver salto de layout. */
.terminal-sku-card-skeleton {
    border: 1px solid var(--tm-border, #D8DADD);
    border-radius: 12px;
    overflow: hidden;
    background-color: #FFFFFF;
    box-sizing: border-box;
}

/* A classe do MudSkeleton entra junto, então a dupla .a.b vence a altura padrão dele sem !important.
   Qualquer teto de altura aplicado ao card real precisa ser espelhado aqui (ver o bloco
   @media de celular mais abaixo), senão o skeleton fica mais alto que o card e a grade salta
   justamente quando o catálogo chega. */
.terminal-sku-card-skeleton-media.mud-skeleton {
    width: 100%;
    height: auto;
    aspect-ratio: 1 / 1;
    transform: none;
}

.terminal-sku-card-skeleton-info {
    padding: 14px 16px 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.terminal-sku-card-check {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background-color: #FFFFFF;
    color: #F15A24;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
}

.terminal-sku-card-info {
    padding: 14px 16px 16px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.terminal-sku-card-name {
    font-weight: 700;
    line-height: 1.25;
}

.terminal-sku-card-code {
    color: var(--tm-text-muted, #747A80);
}

.terminal-sku-card-meta {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-top: 8px;
}

.terminal-sku-card-stock {
    font-size: 0.75rem;
    font-weight: 700;
    color: #2E7D32;
    white-space: nowrap;
}

.terminal-sku-card-stock-low {
    color: #B3261E;
}

.terminal-sku-card-secondary {
    font-size: 0.7rem;
    color: var(--tm-text-muted, #747A80);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ---------- Quantidade ---------- */

.terminal-quantity-stepper {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 24px;
}

.terminal-quantity-value {
    font-size: 2rem;
    font-weight: 700;
    min-width: 60px;
    text-align: center;
}

.terminal-quantity-hint {
    text-align: center;
    color: var(--tm-text-muted, #747A80);
}

/* ---------- Escolha de gaveta na retirada INTEGRAL ----------

   Substitui o seletor de quantidade para quem não tem can_partial_withdrawal: a pessoa não digita
   nada, escolhe UMA gaveta e leva tudo. Cada opção é um alvo de toque cheio (56 px; a tela é
   operada em pé e, muitas vezes, de luva) e a quantidade aparece por extenso — "Retirar todas:
   12 un." —, porque é ela que a pessoa vai conferir contra o que encontrar na gaveta. */

.terminal-position-choice {
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: 100%;
}

.terminal-position-choice-title {
    font-weight: 600;
}

.terminal-position-options {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 12px;
    width: 100%;
}

.terminal-position-option {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    min-height: 56px;
    padding: 12px 16px;
    border: 1px solid var(--tm-border, #D8DADD);
    border-radius: 10px;
    background-color: #FFFFFF;
    color: var(--tm-text, #111111);
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}

.terminal-position-option:focus-visible {
    outline: 2px solid #F15A24;
    outline-offset: 2px;
}

.terminal-position-option-selected {
    border-color: #F15A24;
    background-color: #FDECE4;
}

.terminal-position-option-unavailable {
    cursor: not-allowed;
    opacity: 0.55;
}

.terminal-position-option-name {
    font-size: 1rem;
    font-weight: 700;
}

.terminal-position-option-quantity {
    font-size: 0.95rem;
}

.terminal-position-option-reason {
    font-size: 0.8rem;
    color: var(--tm-text-muted, #747A80);
}

/* Selo da gaveta que saiu da licença. Discreto de propósito: ela CONTINUA selecionável, e um
   aviso em vermelho leria como impedimento. O tom de atenção diz "isto vai acabar", que é
   exatamente o que está acontecendo com a gaveta. */
.terminal-position-option-license {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--tm-warning, #B26A00);
}

/* ---------- Seletor de quantidade (TerminalQuantitySelector) ----------

   Duas linhas de propósito. Seis alvos de 48 px numa linha só passam de 340 px de largura, e num
   quiosque estreito eles seriam espremidos até "−100" virar vizinho de "+1" — o toque errado
   custaria 100 unidades. Separar por magnitude separa também o risco.

   48 px é o mínimo de alvo de toque: a tela é operada em pé e, muitas vezes, de luva. */

.terminal-quantity-selector {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    width: 100%;
}

.terminal-quantity-selector-main {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    width: 100%;
    max-width: 360px;
}

/* min-width/min-height juntos: o MudIconButton encolhe abaixo de 48 px sem os dois. */
.terminal-quantity-selector-step {
    min-width: 48px;
    min-height: 48px;
    flex: 0 0 auto;
}

.terminal-quantity-selector-field {
    flex: 1 1 auto;
    min-width: 0; /* deixa o campo encolher dentro do flex em vez de empurrar os botões para fora */
}

.terminal-quantity-selector-field input {
    text-align: center;
    font-size: 1.75rem;
    font-weight: 700;
}

.terminal-quantity-selector-shortcuts {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    max-width: 360px;
}

.terminal-quantity-selector-shortcut {
    flex: 1 1 0;
    min-width: 64px;
    min-height: 48px;
    font-size: 1rem;
    font-weight: 600;
}

/* Região viva só para leitor de tela: a mensagem VISÍVEL é a que o MudTextField já renderiza
   associada ao campo. Duplicá-la na tela seria dizer a mesma coisa duas vezes. */
.terminal-quantity-selector-error {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.terminal-quantity-selector-hint {
    color: var(--tm-text-muted, #747A80);
    font-size: 0.95rem;
    text-align: center;
    max-width: 360px;
}

/* Telas bem estreitas: os atalhos passam a ocupar duas por linha em vez de encolher abaixo do
   alvo mínimo. Perder uma linha de altura é melhor que perder precisão do toque. */
@media (max-width: 380px) {
    .terminal-quantity-selector-shortcuts {
        flex-wrap: wrap;
    }

    .terminal-quantity-selector-shortcut {
        flex: 1 1 calc(50% - 8px);
    }
}

/* ---------- Comparativo de saldo (reposição) ---------- */

.terminal-balance-preview {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    margin-top: 20px;
    width: 100%;
}

.terminal-balance-preview-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    flex: 1 1 0;
}

.terminal-balance-preview-label {
    font-size: 0.75rem;
    color: var(--tm-text-muted, #747A80);
}

.terminal-balance-preview-value {
    font-size: 1.15rem;
    font-weight: 700;
}

.terminal-balance-preview-value-highlight {
    color: #2E7D32;
}

.terminal-balance-preview-value-error {
    color: #B3261E;
}

.terminal-adjustment-diff {
    text-align: center;
    font-weight: 600;
    margin-top: 4px;
}

/* Os dois tipos de referência ficam lado a lado num quiosque largo e empilham num tablet em pé —
   alvos de toque grandes, nunca um select. */
.terminal-adjustment-reference-kind {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 24px;
    margin-top: 8px;
}

.terminal-balance-preview-arrow {
    color: var(--tm-text-muted, #747A80);
    flex-shrink: 0;
}

/* ---------- Resumo (revisão) ---------- */

.terminal-summary {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.terminal-summary-row {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    padding: 10px 0;
    border-bottom: 1px solid var(--tm-border, #D8DADD);
}

.terminal-summary-row:last-child {
    border-bottom: none;
}

.terminal-summary-label {
    color: var(--tm-text-muted, #747A80);
}

.terminal-summary-value {
    font-weight: 600;
    text-align: right;
}

/* ---------- Posição (gaveta física / posição lógica virtual) ---------- */

.terminal-position-card {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px;
    border: 1px dashed var(--tm-border, #D8DADD);
    border-radius: 12px;
}

.terminal-position-card-blocked {
    color: #B3261E;
}

/* ---------- Execução (física / virtual) ---------- */

.terminal-execution-panel {
    display: flex;
    flex-direction: column;
    gap: 18px;
    padding: 12px 0;
}

.terminal-execution-step {
    display: flex;
    align-items: center;
    gap: 12px;
    color: var(--tm-text-muted, #747A80);
}

.terminal-execution-step-active {
    color: var(--tm-text, #111111);
    font-weight: 600;
}

.terminal-execution-step-done {
    color: var(--tm-text, #111111);
}

.terminal-execution-step-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    border: 2px solid var(--tm-border, #D8DADD);
    box-sizing: border-box;
    flex-shrink: 0;
}

/* Execução física: cada etapa é uma gaveta com título, estado e (quando cabe) a confirmação. */

.terminal-execution-summary {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.terminal-execution-muted {
    color: var(--tm-text-muted, #747A80);
}

.terminal-execution-panel .terminal-execution-step {
    align-items: flex-start;
}

.terminal-execution-panel .terminal-execution-step > .mud-icon-root,
.terminal-execution-panel .terminal-execution-step > .mud-progress-circular,
.terminal-execution-panel .terminal-execution-step > .terminal-execution-step-dot {
    margin-top: 3px;
}

.terminal-execution-step-body {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1 1 auto;
    min-width: 0;
}

.terminal-execution-step-title {
    overflow-wrap: anywhere;
}

.terminal-execution-step-status {
    font-weight: 400;
    color: var(--tm-text-muted, #747A80);
}

.terminal-execution-step-active .terminal-execution-step-status {
    color: var(--tm-text, #111111);
}

.terminal-execution-confirm,
.terminal-execution-resolve,
.terminal-execution-takeover,
.terminal-execution-problem,
.terminal-execution-close {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-top: 8px;
    font-weight: 400;
}

/* Confirmação normal: o planejado é INSTRUÇÃO (não campo editável). */
.terminal-execution-instruction {
    margin: 0;
    padding-left: 20px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 1.05rem;
}

/* Relato de problema: cada posição exige escolha explícita (quantidade ou "não sei"). */
.terminal-execution-problem-line {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 10px 12px;
    border: 1px solid var(--tm-border, #D8DADD);
    border-radius: 8px;
}

.terminal-execution-problem-choice {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

/* ---------- Resultado ---------- */

.terminal-result-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 6px;
    padding: 32px 16px;
}

.terminal-result-state-code {
    font-size: 0.8rem;
    color: var(--tm-text-muted, #747A80);
    margin-top: 4px;
}

.terminal-result-state-actions {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 20px;
    width: 100%;
    max-width: 280px;
}

.terminal-restricted-action {
    display: flex;
    justify-content: center;
    padding-bottom: 8px;
}

/* ---------- Estado vazio ---------- */

.terminal-empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 4px;
    padding: 40px 16px;
    color: var(--tm-text-muted, #747A80);
}

/* ---------- Painel de filtros do terminal (barra de apoio, discreta) ---------- */

.terminal-filter-panel {
    padding: 10px 14px;
    margin-bottom: 16px;
    border: 1px solid var(--tm-border, #D8DADD);
    border-radius: 10px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.terminal-filter-panel-quick {
    display: flex;
    gap: 10px;
}

.terminal-filter-panel-quick > * {
    flex: 1 1 0;
    min-width: 0;
}

.terminal-filter-panel-footer {
    display: flex;
    justify-content: flex-end;
}

.terminal-filter-panel-footer .mud-button-root {
    font-size: 0.75rem;
}

.terminal-filter-panel-expansion,
.terminal-filter-panel-expansion .mud-expand-panel {
    background-color: transparent;
    box-shadow: none;
}

.terminal-filter-panel-expansion .mud-expand-panel-header {
    padding-left: 0;
    padding-right: 0;
    min-height: 36px;
}

.terminal-filter-panel-expansion .mud-expand-panel-content .mud-expand-panel-text {
    padding-left: 0;
    padding-right: 0;
}

.terminal-filter-panel-toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--tm-text-muted, #747A80);
}

.terminal-filter-panel-badge {
    min-width: 18px;
    height: 18px;
    font-size: 0.65rem;
}

.terminal-filter-panel-advanced {
    padding-top: 4px;
    padding-bottom: 4px;
}

.terminal-filter-panel-placeholder {
    color: var(--tm-text-muted, #747A80);
    font-size: 0.8rem;
}

/* ---------- Cartão de destaque do SKU (etapa de quantidade) ---------- */

.terminal-sku-highlight {
    padding: 32px 24px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 4px;
}

.terminal-sku-highlight-photo {
    width: 120px;
    height: 120px;
    border-radius: 16px;
    background-color: #ECEFF1;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    color: #747A80;
    margin-bottom: 16px;
}

.terminal-sku-highlight-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.terminal-sku-highlight-name {
    font-weight: 700;
}

.terminal-sku-highlight-code {
    color: var(--tm-text-muted, #747A80);
    margin-bottom: 8px;
}

.terminal-sku-highlight-meta {
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: 0.85rem;
    color: var(--tm-text-muted, #747A80);
    margin-bottom: 8px;
}

.terminal-sku-highlight-stock {
    font-size: 0.8rem;
    font-weight: 700;
    color: #2E7D32;
}

.terminal-sku-highlight-divider {
    width: 100%;
    margin: 20px 0;
}

/* Quantidade e data de um item aferível: uma caixa só, para os dois campos terminarem
   com a MESMA largura. O card em volta é `align-items: center`, então cada controle
   ficava do tamanho do próprio conteúdo e um saía mais largo que o outro. A caixa é
   exclusiva do fluxo de aferição — o seletor de quantidade dos itens comuns e o resto
   do .terminal-sku-highlight seguem como estavam. */
.terminal-calibration-fields {
    width: 100%;
    max-width: 480px;
    display: flex;
    flex-direction: column;
    gap: 16px;
    /* O card centraliza o texto; aqui o valor digitado precisa nascer do mesmo lado do
       rótulo e do texto de apoio (que o MudBlazor já alinha ao início). */
    text-align: start;
}

/* Os controles do MudBlazor chegam com `flex: 1 1 auto`: numa coluna flex isso é ALTURA.
   Aqui quem manda é a largura — a altura fica a do conteúdo. */
.terminal-calibration-fields > * {
    flex: 0 0 auto;
    width: 100%;
}

/* ---------- Inventário ---------- */

.terminal-inventory-progress {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 12px;
    margin: 12px 0 20px;
}

.terminal-inventory-progress-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 14px 8px;
    border-radius: 10px;
    background-color: #ECEFF1;
}

.terminal-inventory-progress-value {
    font-size: 1.4rem;
    font-weight: 700;
}

.terminal-inventory-progress-label {
    font-size: 0.7rem;
    color: var(--tm-text-muted, #747A80);
    text-align: center;
}

.terminal-inventory-progress-item-ok {
    background-color: #E8F5E9;
}

.terminal-inventory-progress-item-ok .terminal-inventory-progress-value {
    color: #2E7D32;
}

.terminal-inventory-progress-item-error {
    background-color: #FDECEA;
}

.terminal-inventory-progress-item-error .terminal-inventory-progress-value {
    color: #B3261E;
}

.terminal-inventory-actions {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.terminal-inventory-session-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.terminal-inventory-session-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px;
    cursor: pointer;
    color: var(--tm-text-muted, #747A80);
}

.terminal-inventory-session-meta {
    color: var(--tm-text-muted, #747A80);
}

.terminal-inventory-position-tag {
    display: inline-flex;
    padding: 4px 12px;
    border-radius: 999px;
    background-color: var(--tm-primary-tint, #FDEAE1);
    color: var(--tm-primary, #F15A24);
    font-size: 0.875rem;
    font-weight: 700;
}

/* ----- Contagem compacta (estados Counting/Review) -----

   Tudo dimensionado em rem para acompanhar a preferência de texto grande. Nenhum texto abaixo
   de 0.875rem, nenhum alvo interativo abaixo de 2.75rem (= 44px). O orçamento vertical é medido
   dentro do shell real (.terminal-app-content é o único scroll container) — nada aqui usa
   position fixed nem esconde overflow. */

/* Cabeçalho da etapa: contexto/progresso à esquerda, Salvar e sair · Cancelar à direita. Em
   largura estreita o flex-wrap quebra em duas linhas e o margin-left:auto mantém as utilidades
   alinhadas ao fim — nunca posicionadas de forma absoluta. */
.terminal-inventory-page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 4px 16px;
    margin-bottom: 12px;
}

.terminal-inventory-page-header-context {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.terminal-inventory-page-progress {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--tm-text-muted, #747A80);
}

.terminal-inventory-page-header-utilities {
    display: flex;
    gap: 8px;
    margin-left: auto;
}

.terminal-inventory-utility-button {
    min-height: max(48px, 2.75rem);
}

.terminal-inventory-flow-alert {
    margin-bottom: 8px;
}

/* Resumo horizontal do item: foto pequena ao lado de posição · nome · código. Cartão próprio do
   inventário — o .terminal-sku-highlight compartilhado (retirada, reposição, kits) não muda. */
.terminal-inventory-item-card {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    /* O espaçamento vertical da contagem é do inventário, não do panel-card (24px). */
    margin-bottom: 0;
}

.terminal-inventory-item-photo {
    width: 4rem;
    height: 4rem;
    flex-shrink: 0;
    border-radius: 12px;
    background-color: var(--tm-secondary-tint, #ECEDEE);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    color: var(--tm-text-muted, #747A80);
}

.terminal-inventory-item-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.terminal-inventory-item-info {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    min-width: 0;
}

/* Nome e código longos truncam em UMA linha — o valor completo fica no title. */
.terminal-inventory-item-name {
    font-weight: 700;
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.terminal-inventory-item-code {
    font-size: 0.875rem;
    color: var(--tm-text-muted, #747A80);
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.terminal-inventory-item-undo {
    min-height: max(48px, 2.75rem);
}

/* Cartão de contagem: display + teclado + erro + confirmação como um bloco único. */
.terminal-inventory-count-card {
    margin-top: 12px;
    margin-bottom: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px;
}

.terminal-inventory-count-card-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
}

.terminal-inventory-count-label {
    font-weight: 600;
}

/* Orientação, nunca valor: o shape da contagem chega sem a quantidade esperada. */
.terminal-inventory-count-blind {
    font-size: 0.875rem;
    color: var(--tm-text-muted, #747A80);
}

/* O display do teclado vira caixa de leitura de largura total, valor à direita. */
.terminal-inventory-count-card .terminal-keypad-display-value {
    box-sizing: border-box;
    width: 100%;
    min-height: 3rem;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding: 4px 16px;
    border: 1px solid var(--tm-border, #D8DADD);
    border-radius: 12px;
    background-color: var(--tm-bg, #F5F5F6);
    font-size: 1.75rem;
    margin-bottom: 12px;
}

/* O ÚNICO botão preenchido do estado normal de contagem. */
.terminal-inventory-confirm-button {
    min-height: 3rem;
    font-weight: 700 !important;
}

/* Grade funcional: duas colunas nos formatos do terminal; coluna única só em largura realmente
   crítica (bloco @media no fim do arquivo). minmax(0, …) evita estouro por rótulo longo. */
.terminal-inventory-function-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    margin-top: 12px;
}

.terminal-inventory-function-button {
    min-height: max(48px, 2.75rem);
    font-weight: 600 !important;
}

.terminal-inventory-function-span {
    grid-column: 1 / -1;
}

/* Wrapper do estado de contagem: uma coluna por padrão; a variante lado a lado entra só na
   regra de paisagem baixa, mais abaixo. */
.terminal-inventory-counting-main {
    min-width: 0;
}

.terminal-inventory-result-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 10px;
    width: 100%;
    text-align: left;
}

.terminal-inventory-result-card {
    padding: 12px 14px;
    border-radius: 10px;
    border: 1px solid var(--tm-border, #D8DADD);
}

.terminal-inventory-result-card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 0.75rem;
    font-weight: 700;
    margin-bottom: 4px;
}

.terminal-inventory-result-tag {
    font-size: 0.65rem;
    text-transform: uppercase;
    padding: 2px 8px;
    border-radius: 999px;
    background-color: #ECEFF1;
}

.terminal-inventory-result-card-qty {
    color: var(--tm-text-muted, #747A80);
    display: block;
    margin-top: 2px;
}

.terminal-inventory-result-card-ok {
    background-color: #F5FBF6;
    border-color: #A5D6A7;
}

.terminal-inventory-result-card-ok .terminal-inventory-result-tag {
    background-color: #E8F5E9;
    color: #2E7D32;
}

.terminal-inventory-result-card-missing {
    background-color: #FDF6F5;
    border-color: #EFB4AE;
}

.terminal-inventory-result-card-missing .terminal-inventory-result-tag {
    background-color: #FDECEA;
    color: #B3261E;
}

.terminal-inventory-result-card-excess {
    background-color: #FFFBF3;
    border-color: #F0CB8F;
}

.terminal-inventory-result-card-excess .terminal-inventory-result-tag {
    background-color: #FFF3E0;
    color: #C77700;
}

.terminal-inventory-result-card-pending {
    opacity: 0.7;
}

/* ---------- Retiradas recentes (devolução / estorno) ---------- */

.terminal-withdrawal-card {
    position: relative;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 16px;
    border: 1px solid var(--tm-border, #D8DADD);
    border-radius: 12px;
    cursor: pointer;
    background-color: #FFFFFF;
    box-sizing: border-box;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.terminal-withdrawal-card:hover {
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
}

.terminal-withdrawal-card:active {
    transform: scale(0.99);
}

.terminal-withdrawal-card-selected {
    border-color: #F15A24;
    border-width: 2px;
    background-color: #FFF4EE;
}

.terminal-withdrawal-card-photo {
    width: 56px;
    height: 56px;
    border-radius: 10px;
    background-color: #ECEFF1;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    flex-shrink: 0;
    color: #747A80;
}

.terminal-withdrawal-card-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.terminal-withdrawal-card-info {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.terminal-withdrawal-card-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
}

.terminal-withdrawal-card-name {
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.terminal-withdrawal-card-code {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--tm-text-muted, #747A80);
    white-space: nowrap;
}

.terminal-withdrawal-card-sku {
    color: var(--tm-text-muted, #747A80);
}

.terminal-withdrawal-card-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 12px;
    font-size: 0.75rem;
    color: var(--tm-text-muted, #747A80);
    margin-top: 4px;
}

.terminal-withdrawal-card-meta-secondary {
    margin-top: 0;
}

.terminal-withdrawal-card-check {
    flex-shrink: 0;
    color: #F15A24;
    display: flex;
}

.terminal-withdrawal-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* Cartão de custódia em aberto escolhido na etapa "Selecionar" da devolução de uso.

   A classe era aplicada por TerminalDevolucao.razor e não existia em CSS nenhum: escolher um item
   não mudava absolutamente nada na tela, e o único sinal de que a escolha valeu era o botão
   Continuar destravar no rodapé. Mesma anatomia das outras seleções do canal
   (.terminal-withdrawal-card-selected, .terminal-kit-card-selected): borda da marca em 2px e
   superfície tingida — cor NUNCA sozinha. */
.terminal-card-selected {
    border-color: var(--tm-primary, #F15A24);
    border-width: 2px;
    background-color: #FFF4EE;
}

/* ---------- Estorno de retirada ---------- */
/* A lista de operadores e a de gavetas do estorno reaproveitam .terminal-position-option; só o
   cartão do operador tem estrutura própria, porque ele mostra pessoa + contagem, não gaveta. */

.terminal-reversal-operator-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.terminal-reversal-operator {
    padding: 16px;
    border: 2px solid rgba(0, 0, 0, 0.08);
    border-radius: 12px;
    cursor: pointer;
    /* Alvo de toque confortável num quiosque: a lista é operada em pé, muitas vezes de luva. */
    min-height: 72px;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.terminal-reversal-operator:hover {
    border-color: rgba(241, 90, 36, 0.4);
}

.terminal-reversal-operator-selected {
    border-color: #F15A24;
    background-color: rgba(241, 90, 36, 0.06);
}

.terminal-reversal-operator-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}

/* Contador do MudTextField encostado no campo, e não colado no botão de continuar. */
.terminal-reversal-justification {
    margin-top: 16px;
}

/* ---------- Meu perfil ---------- */

.terminal-profile-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 28px 24px;
}

.terminal-profile-registration {
    color: var(--tm-text-muted, #747A80);
}

.terminal-profile-role {
    display: inline-flex;
    margin-top: 8px;
    padding: 3px 12px;
    border-radius: 999px;
    background-color: #ECEFF1;
    color: #303236;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
}

.terminal-profile-role-admin {
    background-color: #FFF4EE;
    color: #F15A24;
}

.terminal-permission-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 10px;
}

.terminal-permission-chip {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    border-radius: 10px;
    border: 1px solid var(--tm-border, #D8DADD);
    background-color: #F5FBF6;
    color: #2E7D32;
    font-size: 0.85rem;
}

.terminal-permission-chip-locked {
    background-color: #ECEFF1;
    color: var(--tm-text-muted, #747A80);
}

/* As ações do PIN preenchem a largura do grupo. Antes eram alinhadas à direita, e "Confirmar"
   ficava com 99px dentro de uma caixa de 318px — um alvo pequeno e visualmente solto justamente
   na única ação que conclui a tela.

   `flex-basis: 0` (e não `auto`) é o que iguala as frações: com `auto` o botão de rótulo mais
   longo ficaria maior que o outro. Com uma ação só ela ocupa a caixa inteira; com duas, cada uma
   fica com metade. Medido em 318px: 147 + 8 + 163. */
.terminal-profile-pin-actions {
    display: flex;
    gap: 8px;
    margin-top: 12px;
}

.terminal-profile-pin-actions > .mud-button-root {
    flex: 1 1 0;
}

/* ---------- Configurações do terminal (/terminal/app/configuracoes) ---------- */

.terminal-settings-header {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    margin-bottom: 20px;
}

/* O padding interno do MudButton alinharia o rótulo à direita da coluna de texto abaixo. */
.terminal-settings-back {
    margin-left: -8px;
}

.terminal-settings-title {
    margin-bottom: 2px;
}

.terminal-settings-subtitle {
    color: var(--tm-text-muted, #747A80);
}

.terminal-settings-section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}

.terminal-settings-section-title {
    font-weight: 600;
}

.terminal-settings-status {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 600;
}

/* Ponto próprio, e não o `.terminal-connection-dot` do rodapé: aquele vive no CSS ESCOPADO do
   TerminalAppLayout, então não alcança o markup desta página. */
.terminal-settings-status-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background-color: #2E7D32;
    display: inline-block;
    flex-shrink: 0;
}

/* O ponto acompanha o texto do estado (nunca o contrário): ativação validada no virtual ou
   resposta física recente com Ready=true ficam verdes; o resto não. */
.terminal-settings-status-negative .terminal-settings-status-dot {
    background-color: #B3261E;
}

.terminal-settings-status-warning .terminal-settings-status-dot {
    background-color: #B26A00;
}

.terminal-settings-status-neutral .terminal-settings-status-dot {
    background-color: #8A9096;
}

.terminal-settings-hint {
    color: var(--tm-text-muted, #747A80);
}

/* ---------- Estado do equipamento físico (configurações) ----------

   UM indicador ("Estado do equipamento · Disponível"), o mesmo do rodapé e do resumo do admin.
   O texto diz o estado; a cor do ponto e da borda é reforço. Sem horários, idades, contagens ou
   motivos: nada aqui muda sem que o estado mude. */
.terminal-equipment-state {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px 10px;
    min-width: 0;
    padding: 12px 14px;
    border-radius: 10px;
    border: 1px solid var(--tm-border, #D8DADD);
    border-left-width: 4px;
    border-left-color: #8A9096;
}

.terminal-equipment-state-positive { border-left-color: #2E7D32; }
.terminal-equipment-state-warning { border-left-color: #B26A00; }
.terminal-equipment-state-negative { border-left-color: #B3261E; }

.terminal-equipment-state-title {
    font-weight: 600;
}

.terminal-equipment-state-separator {
    color: var(--tm-text-muted, #747A80);
}

/* Estreito: título em cima, estado embaixo — o separador não fica pendurado no fim da linha. */
@media (max-width: 520px) {
    .terminal-equipment-state {
        flex-direction: column;
        align-items: flex-start;
    }

    .terminal-equipment-state-separator {
        display: none;
    }
}

.terminal-equipment-state-value {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-weight: 600;
}

.terminal-equipment-state-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
    background-color: #8A9096;
}

.terminal-equipment-state-positive .terminal-equipment-state-dot { background-color: #2E7D32; }
.terminal-equipment-state-warning .terminal-equipment-state-dot { background-color: #B26A00; }
.terminal-equipment-state-negative .terminal-equipment-state-dot { background-color: #B3261E; }

/* Valores longos do cartão de configurações.

   O número de série é uma cadeia CONTÍNUA (ex.: DUR-863A553851D04FB080DF676772FC4514): não tem
   espaço, hífen interno nem qualquer outro ponto onde o navegador possa quebrar sozinho. Numa
   linha de resumo — rótulo à esquerda, valor à direita — ele esticava a caixa do valor além da
   célula e passava por cima do campo de baixo.

   As duas declarações resolvem coisas diferentes e as duas são necessárias:
     * `min-width: 0` — um item flex não encolhe abaixo do próprio conteúdo sem isto, então a
       caixa do valor continuaria com a largura do serial inteiro por mais estreita que fosse a
       linha;
     * `overflow-wrap: anywhere` — dá ao texto o ponto de quebra que ele não tem.

   NADA é truncado: sem reticências, sem `overflow: hidden`. O serial existe para ser conferido
   contra a etiqueta do equipamento, e um serial cortado não serve para isso — ele quebra em
   duas linhas, continua alinhado à direita e continua inteiro na tela.

   Restrito a este cartão de propósito: os outros resumos do terminal (revisão de retirada,
   perfil) têm valores com espaços, e `anywhere` os faria quebrar no meio de palavras. */
.terminal-settings-card .terminal-summary-value {
    min-width: 0;
    overflow-wrap: anywhere;
}

/* Quem cede largura é o VALOR, nunca o rótulo: os rótulos são curtos e fixos, e um rótulo
   quebrado tornaria a lista ilegível. */
.terminal-settings-card .terminal-summary-label {
    flex-shrink: 0;
}

/* Anúncio para leitor de tela, invisível para quem enxerga: o resultado de "Atualizar status"
   já aparece no carimbo da verificação, e um pop-up em cima disso vira ruído. */
.terminal-settings-live {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* Método inicial de login (docs/terminal-preferred-login-method-plan.md). O rótulo é o próprio
   label do switch, que ocupa a linha inteira: tocar em qualquer parte do texto alterna, e a
   altura mínima mantém o alvo acima do piso tátil em retrato e paisagem. */
.terminal-settings-toggle-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    min-height: 48px;
}

/* O piso tátil global não alcança o switch (ver o topo do arquivo): ele vai no label, que já
   centraliza o switch e o texto na vertical. */
.terminal-settings-toggle-row label.mud-switch {
    flex: 1 1 auto;
    min-width: 0;
    min-height: 48px;
}

.terminal-settings-toggle-row .mud-switch .mud-typography {
    overflow-wrap: anywhere;
}

/* Confirmação VISÍVEL — e só depois que o navegador confirmou a gravação. A altura mínima evita
   que o cartão pule quando a mensagem aparece ou some. */
.terminal-settings-pref-live {
    min-height: 1.25rem;
    font-size: 0.85rem;
    color: #2E7D32;
}

/* ---------- Kits ---------- */

.terminal-kit-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 16px;
}

.terminal-kit-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 4px;
    padding: 20px 16px;
    border: 1px solid var(--tm-border, #D8DADD);
    border-radius: 12px;
    cursor: pointer;
    background-color: #FFFFFF;
    box-sizing: border-box;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.terminal-kit-card:hover {
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
}

.terminal-kit-card:active {
    transform: scale(0.99);
}

.terminal-kit-card-selected {
    border-color: #F15A24;
    border-width: 2px;
    background-color: #FFF4EE;
}

.terminal-kit-card-photo {
    width: 72px;
    height: 72px;
    border-radius: 12px;
    background-color: #ECEFF1;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    color: #747A80;
    margin-bottom: 8px;
}

.terminal-kit-card-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.terminal-kit-card-name {
    font-weight: 700;
}

.terminal-kit-card-code {
    color: var(--tm-text-muted, #747A80);
}

.terminal-kit-card-count {
    font-size: 0.7rem;
    font-weight: 600;
    color: #F15A24;
    margin-top: 4px;
}

.terminal-kit-checklist {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.terminal-kit-checklist-item {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 12px 16px;
    border: 1px solid var(--tm-border, #D8DADD);
    border-radius: 12px;
    background-color: #FFFFFF;
    box-sizing: border-box;
}

.terminal-kit-checklist-item-active {
    border-color: #F15A24;
    border-width: 2px;
    background-color: #FFF4EE;
}

.terminal-kit-checklist-item-waiting {
    opacity: 0.55;
}

.terminal-kit-checklist-item-photo {
    width: 44px;
    height: 44px;
    border-radius: 8px;
    background-color: #ECEFF1;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    color: #747A80;
    flex-shrink: 0;
}

.terminal-kit-checklist-item-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.terminal-kit-checklist-item-info {
    flex: 1 1 auto;
    min-width: 0;
}

.terminal-kit-checklist-item-meta {
    color: var(--tm-text-muted, #747A80);
    display: block;
}

.terminal-kit-checklist-item-pending {
    font-size: 0.75rem;
    color: var(--tm-text-muted, #747A80);
    white-space: nowrap;
}

/* Componente já confirmado: verde discreto. A cor é o único sinal que uma pessoa em pé, a um
   metro da tela, consegue ler sem se aproximar — o ícone sozinho não basta. */
.terminal-kit-checklist-item-done {
    border-color: #2E7D32;
    background-color: #F1F8F2;
}

.terminal-kit-position-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: 100%;
}

/* ---------- Montagem de kits: cabeçalho da saga e escolha da gaveta final ---------- */

.terminal-kit-saga-header {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.terminal-kit-position-picker {
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: 100%;
}

.terminal-kit-position-option {
    padding: 12px 16px;
    border: 1px solid var(--tm-border, #D8DADD);
    border-radius: 12px;
    background-color: #FFFFFF;
    cursor: pointer;
    box-sizing: border-box;
}

.terminal-kit-position-option-selected {
    border-color: #F15A24;
    border-width: 2px;
    background-color: #FFF4EE;
}

/* Gaveta inelegível continua VISÍVEL, com o motivo: escondê-la deixaria o colaborador
   procurando a "Gaveta 03" que sumiu da lista. */
.terminal-kit-position-option-disabled {
    opacity: 0.55;
    cursor: not-allowed;
}

/* Resumo e motivo são BLOCOS: Typo.caption gera <span>, e dois spans irmãos ficavam na MESMA
   linha — era daí que saía "cabem mais 0Cabe apenas 0 unidade(s)...". O display: block é o que
   separa, não um espaço literal antes do motivo. Escopo restrito ao cartão da montagem de kits. */
.terminal-kit-position-option-summary {
    display: block;
    color: var(--tm-text-secondary, #5A6069);
}

/* Mesmo papel de .terminal-position-option-reason no seletor da reposição, com a margem superior
   que a separação em blocos exige. overflow-wrap protege a frase longa na largura do quiosque. */
.terminal-kit-position-option-reason {
    display: block;
    margin-top: 6px;
    color: var(--tm-warning, #B26A00);
    overflow-wrap: anywhere;
}

.terminal-kit-position-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 0.85rem;
    color: var(--tm-text-muted, #747A80);
}

/* ---------- Revelação da posição (só após a conclusão) ---------- */

.terminal-result-state-extra {
    width: 100%;
    margin-top: 12px;
}

.terminal-position-reveal {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 20px;
    border: 2px solid #F15A24;
    background-color: #FFF4EE;
    border-radius: 12px;
    text-align: center;
}

.terminal-position-reveal-text {
    font-weight: 700;
    color: #F15A24;
}

/* ---------- Responsivo: tablet e celular ---------- */

@media (max-width: 900px) {
    /* Mesmas trilhas da regra base, repetidas aqui só para manter o minmax(0, …) — um `1fr`
       solto neste bloco reintroduziria o estouro da grade por selo longo. */
    .terminal-home-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .terminal-home-secondary {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}

@media (max-width: 600px) {
    /* Teto de altura da mídia SÓ no celular. Aqui a grade cai para coluna única e o card ocupa
       a largura toda (~327px em 375px de tela), então o quadrado 1:1 viraria uma mídia de ~327px
       e um card de ~426px — um produto por tela. O teto devolve o card para ~339px.
       Deliberadamente NÃO vale para tablet/desktop: lá a coluna fica em ~240-262px e o quadrado
       sai exato, sem nenhuma faixa cinza (o critério de aceite). No celular a faixa lateral
       existe e é o preço aceito por manter a lista navegável.
       O skeleton (.terminal-sku-card-skeleton-media) precisa do mesmo teto para não saltar. */
    .terminal-sku-card-photo-contain,
    .terminal-sku-card-skeleton-media.mud-skeleton {
        max-height: 240px;
    }

    /* O cabeçalho NÃO tem regras aqui: a grade de duas linhas virou o padrão do arquivo (seção
       "Cabeçalho do terminal"), porque ela precisa valer até 699px, e não até 600px. */

    .terminal-home-grid,
    .terminal-home-secondary,
    .terminal-option-pair {
        grid-template-columns: minmax(0, 1fr);
    }

    .terminal-action-card-highlighted {
        grid-column: span 1;
    }

    .terminal-activation-card,
    .terminal-login-card,
    .terminal-flow-card {
        padding: 20px;
    }

    .terminal-step-footer {
        flex-wrap: wrap;
        justify-content: center;
    }

    .terminal-step-indicator {
        order: -1;
        width: 100%;
        text-align: center;
    }

    .terminal-keypad-key {
        min-height: 52px;
    }

    .terminal-cancel-row-button {
        width: 100%;
        max-width: none;
    }

    .terminal-filter-panel-quick {
        flex-direction: column;
    }

    .terminal-sku-highlight {
        padding: 24px 16px;
    }

    .terminal-sku-highlight-photo {
        width: 96px;
        height: 96px;
    }

    .terminal-inventory-progress {
        grid-template-columns: repeat(2, 1fr);
    }

    /* A grade funcional do inventário NÃO empilha aqui de propósito: duas colunas seguem
       cabendo até bem abaixo de 600px; a coluna única só entra no bloco de 380px. */

    .terminal-balance-preview {
        flex-direction: column;
    }

    .terminal-balance-preview-arrow {
        transform: rotate(90deg);
    }
}

/* Largura realmente crítica: só aqui a grade funcional do inventário cai para uma coluna. */
@media (max-width: 380px) {
    .terminal-inventory-function-grid {
        grid-template-columns: minmax(0, 1fr);
    }

    .terminal-inventory-function-span {
        grid-column: auto;
    }
}

/* Paisagem larga e BAIXA (o alvo principal 1280×800 cai aqui): mesmo com todos os pisos
   respeitados — teclas de 44px, display de 3rem, confirmação de 3rem — a coluna única soma mais
   do que a área útil do shell. Em vez de encolher controles abaixo do piso, a grade funcional
   passa a ocupar a largura sobrando ao LADO do bloco operacional. A ordem do DOM (e do foco)
   não muda; em leitura LTR a grade continua vindo depois do cartão de contagem. */
@media (max-height: 900px) and (min-width: 1000px) {
    .terminal-inventory-counting {
        display: flex;
        align-items: flex-start;
        gap: 16px;
    }

    .terminal-inventory-counting-main {
        flex: 1.2 1 0;
    }

    .terminal-inventory-function-grid {
        flex: 1 1 0;
        margin-top: 0;
    }
}

/* Compactação por ALTURA, não só por largura: um terminal em paisagem pode ser largo e ainda ter
   pouca altura. Nada encolhe abaixo do piso — a foto vai a 3.5rem (esta é a única regra que a
   reduz) e os alvos de toque seguem em 2.75rem+. */
@media (max-height: 700px) {
    .terminal-inventory-page-header {
        margin-bottom: 8px;
    }

    .terminal-inventory-item-photo {
        width: 3.5rem;
        height: 3.5rem;
    }

    .terminal-inventory-item-card {
        padding: 10px 16px;
    }

    .terminal-inventory-count-card {
        margin-top: 8px;
        gap: 8px;
        padding: 12px 16px;
    }

    .terminal-inventory-count-card .terminal-keypad-display-value {
        margin-bottom: 8px;
    }

    .terminal-inventory-function-grid {
        margin-top: 8px;
        gap: 8px;
    }
}

/* "Bloquear terminal" é um POST real (/auth/terminal/operator/logout), então o card precisa ser
   um <button type="submit"> de verdade — acessível por teclado e por toque, sem JS. Este reset
   remove a aparência de botão e deixa o MudPaper interno ocupar a célula inteira do grid. */
.terminal-action-card-trigger {
    appearance: none;
    -webkit-appearance: none;
    background: none;
    border: 0;
    margin: 0;
    padding: 0;
    font: inherit;
    color: inherit;
    text-align: inherit;
    display: block;
    width: 100%;
    height: 100%;
    cursor: pointer;
}

.terminal-action-card-trigger > .terminal-action-card {
    height: 100%;
}

/* Formulário oculto de bloqueio: existe só para carregar o token antiforgery e ser alvo do
   atributo `form` dos botões de bloquear (cabeçalho e tela inicial). */
.terminal-lock-form {
    display: none;
}

/* Instruções de coleta reais (retirada virtual): uma linha por gaveta afetada, na ordem
   retornada pela transação. */
.terminal-position-reveal-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
    width: 100%;
    max-width: 420px;
}

.terminal-position-reveal-list-item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 16px;
    border: 1px solid var(--tm-border, #D8DADD);
    border-radius: 10px;
}

.terminal-position-reveal-line-name {
    font-weight: 700;
}

/* Aviso curto sobre a foto do card de SKU (ex.: "Inativo"). */
.terminal-sku-card-badge {
    position: absolute;
    bottom: 6px;
    left: 6px;
    padding: 2px 8px;
    border-radius: 999px;
    background-color: rgba(0, 0, 0, 0.65);
    color: #fff;
    font-size: 0.7rem;
}

/* Tela de continuidade pós-coleta. */
.terminal-continuation-actions {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-top: 8px;
}

/* ---------------------------------------------------------------------------
   Reposição (/terminal/app/reposicao)
   --------------------------------------------------------------------------- */

/* Escolha entre gaveta existente e gaveta nova. As duas ficam SEMPRE visíveis: a
   indisponível aparece desabilitada com o motivo, em vez de sumir — o colaborador
   precisa entender por que uma das opções não está ali. */
.terminal-allocation-modes {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 12px;
}

.terminal-allocation-mode-hint {
    margin: 0 0 10px;
    color: var(--tm-text-secondary, #5A6069);
}

.terminal-allocation-mode-disabled {
    color: var(--tm-warning, #B26A00);
}

/* Lista de gavetas candidatas. Alvos grandes: a tela é operada em pé, muitas vezes
   de luva. */
.terminal-position-list {
    display: flex;
    flex-direction: column;
    gap: 10px;
    margin-top: 12px;
}

.terminal-position-option {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 14px 16px;
    border: 1px solid var(--tm-border, #D8DADD);
    border-radius: 12px;
    cursor: pointer;
}

.terminal-position-option-selected {
    border-color: var(--tm-primary, #1B5E20);
    box-shadow: inset 0 0 0 1px var(--tm-primary, #1B5E20);
}

.terminal-position-option-disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.terminal-position-option-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
}

.terminal-position-option-number {
    font-size: 0.8rem;
    color: var(--tm-text-secondary, #5A6069);
}

.terminal-position-option-body {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 18px;
    font-size: 0.9rem;
    color: var(--tm-text-secondary, #5A6069);
}

.terminal-position-option-reason {
    margin: 0;
    color: var(--tm-warning, #B26A00);
}

/* Instruções de depósito: saldo anterior e novo vêm da transação concluída, nunca de
   uma previsão do cliente. */
.terminal-deposit-balance {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px 20px;
    margin-top: 4px;
    color: var(--tm-text-secondary, #5A6069);
}

.terminal-deposit-mode {
    margin-top: 10px;
    text-align: center;
    color: var(--tm-text-secondary, #5A6069);
}

/* Resumo fixo da gaveta escolhida: ela pode estar em outra página da lista, e o
   colaborador precisa continuar vendo o que escolheu enquanto navega. */
.terminal-position-selected-summary {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    margin-top: 12px;
    border: 1px solid var(--tm-primary, #1B5E20);
    border-radius: 12px;
}

/* ---------------------------------------------------------------------------------------------
   Inventário PARCIAL (sql/terminal/052-055)
   --------------------------------------------------------------------------------------------- */

/* Os dois cartões da escolha de escopo. Empilhados: a tela é operada em pé, com luva, e um par
   lado a lado num quiosque estreito vira dois alvos pequenos em vez de dois alvos grandes. */
.terminal-scope-choices {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* As gavetas já escolhidas, dentro do resumo fixo. Quebram em várias linhas porque um parcial de
   doze gavetas é legítimo, e a lista não pode empurrar o botão de continuar para fora da tela. */
.terminal-scope-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 6px;
    max-height: 30vh;
    overflow-y: auto;
}

/* Gaveta inativa ou bloqueada entra no escopo (o parcial é subconjunto exato do completo), mas
   quem escolhe precisa ver o aviso ANTES de escolher. */
.terminal-position-option-warning {
    color: var(--tm-warning, #B26A00);
    font-weight: 600;
}

/* O selo "Parcial" acompanha o título em toda etapa da contagem. */
.terminal-inventory-scope-chip {
    margin-left: 8px;
    vertical-align: middle;
}

/* Paginação de 5 em 5. Alvos grandes e afastados: a tela é operada em pé. */
.terminal-position-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 14px;
}

.terminal-position-pager-label {
    font-size: 0.95rem;
    color: var(--tm-text-secondary, #5A6069);
    white-space: nowrap;
}

/* Seletor de gavetas (TerminalPositionPicker). A lista atual permanece visível enquanto uma
   busca mais recente está em voo: limpar a tela a cada tecla faria o quiosque piscar durante
   a digitação. */
.terminal-position-picker {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 12px;
}

.terminal-position-list-refreshing {
    opacity: 0.55;
    transition: opacity 120ms ease-in;
}

/* Bloqueio por inatividade (TerminalIdleGuard + wwwroot/js/terminal-idle-lock.js). A camada opaca
   do componente já cobre a viewport; este atributo, posto no <html> pelo módulo, é a SEGUNDA
   defesa: o que o MudBlazor renderiza em portal (diálogo, popover, snackbar) vive fora do
   `.terminal-app` e continuaria pintando por cima. Enquanto o encerramento não conclui — inclusive
   offline —, nada do operador fica visível.

   Regra irmã da que esconde o próprio shell: o guard é montado FORA do `.terminal-app`
   justamente para não se esconder junto. */
html[data-terminal-idle-locked="true"] .terminal-app,
html[data-terminal-idle-locked="true"] .mud-popover-provider,
html[data-terminal-idle-locked="true"] .mud-overlay,
html[data-terminal-idle-locked="true"] .mud-snackbar-provider {
    visibility: hidden;
}
