﻿/* ==========================================================================
   Verniz visual das telas Blazor de ESCRITÓRIO do sis (claro/escuro).

   Baseado no Cadastro de Pessoas do WPF (design "clean/moderno"): campos com
   leve fundo cinza + borda fina, campo desabilitado/readonly mais escuro,
   campo em foco/edição com borda de acento, e grid com cabeçalho diferenciado,
   zebra, hover e linha selecionada com faixa de acento.

   Usa APENAS as CSS custom properties publicadas pelo MudThemeProvider
   (--mud-palette-*), então tudo segue o tema ATIVO — verde no claro, verde
   clareado no escuro — sem cor cravada. As paletas moram em SisThemes.cs.

   POR QUE aqui e não em .razor.css: os bundles de CSS isolado
   ({Assembly}.styles.css) NÃO são referenciados por nenhum host (nem o
   index.html do BlazorWebView, nem o do WASM), então estilo isolado não
   carrega. Este arquivo é asset global da RCL, servido em
   _content/Sis.Presentation.Erp.Components/sis-theme.css e ligado no <head>
   de cada host — é onde o CSS compartilhado de fato entra em vigor.
   ========================================================================== */

/* -------------------------------------------------------------------------
   Fonte da interface: Inter (moderna/elegante), SELF-HOSTED — o woff2 é asset
   da RCL (wwwroot/fonts), servido em _content/.../fonts. É a garantia de
   OFFLINE do app local (WPF/MAUI): a fonte vem do próprio app, não do Google
   Fonts (CDN), então funciona sem internet; na web serve do mesmo lugar. É um
   arquivo variável (todos os pesos num só). URL relativa a este CSS.
   Inter é SIL Open Font License — livre para empacotar.
   ------------------------------------------------------------------------- */
@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 100 900;      /* variável: cobre todos os pesos */
    font-display: swap;        /* pinta com a fallback e troca — nunca texto invisível */
    src: url("fonts/InterVariable.woff2") format("woff2");
}

/* Aplica a Inter em toda a interface (MudBlazor lê --mud-typography-*-family da
   tipografia em SisThemes; isto cobre o resto — body, texto solto, HTML puro).
   A stack de sistema (Segoe UI/Roboto/-apple-system) é a fallback enquanto a
   Inter carrega ou se, por algum motivo, o asset não estiver presente. */
html, body, .mud-typography, .mud-input, .mud-button-root, .mud-nav-link {
    font-family: "Inter", "Segoe UI", "Roboto", -apple-system, "Helvetica", "Arial", sans-serif;
}

/* -------------------------------------------------------------------------
   Campos (MudTextField/MudSelect Outlined, o default global do AddSisUi)
   ------------------------------------------------------------------------- */

/* Campo habilitado: leve fundo cinza dentro da borda, como no WPF.

   O preenchimento é DERIVADO da paleta ativa (uma pitada do texto primário
   misturada à superfície), NÃO de --mud-palette-gray-light. Motivo: essa
   variável NÃO acompanha o modo do jeito que o nome sugere — no claro vale
   #F5F5F5 (o cinza sutil que este verniz queria) e no ESCURO vale #BDBDBD, ou
   seja cinza CLARO. Nos temas escuros (Food do restaurante, Channel, o Dark
   canônico da casca, DashboardDark) todo campo virava um bloco cinza claro com
   texto claro por cima — ilegível. Era o que se via no login e na busca do app
   do garçom.

   Os 6% são calibrados para NÃO mexer no que já existia: sobre a superfície
   branca do tema claro dão ~#F2F2F2, praticamente o #F5F5F5 de antes; sobre a
   superfície #1E1E1E do escuro dão ~#2A2A2A, um degrau acima do fundo, com o
   texto #E8E8E8 por cima. Um mesmo valor fixo não serviria aos dois — é por
   isso que a cor é derivada, e não cravada. */
.mud-input.mud-input-outlined:not(.mud-disabled) .mud-input-slot {
    background-color: color-mix(in srgb, var(--mud-palette-text-primary) 6%, var(--mud-palette-surface));
}

/* Campo desabilitado ou readonly: fundo visivelmente mais escuro (ex.: Cidade
   e UF derivados da busca no cadastro) — a diferença habilitado x desabilitado
   fica inequívoca, não um tom quase idêntico. */
.mud-input.mud-input-outlined.mud-disabled .mud-input-slot,
.mud-input.mud-input-outlined .mud-input-slot[readonly] {
    background-color: var(--mud-palette-action-disabled-background);
}

/* Campo em foco/edição: borda de acento (verde) mais grossa — equivale ao
   realce do campo em edição do cadastro WPF. */
.mud-input.mud-input-outlined.mud-focused .mud-input-outlined-border {
    border-width: 2px !important;
    border-color: var(--mud-palette-primary) !important;
}

/* -------------------------------------------------------------------------
   Casca (ShellLayout): barra superior e menu lateral NAVY, espelhando o shell
   WPF nos dois temas. As cores navy vêm da paleta (--mud-palette-appbar/drawer-*,
   definidas em SisThemes: #10293F/#1B374E no claro, navy escuro no escuro).
   Aqui ficam as PROPORÇÕES e os ESTADOS (hover/ativo), que a paleta não expressa.
   ------------------------------------------------------------------------- */

/* Logo da SoftConn no CENTRO da barra superior (decisão do dono, 2026-07-27).

   Altura fixa e `width: auto`: a MudAppBar tem altura fixa e o arquivo tem 644px de largura — sem travar a
   altura, a imagem empurra a barra inteira. `object-fit: contain` preserva a proporção qualquer que seja o
   arquivo, então trocar o logo por outro de proporção diferente não obriga a mexer aqui.

   `pointer-events: none`: o logo é marca, não botão. Sem isto ele intercepta o clique que passa pela faixa
   central da barra, e um logo que não faz nada ao ser clicado é indistinguível de um botão quebrado. */
.sis-shell-logo {
    /* 54px numa barra de 64px — 5px de respiro de cada lado. O arquivo é 1317×620 (proporção ~2,12:1), então
       isto o desenha com ~115px de largura; é a altura, e não a largura, que decide se a palavra "SoftConn"
       dentro da marca é legível.

       A primeira tentativa foi 28px e o logo virou uma mancha colorida: a marca ficou lá e não se lia. 42px
       resolveu isso e ainda ficava pequeno na tela do cliente (dono, 2026-08-18) — a barra tem 64px e sobrava
       espaço vertical dos dois lados sem nada dentro. ⛔ Não passe de 54px: acima disso a imagem encosta na
       borda da MudAppBar e o corte aparece antes de a marca ficar maior. */
    height: 54px;
    width: auto;
    max-width: 300px;
    object-fit: contain;
    pointer-events: none;
    user-select: none;
}

/* Menu lateral: texto e ícones claros sobre o navy; hover e item ativo com
   realce translúcido branco (como o WPF), não a primária verde. */
.sis-shell-drawer .mud-navmenu .mud-nav-link,
.sis-shell-drawer .mud-navmenu .mud-nav-group .mud-nav-link {
    color: rgba(255, 255, 255, 0.82);
}
.sis-shell-drawer .mud-navmenu .mud-nav-link .mud-icon-root,
.sis-shell-drawer .mud-navmenu .mud-nav-link-expand-icon {
    color: rgba(255, 255, 255, 0.7);
}
.sis-shell-drawer .mud-navmenu .mud-nav-link:hover {
    background-color: rgba(255, 255, 255, 0.10);
    color: #fff;
}
.sis-shell-drawer .mud-navmenu .mud-nav-link.active:not(.mud-nav-link-disabled) {
    background-color: rgba(255, 255, 255, 0.16);
    color: #fff;
    font-weight: 600;
}
.sis-shell-drawer .mud-navmenu .mud-nav-link.active:not(.mud-nav-link-disabled) .mud-icon-root {
    color: #fff;
}

/* Busca do menu sobre o navy: fundo translúcido e texto claro, sobrescrevendo
   o verniz de campo de formulário (fundo cinza) que não cabe aqui. */
.sis-shell-drawer .sis-nav-busca .mud-input-slot {
    background-color: rgba(255, 255, 255, 0.08) !important;
    color: #fff;
}
.sis-shell-drawer .sis-nav-busca .mud-input-outlined-border {
    border-color: rgba(255, 255, 255, 0.25) !important;
}
.sis-shell-drawer .sis-nav-busca input,
.sis-shell-drawer .sis-nav-busca .mud-input-adornment .mud-icon-root {
    color: rgba(255, 255, 255, 0.85);
}
.sis-shell-drawer .sis-nav-busca input::placeholder {
    color: rgba(255, 255, 255, 0.5);
    opacity: 1;
}

/* Menu COLAPSADO (68px): ícones centrados, como o modo Compact do WPF. */
.sis-nav-mini {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 8px 0;
    gap: 2px;
    min-height: 100%;
}
.sis-nav-mini-icon.mud-icon-button {
    color: rgba(255, 255, 255, 0.82);
    width: 48px;
    height: 48px;
}
.sis-nav-mini-icon.mud-icon-button:hover {
    background-color: rgba(255, 255, 255, 0.12);
    color: #fff;
}
.sis-nav-mini-spacer {
    flex: 1 1 auto;
}

/* Flyout do menu colapsado (popover do MudMenu): fundo NAVY como o submenu do WPF
   (não a superfície branca do tema). Usa o mesmo navy do drawer, então casa com o
   menu em claro e escuro. */
.sis-nav-flyout.mud-popover {
    background-color: var(--mud-palette-drawer-background);
    color: rgba(255, 255, 255, 0.9);
    border: 1px solid rgba(255, 255, 255, 0.12);
}
.sis-nav-flyout .mud-menu-item {
    color: rgba(255, 255, 255, 0.85);
}
.sis-nav-flyout .mud-menu-item:hover {
    background-color: rgba(255, 255, 255, 0.10);
    color: #fff;
}
.sis-nav-flyout .sis-nav-flyout-header {
    font-weight: 700;
    font-size: 0.85rem;
    padding: 8px 16px 4px;
    color: #fff;
}
.sis-nav-flyout .sis-nav-flyout-subheader {
    font-weight: 600;
    font-size: 0.68rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 10px 16px 2px;
    color: rgba(255, 255, 255, 0.55);
}

/* -------------------------------------------------------------------------
   RapidView (Painel de Acesso Rápido) — cards de atalho: efeito de hover/clique
   como o CardBotao do WPF (sobe levemente + sombra + brilho ao passar o mouse,
   afunda ao clicar). A cor de fundo (por módulo) vem do componente, na variável
   --sis-rapid-card-bg.

   ⚠️ O `!important` do background NÃO é preguiça — é obrigatório. O MudBlazor
   pinta o botão desabilitado com

       .mud-button-filled:disabled { background-color:
            var(--mud-palette-action-disabled-background) !important }

   e `!important` de folha de estilo vence estilo INLINE sem `!important` (a
   única situação da cascata em que o inline perde). Enquanto a cor vinha por
   `style="background: …"` no componente, todo card desabilitado ficava CINZA —
   e eles são desabilitados em todo head que não registra o IRapidViewLauncher,
   isto é em todos menos o Web.Mock (que finge disponibilidade). Resultado
   medido no head MAUI em 2026-07-27: painel inteiro sem cor, exatamente fora do
   head onde se costuma olhar.

   A escolha de produto: um atalho indisponível continua dizendo DE QUE MÓDULO
   ele é (a cor é identidade, não estado) e diz "indisponível" por opacidade e
   ausência de sombra. Apagar a cor confundia "não posso clicar" com "não
   carregou".
   ------------------------------------------------------------------------- */
.sis-rapid-card.mud-button-root {
    background-color: var(--sis-rapid-card-bg) !important;
    transition: transform 0.12s ease, box-shadow 0.12s ease, filter 0.12s ease;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.14);
}
.sis-rapid-card.mud-button-root:disabled {
    opacity: 0.55;
    box-shadow: none;
}
.sis-rapid-card.mud-button-root:hover:not(:disabled) {
    transform: translateY(-3px);
    box-shadow: 0 10px 22px rgba(0, 0, 0, 0.24);
    filter: brightness(1.07);
}
.sis-rapid-card.mud-button-root:active:not(:disabled) {
    transform: translateY(-1px) scale(0.99);
    box-shadow: 0 3px 8px rgba(0, 0, 0, 0.2);
    filter: brightness(0.98);
}

/* -------------------------------------------------------------------------
   Densidade do menu lateral aproximada do WPF (item ~13px, altura enxuta). O
   MudBlazor parte de 16px e espaça mais; aqui o item fica mais compacto e com
   respiro vertical menor, como o SfNavigationDrawer do WPF.
   ------------------------------------------------------------------------- */
.sis-shell-drawer .mud-navmenu .mud-nav-link {
    font-size: 0.875rem;
    min-height: 40px;
    padding-top: 6px;
    padding-bottom: 6px;
}
/* Ícone do item um pouco menor e mais colado ao texto (WPF: ícone 22px + gap curto). */
.sis-shell-drawer .mud-navmenu .mud-nav-link .mud-nav-link-icon {
    margin-right: 10px;
}
.sis-shell-drawer .mud-navmenu .mud-nav-link .mud-icon-root {
    font-size: 1.25rem;
}

/* -------------------------------------------------------------------------
   SisPageHeader — ícone do cabeçalho tingido pela primária do tema ativo.
   (Estava só no .razor.css isolado, que não carrega; consolidado aqui.)

   Não usa --mud-palette-primary-hover pelo mesmo motivo da linha selecionada do grid: o "-hover" derivado do
   HoverOpacity (~6%) some sobre o card branco. Mistura fixa da primária + contorno fino — o mesmo vocabulário
   visual dos ícones de ação da linha (caixa contornada), pra a tela ter UM idioma de "ícone em caixa".
   ------------------------------------------------------------------------- */
.sis-page-header-icon {
    width: 44px;
    height: 44px;
    border-radius: var(--mud-default-borderradius, 8px);
    background-color: rgba(var(--mud-palette-primary-rgb), 0.12);
    border: 1px solid rgba(var(--mud-palette-primary-rgb), 0.24);
    color: var(--mud-palette-primary);
}

/* -------------------------------------------------------------------------
   Cadastro SIMPLES (poucos campos — ex.: só "Descrição" — e grade com 1-2
   colunas de texto + Ações). A página ganha um TETO de largura em vez de
   esticar borda a borda do monitor.

   Sem isso, um cadastro trivial (Grupos de rota, Tipos de Produto,
   SubGrupos...) numa tela ultrawide vira uma faixa de texto rente à
   esquerda com um vão enorme até a coluna Ações — sobra de largura que
   ninguém pediu, não fluidez. É TETO, não centralização: abaixo dele o
   bloco continua ocupando 100% da largura disponível (tablet, celular),
   e por isso não contradiz a regra de tela fluida/responsiva — só para
   de crescer sem propósito quando o monitor é maior que o conteúdo.
   ------------------------------------------------------------------------- */
.sis-cadastro-simples {
    max-width: 720px;
}

/* -------------------------------------------------------------------------
   SisDataGrid — contorno, cabeçalho, hover e seleção. Tudo escopado em
   .sis-data-grid, então NÃO afeta grids de outros módulos (PDV/Food).
   ------------------------------------------------------------------------- */

/* Foco do container de teclado (ver SisDataGrid.razor.cs, OnGridKeyDownAsync): outline sutil na cor
   primária em vez do outline azul default do navegador — sinaliza "as setas navegam aqui" sem competir com
   a faixa de acento da linha selecionada. Some ao perder o foco (clique fora, Tab para outro campo). */
.sis-data-grid-keyboard-host:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
    border-radius: var(--mud-default-borderradius, 8px);
}

/* Contorno do grid: card com hairline + cantos arredondados do tema, no espírito do "outlined container" do
   Material 3 (contorno fino carrega a delimitação; a elevação fica baixa, sem sombra pesada). O
   overflow:hidden é o que faz o cabeçalho respeitar o canto arredondado — sem ele o fundo cinza do <th>
   vaza e o canto vira um quadrado. Popover de filtro/menu do MudDataGrid não é clipado: renderiza fora,
   no MudPopoverProvider. */
.sis-data-grid.mud-table {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius, 8px);
    overflow: hidden;
}

/* 🔒 A SOMBRA DE ROLAGEM — o que faz a última coluna deixar de sumir sem aviso em 1024×768.

   ⚠️ O diagnóstico que circulava ("o SisDataGrid CORTA colunas em 1024") estava ERRADO, e a diferença muda o
   conserto: medido no navegador, o `.mud-table-container` já tem `overflow-x: auto` e JÁ rola (969px de
   conteúdo em 718px de caixa, na Consulta de Consignações). Nenhuma coluna é inalcançável. O que faltava era
   o operador SABER que há mais à direita: `offsetHeight - clientHeight` dava ZERO, ou seja, a barra é
   overlay — aparece enquanto se arrasta e some parada. Na tela isso vira uma Situação fatiada pela borda do
   card e uma coluna de Ações que simplesmente não existe.

   🔴 A primeira tentativa foi devolver a barra CLÁSSICA com `::-webkit-scrollbar { height }`. Ficou INERTE, e
   a medição vale registrar: quando `scrollbar-width` está declarado no elemento (o MudBlazor declara `thin`),
   o Chromium IGNORA os pseudo-elementos `::-webkit-scrollbar` inteiros. A regra existia no arquivo servido
   (conferido por `curl`) e o `offsetHeight - clientHeight` continuou zero — o mesmo formato de defeito do
   padding da grade de itens: presente, e sem efeito.

   A saída é PINTURA, que não depende de como a plataforma desenha barra: quatro gradientes, dois `local`
   (viajam com o conteúdo e TAPAM a sombra quando aquela ponta está à vista) e dois `scroll` (fixos na caixa,
   são a sombra). O resultado é uma sombra que só aparece do lado em que há conteúdo escondido, e desaparece
   sozinha na consulta que cabe na tela — sem uma linha de JavaScript e sem medir largura.

   ⛔ Não é `overflow-x: scroll`: desenharia trilho em TODA consulta do repo, inclusive nas que cabem, comendo
   altura numa tela onde falta altura (a ordem de sacrifício do catálogo de design).
   ⛔ Também não é coluna de Ações fixa (`position: sticky`): seria mais confortável, mas exige fundo opaco na
   célula e atropelaria o realce da linha selecionada e do hover, que é o outro mecanismo desta grade. Fica
   registrado como possibilidade, não como omissão. */
.sis-data-grid .mud-table-container {
    background-image:
        linear-gradient(to right, var(--mud-palette-surface) 60%, rgba(0, 0, 0, 0)),
        linear-gradient(to left, var(--mud-palette-surface) 60%, rgba(0, 0, 0, 0)),
        linear-gradient(to right, color-mix(in srgb, var(--mud-palette-text-primary) 30%, transparent), rgba(0, 0, 0, 0)),
        linear-gradient(to left, color-mix(in srgb, var(--mud-palette-text-primary) 30%, transparent), rgba(0, 0, 0, 0));
    background-position: left center, right center, left center, right center;
    background-repeat: no-repeat;
    background-size: 28px 100%, 28px 100%, 22px 100%, 22px 100%;
    background-attachment: local, local, scroll, scroll;
}

/* Cabeçalho diferenciado: fundo cinza, texto secundário em caixa alta leve,
   sublinha de 2px. Distingue o header do corpo sem depender de cor forte.
   A sublinha usa table-lines (a mesma cor das linhas do corpo, agora legível) em vez de lines-default —
   assim o cabeçalho é a MESMA linha, só mais grossa, e não uma segunda cor competindo. */
.sis-data-grid .mud-table-head th,
.sis-data-grid .mud-table-head .mud-table-cell {
    background-color: var(--mud-palette-gray-light);
    color: var(--mud-palette-text-secondary);
    font-weight: 600;
    font-size: 0.72rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    border-bottom: 2px solid var(--mud-palette-table-lines);
}

/* SEM zebra por padrão (decidido em 2026-07-25, junto com o reforço das linhas).

   Havia aqui uma regra que listrava as linhas pares de TODO .sis-data-grid, INCONDICIONALMENTE — ela ignorava
   o parâmetro `Striped` do SisDataGrid (que é false por default), então a tela não tinha como desligar a
   zebra nem pedindo. Duas razões pra ela sair:

   1. Enquanto a linha de separação era invisível, a zebra fazia o trabalho dela por tabela. Com o separador
      legível, as duas guiam o olho pela mesma linha — Material Design pede UM dos dois, não os dois, e o
      fundo uniforme devolve destaque ao hover e à seleção, que é onde a informação de estado mora.
   2. Sem a regra, o parâmetro `Striped` volta a FUNCIONAR: quem passar Striped="true" recebe o listrado
      nativo do MudBlazor (que usa o mesmo --mud-palette-table-striped). Deixou de ser sempre-ligado e virou
      opt-in por tela, que é o que a assinatura do componente sempre prometeu.

   O TableStriped continua na paleta justamente por causa do (2) — não é valor órfão. */

/* Transição do realce: a faixa "acende" em vez de piscar. É o que torna o hover perceptível mesmo quando o
   mouse atravessa o grid rápido — o olho registra o movimento da cor, não só o estado final. */
.sis-data-grid .mud-table-body .mud-table-row .mud-table-cell {
    transition: background-color 0.12s ease-out;
}

/* Hover: realce esverdeado (o TableHover da paleta, reforçado em SisThemes.cs — ver o comentário lá), sem
   cobrir a seleção. O !important vence o sombreamento próprio do MudDataGrid, que também escreve
   background-color na linha em hover e, sendo mais específico em alguns temas, apagava este realce. */
.sis-data-grid .mud-table-body .mud-table-row:hover:not(.sis-grid-row-selected) td {
    background-color: var(--mud-palette-table-hover) !important;
}

/* Linha selecionada: fundo tingido com a primária + faixa de acento à esquerda.
   O !important vence o sombreamento de hover/zebra do próprio MudDataGrid.

   NÃO usa --mud-palette-primary-hover (o "-hover" que o MudBlazor deriva de HoverOpacity, ~6% de opacidade —
   pensado pra um :hover discreto, não pra marcar "esta é a linha selecionada"). Com opacidade tão baixa, no
   tema CLARO a seleção quase some sobre o branco do card — foi o que o dono reportou ("não dá pra enxergar").
   Em vez disso, mistura a primária do tema ativo (--mud-palette-primary-rgb, publicada pelo MudThemeProvider)
   numa opacidade fixa e mais forte, dedicada só a este estado — segue o tema (muda com Light/Dark/Food/...)
   mas não depende do HoverOpacity global nem se confunde com o :hover comum de botão/menu.

   Seleção x hover não competem por serem tons diferentes do mesmo verde: a seleção soma DOIS sinais que o
   hover não tem — a faixa de acento de 4px e o peso da fonte. */
.sis-data-grid .mud-table-body tr.sis-grid-row-selected td {
    background-color: rgba(var(--mud-palette-primary-rgb), 0.22) !important;
    font-weight: 600;
}
.sis-data-grid .mud-table-body tr.sis-grid-row-selected td:first-child {
    box-shadow: inset 4px 0 0 0 var(--mud-palette-primary);
}

/* Linha de separação entre registros: o MudBlazor usa var(--mud-palette-table-lines) no border-bottom de
   cada célula (1px). O valor de TableLines pro tema Light era quase invisível sobre o branco do card —
   reforçado em SisThemes.cs (ver o comentário lá) pra ficar claramente perceptível sem virar uma grade
   pesada. Aqui só reafirma a intenção — o valor real é publicado pela paleta ativa. */
.sis-data-grid .mud-table-body .mud-table-row .mud-table-cell {
    border-bottom: 1px solid var(--mud-palette-table-lines);
}

/* Última linha sem separador: quem fecha o corpo é o contorno do card. Evita a linha dupla (separador +
   borda) que aparece logo acima do rodapé/paginador. */
.sis-data-grid .mud-table-body .mud-table-row:last-child .mud-table-cell {
    border-bottom: none;
}

/* -------------------------------------------------------------------------
   CÉLULA DE COBRANÇA — na consulta de Contas a Receber, o estado do boleto, o
   nosso número e o banco/PSP na MESMA célula.

   🔑 Uma coluna, três informações empilhadas — ⛔ não três colunas. A grade já
   tem nove; em 1024×768 três colunas de cobrança empurrariam Valor e Saldo
   para fora, e o operador perderia de vista o dinheiro para ganhar o número
   do boleto.

   A hierarquia é deliberada: o ESTADO é o chip (é o que muda e o que decide
   se cabe emitir de novo); número e banco são identificação, e ficam em
   secundário, menores, numa linha só.
   ------------------------------------------------------------------------- */

.sis-cobranca-cell {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 1px;
    /* Sem o line-height curto a célula cresce ~8px e a linha inteira da grade
       engorda — 50 linhas mais altas por causa de dois textos de apoio. */
    line-height: 1.25;
}

.sis-cobranca-numero {
    font-size: 0.75rem;
    /* Tabular para o número não "dançar" entre linhas: nosso número é código,
       e código desalinhado é mais difícil de conferir de olho. */
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-primary);
}

.sis-cobranca-banco {
    font-size: 0.7rem;
    color: var(--mud-palette-text-secondary);
}

/* -------------------------------------------------------------------------
   LINHA EXPANSÍVEL — o painel que abre abaixo da linha (SisDataGrid +
   SisRowDetail). O gesto é: clicar no chevron da linha e ver, ali mesmo, o
   que aquele registro tem do outro lado do vínculo (os boletos do título, o
   título do boleto, os itens e a cobrança do documento).

   🔑 O princípio visual é UM: o painel é CONTINUAÇÃO da linha, não outro
   componente. Por isso ele não tem contorno próprio, não tem sombra e não
   estreia cor nenhuma — ele reusa o idioma que a grade já fala (a faixa de
   acento da linha selecionada, a hairline das linhas, o tratamento do
   cabeçalho). Um card dentro do card faria o olho ler "abriu outra tela".
   ------------------------------------------------------------------------- */

/* O botão de expandir. Discreto por padrão — ele repete em TODA linha, e um
   ícone forte multiplicado por 50 linhas vira ruído que compete com o dado. */
.sis-row-detail-toggle.mud-icon-button {
    color: var(--mud-palette-text-secondary);
    transition: color 0.12s ease-out, transform 0.12s ease-out;
}

.sis-row-detail-toggle.mud-icon-button:hover:not(.mud-disabled) {
    color: var(--mud-palette-primary);
}

/* Linha sem detalhe: apagado, NÃO ausente. Botão que some de algumas linhas faz
   a coluna piscar conforme o filtro, e o operador conclui que a tela quebrou. */
.sis-row-detail-toggle.mud-icon-button.mud-disabled {
    opacity: 0.28;
}

/* A célula que hospeda o painel é do PRÓPRIO MudDataGrid (ele embrulha o child row
   com o colspan certo — ⛔ não emita <td> no fragmento, ver SisDataGrid.razor.cs).
   O que se tira dela é o padding: quem respira é o painel, e o padding da célula
   deixaria uma moldura clara em volta do fundo tingido.

   🩸 MEDIDO numa captura: com um <td> próprio dentro do child row (HTML inválido —
   td dentro de td), o navegador extrai o elemento e o painel para no MEIO da
   largura da grade, com o fundo cortado. Build, bUnit e E2E ficavam verdes. */
.sis-data-grid .mud-table-body tr.mud-table-row-hierarchy td {
    padding: 0;
}

/* O painel.

   O fundo é um DEGRAU abaixo da superfície do card (color-mix com o texto
   primário, ~4%), e não uma cor nova: funciona nos dois temas sem uma segunda
   definição, porque as duas variáveis já invertem com o tema.

   A faixa de acento à esquerda é o mesmo gesto da .sis-grid-row-selected — é ela
   que faz o olho LIGAR o painel à linha que o abriu, que é a única informação
   que a moldura precisa carregar. */
.sis-row-detail {
    background-color: color-mix(in srgb, var(--mud-palette-text-primary) 4%, var(--mud-palette-surface));
    box-shadow: inset 3px 0 0 0 var(--mud-palette-primary);
    padding: 12px 16px 12px 20px;
}

.sis-row-detail-inner {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* Os estados de carregamento e de erro (ver SisRowDetail.razor). Linha única,
   discreta: eles são transitórios e não podem empurrar o resto da grade. */
.sis-row-detail-estado {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary);
    min-height: 32px;
}

.sis-row-detail-erro {
    color: var(--mud-palette-error-text, var(--mud-palette-error));
}

/* Seção: cabeçalho no MESMO tratamento do cabeçalho da grade — a hierarquia sai
   da repetição de um padrão que já existe na tela. */
.sis-row-detail-section-header {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 6px;
}

.sis-row-detail-section-title {
    font-size: 0.72rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

/* O contador ao lado do título: pílula neutra. ⛔ Não usa cor semântica — ele
   conta linhas, não classifica nada, e cor aqui sugeriria um estado. */
.sis-row-detail-section-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 18px;
    padding: 0 6px;
    border-radius: 9px;
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    background-color: color-mix(in srgb, var(--mud-palette-text-primary) 10%, transparent);
}

.sis-row-detail-section-actions {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 4px;
}

/* O aviso que EXPLICA um conteúdo vazio. Vazio mudo é indistinguível de defeito
   — é a diferença entre "a consulta falhou" e "ainda não foi faturado". */
.sis-row-detail-aviso {
    margin: 0 0 6px;
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary);
}

/* A tabela interna do painel: SEM contorno próprio. Ela separa por linhas com a
   mesma hairline da grade, então lê-se como uma continuação dela — um segundo
   card aqui empilharia duas molduras no mesmo lugar. */
.sis-row-detail-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.8125rem;
}

.sis-row-detail-table th {
    text-align: left;
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    padding: 4px 8px;
    border-bottom: 1px solid var(--mud-palette-table-lines);
    white-space: nowrap;
}

.sis-row-detail-table td {
    padding: 5px 8px;
    border-bottom: 1px solid color-mix(in srgb, var(--mud-palette-table-lines) 55%, transparent);
}

.sis-row-detail-table tr:last-child td {
    border-bottom: none;
}

/* Dinheiro e quantidade à direita — UTILITÁRIO GLOBAL. ⛔ Aqui é `text-align`, não
   `d-flex` no <td>: classe de layout numa célula de tabela desmonta a linha (a
   cicatriz do CellClass="d-flex" no TemplateColumn), e build, bUnit e E2E ficam
   verdes.

   🩸 (2026-08-20) Ele era escopado em `.sis-row-detail-table` e virou global porque
   as duas grafias que o repositório usava para alinhar dinheiro — `text-end` e
   `text-right` — NÃO EXISTEM em CSS nenhum que os heads carregam (MudBlazor.min.css
   + este arquivo + pdv.css, e só). Medido: `grep -c` das duas neste arquivo devolvia
   0, e a captura do PR #1140 mostrava os valores encostados à esquerda. Ou seja, o
   alinhamento de dinheiro nas grades provavelmente nunca funcionou.
   ✅ (2026-08-22) A pendência acima foi RESOLVIDA — pelo lado do CSS, não reescrevendo
   os arquivos. `text-right` e `text-end` passaram a EXISTIR (logo abaixo), e com isso
   as 111 ocorrências espalhadas por 30 telas voltaram a alinhar de uma vez.
   🔑 Por que assim, e não convertendo tela a tela: as duas grafias são o vocabulário
   padrão da indústria (Bootstrap, Tailwind) e foi por isso que o repositório as
   escreveu 111 vezes sozinho — fazê-las existir custa três linhas e zero risco, e
   reescrever 30 telas custaria 30 recapturas para obter o MESMO pixel.
   ⚠️ Elas dão só o alinhamento. Em coluna de NÚMERO prefira `.sis-num`, que traz
   também `nowrap` e dígitos tabulares (as casas decimais empilham na vertical). */
.sis-num {
    text-align: right;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* 🩸 (2026-08-22) O CABEÇALHO da coluna precisa destas linhas à parte, e são TRÊS níveis porque o
   MudDataGrid empilha três elementos dentro do `<th>` (medido no MudBlazor.min.css 8.13.0):
   `.column-header` é flex com `space-between`, e dentro dele `.sortable-column-header` tem `width:100%`
   — com o filho ocupando tudo, mexer só no `justify-content` do pai não move NADA, que foi a primeira
   tentativa e ficou igual na captura. Sem isto, o título fica à esquerda enquanto os números vão para a
   direita: pior que não alinhar, porque parece coluna trocada. */
.sis-num .column-header {
    /* ⚠️ O `!important` aqui é MEDIÇÃO, não preguiça: sem ele a regra do MudBlazor vence e o cabeçalho
       fica à esquerda — conferido em três capturas seguidas, com o seletor descendente já mais específico
       que o `.column-header{...}` do pacote. ⛔ Não o remova "para limpar": o efeito volta a sumir e nada
       acusa (build, bUnit e E2E ficam verdes com o título torto). */
    justify-content: flex-end !important;
}

.text-right,
.text-end {
    text-align: right;
}

/* Mesma história, medida junto: `text-center` era usada em 8 lugares e também não existia em CSS
   nenhum — o MudBlazor declara as `align-*` (flexbox), e nenhuma das `text-*`. */
.text-center {
    text-align: center;
}

/* Rodapé de totais da seção: separado por uma linha um pouco mais firme, para o
   olho parar ali sem precisar de negrito em tudo. */
.sis-row-detail-total {
    border-top: 2px solid var(--mud-palette-table-lines);
    font-weight: 600;
}

/* Em telas estreitas (1024×768 é o piso das capturas) a tabela do painel rola
   sozinha, em vez de empurrar a grade inteira para a horizontal. */
.sis-row-detail-scroll {
    overflow-x: auto;
}

/* -------------------------------------------------------------------------
   SisRowActions — ícones de ação (editar/excluir) na linha do grid. Cores
   centralizadas AQUI: mude estas regras e TODO grid do sis (qualquer tela
   que usa SisRowActions) muda junto — é o "tema global" dos ícones de
   ação, deliberadamente desacoplado do Color.Primary/Error do MudBlazor
   (que também pinta botão Salvar, chip de status etc. — mudar só a ação de
   linha não deve mexer no resto da tela, e vice-versa).

   .sis-row-action é a FORMA (caixa contornada, comum aos dois); as classes
   -edit/-delete são só a COR. Separar as duas é o que permite acrescentar uma
   terceira ação amanhã sem repetir a geometria.
   ------------------------------------------------------------------------- */

/* Espaçamento entre as caixas: um respiro maior que o gap-1 (4px) do utilitário,
   pra os contornos não encostarem e virarem uma barra só. */
.sis-row-actions {
    gap: 6px;
}

/* A caixa: contorno fino no cinza de linha do tema, canto arredondado do tema e um quadrado justo em volta
   do ícone. Fundo transparente em repouso (o contorno já delimita) — a cor entra no hover, então a linha do
   grid não fica poluída por dois blocos coloridos em cada registro. */
.sis-row-action.mud-icon-button {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius, 8px);
    width: 30px;
    height: 30px;
    padding: 0;
    background-color: transparent;
    transition: background-color 0.15s ease-out, border-color 0.15s ease-out, box-shadow 0.15s ease-out,
                transform 0.1s ease-out;
}
.sis-row-action.mud-icon-button .mud-icon-root {
    font-size: 1.05rem;
}

/* Clique: a caixa afunda. Par do hover colorido definido junto das cores, mais abaixo — juntos formam a
   "elevação de estado" do Material (repouso → hover eleva → :active afunda), sem exagero. */
.sis-row-action.mud-icon-button:active:not(.mud-disabled) {
    transform: scale(0.94);
    box-shadow: none;
}

/* Contorno apagado quando desabilitado: a caixa não pode parecer clicável se a ação não está disponível. */
.sis-row-action.mud-icon-button.mud-disabled {
    border-color: var(--mud-palette-action-disabled-background);
}

.sis-row-action-edit.mud-icon-button {
    color: var(--mud-palette-primary);
}
/* Ver detalhe: cor INFO — leitura pura, não pode disputar com Editar (primary) nem parecer destrutiva. E a
   classe é PRÓPRIA (não reusa a -edit) porque o SeletorDeTesteConventionTests exige seletor de teste sem
   ambiguidade: os E2E selecionam .sis-row-action-edit esperando o SisRowActions. Só a COR; a caixa vem da
   .sis-row-action, comum a todas. */
.sis-row-action-view.mud-icon-button {
    color: var(--mud-palette-info);
}
/* Tornar permanente (consolidar importação): cor SUCCESS — ação protetiva, não destrutiva nem de edição.
   Classe PRÓPRIA pela mesma regra da -view: o SeletorDeTesteConventionTests exige seletor sem ambiguidade,
   e os E2E selecionam .sis-row-action-edit esperando o SisRowActions. Só a COR; a caixa vem da
   .sis-row-action. */
.sis-row-action-lock.mud-icon-button {
    color: var(--mud-palette-success);
}
.sis-row-action-view.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-info-rgb), 0.12);
    border-color: var(--mud-palette-info);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-info-rgb), 0.28);
}
.sis-row-action-edit.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-primary-rgb), 0.12);
    border-color: var(--mud-palette-primary);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-primary-rgb), 0.28);
}
/* Imprimir em PDF: cor SECUNDÁRIA, não primária. A ação convive com "Editar" na mesma linha e as duas são
   não-destrutivas — pintar as duas de primary tiraria de "Editar" o posto de ação principal da linha. E não
   é error: imprimir não destrói nada. Só a COR muda; a caixa vem da .sis-row-action, comum às três. */
.sis-row-action-print.mud-icon-button {
    color: var(--mud-palette-secondary);
}
.sis-row-action-print.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-secondary-rgb), 0.12);
    border-color: var(--mud-palette-secondary);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-secondary-rgb), 0.28);
}

/* CUPOM (a via de bobina): a MESMA cor secundária de "Imprimir em PDF", e é deliberado — os dois são o mesmo
   gesto (entregar um documento da venda) em formatos diferentes, e cores distintas sugeririam consequências
   distintas. O que os separa é o ícone, que é onde a diferença de fato está. */
.sis-row-action-receipt.mud-icon-button {
    color: var(--mud-palette-secondary);
}
.sis-row-action-receipt.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-secondary-rgb), 0.12);
    border-color: var(--mud-palette-secondary);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-secondary-rgb), 0.28);
}

/* Registrar PAGAMENTO (liquidar o boleto e baixar o título): cor SUCCESS — o dinheiro entrou, e ela divide a
   linha com "Baixar sem pagamento" (error), que é a operação de desfecho OPOSTO. Vestir as duas da mesma cor
   convidaria ao clique errado justamente onde ele custa dinheiro.

   E a classe é PRÓPRIA (não reusa a -edit, que tem a mesma família de "operação normal") pela regra do
   SeletorDeTesteConventionTests: os E2E selecionam .sis-row-action-edit esperando o SisRowActions, e aplicá-la
   aqui tornaria o seletor deles ambíguo. Só a COR; a caixa vem da .sis-row-action. */
.sis-row-action-settle.mud-icon-button {
    color: var(--mud-palette-success);
}
.sis-row-action-settle.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-success-rgb), 0.12);
    border-color: var(--mud-palette-success);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-success-rgb), 0.28);
}

/* Ação que TRANSMITE a uma autoridade externa — INFO, não primary: é ação de peso, e a cor primária a
   colocaria no mesmo degrau visual de editar, que é a do dia a dia. A geometria vem toda de `.sis-row-action`.

   ⚠️ O nome diz "fiscal" por origem: a classe nasceu para o ícone de classificação fiscal do catálogo de
   produtos, removido em 2026-08-17. Quem a usa hoje é o "Emitir no banco" da tela de Boletos, que a escolheu
   DE PROPÓSITO (o comentário lá explica: mandar o boleto ao banco é transmitir documento a terceiro, como a
   NF-e). ⛔ Não a apague junto com o `OnFiscal` do SisRowActions — aquele slot morreu, esta regra não: ela é
   aplicada direto no markup, e `grep` só em *.css não a encontra. */
.sis-row-action-fiscal.mud-icon-button {
    color: var(--mud-palette-info);
}
.sis-row-action-fiscal.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-info-rgb), 0.12);
    border-color: var(--mud-palette-info);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-info-rgb), 0.28);
}

/* Estornar: cor de AVISO — o degrau que a ação realmente ocupa, entre o não-destrutivo (editar/imprimir) e o
   destrutivo (excluir). Estorno não apaga nada: registra o movimento CONTRÁRIO e preserva a trilha. Mas mexe
   em dinheiro já lançado e não é rotina. Pintá-la de error a confundiria com excluir; de primary, com editar.
   Só a COR muda; a caixa vem da .sis-row-action, comum a todas. */
.sis-row-action-reverse.mud-icon-button {
    color: var(--mud-palette-warning);
}
.sis-row-action-reverse.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-warning-rgb), 0.12);
    border-color: var(--mud-palette-warning);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-warning-rgb), 0.28);
}

/* Corrigir QUANTIDADE: cor primária, a mesma família de editar — é alteração do que já está lançado, não
   destruição nem afirmação. Ícone diferente basta para distinguir os dois gestos; pintá-la de outra cor
   sugeriria uma consequência que ela não tem. Só a COR muda; a caixa vem da .sis-row-action. */
/* Desconto e acréscimo da LINHA: as mesmas cores que os totais usam para os dois sinais (vermelho abate,
   âmbar cobra), para o operador ler o mesmo significado na linha e no resumo. Âmbar e não verde porque a
   primária do sis É verde, e um acréscimo verde ficaria com a cor do botão que fecha a venda. */
.sis-row-action-discount.mud-icon-button {
    color: var(--mud-palette-error);
}
.sis-row-action-discount.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-error-rgb), 0.12);
    border-color: var(--mud-palette-error);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-error-rgb), 0.28);
}

.sis-row-action-surcharge.mud-icon-button {
    color: var(--mud-palette-warning);
}
.sis-row-action-surcharge.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-warning-rgb), 0.12);
    border-color: var(--mud-palette-warning);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-warning-rgb), 0.28);
}

.sis-row-action-quantity.mud-icon-button {
    color: var(--mud-palette-primary);
}
.sis-row-action-quantity.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-primary-rgb), 0.12);
    border-color: var(--mud-palette-primary);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-primary-rgb), 0.28);
}

/* CANCELAR: cor de AVISO, o mesmo degrau do estorno — encerra o documento e preserva o histórico, sem
   apagar nada. Pintá-la de error a igualaria a excluir, que é justamente a distinção que o ícone próprio
   existe para carregar. Só a COR muda; a caixa vem da .sis-row-action. */
.sis-row-action-cancel.mud-icon-button {
    color: var(--mud-palette-warning);
}
.sis-row-action-cancel.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-warning-rgb), 0.12);
    border-color: var(--mud-palette-warning);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-warning-rgb), 0.28);
}

/* Eleger como PADRÃO: cor de sucesso. É a única ação da coluna que AFIRMA algo em vez de alterar ou desfazer —
   e não é destrutiva nem rotina, então nem primary (que a igualaria a editar) nem warning (que sugeriria
   risco). Usa color-mix e não `--mud-palette-success-rgb` porque essa variável não existe no tema: a forma
   -rgb só está definida para primary/info/warning/error. Só a COR muda; a caixa vem da .sis-row-action. */
.sis-row-action-default.mud-icon-button {
    color: var(--mud-palette-success);
}
.sis-row-action-default.mud-icon-button:hover:not(.mud-disabled) {
    background-color: color-mix(in srgb, var(--mud-palette-success) 12%, transparent);
    border-color: var(--mud-palette-success);
    box-shadow: 0 1px 3px color-mix(in srgb, var(--mud-palette-success) 28%, transparent);
}

.sis-row-action-delete.mud-icon-button {
    color: var(--mud-palette-error);
}
.sis-row-action-delete.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-error-rgb), 0.12);
    border-color: var(--mud-palette-error);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-error-rgb), 0.28);
}

/* -------------------------------------------------------------------------
   SisCrudToolbar — largura do campo de busca: fixa no desktop (não engole a
   barra), fluida no celular.

   Estava só no .razor.css isolado, que NÃO carrega em host nenhum (mesmo
   motivo do SisPageHeader acima) — ou seja, a regra nunca chegou a valer e a
   busca esticava. Consolidado aqui, onde de fato entra em vigor.
   ------------------------------------------------------------------------- */
.sis-crud-toolbar .sis-crud-toolbar-search {
    max-width: 360px;
    min-width: 200px;
    flex: 1 1 auto;
}

/* -------------------------------------------------------------------------
   Foco visível por teclado (acessibilidade + acabamento moderno).

   :focus-visible só acende na navegação por TECLADO — o clique de mouse não
   deixa o anel para trás. Sem isso, quem usa Tab (o operador de ERP passa o
   dia nisso — ver "Teclado e navegação" no CLAUDE.md) não enxerga onde está,
   porque o outline default do browser é apagado pelo reset do MudBlazor.
   ------------------------------------------------------------------------- */
.mud-button-root:focus-visible,
.mud-icon-button:focus-visible,
.mud-nav-link:focus-visible,
.mud-table-row:focus-visible {
    outline: 2px solid rgba(var(--mud-palette-primary-rgb), 0.6);
    outline-offset: 2px;
}
/* Sobre a casca navy o verde some — ali o anel é branco. */
.sis-shell-drawer .mud-nav-link:focus-visible,
.sis-nav-mini-icon.mud-icon-button:focus-visible {
    outline-color: rgba(255, 255, 255, 0.75);
}

/* -------------------------------------------------------------------------
   Barra de rolagem.

   O MudThemeProvider já injeta um bloco ::-webkit-scrollbar (8px, thumb em
   --mud-palette-lines-inputs) — cobre Chromium e o WebView2 do host WPF. Aqui
   ficam só as DUAS coisas que faltam ou destoam:

   1. Firefox não lê ::-webkit-scrollbar e o MudBlazor não emite os equivalentes
      padronizados — sem isto, no Firefox a barra é a gorda do sistema.
   2. O bloco do MudBlazor usa `border-radius: 1px` (thumb praticamente
      quadrado) e `cursor: crosshair` sobre a barra. O !important é necessário
      porque aquele <style> é injetado pelo provider DEPOIS deste arquivo no
      documento — sem ele, mesma especificidade, e quem vem por último vence.
   ------------------------------------------------------------------------- */
* {
    scrollbar-width: thin;
    scrollbar-color: var(--mud-palette-lines-inputs) transparent;
}
::-webkit-scrollbar {
    cursor: default !important;
}
::-webkit-scrollbar-thumb {
    border-radius: 8px !important;
}

/* -------------------------------------------------------------------------
   Login (LoginView) — réplica do LoginWindow do WPF: card dividido em dois
   painéis (marca à esquerda, formulário à direita), título/botão no AZUL do
   login (#4154F1), independente do verde do tema do app. Um head só de login,
   então cores próprias por classe (não pela paleta do tema).
   ------------------------------------------------------------------------- */
.sis-login-bg {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: 16px;
    background: var(--mud-palette-background);
    position: relative;
}
.sis-login-card {
    display: flex;
    width: 720px;
    max-width: 100%;
    min-height: 440px;
    border-radius: 14px !important;
    overflow: hidden;
}

/* ⛔ As classes do modo FRAMESS do login (.sis-login-bg--frameless, .sis-login-dragbar, .sis-login-winctl,
   .sis-login-winbtn*) foram APAGADAS em 2026-07-27, junto com o markup que as usava. Elas serviam a janela sem
   moldura do head WPF, que já não existe — nenhum head passava `Frameless`, então eram estilo morto de um
   componente morto. Controle de janela não pertence à RCL compartilhada: ver a nota no LoginView.razor. */

/* Painel esquerdo (marca): fundo claro levemente distinto do branco do form. */
.sis-login-brand {
    flex: 0 0 42%;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 32px 24px;
    background: #f4f6f9;
    border-right: 1px solid #e6e9ef;
}
.sis-login-logo {
    width: 200px;
    max-width: 80%;
    height: auto;
    object-fit: contain;
}
.sis-login-social.mud-icon-button {
    border: 1px solid #b9bec9;
    color: #3f3f3f;
    width: 44px;
    height: 44px;
}
.sis-login-social.mud-icon-button:hover {
    background-color: #e8eaee;
    color: #000;
}
/* Ação secundária do login: "Endereço do servidor" (só nos heads que registram a IApiEndpointFacade — os apps
   locais do ERP). Herda a forma do antigo "Configurar Conexão", que caiu em 2026-07-26: a regra continua sendo
   discreta, arredondada e em caixa normal, para não competir com o botão Login. */
.sis-login-endpoint.mud-button-root {
    border-radius: 20px;
    text-transform: none;
    border-color: #b9bec9;
    color: #3f3f3f;
}
/* Painel direito (formulário): branco, campos e ações centrados. */
.sis-login-form {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 40px 48px;
    background: #ffffff;
}
.sis-login-title {
    font-size: 2.25rem;
    font-weight: 700;
    text-align: center;
    color: #4154f1;             /* azul do login (WPF) */
    line-height: 1.1;
}
.sis-login-subtitle {
    font-size: 1rem;
    text-align: center;
    color: #878787;
    margin-top: 6px;
    margin-bottom: 8px;
}
/* Texto dos campos SEMPRE escuro. O painel do formulário é branco cravado (independe do tema claro/escuro do
   app), mas o texto digitado, o rótulo e os ícones dos campos herdam --mud-palette-text-primary do tema — que
   no tema ESCURO é branco, sumindo no branco do painel. Forço escuro aqui (o rótulo em foco continua azul,
   pela regra mais específica logo abaixo). */
.sis-login-form .mud-input-slot,
.sis-login-form .mud-input-root,
.sis-login-form .mud-input-label,
.sis-login-form .mud-input-adornment .mud-icon-root {
    color: #1f2430 !important;
}
.sis-login-form .mud-input-slot::placeholder {
    color: #9aa1ad !important;
}
/* Foco dos campos do login em AZUL (#4154F1), não no verde do tema do app — o acento do login WPF. */
.sis-login-form .mud-input.mud-input-underline::after {
    border-bottom-color: #4154f1 !important;
}
.sis-login-form .mud-input-control.mud-focused .mud-input-label,
.sis-login-form .mud-input.mud-focused ~ .mud-input-label {
    color: #4154f1 !important;
}
/* ── Escolha de empresa no logon (multiempresa, 2026-08-18) ───────────────────────────────────────────────
   A MESMA armadilha dos campos logo acima, e pela MESMA razão — o radio, entrando depois, ficou de fora da
   regra que só citava `.mud-input-*`. O nome da empresa é um `<p class="mud-typography">` que NÃO declara
   cor nenhuma (`.mud-typography { margin: 0 }` é tudo que o MudBlazor lhe dá), então ele herde direto de
   `body { color: var(--mud-palette-text-primary) }` — o tema do APP. Só que este painel é branco CRAVADO e
   não acompanha o tema: no escuro sai #E7E9F0 sobre #FFFFFF, contraste ~1.1:1. Foi assim que a tela chegou
   em produção, com o nome legível só de perto. O ícone do rádio tinha o mesmo problema, por
   `--mud-palette-action-default`.

   Além do contraste, a opção deixou de ser um rádio solto e virou uma LINHA clicável inteira: moldura,
   hover, anel de foco e escolhida em #4154F1 (o azul do login; o tema do app é verde e não serve de acento
   aqui). Nome longo quebra DENTRO da linha, em vez de empurrar o rádio para longe do texto.

   ⚠️ Os seletores abaixo saem do markup RENDERIDO (MudBlazor 8.13), não do que ele parece ser:
     div.sis-login-empresas
       └ div.mud-input-control.mud-input-control-boolean-input       ← o grupo
           └ div.mud-input-control-input-container
               └ div.mud-radio-group[role=radiogroup]
                   └ div.mud-input-control…mud-input-with-content.sis-login-empresa   ← A LINHA (o `Class`
                       └ div.mud-input-control-input-container          do MudRadio cai AQUI, não no <label>)
                           └ label.mud-radio                            ← o clicável
                               ├ span.mud-button-root…mud-radio-dense
                               │   ├ input.mud-radio-input
                               │   └ svg.mud-icon-root                  ← o rádio
                               └ p.mud-typography.mud-typography-body1  ← o NOME
   ⛔ Não existe `.mud-radio-content` na v8 — a primeira versão desta regra mirava nele e não pintava nada. */
.sis-login-empresas {
    width: 100%;
    max-width: 340px;
    margin: 16px auto 0;
}
/* Uma empresa POR LINHA. O `!important` é necessário, não decorativo: a regra do MudBlazor
   (`.mud-input-control.mud-input-control-boolean-input .mud-radio-group`) empilha em `row`+`wrap` com
   especificidade (0,3,0) e ganharia deste seletor. */
.sis-login-empresas .mud-radio-group {
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 8px;
    width: 100%;
}
/* A LINHA. A marca de escolhida (`--ativa`) é calculada pelo LoginView a partir do mesmo `_empresaEscolhida`
   que o botão Entrar envia — NÃO da `mud-checked` interna do MudBlazor: é o que prende o que a tela destaca
   ao que a confirmação usa, e o que um teste bUnit consegue afirmar. */
.sis-login-empresas .sis-login-empresa {
    border: 1px solid #d7dbe4;
    border-radius: 10px;
    background: #ffffff;
    transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease;
}
.sis-login-empresas .sis-login-empresa:hover {
    border-color: #aeb6f7;
    background: #f7f8ff;
}
/* Teclado: o foco cai no <input> lá dentro, então o anel vai no :focus-within da linha. */
.sis-login-empresas .sis-login-empresa:focus-within {
    border-color: #4154f1;
    box-shadow: 0 0 0 3px rgba(65, 84, 241, 0.18);
}
/* O <label> é o clicável: ocupa a linha toda, para o clique valer em qualquer ponto dela. */
.sis-login-empresas .mud-radio {
    display: flex;
    align-items: center;
    width: 100%;
    margin: 0;
    padding: 6px 12px 6px 6px;
}
/* O nome da empresa: contraste DECLARADO (o porquê está no cabeçalho do bloco) e alinhado à esquerda. */
.sis-login-empresas .mud-radio .mud-typography {
    color: #1f2430 !important;
    font-size: .95rem;
    line-height: 1.3;
    text-align: left;
}
/* Ícone solto: cinza legível. `!important` + especificidade porque o MudBlazor pinta o <span> do rádio com
   `.mud-default-text { color: var(--mud-palette-action-default) !important }`. */
.sis-login-empresas .mud-radio .mud-icon-root {
    color: #6b7280 !important;
}
/* Escolhida: moldura, fundo tingido e o rádio no azul do login. ⛔ Sem mudar peso/tamanho da fonte — o nome
   quebra em duas linhas nesta largura, e engrossá-lo na seleção faria a linha pular de altura.

   🩸 O `:hover` PRECISA estar nesta lista, e a razão é especificidade, não estética: `…empresa:hover` é
   (0,3,0) e `…empresa--ativa` sozinha é (0,2,0), então passar o mouse sobre a linha JÁ escolhida apagava a
   moldura azul e a fazia parecer não-selecionada. Medido pelo E2E do tema escuro, que voltou #ABB3F7 (a cor
   de hover) onde esperava o azul. */
.sis-login-empresas .sis-login-empresa--ativa,
.sis-login-empresas .sis-login-empresa--ativa:hover {
    border-color: #4154f1;
    background: #eef0ff;
}
.sis-login-empresas .sis-login-empresa--ativa:hover {
    background: #e4e8ff;
}
.sis-login-empresas .sis-login-empresa--ativa .mud-icon-root {
    color: #4154f1 !important;
}

/* Ações secundárias em TEXTO do login ("Voltar" dos quatro painéis e "Esqueci minha senha"): a MESMA
   armadilha do rótulo do rádio, e a razão de esta regra existir uma vez só, larga, em vez de por painel — o
   `.sis-login-form` é branco cravado, então TUDO que entra nele declara o próprio contraste, senão herda
   `--mud-palette-text-primary` do tema do app e some no escuro.

   ⚠️ As duas exclusões não são zelo:
     • o botão Entrar TAMBÉM é `mud-button-text` (a pílula azul é background próprio) — sem `:not()` esta
       regra repintaria o texto branco dele de azul;
     • o "Endereço do servidor" (`.sis-login-endpoint`) já declara o próprio #3F3F3F, e este seletor é mais
       específico que o dele.
   O `:not(:disabled)` preserva o cinza de desabilitado enquanto o login está em voo. */
.sis-login-form .mud-button-root.mud-button-text:not(.sis-login-btn):not(.sis-login-endpoint):not(:disabled) {
    color: #4154f1;
}

/* Botão Login: pílula azul, cores próprias (o tema do app é verde). */
.sis-login-btn.mud-button-root {
    background-color: #4154f1;
    color: #fff;
    border-radius: 24px;
    text-transform: none;
    font-weight: 600;
    min-width: 200px;
    padding: 10px 24px;
    box-shadow: 0 2px 8px rgba(65, 84, 241, 0.30);
}
.sis-login-btn.mud-button-root:hover:not(:disabled) {
    background-color: #3244d6;
}
.sis-login-btn.mud-button-root:disabled {
    background-color: #bdbdbd;
    color: #757575;
    box-shadow: none;
}

/* "Lembrar minha senha" (SisRememberLoginCheck) — a caixa e a nota do aparelho compartilhado.

   O componente serve DOIS fundos: o painel branco cravado do ERP (`.sis-login-form`) e o cartão temático
   dos apps, que segue o tema do head (escuro no restaurante). Por isso o layout é neutro aqui e só o
   CONTRASTE é declarado dentro do painel branco — a mesma armadilha das ações em texto logo acima: o que
   entra no `.sis-login-form` e não declara cor herda `--mud-palette-text-primary` do tema do app e some no
   escuro. ⛔ Não pinte a caixa fora do `.sis-login-form`: nos apps ela precisa seguir o tema. */
.sis-login-lembrar {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
/* A nota fica ALINHADA ao rótulo, não à borda do cartão: o recuo do MudCheckBox é o botão de toque, e sem
   compensá-lo a legenda parece pertencer ao campo de cima. */
.sis-login-lembrar-nota {
    padding-left: 34px;
    line-height: 1.25;
    opacity: .72;
}
/* Painel branco do ERP: rótulo e nota declaram o próprio contraste. */
.sis-login-form .sis-login-lembrar .mud-typography,
.sis-login-form .sis-login-lembrar .mud-checkbox span.mud-typography {
    color: #3f3f3f;
}

/* Mobile: o card empilha e o painel de marca some (d-none d-sm-flex no markup). */
@media (max-width: 599.98px) {
    .sis-login-card {
        width: 100%;
        min-height: 0;
    }
    .sis-login-form {
        padding: 32px 24px;
    }
}

/* -------------------------------------------------------------------------
   SPLASH (tela de abertura) — mesmo espírito do login: card claro, sem moldura
   (a janela é arredondada pelo DWM/Win11). Mostrada no boot, antes do login.
   ------------------------------------------------------------------------- */
.sis-splash-bg {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100vh;
    background: #ffffff;
}
.sis-splash-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 32px 48px;
    text-align: center;
}
.sis-splash-logo {
    width: 260px;
    max-width: 72%;
    height: auto;
    object-fit: contain;
    margin-bottom: 8px;
}
.sis-splash-text {
    font-size: 1rem;
    color: #878787;
    margin-top: 6px;
    margin-bottom: 20px;
}
.sis-splash-progress {
    width: 280px;
    max-width: 80%;
    height: 5px !important;
}
.sis-splash-progress .mud-progress-linear-bar {
    background-color: #4154f1 !important;   /* acento azul, igual ao login */
}

/* -------------------------------------------------------------------------
   BUSY OVERLAY (máscara + spinner de "ocupado") — o SisBusyOverlay do ShellLayout.
   Equivalente ao IsLoading do BaseForm legado: caixa central com spinner e rótulo opcional.
   ------------------------------------------------------------------------- */
.sis-busy-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
    padding: 24px 32px;
}
.sis-busy-label {
    color: #ffffff;
    font-size: 0.95rem;
    font-weight: 500;
    letter-spacing: 0.2px;
}

/* =========================================================================
   APPS DE CELULAR (garçom, Sis Food, Força de Vendas) — mobile-first.

   Estas regras existem porque estas são as superfícies do sis operadas em
   celular na mão, em pé, durante o serviço: alvo de toque grande, nada de
   conteúdo essencial abaixo da dobra, e respeito ao notch/gesture bar (o
   index.html de cada head declara viewport-fit=cover, mas quem consome os
   env(safe-area-inset-*) é este arquivo — sem isto a barra superior fica sob o
   relógio/status bar e a barra de ação sob o indicador de home).

   ⚠️ viewport-fit=cover SEM estas regras é PIOR que não tê-lo: ele manda o
   conteúdo ocupar a tela inteira, incluindo o que fica embaixo das barras do
   sistema. Foi exatamente esse o defeito da Força de Vendas (2026-07-28) — o
   head declarava cover, nenhuma regra consumia os insets, e a barra superior
   nascia por baixo do relógio do Android, com o toque indo para a status bar
   em vez do botão. O Android nativo dos dois apps é IDÊNTICO (mesmo
   MainActivity, mesmo manifesto): a diferença era só a ausência do seletor
   abaixo. É por isso que os shells dividem a MESMA regra em vez de cada app
   ter a sua cópia — cópia é como um deles volta a ficar para trás.

   Todo env(...) tem fallback 0px: no desktop e no WebView do MAUI as regras
   degradam exatamente para o layout de antes.
   ========================================================================= */

/* Casca: a barra fina desce abaixo do notch e o conteúdo acompanha. */
.sis-waiter-shell .mud-appbar,
.sis-fv-shell .mud-appbar {
    padding-top: env(safe-area-inset-top, 0px);
    height: calc(var(--mud-appbar-height, 48px) + env(safe-area-inset-top, 0px));
}

.sis-waiter-shell .mud-main-content,
.sis-fv-shell .mud-main-content {
    padding-top: calc(var(--mud-appbar-height, 48px) + env(safe-area-inset-top, 0px));
}

/* O drawer é overlay de altura inteira: sem isto o cabeçalho do menu (nome do
   vendedor) nasce embaixo do relógio. Só a Força de Vendas tem drawer — o
   garçom e o Sis Food são de uma tela só. */
.sis-fv-shell .mud-drawer {
    padding-top: env(safe-area-inset-top, 0px);
}

/* Snackbar ancorado embaixo (PositionClass = BottomRight em AddSisUi): a
   mensagem nascia METADE embaixo da barra de navegação do Android — e o botão
   de fechar junto. Regra GLOBAL, e não por shell, porque o provider é montado
   FORA do MudLayout (no SisThemeProvider), então nenhum seletor de casca o
   alcança. Nos heads de desktop o env() vale 0px e nada muda. */
.mud-snackbar-location-bottom-left,
.mud-snackbar-location-bottom-center,
.mud-snackbar-location-bottom-right {
    padding-bottom: env(safe-area-inset-bottom, 0px);
}

/* Área de trabalho da Força de Vendas. O padding-bottom cobre a faixa de
   gestos; nas telas que têm barra de ação fixa própria (o editor de pedido) ela
   soma folga de rolagem, o que é inofensivo — o contrário, faltar, esconde o
   último item da lista atrás da barra do sistema. */
.sis-fv-content {
    padding: 8px 8px calc(24px + env(safe-area-inset-bottom, 0px)) 8px;
    min-height: 100%;
}

/* Área de trabalho: padding lateral menor no celular (cada pixel conta na
   largura do card) e folga inferior para a barra de ação fixa não cobrir o
   último item da lista. */
.sis-waiter-content {
    padding: 12px 12px calc(96px + env(safe-area-inset-bottom, 0px)) 12px;
    min-height: 100%;
}

@media (min-width: 600px) {
    .sis-waiter-content {
        padding: 20px 20px calc(104px + env(safe-area-inset-bottom, 0px)) 20px;
    }
}

/* -------------------------------------------------------------------------
   Card de comanda do board
   -------------------------------------------------------------------------
   O card ANTIGO era um retângulo de cor chapada (laranja/cinza/vermelho) com
   TODO o texto branco por cima, em duas linhas de flex com MudSpacer. Em
   telefone (3 colunas fixas, ~100px de largura útil) "A enviar" e "R$ 58,00"
   dividiam a mesma linha e se sobrepunham — era o "texto fora do card" do
   relato. Além disso branco sobre #FF9800 dá ~2,1:1 de contraste (WCAG AA pede
   4,5:1).

   O card novo é Material: superfície do tema + faixa de acento colorida à
   esquerda + chip de status na cor. A cor continua legível do outro lado do
   salão (é o ponto do board), mas o texto fica sobre a superfície, com
   contraste do tema, e cada informação em sua própria linha. */
.sis-tab-card {
    position: relative;
    display: flex;
    flex-direction: column;
    /* align-items explícito: o Chrome aplica `align-items: center` na UA stylesheet de <button>, o que
       encolhia e centralizava as linhas internas em vez de esticá-las na largura do card. */
    align-items: stretch;
    gap: 6px;
    width: 100%;
    height: 100%;
    padding: 12px 12px 12px 18px;
    border: 1px solid var(--mud-palette-lines-default);
    border-left: 6px solid var(--sis-tab-accent, var(--mud-palette-primary));
    border-radius: var(--mud-default-borderradius, 12px);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    text-align: left;
    cursor: pointer;
    transition: transform .12s ease, box-shadow .12s ease, background-color .12s ease;
    -webkit-tap-highlight-color: transparent;
}

.sis-tab-card:hover,
.sis-tab-card:focus-visible {
    background-color: color-mix(in srgb, var(--sis-tab-accent, var(--mud-palette-primary)) 10%, var(--mud-palette-surface));
    box-shadow: 0 2px 10px rgba(0, 0, 0, .35);
    outline: none;
}

.sis-tab-card:active {
    transform: scale(.98);
}

/* Número da comanda: a informação que o garçom procura primeiro. */
.sis-tab-card__number {
    font-size: 1.75rem;
    font-weight: 700;
    line-height: 1.1;
}

/* Tempo aberto — discreto, à direita do número. */
.sis-tab-card__elapsed {
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

/* Chip de status: é ele que carrega a cor do estado (a mesma da legenda). */
.sis-tab-card__status {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    align-self: flex-start;
    max-width: 100%;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: .7rem;
    font-weight: 600;
    line-height: 1.5;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    background-color: color-mix(in srgb, var(--sis-tab-accent) 22%, transparent);
    color: var(--sis-tab-accent);
}

/* Total: linha própria, alinhado à direita, nunca disputando espaço com o
   status (era exatamente essa disputa que quebrava o layout). */
.sis-tab-card__total {
    margin-top: auto;
    font-size: 1.05rem;
    font-weight: 700;
    text-align: right;
    white-space: nowrap;
}

/* Ponto colorido da legenda. */
.sis-legend-dot {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 4px;
    flex: 0 0 auto;
}

/* -------------------------------------------------------------------------
   Barra de ação fixa no rodapé (workspace e lançamento)
   -------------------------------------------------------------------------
   No celular as ações principais ficavam no TOPO, acima da lista de itens: com
   a comanda cheia o garçom precisava rolar de volta pra salvar. Fixa no
   rodapé, ficam sempre no alcance do polegar. */
.sis-waiter-actionbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1200;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px)) 12px;
    background-color: var(--mud-palette-surface);
    border-top: 1px solid var(--mud-palette-lines-default);
    box-shadow: 0 -2px 12px rgba(0, 0, 0, .35);
}

.sis-waiter-actionbar .mud-button-root {
    min-height: 48px;   /* alvo de toque mínimo recomendado */
}

/* -------------------------------------------------------------------------
   Faixa de MODO DEMONSTRAÇÃO
   -------------------------------------------------------------------------
   Largura inteira, no topo do conteúdo, `sticky` — e isso é decisão, não
   inércia. Em 2026-07-26 eu a troquei por um ícone pequeno no rodapé e o
   dono corrigiu: o que ele pediu para virar ícone foi o botão de ENTRAR na
   demonstração, no LOGIN. O AVISO de que se está nela continua sendo faixa,
   porque ele existe justamente para não passar despercebido — sem ele
   alguém olha um total (ou uma comanda) fictício e acha que é real.

   Virou classe compartilhada aqui em vez dos dois blocos de `style` inline
   que existiam antes: um lugar só, os dois apps, e a regra do repo de que
   estilo de componente da RCL mora no sis-theme.css (o .razor.css não
   carrega em host nenhum). */
.sis-demo-banner {
    position: sticky;

    /* ⚠️ `top: 0` NÃO funcionava, e isso passou despercebido desde que a faixa nasceu: sticky ancora no
       VIEWPORT, e o viewport começa atrás da MudAppBar, que é `fixed`. Ao rolar, a faixa "grudava" debaixo
       da barra e sumia de vista — exatamente o cenário em que ela precisa estar (o total fictício aparece
       ao rolar). Só apareceu numa captura com a tela rolada; nenhum teste pegaria, porque `position:sticky`
       estava lá e o elemento estava no DOM.

       48px é a altura da MudAppBar `Dense`, que os dois apps usam; o `env()` cobre o notch do garçom, cuja
       casca desce a barra pelo inset (sis-waiter-shell). */
    top: calc(48px + env(safe-area-inset-top, 0px));

    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    width: 100%;
    border: 0;
    cursor: pointer;
    padding: .35rem .5rem;
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .03em;
    background-color: var(--mud-palette-warning);
    color: var(--mud-palette-warning-text);
}

/* -------------------------------------------------------------------------
   Ícone de "ver demonstração" no LOGIN
   -------------------------------------------------------------------------
   Era um botão de largura inteira embaixo do "Entrar", com legenda. O dono
   pediu ícone (2026-07-26): quem loga todo dia não precisa da vitrine
   ocupando o mesmo peso visual da ação principal.

   Fica na MESMA linha do alternador de tema, no rodapé do cartão de login —
   é onde já moram as ações secundárias da tela. */
.sis-demo-login-icon {
    color: var(--mud-palette-warning);
}

/* FAB de "abrir comanda" — acima da barra de ação e do inset inferior. */
.sis-waiter-fab {
    position: fixed;
    right: 16px;
    bottom: calc(20px + env(safe-area-inset-bottom, 0px));
    z-index: 1210;
}

/* -------------------------------------------------------------------------
   Faixa de categorias do lançamento
   -------------------------------------------------------------------------
   Eram cartões de 110px com quebra de linha: no telefone ocupavam TRÊS linhas
   (~450px) antes do primeiro produto aparecer. Vira uma faixa de rolagem
   horizontal — padrão Material de "filter chips" — e o produto sobe pra área
   visível. */
.sis-cat-strip {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom: 6px;
    scrollbar-width: thin;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
}

.sis-cat-strip::-webkit-scrollbar {
    height: 4px;
}

.sis-cat-strip::-webkit-scrollbar-thumb {
    background-color: var(--mud-palette-lines-default);
    border-radius: 4px;
}

.sis-cat-chip {
    /* Coluna EXPLÍCITA: o Chrome trata a caixa de conteúdo de um <button> como flex row, então os dois
       <span> ficavam lado a lado mesmo declarados display:block. */
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    flex: 0 0 auto;
    scroll-snap-align: start;
    min-width: 104px;
    padding: 8px 14px;
    border-radius: 999px;
    border: 2px solid transparent;
    cursor: pointer;
    line-height: 1.25;
    text-align: left;
    -webkit-tap-highlight-color: transparent;
}

.sis-cat-chip--selected {
    border-color: var(--mud-palette-primary);
}

.sis-cat-chip__name {
    display: block;   /* nome em cima, contagem embaixo — sem depender de utilitário do MudBlazor */
    font-size: .875rem;
    font-weight: 600;
    white-space: nowrap;
}

.sis-cat-chip__count {
    display: block;
    font-size: .7rem;
    opacity: .75;
    white-space: nowrap;
}

/* -------------------------------------------------------------------------
   Card de produto do lançamento
   ------------------------------------------------------------------------- */
.sis-product-card {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: stretch;   /* idem .sis-tab-card: neutraliza o align-items: center do <button> */
    gap: 8px;
    width: 100%;
    height: 100%;
    min-height: 92px;
    padding: 12px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius, 12px);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    text-align: left;
    cursor: pointer;
    transition: border-color .12s ease, transform .12s ease;
    -webkit-tap-highlight-color: transparent;
}

.sis-product-card:hover,
.sis-product-card:focus-visible {
    border-color: var(--mud-palette-primary);
    outline: none;
}

.sis-product-card:active {
    transform: scale(.98);
}

.sis-product-card__name {
    font-size: .875rem;
    line-height: 1.25;
    /* Nome longo ocupa até 3 linhas e vira reticências — não estica o card nem
       vaza pra fora dele. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.sis-product-card__price {
    font-size: .95rem;
    font-weight: 700;
    color: var(--mud-palette-primary);
    white-space: nowrap;
}

/* -------------------------------------------------------------------------
   Linha de item da comanda (workspace e resumo do lançamento)
   ------------------------------------------------------------------------- */
.sis-tab-item {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 4px;
}

.sis-tab-item__qty {
    flex: 0 0 auto;
    min-width: 38px;
    padding: 2px 6px;
    border-radius: 8px;
    background-color: color-mix(in srgb, var(--mud-palette-primary) 18%, transparent);
    color: var(--mud-palette-primary);
    font-size: .8rem;
    font-weight: 700;
    text-align: center;
}

.sis-tab-item__body {
    flex: 1 1 auto;
    min-width: 0;   /* deixa o texto longo quebrar em vez de empurrar o preço pra fora */
}

/* Link de observação, logo abaixo da descrição do item (app do garçom). Compacto e numa linha só: a linha
   de item divide 390px com quantidade, preço e dois botões de 30px, e um rótulo que quebra empurra a altura
   de TODAS as linhas da comanda. */
.sis-tab-item__note-action {
    min-width: 0;
    height: 28px;
    white-space: nowrap;
    text-transform: none;
    font-size: .78rem;
}

.sis-tab-item__total {
    flex: 0 0 auto;
    font-weight: 700;
    white-space: nowrap;
}

/* =========================================================================
   RESTAURANTE — tela de gerência (RestaurantPage e subtelas), tema Food.

   Segue o vocabulário fixado pelo redesenho do PDV (2026-07-25): card como
   unidade de superfície, hierarquia de botão (tonais + UM sólido, o que fecha
   a conta), container tonal via rgba(var(--mud-palette-*-rgb), a) — nenhum
   hexadecimal cravado, para o tema continuar sendo a fonte única da cor.
   ========================================================================= */

/* Abas "Mesas"/"Venda rápida": o MudTabs força CAIXA ALTA por conta própria,
   ignorando o TextTransform="none" da tipografia do tema. */
.sis-restaurant-tabs .mud-tab {
    text-transform: none;
    font-weight: 600;
}

/* Respiro lateral PRÓPRIO da tela, em vez de depender do padding do host.
   O FoodHost do WPF dá pa-2 (8px) e o painel de inspeção dava menos ainda: o
   total do cabeçalho e o "Fechar conta" ficavam colados na quina da viewport.
   Com o padding aqui, a tela fica correta em qualquer host que a monte. */
.sis-restaurant-tabs .mud-tabs-panels {
    padding-inline: clamp(8px, 1.5vw, 20px);
}

/* -------------------------------------------------------------------------
   Cabeçalho de comanda (workspace e fechamento)
   -------------------------------------------------------------------------
   O total ficava na MESMA linha de flex do título e dos chips, empurrado por
   um MudSpacer. Abaixo de ~1100px isso o encostava na borda — em 820px ele
   saía cortado, junto com o "Fechar conta". Agora título e total são blocos
   independentes que quebram em coluna quando não cabem. */
.sis-tab-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px 16px;
    margin-bottom: 16px;
}

.sis-tab-header__id {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    min-width: 0;   /* deixa os chips encolherem em vez de empurrar o total */
}

.sis-tab-header__total {
    margin-left: auto;
    text-align: right;
    white-space: nowrap;
}

.sis-tab-header__total-label {
    display: block;
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
    line-height: 1.2;
}

.sis-tab-header__total-value {
    display: block;
    font-size: clamp(1.25rem, 2.2vw, 1.75rem);
    font-weight: 700;
    color: var(--mud-palette-primary);
    line-height: 1.2;
}

/* -------------------------------------------------------------------------
   Barra de ações da comanda
   -------------------------------------------------------------------------
   Eram SETE botões numa linha de flex com MudSpacer: quebravam em duas
   fileiras e deixavam o "Fechar conta" órfão na ponta, colado na borda. Agora
   as ações secundárias vivem num grupo que rola/quebra por conta própria e a
   ação primária (única sólida) fica ancorada à direita, nunca cortada. */
.sis-tab-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 16px;
}

.sis-tab-actions__group {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    min-width: 0;
    flex: 1 1 auto;
}

.sis-tab-actions__primary {
    flex: 0 0 auto;
    margin-left: auto;
}

/* Ícone dentro de botão/chip nunca encolhe nem vira elipse. */
.sis-tab-actions .mud-icon-root,
.sis-tab-header .mud-icon-root {
    flex: 0 0 auto;
}

/* -------------------------------------------------------------------------
   Card de mesa do board da gerência
   -------------------------------------------------------------------------
   O card usava min-height cravado em três pontos (20px no nome, 60px na
   prévia de itens) só para os cards de uma linha terminarem na mesma altura —
   o que o grid já faz com height:100% + flex. E não havia indicação nenhuma
   de estado: mesa com item pendente de cozinha era idêntica a mesa com tudo
   enviado. A faixa de acento resolve os dois. */
.sis-table-card {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    width: 100%;
    height: 100%;
    padding: 14px 14px 14px 18px;
    border: 1px solid var(--mud-palette-lines-default);
    border-left: 6px solid var(--sis-table-accent, var(--mud-palette-lines-default));
    border-radius: var(--mud-default-borderradius, 12px);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    text-align: left;
    cursor: pointer;
    transition: background-color .12s ease, box-shadow .12s ease;
    -webkit-tap-highlight-color: transparent;
}

.sis-table-card:hover,
.sis-table-card:focus-visible {
    background-color: color-mix(in srgb, var(--sis-table-accent, var(--mud-palette-primary)) 10%, var(--mud-palette-surface));
    box-shadow: 0 2px 10px rgba(0, 0, 0, .35);
    outline: none;
}

.sis-table-card__top {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.sis-table-card__number {
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1.1;
    color: var(--mud-palette-primary);
}

/* 🔢 O SEGUNDO número do card: o do PEDIDO ("#128"), sequencial da empresa. Discreto de propósito — o
   número GRANDE é o que o operador procura de longe (a mesa), e este é o que ele cita ao telefone e casa
   com o cupom. Monoespaçado para os dígitos não dançarem entre um card e outro. */
.sis-table-card__order {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    opacity: .85;
}

.sis-table-card__meta {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.sis-table-card__name {
    font-size: .8rem;
    color: var(--mud-palette-text-secondary);
    /* Sem min-height: o alinhamento entre cards vem do height:100% + flex. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Entregador do delivery, logo abaixo do cliente. Nome longo trunca em vez de
   alargar o card — o board é uma grade, e um card mais largo desalinha a linha. */
.sis-table-card__courier {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: .78rem;
    /* Texto no tom do CORPO, não no azul do info: nome de gente é informação que se
       lê, e #2196F3 sobre a superfície branca dá ~3:1 — abaixo do que a WCAG AA pede
       para texto pequeno. O azul fica só no ícone, que é decorativo. */
    color: var(--mud-palette-text-primary);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sis-table-card__courier .mud-icon-root {
    font-size: .95rem;
    flex: 0 0 auto;
    color: var(--mud-palette-info);
}

/* Ainda não saiu com ninguém: mesma linha, tom mais quieto e itálico. Não é alerta —
   pedido recém-aberto não tem entregador e isso é normal; o que se quer é poder
   varrer o board e ver quais já saíram. */
.sis-table-card__courier--none,
.sis-table-card__courier--none .mud-icon-root {
    color: var(--mud-palette-text-secondary);
    font-style: italic;
}

/* ORIGEM da comanda: veio de um canal externo (iFood, delivery direto…). Mesma
   geometria da linha do entregador — as duas respondem "de onde / para onde", são
   lidas na mesma varredura vertical do card, e alinhá-las evita criar um segundo
   eixo visual para dizer a mesma classe de coisa.

   Tom SECUNDÁRIO, e não a cor da marca do canal: o vermelho do iFood competiria
   com o vermelho de atraso/erro, que no board já significa outra coisa. Origem é
   contexto, não alerta — quem precisa reagir tem o selo de pronto e o contador da
   cozinha. O ícone Hub é o que distingue esta linha da do entregador sem gritar. */
.sis-table-card__origin {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: .78rem;
    color: var(--mud-palette-text-secondary);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sis-table-card__origin .mud-icon-root {
    font-size: .95rem;
    flex: 0 0 auto;
    color: var(--mud-palette-secondary);
}

/* Contador de itens PRONTOS na cozinha, no rodapé do card. Cor de sucesso na
   borda e no texto, fundo translúcido: chama o olho sem virar um bloco chapado
   competindo com o total (que é o número mais importante do card). */
.sis-table-card__ready {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 1px 6px;
    border: 1px solid var(--mud-palette-success);
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 600;
    line-height: 1.5;
    color: var(--mud-palette-success);
    background-color: color-mix(in srgb, var(--mud-palette-success) 12%, transparent);
}

.sis-table-card__ready .mud-icon-root {
    font-size: .9rem;
}

/* Prévia dos itens: cresce e empurra o rodapé do card pra baixo, o que
   alinha os totais de todos os cards da linha sem altura cravada. */
.sis-table-card__items {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    gap: 2px;
    font-size: .75rem;
    color: var(--mud-palette-text-primary);
}

.sis-table-card__items span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Rodapé do card: selo de estado + selos opcionais (prontos na cozinha, pendente
   de envio) + o TOTAL.

   ⚠️ Quem cede espaço aqui é o SELO, nunca o total — e isso precisa estar escrito
   em `flex`, não implícito. Medido em 2026-08-08: com o `flex-shrink: 1` default
   em todos os filhos, o card que ganhava um selo a mais (o contador de prontos,
   o relógio do delivery) estourava a linha, e o dinheiro — que é `nowrap` —
   encolhia a CAIXA e ficava cortado pela borda: "R$ 58,0". Ou seja, o valor da
   conta sumia justamente na comanda que a cozinha já tinha atendido, e só na que
   já tinha sido atendida. Nada quebrava: build, bUnit e E2E passavam; quem viu
   foi a captura. */
.sis-table-card__foot {
    display: flex;
    align-items: center;
    /* QUEBRA quando não cabe: o total desce para uma linha só dele, ainda à
       direita (o `margin-left: auto` continua valendo), e o card cresce alguns
       pixels. Encolher o selo sozinho NÃO bastava — medido: levou o transbordo de
       39 px para 3 px em 1024×768, e 3 px continua sendo um dígito cortado. É a
       mesma conclusão a que o card do BOARD DO GARÇOM já tinha chegado
       (`.sis-tab-card__total`: "linha própria, nunca disputando espaço com o
       status"); este rodapé só não tinha aprendido. */
    flex-wrap: wrap;
    gap: 8px;
    /* Sem isto, o mínimo automático de conteúdo do filho impede o encolhimento
       do selo e a sobra volta a recair no total. */
    min-width: 0;
    padding-top: 8px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.sis-table-card__total {
    margin-left: auto;
    /* NUNCA encolhe: o total é o número mais importante do card, e meio número é
       pior que nenhum — "R$ 58,0" se lê como um valor válido. */
    flex: 0 0 auto;
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--mud-palette-primary);
    white-space: nowrap;
}

/* Os selos pequenos e o ícone de pendência: largura própria, sem disputa. São
   curtos por construção (um número, um ícone) — encolhê-los não devolve espaço
   útil e ainda os deixa ilegíveis. */
.sis-table-card__ready,
.sis-table-card__foot > .mud-icon-root {
    flex: 0 0 auto;
}

/* Selo de estado: tinta do próprio acento, como no PDV (container tonal).
   É ELE quem cede — o rótulo ("Aberta", "Delivery", "Fechada") continua
   reconhecível truncado, e o total fica inteiro. */
.sis-table-card__status {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    min-width: 0;
    overflow: hidden;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: .68rem;
    font-weight: 600;
    white-space: nowrap;
    text-overflow: ellipsis;
    background-color: color-mix(in srgb, var(--sis-table-accent) 22%, transparent);
    color: var(--sis-table-accent);
}

/* -------------------------------------------------------------------------
   Fechamento (CheckoutPanel)
   ------------------------------------------------------------------------- */

/* Linha de resultado (Total / Falta / Troco): rótulo e valor sem disputa. */
.sis-checkout-line {
    display: flex;
    align-items: baseline;
    gap: 12px;
    margin-bottom: 12px;
}

.sis-checkout-line__label {
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;   /* a CAIXA ALTA é estilo, não conteúdo */
    color: var(--mud-palette-text-secondary);
}

.sis-checkout-line__value {
    margin-left: auto;
    font-weight: 700;
    white-space: nowrap;
    font-size: clamp(1.1rem, 2vw, 1.6rem);
}

.sis-checkout-line--total .sis-checkout-line__value { color: var(--mud-palette-primary); }
.sis-checkout-line--due .sis-checkout-line__label,
.sis-checkout-line--due .sis-checkout-line__value { color: var(--mud-palette-warning); }
.sis-checkout-line--change .sis-checkout-line__label,
.sis-checkout-line--change .sis-checkout-line__value { color: var(--mud-palette-success); }

/* Botão de forma de pagamento: ícone em círculo tonal, como o PDV. */
.sis-payment-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 100%;
    height: 100%;
    min-height: 88px;
    padding: 12px 8px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius, 12px);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    cursor: pointer;
    transition: border-color .12s ease, background-color .12s ease;
    -webkit-tap-highlight-color: transparent;
}

.sis-payment-card:hover:not(:disabled),
.sis-payment-card:focus-visible {
    border-color: var(--mud-palette-primary);
    background-color: rgba(var(--mud-palette-primary-rgb), .08);
    outline: none;
}

.sis-payment-card:disabled {
    opacity: .5;
    cursor: default;
}

.sis-payment-card__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background-color: rgba(var(--mud-palette-primary-rgb), .14);
}

.sis-payment-card__label {
    font-size: .75rem;
    line-height: 1.2;
    text-align: center;
}

/* -------------------------------------------------------------------------
   Venda rápida — estado inicial
   ------------------------------------------------------------------------- */
.sis-quicksale-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    padding: clamp(24px, 6vw, 64px) 16px;   /* era pa-12 fixo */
    text-align: center;
}

/* Mesa LIVRE do mapa fixo: mesma geometria do card ocupado (a grade tem de ficar
   regular), mas sem preenchimento visual — o olho precisa varrer o salão e achar
   as ocupadas, não as vazias. Borda tracejada + conteúdo apagado dizem "aqui não
   tem nada" sem gritar. */
.sis-table-card--free {
    background-color: transparent;
    border-style: dashed;
    border-left-style: solid;   /* a faixa de acento continua sólida, como nas demais */
    opacity: .72;
}

.sis-table-card--free:hover,
.sis-table-card--free:focus-visible {
    opacity: 1;
    background-color: rgba(var(--mud-palette-primary-rgb), .06);
    border-color: var(--mud-palette-primary);
}

.sis-table-card--free .sis-table-card__number {
    color: var(--mud-palette-text-secondary);
}

/* "Abrir" no rodapé: a ação que o clique dispara, dita em palavra. */
.sis-table-card__free-hint {
    margin-left: auto;
    font-size: .75rem;
    font-weight: 600;
    color: var(--mud-palette-primary);
    white-space: nowrap;
}

/* -------------------------------------------------------------------------
   Visualizador de PDF (PdfViewer) e a execução do relatório do B.I.

   Mora AQUI, e não num PdfViewer.razor.css, porque CSS isolado não carrega em
   host nenhum (ver o cabeçalho deste arquivo). Isto não é preferência: com o
   estilo no arquivo isolado, o visualizador renderizava sem NADA — a barra de
   ações empilhada e o <iframe> no tamanho default do navegador (300x150), o
   que fazia a visualização do relatório do B.I. parecer quebrada.
   ------------------------------------------------------------------------- */
.sis-pdf-viewer {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
    width: 100%;
    gap: 12px;
}

/* Cabeçalho: identidade do arquivo à esquerda, ações à direita. Superfície
   contornada (Material "outlined container"), não elevada — o destaque da tela
   é o documento, não a barra. */
.sis-pdf-viewer__bar {
    position: relative;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    padding: 10px 12px;
    overflow: hidden;   /* segura o MudProgressLinear dentro do canto arredondado */
}

.sis-pdf-viewer__id {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}

/* Ícone em círculo tonal — mesma linguagem do .sis-payment-card do PDV. */
.sis-pdf-viewer__avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background-color: rgba(var(--mud-palette-error-rgb), .12);
    color: var(--mud-palette-error);
}

.sis-pdf-viewer__meta {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.25;
}

.sis-pdf-viewer__filename {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 38vw;
    font-weight: 600;
}

.sis-pdf-viewer__hint {
    color: var(--mud-palette-text-secondary);
}

.sis-pdf-viewer__actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

/* Ações secundárias (baixar/imprimir): caixa contornada discreta, mesma FORMA
   do .sis-row-action do grid — a geometria da ação de ícone é uma só no sis. */
.sis-pdf-viewer__ghost.mud-icon-button {
    width: 36px;
    height: 36px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius, 8px);
    color: var(--mud-palette-text-secondary);
    background-color: transparent;
}

.sis-pdf-viewer__ghost.mud-icon-button:hover:not(:disabled) {
    background-color: rgba(var(--mud-palette-primary-rgb), .10);
    border-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary);
}

/* Separador entre as ações secundárias e as principais: dá a hierarquia sem
   precisar de mais uma linha de texto. */
.sis-pdf-viewer__divider {
    width: 1px;
    align-self: stretch;
    margin: 2px 2px;
    background-color: var(--mud-palette-lines-default);
}

.sis-pdf-viewer__progress {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 3px;
}

.sis-pdf-viewer__surface {
    position: relative;
    flex: 1 1 auto;
    min-height: 420px;   /* piso: dentro de um MudTabPanel a altura do pai é auto */
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius, 12px);
    overflow: hidden;
    background-color: var(--mud-palette-background-gray);
}

/* ⛔ NÃO troque por `height: 100%` — foi assim e o PDF aparecia cortado (2026-07-28).
   `height: 100%` resolve contra a ALTURA do pai, e `.sis-pdf-viewer__surface` declara
   `min-height`, não `height`. Percentual contra pai sem altura definida é indeterminado:
   o <iframe> cai na altura intrínseca padrão (150px) e o documento vira uma miniatura
   num retângulo vazio.

   Isso reapareceu em toda tela que embute o visualizador — B.I., pedido de venda — e a
   correção anterior foi dar altura à CADEIA por fora (`.sis-report-viewer`), tela a tela.
   Não é sustentável: a próxima tela nasce quebrada de novo.

   `position: absolute; inset: 0` preenche o pai posicionado sem depender da altura dele —
   é o mesmo que `.sis-pdf-viewer__empty` já fazia logo abaixo. O visualizador passa a ser
   autossuficiente, e quem o embute não precisa saber de nada. */
.sis-pdf-viewer__frame {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
}

.sis-pdf-viewer__empty {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    text-align: center;
    padding: 24px;
}

.sis-pdf-viewer__empty-icon.mud-icon-root {
    width: 56px;
    height: 56px;
    font-size: 56px;
    color: var(--mud-palette-text-disabled);
}

/* Tablet: o cabeçalho empilha e as ações ocupam a linha inteira. */
@media (max-width: 900px) {
    .sis-pdf-viewer__filename {
        max-width: 60vw;
    }

    .sis-pdf-viewer__actions {
        width: 100%;
    }

    .sis-pdf-viewer__actions .sis-pdf-viewer__action {
        flex: 1 1 auto;
    }
}

/* Celular: os rótulos saem (sobra o ícone), o separador some e o documento
   ganha praticamente a tela toda. */
@media (max-width: 600px) {
    .sis-pdf-viewer__action-label {
        display: none;
    }

    .sis-pdf-viewer__divider {
        display: none;
    }

    .sis-pdf-viewer__surface {
        min-height: 60vh;
    }
}

/* Execução do relatório do B.I.: o diálogo é FullScreen, então o conteúdo
   precisa esticar em coluna até o rodapé — senão o visualizador de PDF não tem
   altura nenhuma pra ocupar e o documento fica espremido no topo. */
.sis-report-viewer {
    display: flex;
    flex-direction: column;
    min-height: 0;
    height: 100%;
    padding-top: 8px;
}

.sis-report-viewer .mud-tabs,
.sis-report-viewer .mud-tabs-panels,
.sis-report-viewer .mud-tab-panel {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
}

.sis-report-viewer .mud-tabs-panels {
    overflow: auto;
}

/* O visualizador ocupa o que sobra da aba (a barra de ações tem altura própria).
   Fora de um pai flex, `flex` é ignorado — então isto não afeta os outros usos. */
.sis-pdf-viewer {
    flex: 1 1 auto;
}

/* Tabela de dados do relatório dentro de uma superfície contornada, com o
   cabeçalho grudado no topo na rolagem (relatório é feito pra ser lido de cima
   a baixo — perder o cabeçalho na linha 40 é perder o significado da coluna). */
.sis-report-table {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius, 12px);
}

.sis-report-table table thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background-color: var(--mud-palette-background-gray);
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    text-transform: uppercase;
    font-size: .75rem;
    letter-spacing: .02em;
}

.sis-report-table .sis-report-group td {
    background-color: rgba(var(--mud-palette-primary-rgb), .10);
    color: var(--mud-palette-text-primary);
    font-weight: 600;
}

.sis-report-table .sis-report-subtotal td {
    background-color: var(--mud-palette-background-gray);
    font-weight: 600;
}

.sis-report-table .sis-report-total td {
    background-color: rgba(var(--mud-palette-primary-rgb), .14);
    font-weight: 700;
    border-top: 2px solid var(--mud-palette-primary);
}

/* =========================================================================
   Overlay de etapa (fechamento de venda, e o que vier depois)
   -------------------------------------------------------------------------
   É OUTRA TELA, não um diálogo: cobre a viewport inteira, com barra própria e
   corpo rolável. O molde é o `.pdv-overlay` do PDV varejo, que o dono apontou
   como o desenho certo pra receber dinheiro — a diferença é que aqui as cores
   vêm todas do tema (o overlay do PDV nasceu antes da unificação).

   Por que não MudDialog: diálogo carrega a promessa de "cabe numa caixa", e
   fechamento com várias formas + parcelas + troco não cabe. Foi exatamente o
   erro do VendaEditorDialog, em escala menor.
   ========================================================================= */
.sis-overlay {
    position: fixed;
    inset: 0;
    z-index: 1300;                       /* acima do conteúdo, abaixo do Snackbar do MudBlazor */
    display: flex;
    flex-direction: column;
    background-color: var(--mud-palette-background);
}

.sis-overlay__bar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-surface);
}

.sis-overlay__title {
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;           /* CAIXA ALTA é estilo, não conteúdo */
}

.sis-overlay__body {
    flex: 1;
    min-height: 0;                       /* sem isto o filho rolável estoura o flex */
    overflow-y: auto;
    padding: 16px;
}

/* Grade de formas de pagamento: cresce com a largura sem quebrar em 1024x768,
   onde a coluna do overlay tem ~600px. auto-fill + minmax evita ter de escolher
   um número de colunas por breakpoint. */
.sis-payment-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 12px;
}

/* Lançamento já feito, na lista do resumo. */
.sis-payment-entry {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 0;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.sis-payment-entry__name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sis-payment-entry__amount { margin-left: auto; font-weight: 600; white-space: nowrap; }

/* Detalhe de um lançamento (as parcelas embaixo do bloco "a prazo"): recuado, menor e sem a divisória —
   é uma sublinha do que está acima, não outro lançamento. */
.sis-payment-entry--child {
    padding: 2px 0 2px 28px;
    border-bottom: none;
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary);
}

.sis-payment-entry--child .sis-payment-entry__amount { font-weight: 500; }

/* --------------------------------------------------------------------------
   Selo de andamento na COZINHA, na linha de item da comanda (.sis-tab-item).

   Substitui o ícone de impressora solto que só dizia "saiu do salão". As cores
   vêm da PALETA (sucesso/aviso/info), nunca de hexadecimal — o restaurante roda
   num tema escuro próprio e o escritório no claro/escuro do toggle, e um valor
   cravado só ficaria certo num dos três.

   O TEXTO some abaixo de 600px: no celular a linha de item tem quantidade,
   descrição, selo, preço e o botão de excluir disputando a mesma largura, e é o
   preço que começa a ser espremido. O ícone sozinho, com o tooltip, continua
   dizendo tudo.
   -------------------------------------------------------------------------- */
.sis-kitchen-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    flex: 0 0 auto;
    padding: 1px 8px;
    border-radius: 999px;
    border: 1px solid currentColor;
    font-size: .72rem;
    font-weight: 600;
    line-height: 1.6;
    white-space: nowrap;
}

.sis-kitchen-chip .mud-icon-root {
    font-size: .9rem;
}

/* Na fila: quieto — é o estado normal de quem acabou de mandar o pedido. */
.sis-kitchen-chip--fila {
    color: var(--mud-palette-text-secondary);
}

.sis-kitchen-chip--preparo {
    color: var(--mud-palette-warning);
    background-color: color-mix(in srgb, var(--mud-palette-warning) 12%, transparent);
}

/* Pronto é o único com preenchimento mais forte: é o estado que pede AÇÃO
   (alguém tem de levar o prato). */
.sis-kitchen-chip--pronto {
    color: var(--mud-palette-success);
    background-color: color-mix(in srgb, var(--mud-palette-success) 18%, transparent);
}

.sis-kitchen-chip--entregue {
    color: var(--mud-palette-text-disabled);
}

@media (max-width: 599px) {
    .sis-kitchen-chip__text {
        display: none;
    }

    .sis-kitchen-chip {
        padding: 1px 4px;
    }
}

/* --------------------------------------------------------------------------
   Configuração do aviso de "prato pronto" (menu do cabeçalho das abas da
   gerência).

   Painel curto de propósito: são dois interruptores e uma frase. Configuração
   que vira formulário deixa de ser mexida.
   -------------------------------------------------------------------------- */
.sis-kitchen-alerts {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.sis-kitchen-alerts__hint {
    color: var(--mud-palette-text-secondary);
    margin-bottom: 8px;
}

.sis-kitchen-alerts__switch {
    margin: 0;
}

/* Aviso de que os DOIS canais estão desligados. Fica em cor de atenção, e não
   em texto secundário, porque é o único ponto da tela que diz que o operador
   deixou de ser interrompido — descobrir isso com um prato frio no balcão é
   caro. */
.sis-kitchen-alerts__off {
    margin-top: 8px;
    color: var(--mud-palette-warning);
}

/* --------------------------------------------------------------------------
   KDS (terminal de cozinha): LISTA de pedidos em três abas, um card por pedido.

   O board de colunas por estado SAIU. A unidade passou a ser o PEDIDO (o lote de
   envio), e um pedido tem itens em estados diferentes — não cabe numa coluna só.

   ⚠️ Sem colunas, a POSIÇÃO não comunica mais o estado. Cor, chip e botão do
   rodapé viram informação crítica: são os três sinais que sobraram, e por isso
   estão redundantes de propósito.

   Alvos grandes e um toque por ação: a tela é operada com a mão suja e às vezes
   com luva. As cores vêm da paleta — o restaurante roda num tema escuro próprio.
   -------------------------------------------------------------------------- */
.sis-kds {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.sis-kds__bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
}

.sis-kds__scopes {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

/* Aba como botão, e não MudTabs: este controle é montado DENTRO do MudTabs da
   gerência, e MudTabs aninhado quebra os cabeçalhos dos dois. */
.sis-kds-scope {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 999px;
    background-color: transparent;
    color: var(--mud-palette-text-secondary);
    font: inherit;
    font-weight: 600;
    font-size: .85rem;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.sis-kds-scope:hover {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 10%, transparent);
}

.sis-kds-scope--on {
    border-color: var(--mud-palette-primary);
    background-color: color-mix(in srgb, var(--mud-palette-primary) 18%, transparent);
    color: var(--mud-palette-primary);
}

.sis-kds-scope__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    padding: 0 5px;
    border-radius: 999px;
    background-color: color-mix(in srgb, var(--mud-palette-primary) 28%, transparent);
    font-size: .72rem;
}

/* A espera do pedido mais antigo. Numa lista longa o card que importa pode estar
   fora da tela — é esta linha que diz "a cozinha atrasou" sem obrigar a rolar. */
.sis-kds__oldest {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-left: auto;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    color: var(--mud-palette-text-secondary);
}

.sis-kds__oldest-label {
    font-weight: 400;
    font-size: .8rem;
}

.sis-kds__oldest--atraso {
    color: var(--mud-palette-error);
}

.sis-kds__empty {
    padding: 24px 4px;
    color: var(--mud-palette-text-disabled);
    font-size: .9rem;
    font-style: italic;
}

/* Grade fluida: um terminal de cozinha vai de um monitor 4K na parede a um tablet
   preso na bancada. `auto-fill` com mínimo em 300px cobre os dois sem media query. */
.sis-kds__list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 12px;
    align-items: start;
}

/* --sis-kds-accent é a cor do ESTADO: entra na faixa lateral e no chip. Faixa de
   acento, não fundo chapado — fundo colorido inteiro derruba o contraste do texto
   e faz o card competir com a observação, que é o que precisa gritar. */
.sis-kds-order {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px 12px 12px 16px;
    border: 1px solid var(--mud-palette-lines-default);
    border-left: 6px solid var(--sis-kds-accent, var(--mud-palette-primary));
    border-radius: 10px;
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
}

.sis-kds-order--novo { --sis-kds-accent: var(--mud-palette-warning); }
.sis-kds-order--preparo { --sis-kds-accent: var(--mud-palette-info); }
.sis-kds-order--pronto { --sis-kds-accent: var(--mud-palette-success); }
.sis-kds-order--entregue { --sis-kds-accent: var(--mud-palette-text-disabled); }
.sis-kds-order--cancelado { --sis-kds-accent: var(--mud-palette-error); }

/* Atrasado engrossa a faixa e tinge o cronômetro. É o ÚNICO sinal que muda de cor
   além do estado — se tudo gritasse, nada gritaria. */
.sis-kds-order--atraso {
    border-left-width: 10px;
    --sis-kds-accent: var(--mud-palette-error);
}

.sis-kds-order--atraso .sis-kds-order__timer {
    color: var(--mud-palette-error);
}

/* NÃO quebra linha. Com `flex-wrap: wrap`, o chip e o número caíam para a segunda linha só em ALGUNS
   cards (depende do comprimento do nome da mesa), e o cabeçalho ficava com layout diferente card a card —
   o oposto do que se quer numa tela em que chip e número são a informação crítica. Quem cede espaço é o
   NOME da mesa, que trunca; o número nunca sai do canto direito. */
.sis-kds-order__head {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: 8px;
}

.sis-kds-order__table {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-weight: 700;
    font-size: 1rem;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sis-kds-order__chip {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
    padding: 2px 10px;
    border-radius: 999px;
    background-color: color-mix(in srgb, var(--sis-kds-accent) 22%, transparent);
    color: var(--sis-kds-accent);
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    white-space: nowrap;
}

/* Número do pedido: é o que o cozinheiro grita e o que o garçom procura. Fica à
   direita, sozinho, para não disputar espaço com a mesa. */
.sis-kds-order__number {
    margin-left: auto;
    font-variant-numeric: tabular-nums;
    font-size: .82rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

/* O cronômetro é a segunda linha do cabeçalho e é grande de propósito: é por ele
   que a cozinha prioriza, e ele é lido a metros de distância. */
.sis-kds-order__timer {
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-secondary);
}

.sis-kds-order__items {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin: 0;
    padding: 0;
    list-style: none;
}

.sis-kds-item {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    width: 100%;
    padding: 8px;
    border: 1px solid transparent;
    border-radius: 8px;
    background-color: color-mix(in srgb, var(--mud-palette-text-primary) 5%, transparent);
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.sis-kds-item:hover:not(:disabled) {
    border-color: var(--mud-palette-lines-default);
}

.sis-kds-item:disabled {
    opacity: .6;
    cursor: default;
}

.sis-kds-item__qty {
    flex: 0 0 auto;
    min-width: 34px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* min-width:0 na cadeia: sem ele, descrição longa empurra o selo de estado para
   fora do card em vez de quebrar. */
.sis-kds-item__body {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1 1 auto;
    min-width: 0;
}

.sis-kds-item__desc {
    overflow-wrap: anywhere;
}

.sis-kds-item__options {
    font-size: .78rem;
    color: var(--mud-palette-text-secondary);
}

/* Observação: o que faz o prato voltar quando passa despercebido. */
.sis-kds-item__note {
    font-size: .8rem;
    font-weight: 600;
    color: var(--mud-palette-warning);
}

.sis-kds-item__state {
    flex: 0 0 auto;
    align-self: center;
    padding: 1px 8px;
    border-radius: 999px;
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    white-space: nowrap;
    background-color: color-mix(in srgb, var(--sis-kds-item-accent, var(--mud-palette-text-primary)) 18%, transparent);
    color: var(--sis-kds-item-accent, var(--mud-palette-text-secondary));
}

.sis-kds-item--fila { --sis-kds-item-accent: var(--mud-palette-text-secondary); }
.sis-kds-item--preparo { --sis-kds-item-accent: var(--mud-palette-info); }
.sis-kds-item--pronto { --sis-kds-item-accent: var(--mud-palette-success); }
.sis-kds-item--entregue { --sis-kds-item-accent: var(--mud-palette-text-disabled); }
.sis-kds-item--cancelado { --sis-kds-item-accent: var(--mud-palette-error); }

/* CANCELADO EM DESTAQUE (regra do dono, 2026-07-27).
   O item cancelado que CHEGA a renderizar é, por construção, um que a cozinha já começou — o cancelado
   que ninguém tocou é filtrado antes (ver KdsBoard.ItensVisiveis). Ou seja: alguém está com este prato
   na mão, e o sinal precisa ser NOTADO do outro lado da cozinha, com o board cheio.

   Por isso ele CANCELA o esmaecimento do :disabled — a linha herdava opacity:.6 e ficava mais discreta
   que as vivas, exatamente ao contrário do que a situação pede. Três sinais somados (faixa sólida, fundo
   tingido e selo sólido), porque um só se perde à distância; e tudo pela paleta (--mud-palette-error),
   nunca hexadecimal solto. */
.sis-kds-item--cancelado:disabled {
    opacity: 1;
}

.sis-kds-item--cancelado {
    border-color: var(--mud-palette-error);
    border-left-width: 4px;
    background-color: color-mix(in srgb, var(--mud-palette-error) 14%, transparent);
}

.sis-kds-item--cancelado .sis-kds-item__desc {
    text-decoration: line-through;
    font-weight: 700;
}

/* Selo SÓLIDO (o dos vivos é um tingido de 18%): é o que se lê primeiro à distância. */
.sis-kds-item--cancelado .sis-kds-item__state {
    background-color: var(--mud-palette-error);
    color: var(--mud-palette-error-text);
}

.sis-kds-order__reason {
    padding: 6px 8px;
    border-radius: 6px;
    background-color: color-mix(in srgb, var(--mud-palette-error) 12%, transparent);
    color: var(--mud-palette-error);
    font-size: .8rem;
    font-weight: 600;
}

.sis-kds-order__foot {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 2px;
    padding-top: 8px;
    border-top: 1px dashed var(--mud-palette-lines-default);
}

.sis-kds-order__confirm {
    flex: 1 1 auto;
    min-width: 0;
    font-size: .82rem;
    font-weight: 600;
    color: var(--mud-palette-error);
}

/* Hierarquia de ação: UM sólido (o avanço, que é o gesto do turno inteiro) e o
   resto tonal. Dois botões sólidos lado a lado fariam "cancelar" parecer tão
   normal quanto "pronto". */
.sis-kds-btn {
    padding: 10px 16px;
    border: 1px solid transparent;
    border-radius: 8px;
    font: inherit;
    font-weight: 700;
    font-size: .85rem;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.sis-kds-btn:disabled {
    opacity: .6;
    cursor: default;
}

.sis-kds-btn--primary {
    margin-left: auto;
    background-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
}

.sis-kds-btn--ghost {
    background-color: transparent;
    border-color: var(--mud-palette-lines-default);
    color: var(--mud-palette-text-secondary);
}

.sis-kds-btn--danger {
    background-color: var(--mud-palette-error);
    color: var(--mud-palette-error-text, #fff);
}

/* ===================================================================================================
   Tutoriais interativos (SisTutorialHost / tutorial.js)

   Mora AQUI, e não num .razor.css: o bundle {Assembly}.styles.css não é referenciado por nenhum
   index.html do sis (WPF, WASM, Waiter, Mock), então CSS isolado não carrega em host nenhum — some
   junto com o layout, sem erro. Ver CLAUDE.md, "CSS isolado (.razor.css) NÃO carrega em host nenhum".

   Tudo usa variável de tema (--mud-palette-*), então claro e escuro saem de graça: nada de hexadecimal
   cravado, que é o que faria o cartão do tutorial ficar branco-no-branco no tema escuro.
   =================================================================================================== */

/* Camada do tour. Acima do drawer (1100) e do appbar (1300) do MudBlazor, porque o tour precisa destacar
   os DOIS; abaixo de diálogo modal (1400), pra não cobrir uma confirmação de verdade.

   ⚠️ `pointer-events: none` na CAMADA (o cartão reativa pra si): o tour é passivo e não pode sequestrar a
   tela. Com a camada capturando clique, o usuário não conseguia nem experimentar o botão que o passo está
   ensinando — e quem entrava pela primeira vez ficava travado até dispensar o tour. O defeito apareceu de
   forma inequívoca no E2E de outro cadastro, que passou a falhar com "sis-tour-overlay intercepts pointer
   events" num clique que nada tinha a ver com tutorial. */
.sis-tour-overlay {
    position: fixed;
    inset: 0;
    z-index: 1392;
    pointer-events: none;
}

/* 🩸 (2026-08-18) O z-index da CAMADA tem de ficar ACIMA do .sis-tour-target (1391), e por muito tempo
   ficou abaixo (1390) — o que deixava o elemento destacado por cima do CARTÃO INTEIRO.

   A causa é uma regra do navegador que não aparece no CSS: `position: fixed` cria um CONTEXTO DE
   EMPILHAMENTO no Blink mesmo com `z-index: auto`. Logo o `z-index: 1392` do cartão nunca competiu na
   página — ele só ordena o cartão DENTRO da camada, e quem disputa com o resto da tela é a camada.

   Efeito medido no passo 8 do tour de Contas a Receber (âncora no GRID, alto o bastante para ocupar a
   área onde o cartão cabe): `document.elementsFromPoint` no centro do botão "Próximo" devolvia
   `TH.mud-table-cell` no topo e o `SPAN.mud-button-label` do cartão em SEXTO — o botão estava lá,
   coberto. O Playwright recusava o clique ("element is not stable") e o operador acertaria uma faixa de
   poucos pixels. ⚠️ Só aparece com âncora GRANDE: com um botão pequeno o cartão é posicionado ao lado, e
   é por isso que 139 dos 140 tours passavam.

   ⚠️ Subir a camada acima do alvo NÃO escurece o que está destacado: a máscara é o `box-shadow` do
   spotlight, que pinta só FORA do próprio retângulo — o buraco continua transparente, e o
   `pointer-events: none` mantém o alvo clicável.

   ⛔ 1392 é o teto: diálogo modal do MudBlazor é 1400, e o tour não pode cobrir uma confirmação de
   verdade. ⛔ E não tente consertar isto tirando o z-index da camada — sem ele ela cai para o nível 0 da
   página (o `fixed` continua abrindo contexto) e o defeito piora. */

/* O recorte: um elemento só, com sombra gigante fazendo o papel de máscara em volta. Quatro divs de
   máscara dariam o mesmo efeito e quatro oportunidades de dessincronizar em 1px. pointer-events:none
   deixa o clique passar — o usuário continua vendo (e podendo usar) o que está destacado. */
.sis-tour-spotlight {
    position: fixed;
    z-index: 1;   /* dentro da CAMADA: máscara embaixo, cartão em cima */
    border-radius: 8px;
    pointer-events: none;
    box-shadow: 0 0 0 9999px rgba(0, 0, 0, .55),
                0 0 0 2px var(--mud-palette-primary);
    transition: left .18s ease, top .18s ease, width .18s ease, height .18s ease;
}

/* Realce no próprio elemento (classe posta pelo tutorial.js). Só o brilho — geometria e posição
   continuam sendo do layout da tela, que o tour não pode alterar. */
.sis-tour-target {
    position: relative;
    z-index: 1391;
}

/* 🩸 (2026-08-22) `max-height` + a coluna flex NÃO são estética: são o que mantém o botão "Próximo"
   DENTRO da viewport. O cartão é position:fixed e o C# o posiciona por uma altura ESTIMADA (190px, ver
   SisTutorialHost.AlturaEstimadaDoCartao); passo com texto comprido cresce além disso, o rodapé com as
   ações cai para fora da tela, e como fixed NÃO se move com a rolagem o botão fica INCLICÁVEL — o tour
   trava no passo, para o usuário e para o Playwright ("element is outside of the viewport", medido em
   2026-08-22 em 8 dos 15 tours quebrados). O `max-height` inline (com o `top` real) vem do C#; este aqui
   é o piso para o cartão centralizado e para quem não recebeu inline. */
.sis-tour-card {
    position: fixed;
    z-index: 2;   /* dentro da CAMADA — ver a nota na .sis-tour-overlay */
    pointer-events: auto;   /* a camada é transparente ao clique; o cartão precisa receber os dele */
    display: flex;
    flex-direction: column;
    width: 340px;
    max-width: calc(100vw - 24px);
    max-height: calc(100vh - 24px);
    padding: 16px;
    border-radius: 12px;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    border: 1px solid var(--mud-palette-lines-default);
    box-shadow: 0 10px 30px rgba(0, 0, 0, .28);
}

/* Passo sem âncora (abertura/fechamento) — e também o fallback de quando nada coube na viewport. */
.sis-tour-card--centro {
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
}

.sis-tour-card-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 4px;
}

.sis-tour-card-contador {
    font-size: .75rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--mud-palette-text-secondary);
}

.sis-tour-card-titulo {
    font-weight: 600;
    margin-bottom: 6px;
}

/* O TEXTO é o único que rola quando o cartão bate no `max-height` — contador, título, barra e ações ficam
   sempre à vista. Rolar o cartão inteiro deixaria o "Próximo" abaixo da dobra do próprio cartão, que é o
   mesmo defeito uma camada abaixo. `min-height:0` é obrigatório: sem ele um filho de flex não encolhe
   abaixo do conteúdo e o `overflow` nunca chega a acontecer. */
.sis-tour-card-texto {
    color: var(--mud-palette-text-secondary);
    margin-bottom: 12px;
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

.sis-tour-card-head,
.sis-tour-card-titulo,
.sis-tour-progresso,
.sis-tour-card-acoes {
    flex: 0 0 auto;
}

.sis-tour-progresso {
    height: 3px;
    margin-bottom: 12px;
}

.sis-tour-card-acoes {
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Em tela estreita o cartão vira faixa no rodapé: ancorar um cartão de 340px a um botão pequeno num
   celular joga metade dele pra fora, e é um defeito que só aparece no tamanho pequeno. */
@media (max-width: 600px) {
    .sis-tour-card,
    .sis-tour-card--centro {
        left: 12px !important;
        right: 12px;
        top: auto !important;
        bottom: calc(12px + env(safe-area-inset-bottom, 0px)) !important;
        width: auto !important;
        transform: none !important;
    }
}

/* ==========================================================================
   Campo de busca com registro vinculado (SisLookupField / SisLookupSearchDialog)
   Ver CLAUDE.md, "Campo de busca com registro vinculado", e a skill criar-tela-blazor.
   Mora aqui e não num .razor.css porque CSS isolado NÃO carrega em host nenhum neste repo.
   ========================================================================== */

/* GRID de duas linhas: em cima [campo][lupa], embaixo o texto de ajuda ocupando as duas colunas.
   `align-items: end` alinha a lupa pelo FIM DO CAMPO — e só continua fazendo isso enquanto o texto de ajuda
   NÃO estiver dentro do controle do campo. Era esse o defeito relatado pelo dono: com `HelperText` no
   MudTextField, o controle cresce, o `end` passa a medir o fim da FRASE e a lupa desce para o lado dela
   (pior em coluna estreita, onde a frase quebra em duas linhas). Ver o comentário do SisCepField.razor.

   ⛔ Grid, e NÃO flex com `flex-wrap: wrap`, por medição: a versão em flex-wrap alinhava certo a 1600×900 e a
   1024×768 punha a LUPA na linha de baixo — na coluna md=3 o campo mais a lupa não cabiam, e com a quebra
   habilitada (necessária para o texto de ajuda descer) quem quebrava era o botão. No grid isso é impossível
   por construção: a lupa é a coluna 2 da linha 1, sempre. O `minmax(0, 1fr)` é o que faz o campo ENCOLHER em
   vez de empurrar — o equivalente do antigo `min-width: 0` do flex item.

   Sem `row-gap`: a distância entre campo e ajuda quem dá é o `margin-top` do próprio contêiner de ajuda do
   MudBlazor (3px). Um gap de linha somaria por cima e afastaria a frase mais do que nos demais campos. */
.sis-lookup-field {
    display: grid;
    /* Colunas 3, 4 e 5: os botões OPCIONAIS "criar novo" (OnCriarNovo), "histórico" (OnHistory) e "ver
       cadastro" (OnDetails) — sem eles as colunas somem por conteúdo, igual antes. `position: relative`
       ancora o dropdown de sugestões abaixo (ver .sis-lookup-suggestions).

       🔴 A CONTAGEM É PARTE DO COMPONENTE: botão novo no .razor exige coluna nova AQUI. Faltando a coluna,
       o grid joga o excedente numa SEGUNDA LINHA implícita — o botão aparece embaixo do campo, sem erro
       nenhum, e bUnit fica verde porque o markup está perfeito. Quem vê é a captura. */
    grid-template-columns: minmax(0, 1fr) auto auto auto auto;
    align-items: end;
    column-gap: 4px;
    width: 100%;
    position: relative;
}

/* SUGESTÕES ao digitar (autocomplete com debounce) — fora do fluxo do grid (absolute), pra flutuar por cima
   do que vem depois em vez de empurrar layout. Mesma linguagem visual da tela de busca (.sis-lookup-result),
   só que num popover local em vez de diálogo — ver o porquê da coexistência no comentário do .razor.

   🔑 O `max-height` é o que separa "mostrar mais" de "tapar a tela": a caixa serve até 10 sugestões
   (SisLookupField.LimiteSugestoes, 2026-08-26) e mostra ~9 por vez; a última chega pela rolagem e pelas setas
   ↑/↓, que arrastam a lista atrás do destaque (lookup.js). ⛔ Subir a altura para caber todas cobriria os
   campos seguintes do documento, que é o que o operador precisa ver enquanto lança o item. */
.sis-lookup-suggestions {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 10;
    max-height: 320px;
    overflow-y: auto;
    margin-top: 2px;
}

.sis-lookup-suggestion {
    cursor: pointer;
    border-radius: var(--mud-default-borderradius);
}

/* A sugestão DESTACADA pelas setas ↑/↓ (2026-08-26). O foco continua no campo — quem anda é o destaque —,
   então o navegador não pinta nada sozinho: sem esta regra a navegação por teclado é INVISÍVEL.
   Cor de seleção do próprio MudBlazor, para o destaque ser o mesmo do resto do ERP, e barra à esquerda
   porque só o fundo se confunde com o hover do mouse quando os dois aparecem ao mesmo tempo. */
.sis-lookup-suggestion--ativa {
    background-color: var(--mud-palette-action-default-hover);
    box-shadow: inset 3px 0 0 0 var(--mud-palette-primary);
}

/* A frase toma a linha inteira, abaixo do campo E da lupa. Ocupar também a faixa da lupa não é detalhe — é o
   que faz o texto caber em menos linhas na coluna estreita. */
.sis-lookup-helper {
    grid-column: 1 / -1;
    min-width: 0;
}

/* min-width:0 também aqui: o contêiner já declara `minmax(0, 1fr)`, mas o controle do MudBlazor tem conteúdo
   próprio (rótulo, adornos) e sem isto ele volta a assumir a largura do conteúdo em coluna estreita. */
.sis-lookup-input {
    min-width: 0;
}

/* A lupa herda a FORMA da ação de linha do grid (sis-row-action): mesma caixa contornada, mesma altura de
   toque. O `margin-bottom` a põe na linha de base do campo, não do rótulo. */
.sis-lookup-search-button {
    margin-bottom: 4px;
    border: 1px solid var(--mud-palette-table-lines);
    border-radius: var(--mud-default-borderradius);
    height: 36px;
    width: 36px;
}

/* ── A ÁREA ROLÁVEL da tela de busca (lookup) ──────────────────────────────────────────────────────
   🩸 (2026-08-30) A lista ESCONDIA as linhas que não cabiam, e o defeito era de ESPECIFICIDADE. Os dois
   diálogos da `BuscaCompleta` — produto e cliente, os que servem as 19 chamadas das telas transacionais e
   dos PDVs — aplicavam `sis-lookup-results` no PRÓPRIO `<SisDataGrid>`, e ali ela cai no `.mud-table`
   raiz, onde `.sis-data-grid.mud-table { overflow: hidden }` (a regra dos cantos arredondados, ~2.900
   linhas acima) VENCE: (0,2,0) contra (0,1,0). Medido num navegador real, na busca de produto: caixa de
   493px sobre 1025px de conteúdo, com `overflow-y` computado **hidden**.
   ⇒ O servidor mandava a página inteira, o grid desenhava as 50 linhas, e o operador via SETE — sem
   barra, sem reticências, sem nada acusando. Indistinguível de "o sistema só trouxe sete", que foi
   exatamente como o defeito chegou.

   🔑 **Quem rola é o `.mud-table-container`, ⛔ NUNCA o `<div>` de fora — e a razão é a SOMBRA.** O
   primeiro conserto pôs `max-height`+`overflow` no `<div>`: a lista passou a rolar, e a captura saiu sem
   pista nenhuma de que havia mais.
   🩸 **A explicação que eu dei para isso era FALSA e fica registrada**: escrevi que "a barra do Chromium é
   overlay e nenhuma variante a devolve", medindo `offsetWidth - clientWidth` = 0 no headless. O que aquela
   medição provava é OUTRA coisa — este headless **não desenha barra em elemento nenhum** (um `<div>`
   sintético com `overflow-y: scroll` e `::-webkit-scrollbar { width: 14px }` também dá 0, com e sem
   `--disable-features=OverlayScrollbar`). ⇒ **o ambiente não conseguia medir a pergunta**, e eu li a
   incapacidade dele como propriedade do navegador. No Chrome do usuário a barra existe.
   ⚪ A sombra pintada continua valendo — ela é a rede para onde a barra de fato não aparece (celular,
   macOS com barra oculta, overlay real) —, e a técnica só funciona sobre fundo transparente: o `<div>` tem
   o `.mud-table` OPACO por cima e lá ela nasce inerte; no container o conteúdo é a `<table>`, e ela
   aparece. ⇒ **a escolha do elemento que rola é a escolha de haver sinal.**

   🔑 O teto deixou de ser `55vh` cravado: numa janela de 900px ele dava ~7 linhas com espaço sobrando no
   diálogo. ⚠️ **O desconto é MEDIDO, ⛔ não estimado.** A primeira tentativa foi 260px e ficou GRANDE
   DEMAIS: o diálogo passou de `100dvh - var(--mud-appbar-height)` (o teto do próprio `.mud-dialog`), o
   corpo dele começou a rolar por fora, e o RODAPÉ DE PAGINAÇÃO saiu da vista — duas rolagens aninhadas,
   o oposto do que este bloco resolve. Os 320px são a soma real do que fica em volta: 64 do topo reservado
   + 64 do título + 56 do campo + 16 de margem + 52 do paginador + 52 das ações. ⇒ mexer neste número pede
   a medição de novo (`.mud-dialog` com `scrollHeight == clientHeight` e o paginador visível), ⛔ nunca
   aritmética de cabeça. O piso existe para a janela baixa continuar mostrando alguma coisa em vez de virar
   uma fresta; a dupla declaração `vh`/`dvh` é o mesmo idioma do `.mud-dialog`.

   🔑 E a classe vai num `<div>` em volta do grid, ⛔ nunca no `Class` dele — travado por
   `AreaRolavelDaBuscaTests`. O `overflow: hidden` do grid não é ruído: é o que faz o `<th>` cinza
   respeitar o canto arredondado. */
.sis-lookup-results .mud-table-container {
    max-height: max(220px, calc(100vh - 320px));
    max-height: max(220px, calc(100dvh - 320px));
    overflow-y: auto;

    /* 🔒 BARRA PADRÃO, ⛔ não a `thin` global. O `* { scrollbar-width: thin }` deste arquivo (~linha 965)
       alcança TODO elemento, e numa lista que é o conteúdo principal da tela a barra fina passa
       despercebida — foi o que o dono relatou duas vezes ("continua sem barra de rolagem"). Aqui ela é a
       do sistema, mais larga, e a cor tem contraste em vez de acompanhar a linha de input.
       ⚠️ Com `scrollbar-width` declarado no elemento, o Chromium IGNORA os `::-webkit-scrollbar` (a
       cicatriz registrada na regra da rolagem horizontal, ~linha 341) — então a largura se pede por AQUI,
       ⛔ nunca por pseudo-elemento.
       🩸 **Isto não é mensurável no headless deste repositório**, e a medição que prova a limitação está
       registrada: um `<div>` sintético com `overflow-y: scroll` e `::-webkit-scrollbar { width: 14px }` dá
       `offsetWidth - clientWidth` = **0** ali, com e sem `--disable-features=OverlayScrollbar`. ⇒ o
       ambiente não desenha barra nenhuma, então ⛔ não conclua dele que "não dá para ter barra" — foi o
       erro que eu cometi e que esta linha corrige. Quem responde é o navegador do usuário; a sombra abaixo
       é a rede para onde a barra de fato não aparecer. */
    scrollbar-width: auto;
    scrollbar-color: var(--mud-palette-text-secondary) transparent;

    /* 🔒 A SOMBRA DE ROLAGEM, agora nos DOIS EIXOS — oito gradientes numa declaração só, porque
       `background-image` é uma propriedade: declarar a vertical à parte APAGARIA a horizontal (a de
       `.sis-data-grid .mud-table-container`, ~2.900 linhas acima), e a última coluna voltaria a sumir sem
       aviso em 1024×768. ⇒ ⛔ nunca acrescente um eixo em regra separada; some ao conjunto.
       Em cada eixo: dois gradientes `local` (viajam com o conteúdo e TAPAM a sombra quando aquela ponta
       está à vista) e dois `scroll` (fixos na caixa, são a sombra). É pintura, então não depende de como a
       plataforma desenha barra — que aqui não desenha nada.
       ⛔ Não é `overflow-y: scroll`: com barra overlay ele não pinta trilho nenhum parado, e onde pinta,
       pinta também na busca que cabe inteira, comendo altura onde falta altura. */
    background-image:
        linear-gradient(to right, var(--mud-palette-surface) 60%, rgba(0, 0, 0, 0)),
        linear-gradient(to left, var(--mud-palette-surface) 60%, rgba(0, 0, 0, 0)),
        linear-gradient(to right, color-mix(in srgb, var(--mud-palette-text-primary) 30%, transparent), rgba(0, 0, 0, 0)),
        linear-gradient(to left, color-mix(in srgb, var(--mud-palette-text-primary) 30%, transparent), rgba(0, 0, 0, 0)),
        linear-gradient(to bottom, var(--mud-palette-surface) 60%, rgba(0, 0, 0, 0)),
        linear-gradient(to top, var(--mud-palette-surface) 60%, rgba(0, 0, 0, 0)),
        linear-gradient(to bottom, color-mix(in srgb, var(--mud-palette-text-primary) 35%, transparent), rgba(0, 0, 0, 0)),
        linear-gradient(to top, color-mix(in srgb, var(--mud-palette-text-primary) 35%, transparent), rgba(0, 0, 0, 0));
    background-position:
        left center, right center, left center, right center,
        center top, center bottom, center top, center bottom;
    background-repeat: no-repeat;
    background-size:
        28px 100%, 28px 100%, 22px 100%, 22px 100%,
        100% 26px, 100% 26px, 100% 20px, 100% 20px;
    background-attachment: local, local, scroll, scroll, local, local, scroll, scroll;
}

/* 🔑 O CABEÇALHO FICA. Com a lista rolando, um `<thead>` que sobe junto deixa o operador olhando números
   sem saber de que coluna são — e nesta grade as colunas são Preço e Saldo. O fundo do `<th>` já é opaco
   (`--mud-palette-gray-light`, ver a regra do `.sis-data-grid`), então ele cobre a linha que passa por
   baixo sem precisar de cor nova. */
.sis-lookup-results .mud-table-head th,
.sis-lookup-results .mud-table-head .mud-table-cell {
    position: sticky;
    top: 0;
    z-index: 2;
}

.sis-lookup-result {
    cursor: pointer;
    border-radius: var(--mud-default-borderradius);
}

.sis-lookup-empty {
    opacity: .7;
}

/* --------------------------------------------------------------------------
   TECLADO NUMÉRICO VIRTUAL (SisKeypadHost / SisNumericKeypad).

   Painel ancorado à DIREITA da viewport, sem máscara: não é modal de propósito
   — o operador precisa continuar vendo e tocando o que está por baixo, que é a
   razão de um teclado existir.

   ⛔ E ele EMPURRA o conteúdo em vez de cobri-lo (decisão do dono, 2026-07-28,
   com o CosyPOS como referência). Como overlay puro, um campo que estivesse do
   lado direito da tela ficava ESCONDIDO pelo próprio teclado que ia preenchê-lo
   — e o operador não tinha como ver o que estava digitando. Ver o bloco "empurra
   a tela" logo abaixo.

   z-index 1450: ACIMA do diálogo do MudBlazor (1400), porque metade dos campos
   numéricos do sis vive dentro de diálogo (desconto do PDV, abrir comanda,
   quantidade do item) e um teclado atrás deles seria inalcançável justamente
   onde é mais necessário. Abaixo do Snackbar (1500), que é quem avisa erro.

   Cor SÓ da paleta — o PDV e o restaurante rodam em temas diferentes, e o
   teclado é o mesmo componente nos dois.
   -------------------------------------------------------------------------- */
:root {
    /* Uma variável, três consumidores: a largura do painel, o quanto o conteúdo
       recua e o quanto o diálogo se recentraliza. Separá-los deixaria o teclado
       e o buraco que ele ocupa com tamanhos diferentes no dia em que alguém
       mexesse num só. */
    --sis-keypad-width: 380px;
}

.sis-keypad {
    position: fixed;
    /* ABAIXO da barra superior, não colado no topo. Não é estética: o painel fica aberto o turno inteiro, e
       em `top: 0` ele cobria os ícones da direita da MudAppBar — inclusive o PRÓPRIO botão que o abre, além
       do tema, da ajuda e do Sair. Flagrado na captura de 1600×900, e o E2E não conseguia clicar no
       alternador de tema. No PdvHost, que tem faixa própria e não MudAppBar, a variável ainda resolve e o
       painel encosta logo abaixo da faixa do terminal. */
    top: var(--mud-appbar-height, 64px);
    right: 0;
    bottom: 0;
    z-index: 1450;
    width: var(--sis-keypad-width);
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 14px;
    padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px));
    background: var(--mud-palette-surface);
    border-left: 1px solid var(--mud-palette-table-lines);
    box-shadow: -14px 0 34px rgba(0, 0, 0, .20);
    animation: sis-keypad-in 150ms ease-out;
}

@keyframes sis-keypad-in {
    from { transform: translateX(16px); opacity: 0; }
    to   { transform: translateX(0);    opacity: 1; }
}

/* Monitor estreito (o 1024×768 de terminal): 380px de teclado MAIS 280px de menu deixariam menos de 400px
   para a tela de trabalho. A tecla continua bem acima do alvo de toque confortável. */
@media (max-width: 1279px) {
    :root {
        --sis-keypad-width: 320px;
    }
}

/* ---- O teclado EMPURRA a tela, não a cobre ------------------------------
   O seletor é `:has()` e não uma classe posta por JS: o painel EXISTIR no DOM
   já é a única condição, então não há segundo estado para dessincronizar — o
   caso clássico é o teclado fechar por um caminho que esqueceu de limpar a
   classe e a tela ficar com um buraco de 380px para sempre.

   `.mud-main-content` cobre a casca (ShellLayout) e o FoodHost; `.pdv` é o
   terminal de PDV, que é `position: fixed` por conta própria e por isso recua
   pelo `right`, não por padding. O contêiner de diálogo entra junto para o
   modal se RECENTRALIZAR no espaço que sobrou — senão o teclado voltaria a
   cobrir metade dele, que é o defeito que este bloco existe para corrigir.

   Onde NÃO empurra: no celular e no monitor deitado baixo (media query no fim
   deste bloco), onde o painel vira faixa inferior. Ali empurrar comeria a
   altura útil, e o comportamento esperado é o do teclado do próprio aparelho:
   sobrepor, com o campo rolando para a vista (scrollIntoView no keypad.js). */
.mud-main-content,
.mud-dialog-container {
    transition: padding-right .16s ease;
}

body:has(.sis-keypad) .mud-main-content,
body:has(.sis-keypad) .mud-dialog-container {
    padding-right: var(--sis-keypad-width);
}

body:has(.sis-keypad) .pdv {
    right: var(--sis-keypad-width);
}

.sis-keypad__bar {
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--mud-palette-text-secondary);
}

.sis-keypad__title {
    font-size: .75rem;
    font-weight: 700;
    letter-spacing: .08em;
}

/* margin-left:auto e não um spacer: o X fica na ponta com qualquer largura de painel. */
.sis-keypad__close {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border: 0;
    border-radius: var(--mud-default-borderradius);
    background: transparent;
    color: inherit;
    cursor: pointer;
}

.sis-keypad__close:hover {
    background: rgba(var(--mud-palette-text-primary-rgb), .08);
}

/* ---- Visor ----------------------------------------------------------------
   Repete o valor do campo em corpo grande, para quem opera olhando o teclado.
   Fica logo abaixo do título e ANTES do `margin-top:auto` do aviso, então é ele
   que ocupa a folga do topo do painel — a mesma folga que antes era buraco. */
.sis-keypad__display {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    /* Duas linhas de altura mínima: o visor não pode mudar de tamanho entre
       vazio e preenchido, ou as teclas subiriam e desceriam sob o dedo. */
    min-height: 64px;
    padding: 6px 12px;
    border-radius: 12px;
    background: rgba(var(--mud-palette-text-primary-rgb), .04);
    border: 1px solid var(--mud-palette-table-lines);
    /* Números longos cortam em vez de quebrar: o visor tem uma linha, sempre. */
    overflow: hidden;
    white-space: nowrap;
}

.sis-keypad__display-value {
    font-size: 2.1rem;
    font-weight: 600;
    line-height: 1.1;
    /* tnum: dígitos de largura fixa. Sem isso o número "dança" para os lados a
       cada tecla, porque 1 é mais estreito que 8 na fonte de texto. */
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-primary);
}

.sis-keypad__display-empty {
    font-size: 1.6rem;
    color: var(--mud-palette-text-disabled);
}

/* Altura reservada mesmo apagado — ver o comentário do aviso no SisKeypadHost.razor: tecla que dança sob o
   dedo é como se erra o toque num terminal. */
.sis-keypad__hint {
    /* margin-top:auto empurra aviso + teclas + rodapé para a BASE do painel. O teclado fica onde a mão já
       está, e o espaço que sobra num monitor alto vira folga em cima, não um buraco entre o aviso e as
       teclas. */
    margin: auto 0 0;
    min-height: 2.4em;
    font-size: .78rem;
    line-height: 1.2;
    color: var(--mud-palette-text-secondary);
}

.sis-keypad__hint--alert {
    color: var(--mud-palette-warning);
    font-weight: 600;
}

.sis-keypad__keys {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    /* Altura natural (não estica): num monitor alto o grid viraria faixas de 200px e a mão subiria e
       desceria mais do que precisa. O minmax dá o alvo confortável com teto. */
    /* Teclas grandes, no tamanho do PDV de referência: são operadas com o dedo,
       muitas vezes por quem não está olhando para elas. */
    grid-auto-rows: minmax(72px, 96px);
    gap: 10px;
    flex: 0 0 auto;
}

.sis-keypad__key {
    display: flex;
    align-items: center;
    justify-content: center;
    /* 72px é o alvo de toque do teclado de PDV — bem acima do piso de 48px de
       acessibilidade, porque aqui a tecla é o instrumento de trabalho. */
    min-height: 72px;
    font-size: 1.6rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
    background: var(--mud-palette-background-gray);
    border: 1px solid var(--mud-palette-table-lines);
    border-radius: 12px;
    cursor: pointer;
    user-select: none;
    transition: background-color .12s ease, transform .06s ease;
}

.sis-keypad__key:hover:not(:disabled) {
    background: rgba(var(--mud-palette-primary-rgb), .12);
}

/* O afundar é o retorno tátil que um teclado de vidro não tem. Sem :active o operador não sabe se a tecla
   pegou, e acaba tocando duas vezes. */
.sis-keypad__key:active:not(:disabled) {
    transform: scale(.96);
    background: rgba(var(--mud-palette-primary-rgb), .20);
}

.sis-keypad__key:disabled {
    opacity: .45;
    cursor: default;
}

/* Apagar e limpar: tonais, para não competirem com os dígitos nem com o ENTER. */
.sis-keypad__key--action {
    background: rgba(var(--mud-palette-text-primary-rgb), .06);
    color: var(--mud-palette-text-secondary);
    font-size: 1.1rem;
}

/* O ÚNICO sólido do painel — a hierarquia "tonais + um sólido" das telas de operação. */
.sis-keypad__key--enter {
    grid-row: span 2;
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    border-color: transparent;
}

.sis-keypad__key--enter:hover:not(:disabled) {
    background: var(--mud-palette-primary-darken);
}

.sis-keypad__key--enter:active:not(:disabled) {
    background: var(--mud-palette-primary-darken);
}

.sis-keypad__key--zero {
    grid-column: span 2;
}

/* Sem vírgula (modo inteiro), o zero toma a linha inteira em vez de deixar um buraco no grid. */
.sis-keypad__keys--integer .sis-keypad__key--zero {
    grid-column: span 3;
}

.sis-keypad__foot {
    border-top: 1px solid var(--mud-palette-table-lines);
    padding-top: 8px;
}

.sis-keypad__switch .mud-typography {
    font-size: .78rem;
    line-height: 1.15;
}

/* Celular e terminal deitado baixo: à direita o painel comeria a largura útil da tela de venda. Vira faixa
   inferior, que é onde todo teclado de aparelho aparece — e o operador não precisa reaprender nada. */
@media (max-width: 720px), (max-height: 560px) {
    .sis-keypad {
        top: auto;
        left: 0;
        width: auto;
        max-height: 62vh;
        border-left: 0;
        border-top: 1px solid var(--mud-palette-table-lines);
        box-shadow: 0 -14px 34px rgba(0, 0, 0, .20);
        animation: sis-keypad-in-bottom 150ms ease-out;
    }

    .sis-keypad__keys {
        grid-auto-rows: minmax(56px, 72px);
    }

    .sis-keypad__key {
        min-height: 56px;
        font-size: 1.4rem;
    }

    /* Faixa inferior: empurrar aqui comeria a altura útil, que é o que falta num
       celular. Sobrepõe, como o teclado do próprio aparelho. */
    body:has(.sis-keypad) .mud-main-content,
    body:has(.sis-keypad) .mud-dialog-container {
        padding-right: 0;
    }

    body:has(.sis-keypad) .pdv {
        right: 0;
    }
}

@keyframes sis-keypad-in-bottom {
    from { transform: translateY(16px); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
}

/* ==========================================================================
   Ordem de serviço
   ========================================================================== */

/* Previsão vencida numa OS que ainda pode ser atendida.
   Cor pela variável do TEMA, não hexadecimal: um vermelho cravado que funciona no claro fica
   ilegível no escuro, e é o tipo de defeito que só aparece na captura. */
.sis-os-atrasada {
    color: var(--mud-palette-error);
    font-weight: 600;
}

/* O painel de itens/checklist da tela de operação. Altura mínima para a lista vazia não colapsar o
   layout e fazer o rodapé de totais subir por cima do cabeçalho. */
.sis-os-painel {
    min-height: 180px;
}

/* Linha de item da OS — mesma geometria da linha de comanda, com o rótulo de peça/serviço à direita. */
.sis-os-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border-bottom: 1px solid var(--mud-palette-table-lines);
}

.sis-os-item:last-child {
    border-bottom: none;
}

.sis-os-item-descricao {
    flex: 1 1 auto;
    /* Sem isto, uma descrição longa empurra quantidade e preço para fora do painel em vez de truncar. */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Card do MONITOR de O.S.
   Mesma família do `sis-table-card` do board de comandas (faixa de acento à
   esquerda, botão nativo, cor pela paleta) — mas MAIOR: o card de mesa mostra
   um número e um total; este responde "o que é, de quem é e para quando" sem
   que o técnico precise abrir a ordem.
   -------------------------------------------------------------------------- */
.sis-os-card {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    width: 100%;
    height: 100%;
    padding: 14px 16px 14px 18px;
    border: 1px solid var(--mud-palette-lines-default);
    border-left: 6px solid var(--sis-table-accent, var(--mud-palette-lines-default));
    border-radius: var(--mud-default-borderradius, 12px);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    text-align: left;
    cursor: pointer;
    transition: background-color .12s ease, box-shadow .12s ease;
    -webkit-tap-highlight-color: transparent;
}

.sis-os-card:hover,
.sis-os-card:focus-visible {
    background-color: color-mix(in srgb, var(--sis-table-accent, var(--mud-palette-primary)) 10%, var(--mud-palette-surface));
    box-shadow: 0 2px 10px rgba(0, 0, 0, .35);
    outline: none;
}

/* Atrasada: a faixa já é vermelha (o acento vence o status), e o contorno inteiro
   acompanha. Fundo NÃO chapado — um card vermelho sólido apaga o texto que o
   técnico precisa ler, que é justamente o defeito. */
.sis-os-card--atrasada {
    border-color: var(--mud-palette-error);
}

.sis-os-card__top {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.sis-os-card__number {
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.1;
    color: var(--mud-palette-primary);
}

.sis-os-card__number::before {
    content: "Nº ";
    font-size: .7rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
}

/* Selo do estado, na cor do acento do próprio card — é o que amarra a faixa da
   esquerda ao texto, para quem não distingue as cores. */
.sis-os-card__status {
    padding: 2px 8px;
    border: 1px solid var(--sis-table-accent, var(--mud-palette-lines-default));
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 600;
    white-space: nowrap;
    color: var(--sis-table-accent, var(--mud-palette-text-secondary));
}

.sis-os-card__meta {
    margin-left: auto;
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.sis-os-card__client,
.sis-os-card__equipment {
    display: flex;
    align-items: center;
    gap: 5px;
    /* min-width:0 na cadeia inteira: sem ele o nome longo ALARGA o card em vez de
       truncar, e um card mais largo desalinha a linha inteira da grade. */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sis-os-card__client {
    font-weight: 600;
    font-size: .92rem;
}

.sis-os-card__equipment {
    font-size: .84rem;
    color: var(--mud-palette-text-secondary);
}

.sis-os-card__client .mud-icon-root,
.sis-os-card__equipment .mud-icon-root {
    font-size: .95rem;
    flex: 0 0 auto;
    color: var(--mud-palette-text-secondary);
}

/* O defeito CRESCE (flex:1) e é ele que alinha o rodapé — e portanto a previsão —
   de todos os cards da linha, sem altura cravada. Duas linhas e reticências: o
   relato do cliente pode ter um parágrafo, e o card não é o lugar de lê-lo inteiro. */
.sis-os-card__defect {
    flex: 1 1 auto;
    font-size: .84rem;
    line-height: 1.35;
    color: var(--mud-palette-text-primary);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: 2.4em;
}

.sis-os-card__foot {
    display: flex;
    align-items: center;
    gap: 10px;
    padding-top: 8px;
    border-top: 1px solid var(--mud-palette-table-lines);
}

.sis-os-card__due {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: .8rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.sis-os-card__due .mud-icon-root {
    font-size: .95rem;
}

/* Na atrasada o prazo é a informação que muda a ação — vai para a cor de erro,
   junto com o ícone. */
.sis-os-card--atrasada .sis-os-card__due,
.sis-os-card--atrasada .sis-os-card__due .mud-icon-root {
    color: var(--mud-palette-error);
    font-weight: 600;
}

.sis-os-card__total {
    margin-left: auto;
    font-weight: 700;
    white-space: nowrap;
}

/* Item de checklist já conferido. Riscado E esmaecido — o risco sozinho some no tema escuro,
   e o esmaecimento sozinho se confunde com "desabilitado". */
.sis-os-check--feito {
    text-decoration: line-through;
    color: var(--mud-palette-text-secondary);
}

/* --------------------------------------------------------------------------
   Card do MONITOR de O.P. — a MESMA receita do `sis-os-card` (faixa de acento
   à esquerda, botão nativo, cor pela paleta), copiada com nome próprio: o
   nome carrega a origem (Ordem de Serviço), e aqui o card é de PRODUÇÃO.
   -------------------------------------------------------------------------- */
.sis-pcp-card {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    width: 100%;
    height: 100%;
    padding: 14px 16px 14px 18px;
    border: 1px solid var(--mud-palette-lines-default);
    border-left: 6px solid var(--sis-table-accent, var(--mud-palette-lines-default));
    border-radius: var(--mud-default-borderradius, 12px);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    text-align: left;
    cursor: pointer;
    transition: background-color .12s ease, box-shadow .12s ease;
    -webkit-tap-highlight-color: transparent;
}

.sis-pcp-card:hover,
.sis-pcp-card:focus-visible {
    background-color: color-mix(in srgb, var(--sis-table-accent, var(--mud-palette-primary)) 10%, var(--mud-palette-surface));
    box-shadow: 0 2px 10px rgba(0, 0, 0, .35);
    outline: none;
}

.sis-pcp-card--atrasada {
    border-color: var(--mud-palette-error);
}

.sis-pcp-card__top {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.sis-pcp-card__number {
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.1;
    color: var(--mud-palette-primary);
}

.sis-pcp-card__number::before {
    content: "Nº ";
    font-size: .7rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
}

.sis-pcp-card__status {
    padding: 2px 8px;
    border: 1px solid var(--sis-table-accent, var(--mud-palette-lines-default));
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 600;
    white-space: nowrap;
    color: var(--sis-table-accent, var(--mud-palette-text-secondary));
}

.sis-pcp-card__meta {
    margin-left: auto;
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.sis-pcp-card__products {
    display: flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
    font-size: .92rem;
    flex: 1 1 auto;
}

.sis-pcp-card__products .mud-icon-root {
    font-size: .95rem;
    flex: 0 0 auto;
    color: var(--mud-palette-text-secondary);
}

.sis-pcp-card__foot {
    display: flex;
    align-items: center;
    gap: 10px;
    padding-top: 8px;
    border-top: 1px solid var(--mud-palette-table-lines);
}

.sis-pcp-card__due {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: .8rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.sis-pcp-card__due .mud-icon-root {
    font-size: .95rem;
}

.sis-pcp-card--atrasada .sis-pcp-card__due,
.sis-pcp-card--atrasada .sis-pcp-card__due .mud-icon-root {
    color: var(--mud-palette-error);
    font-weight: 600;
}

.sis-pcp-card__total {
    margin-left: auto;
    font-weight: 700;
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Abas da GERÊNCIA DE ATENDIMENTO (AtendimentoGerenciaPage).

   Mesmas duas regras da `.sis-restaurant-tabs`, sob nome PRÓPRIO: o
   SeletorDeTesteConventionTests proíbe classe aplicada por mais de um
   componente, e reusar a do restaurante ainda amarraria o salão de beleza ao
   tema Food. O MudTabs força CAIXA ALTA por conta própria, ignorando o
   TextTransform="none" da tipografia do tema.
   -------------------------------------------------------------------------- */
/* 🩸 COMBINADOR DE FILHO, e ⛔ nunca descendente (2026-08-29). Desde que a operação do
   atendimento virou abas, a gerência hospeda um SEGUNDO MudTabs dentro do painel
   "Atendimento" — e um seletor descendente atravessa a fronteira do componente
   hospedado e pinta as pílulas do documento com o estilo da barra de fora. É a
   mesma régua já escrita na `sis-os-gerencia-tabs`, que hospeda a O.S.

   🩸 E o `padding: 0 20px` não é cosmético: ele é o respiro que o
   `MinimumTabWidth="0px"` do markup deixou de dar. Os dois andam JUNTOS — sem o
   parâmetro, a aba fica com os 160px fixos que o MudBlazor aplica como estilo
   INLINE (⛔ CSS nenhum o alcança); sem o padding, com o parâmetro, as abas ficam
   coladas no texto. Medido em 1024×768 em 2026-08-29: as quatro abas de 160px não
   cabiam na barra de 720px depois que o MudBlazor reservou espaço para as próprias
   setas, e ele desenhava DUAS SETAS DE ROLAGEM — "Venda Rápida" atrás de uma seta
   que ninguém percebe que existe. O defeito era ANTERIOR a esta leva; o que faltava
   era alguém medir a barra, e foi a ReguaDeAbas do cenário novo que o encontrou. */
.sis-atendimento-tabs > .mud-tabs-tabbar .mud-tab {
    text-transform: none;
    font-weight: 600;
    padding: 0 20px;
}

/* 🩸 O aperto abaixo de 1280px, medido em 2026-08-29 — e ele é PRÓPRIO desta gerência, não
   copiado por simetria: os rótulos daqui são mais longos que os da O.S. ("Atendimento" no
   lugar de "O.S."), e a régua das quatro abas passava de 587px numa barra de 720px em que o
   MudBlazor ainda reserva o espaço dos próprios botões de rolagem. Com o padding cheio ele
   continuava desenhando as duas setas mesmo com o `MinimumTabWidth="0px"` já no lugar —
   ⚠️ consertar UMA das duas coisas não muda nada na tela, que é a mesma lição da
   `sis-os-doc-tabs`. Portão: AtendimentoGerenciaTests.As_pilulas_do_documento_convivem…, que
   mede as duas barras em 1024×768. */
@media (max-width: 1280px) {
    .sis-atendimento-tabs > .mud-tabs-tabbar .mud-tab {
        padding: 0 10px;
        font-size: .875rem;
    }
}

/* Respiro lateral próprio da tela, para a gerência não depender do padding do
   host que a monta. */
.sis-atendimento-tabs > .mud-tabs-panels {
    padding-inline: clamp(8px, 1.5vw, 20px);
}

/* --------------------------------------------------------------------------
   Abas da GERÊNCIA DE ORDEM DE SERVIÇO (OrdemServicoGerenciaPage).

   Mesmas duas regras das irmãs, sob nome PRÓPRIO — e o nome próprio é
   OBRIGATÓRIO, não preferência: o SeletorDeTesteConventionTests proíbe classe
   de estilo aplicada por mais de um componente ser usada como seletor de
   teste, e as outras gerências já são selecionadas pela delas no E2E.

   O MudTabs força CAIXA ALTA por conta própria, ignorando o
   TextTransform="none" da tipografia do tema — sem isto as abas apareceriam
   "AGENDA"/"VENDA RÁPIDA" enquanto o resto do sis já é sentence case.
   -------------------------------------------------------------------------- */
/* 🩸 FILHO DIRETO (`>`), e ⛔ não descendente — desde 2026-08-18 esta tela HOSPEDA outra que também tem
   MudTabs (a operação da O.S., em cinco abas, dentro do painel "O.S."). Com o seletor descendente, tudo que
   se escreve aqui atravessa a fronteira do componente hospedado e pinta as pílulas dele — sem erro, sem
   aviso, e sem ninguém pedir. Hoje as duas regras coincidem e o dano seria zero; o problema é a PRÓXIMA
   regra que alguém acrescentar. */
.sis-os-gerencia-tabs > .mud-tabs-tabbar .mud-tab {
    text-transform: none;
    font-weight: 600;
    /* O respiro que o `MinimumTabWidth="0px"` do markup deixou de dar. Sem ele as abas ficam coladas no
       texto: com o mínimo removido, quem separa uma aba da outra é este padding. */
    padding: 0 20px;
}

/* Respiro lateral próprio da tela, para a gerência não depender do padding do
   host que a monta — no head próprio quem monta é a casca do app, não o
   ShellLayout do ERP. */
.sis-os-gerencia-tabs > .mud-tabs-panels {
    padding-inline: clamp(8px, 1.5vw, 20px);
}

/* --------------------------------------------------------------------------
   Card do MONITOR de Atendimento (salão de beleza / clínica) — a MESMA receita
   do `sis-os-card`/`sis-pcp-card` (faixa de acento à esquerda, botão nativo,
   cor pela paleta), copiada com nome próprio: aqui o card é de ATENDIMENTO —
   cliente + atendente + horário, sem o vocabulário de oficina (equipamento,
   defeito) que o card de O.S. carrega.
   -------------------------------------------------------------------------- */
.sis-atendimento-card {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    width: 100%;
    height: 100%;
    padding: 14px 16px 14px 18px;
    border: 1px solid var(--mud-palette-lines-default);
    border-left: 6px solid var(--sis-table-accent, var(--mud-palette-lines-default));
    border-radius: var(--mud-default-borderradius, 12px);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    text-align: left;
    cursor: pointer;
    transition: background-color .12s ease, box-shadow .12s ease;
    -webkit-tap-highlight-color: transparent;
}

.sis-atendimento-card:hover,
.sis-atendimento-card:focus-visible {
    background-color: color-mix(in srgb, var(--sis-table-accent, var(--mud-palette-primary)) 10%, var(--mud-palette-surface));
    box-shadow: 0 2px 10px rgba(0, 0, 0, .35);
    outline: none;
}

.sis-atendimento-card--atrasado {
    border-color: var(--mud-palette-error);
}

.sis-atendimento-card__top {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.sis-atendimento-card__number {
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.1;
    color: var(--mud-palette-primary);
}

.sis-atendimento-card__number::before {
    content: "Nº ";
    font-size: .7rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
}

.sis-atendimento-card__status {
    padding: 2px 8px;
    border: 1px solid var(--sis-table-accent, var(--mud-palette-lines-default));
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 600;
    white-space: nowrap;
    color: var(--sis-table-accent, var(--mud-palette-text-secondary));
}

.sis-atendimento-card__meta {
    margin-left: auto;
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.sis-atendimento-card__client,
.sis-atendimento-card__attendant {
    display: flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sis-atendimento-card__client {
    font-weight: 600;
    font-size: .92rem;
}

.sis-atendimento-card__attendant {
    font-size: .84rem;
    color: var(--mud-palette-text-secondary);
    flex: 1 1 auto;
}

.sis-atendimento-card__client .mud-icon-root,
.sis-atendimento-card__attendant .mud-icon-root {
    font-size: .95rem;
    flex: 0 0 auto;
    color: var(--mud-palette-text-secondary);
}

.sis-atendimento-card__foot {
    display: flex;
    align-items: center;
    gap: 10px;
    padding-top: 8px;
    border-top: 1px solid var(--mud-palette-table-lines);
}

.sis-atendimento-card__due {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: .8rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.sis-atendimento-card__due .mud-icon-root {
    font-size: .95rem;
}

.sis-atendimento-card--atrasado .sis-atendimento-card__due,
.sis-atendimento-card--atrasado .sis-atendimento-card__due .mud-icon-root {
    color: var(--mud-palette-error);
    font-weight: 600;
}

.sis-atendimento-card__total {
    margin-left: auto;
    font-weight: 700;
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   KANBAN de ordens de produção — colunas de VERDADE por status (diferente do
   board de comandas do restaurante, que abandonou colunas em favor de abas de
   escopo). Aqui a posição da coluna É a informação: o encarregado varre da
   esquerda pra direita e vê o funil de produção inteiro de uma vez.
   -------------------------------------------------------------------------- */
.sis-pcp-kanban {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    overflow-x: auto;
    padding-bottom: 8px;
}

.sis-pcp-kanban-column {
    display: flex;
    flex-direction: column;
    flex: 1 1 260px;
    min-width: 260px;
    max-width: 340px;
    background-color: var(--mud-palette-background-grey);
    border-radius: var(--mud-default-borderradius, 12px);
    border-top: 4px solid var(--sis-table-accent, var(--mud-palette-lines-default));
    padding: 12px;
    gap: 10px;
}

.sis-pcp-kanban-column__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 0 2px;
}

.sis-pcp-kanban-column__title {
    font-weight: 700;
    font-size: .95rem;
    color: var(--sis-table-accent, var(--mud-palette-text-primary));
}

.sis-pcp-kanban-column__count {
    font-size: .78rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    background-color: var(--mud-palette-surface);
    border-radius: 999px;
    padding: 1px 9px;
}

.sis-pcp-kanban-column__body {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-height: 60px;
}

.sis-pcp-kanban-column__empty {
    font-size: .8rem;
    color: var(--mud-palette-text-secondary);
    text-align: center;
    padding: 18px 4px;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius, 8px);
}

/* O CARD é um <div> (não <button>) porque ele contém DOIS controles: a área que abre a ordem e o botão de
   ação (Iniciar/Concluir) — botão dentro de botão é HTML inválido e quebra o clique. A área de abrir é o
   `__open`, um <button> "desenhado" (all:unset) para ocupar o espaço sem parecer um botão solto. */
.sis-pcp-kanban-card {
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: 100%;
    padding: 10px 12px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius, 10px);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
}

.sis-pcp-kanban-card--atrasada {
    border-color: var(--mud-palette-error);
}

.sis-pcp-kanban-card__open {
    all: unset;
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 100%;
    box-sizing: border-box;
    cursor: pointer;
    text-align: left;
    border-radius: var(--mud-default-borderradius, 8px);
    padding: 2px;
    -webkit-tap-highlight-color: transparent;
}

.sis-pcp-kanban-card__open:hover,
.sis-pcp-kanban-card__open:focus-visible {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 8%, var(--mud-palette-surface));
    outline: none;
}

.sis-pcp-kanban-card__top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.sis-pcp-kanban-card__number {
    font-weight: 700;
    font-size: .95rem;
}

.sis-pcp-kanban-card__due {
    font-size: .74rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.sis-pcp-kanban-card--atrasada .sis-pcp-kanban-card__due {
    color: var(--mud-palette-error);
    font-weight: 600;
}

.sis-pcp-kanban-card__products {
    font-size: .82rem;
    color: var(--mud-palette-text-secondary);
}

.sis-pcp-kanban-card__total {
    font-size: .84rem;
    font-weight: 600;
}

.sis-pcp-kanban-card__action {
    margin-top: 2px;
}

/* =========================================================================
   Seletor de observações de produto (ProductObservationPicker).

   Faixa de chips que envolve, e não rola na horizontal: aqui a lista é curta
   (os rótulos de UMA categoria) e o operador precisa ver todos de uma vez —
   diferente da .sis-cat-strip, onde rolar é o certo porque a lista cresce
   com o cardápio. Um rótulo escondido fora da tela é um rótulo que ninguém
   usa, e o operador volta a digitar a frase à mão.

   Sem cor cravada: quem pinta o chip é o Variant/Color do MudBlazor, para o
   estado ligado/desligado acompanhar o tema (o restaurante roda num tema
   escuro próprio, o escritório no toggle claro/escuro). */
.sis-obs-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 4px 0 8px;
}

/* Área de toque: 32px é o piso confortável para o dedo num terminal de
   balcão. O chip Small do MudBlazor nasce menor que isso. */
.sis-obs-picker .mud-chip {
    min-height: 32px;
    margin: 0;
}

/* Os rótulos escolhidos, exibidos na LINHA DO ITEM (comanda, garçom, gerência).
   Classe própria, e não a do seletor: ali os chips são controles que o operador
   toca; aqui são leitura. Compartilhar a classe amarraria o espaçamento de um ao
   do outro, e foi o que o portão de seletor de teste acusou. */
.sis-obs-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin: 2px 0 4px;
}

.sis-obs-tags .mud-chip {
    margin: 0;
}

/* ---------------------------------------------------------------------------
   Grupo de campos com LEGENDA NA BORDA (`<fieldset>` + `<legend>`).

   É o mesmo desenho que o MudTextField `Outlined` usa para o rótulo dele — e não
   é imitação por CSS: o corte da borda em volta da legenda é comportamento
   NATIVO do par fieldset/legend no navegador. Um `MudPaper` com o título dentro
   não consegue isso sem gambiarra (fundo opaco sobreposto à borda, que quebra em
   cima de superfície de cor diferente e nos dois temas).

   Os valores vêm da receita do próprio MudBlazor (`.mud-input-outlined-border`),
   para o contorno bater com o dos campos ao lado: 1px, o raio padrão, a variável
   de cor de linha de input, legenda em .75rem com margem 11px e padding 5px.
   Usar as VARIÁVEIS, e não hexadecimal, é o que faz a caixa acompanhar o tema
   claro e o escuro sozinha.
   --------------------------------------------------------------------------- */
.sis-field-group {
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: var(--mud-default-borderradius);
    /* O padding-top menor compensa o espaço que a legenda já ocupa na borda. */
    padding: 2px 12px 6px;
    margin: 0;
    min-width: 0;
}

.sis-field-group > legend {
    font-size: .75rem;
    line-height: 1;
    padding: 0 5px;
    margin: 0 6px;
    color: var(--mud-palette-text-secondary);
}

/* Os controles do grupo numa linha só, quebrando quando não couber. */
.sis-field-group-inline {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
}

/* ---------------------------------------------------------------------------
   MudChart: o <svg> raiz recorta o próprio conteúdo por padrão (overflow:
   hidden é o default do UA para <svg>). O MudChart de barra posiciona a 1ª e a
   ÚLTIMA categoria NA BORDA do viewBox (não centralizadas no slot), então o
   rótulo do eixo X rotacionado da ponta nasce cortado pela borda do PRÓPRIO
   svg — padding no elemento HTML em volta não alcança isso, porque o corte
   acontece dentro do svg, não no container. `overflow: visible` deixa o texto
   desenhar além do viewBox; a folga (padding do container que hospeda o
   MudChart) é quem garante que esse excedente não estoure a TELA.
   --------------------------------------------------------------------------- */
.mud-chart svg {
    overflow: visible;
}

/* -------------------------------------------------------------------------
   Tela de CMV (Custo de Mercadorias Vendidas) — Estoque/Cmv/CmvPage
   -------------------------------------------------------------------------
   Os cartões de resumo do topo usam cor sólida SÓ na borda esquerda (6px), não
   no fundo — mesmo raciocínio do sis-table-card: fundo saturado apaga o
   número por cima, e aqui o número é o que importa. */
.sis-cmv-summary-card {
    display: flex;
    flex-direction: column;
    gap: 2px;
    height: 100%;
    padding: 16px;
    border-left: 4px solid var(--mud-palette-lines-default);
}

/* Campo "Buscar item ou categoria" — largura por CLASSE, nunca por Style inline no MudTextField. Medido:
   o MudBlazor aplica o Style do componente no `.mud-input` INTERNO (variante outlined), que é filho de
   `.mud-input-control-input-container` — um flex COLUMN. Um `flex: 1 1 220px` ali vira flex-basis de
   ALTURA (o eixo principal da coluna), não de largura, e o campo nascia com ~220px de altura. A largura
   é resolvida no `.mud-input-control` de fora (que já cresce sozinho na barra — é ele quem tem
   flex-grow:1 por padrão da lib), então aqui só min/max-width bastam. */
.sis-cmv-search {
    min-width: 240px;
    max-width: 420px;
}

/* Campo "Meta de CMV %" — a MESMA cura do `.sis-cmv-search` acima, aplicada ao vizinho que ficou de fora
   dela. Ele pedia a largura por `Style="max-width: 140px"` e nascia com 356px: o Style do componente pousa
   no `.mud-input` INTERNO, então limitava o input e não o `.mud-input-control` de fora — que tem
   flex-grow:1 por padrão da lib e seguia crescendo. Um percentual de dois dígitos ocupava 356px e empurrava
   os três botões para longe do campo sobre o qual eles agem.

   🔑 `max-width` sozinho basta, e isso foi MEDIDO nas duas viewports (1600 e 1024): o campo fica em 160px
   nas duas e o rótulo cabe inteiro (`scrollWidth == clientWidth`). ⛔ Não acrescente `min-width` nem
   `flex-grow: 0` "por segurança" — tentei os dois, e sem eles o resultado é idêntico.

   ⚠️ Para conferir truncamento de rótulo aqui, compare `scrollWidth` com `clientWidth`, ⛔ nunca com
   `getBoundingClientRect().width`: o label flutuante do MudBlazor carrega `transform: scale(.75)`, então o
   rect vem 25% menor e QUALQUER rótulo parece truncado (135 vira 101). Foi o que quase me fez "consertar"
   um campo que estava certo. */
.sis-cmv-meta {
    max-width: 160px;
}

.sis-cmv-summary-card--saudavel {
    border-left-color: var(--mud-palette-success);
}

.sis-cmv-summary-card--alerta {
    border-left-color: var(--mud-palette-warning);
}

.sis-cmv-summary-card--sem-custo {
    border-left-color: var(--mud-palette-text-secondary);
}

/* Os dois acentos que a tela de CMV CONTÁBIL acrescenta à mesma família. O total do período é o número que
   o contador leva, e por isso é o único em cor primária; os ajustes ganham "info" porque podem ser positivos
   OU negativos — pintá-los de verde/vermelho fixo daria significado a um sinal que muda de linha para linha
   (quem colore por sinal é o chip da célula, não o card). */
.sis-cmv-summary-card--primario {
    border-left-color: var(--mud-palette-primary);
}

.sis-cmv-summary-card--info {
    border-left-color: var(--mud-palette-info);
}

.sis-cmv-summary-label {
    color: var(--mud-palette-text-secondary);
}

.sis-cmv-summary-value {
    font-weight: 700;
    line-height: 1.2;
}

/* Card de item: mesma receita de faixa de acento à esquerda dos cards de
   comanda/O.S./O.P. — o estado (saudável/alerta/sem custo) importa à
   distância, sem precisar abrir o item. */
.sis-cmv-item-card {
    border-left: 6px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius, 12px);
    overflow: hidden;
}

.sis-cmv-item-card--saudavel {
    border-left-color: var(--mud-palette-success);
}

.sis-cmv-item-card--alerta {
    border-left-color: var(--mud-palette-warning);
}

.sis-cmv-item-card--sem-custo {
    border-left-color: var(--mud-palette-text-secondary);
}

.sis-cmv-item-card__header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px;
    padding: 12px 16px;
}

.sis-cmv-item-card__title {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 160px;
    flex: 1 1 200px;
}

.sis-cmv-item-card__metrics {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 20px;
}

.sis-cmv-metric {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    min-width: 0;
}

.sis-cmv-metric__label {
    font-size: .68rem;
    font-weight: 600;
    letter-spacing: .03em;
    color: var(--mud-palette-text-secondary);
    text-transform: uppercase;
}

.sis-cmv-ficha {
    padding: 4px 16px 16px 22px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.sis-cmv-ficha__title {
    display: block;
    margin: 10px 0 6px;
    color: var(--mud-palette-text-secondary);
}

.sis-cmv-ficha__tabela th {
    font-size: .72rem;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

/* --------------------------------------------------------------------------
   AGENDA de O.S. — o calendário de atendimentos (/ordem-servico/agenda).

   A geometria (posição e altura do card, altura da grade) vem do C# como
   `style` inline, porque depende de DADO — horário e duração — e CSS não faz
   essa conta. O que mora aqui é aparência, estado e comportamento de arraste.

   ⛔ Nada de cor cravada: tudo pela paleta do MudBlazor, senão o que funciona
   no tema claro fica ilegível no escuro — o defeito que só aparece na captura.
   -------------------------------------------------------------------------- */
.sis-agenda__cabecalho {
    display: grid;
    position: sticky;
    top: 0;
    z-index: 2;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-surface);
}

.sis-agenda__canto {
    border-right: 1px solid var(--mud-palette-lines-default);
}

.sis-agenda__dia-nome {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: 6px;
    padding: 8px 4px;
    border-right: 1px solid var(--mud-palette-lines-default);
    color: var(--mud-palette-text-secondary);
    font-size: .78rem;
    text-transform: uppercase;
}

.sis-agenda__dia-numero {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--mud-palette-text-primary);
}

/* HOJE marcado na coluna inteira: num calendário aberto o dia todo, a primeira
   pergunta é sempre "onde é hoje" — e sem marca ela custa uma leitura de data. */
.sis-agenda__dia-nome--hoje,
.sis-agenda__dia-nome--hoje .sis-agenda__dia-numero {
    color: var(--mud-palette-primary);
}

.sis-agenda {
    display: grid;
    overflow-x: auto;
}

.sis-agenda__horas {
    position: relative;
    border-right: 1px solid var(--mud-palette-lines-default);
}

.sis-agenda__hora {
    position: relative;
    border-bottom: 1px solid var(--mud-palette-table-lines);
}

.sis-agenda__hora > span {
    position: absolute;
    top: -8px;
    right: 6px;
    font-size: .72rem;
    color: var(--mud-palette-text-secondary);
}

.sis-agenda__coluna {
    position: relative;
    border-right: 1px solid var(--mud-palette-lines-default);
}

.sis-agenda__coluna--hoje {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 6%, transparent);
}

/* SLOT vazio: alvo de clique (marcar) e de solta (remarcar). É `button` para o
   teclado alcançar — a agenda não pode depender de arraste, que não existe no
   toque nem no leitor de tela. */
.sis-agenda__slot {
    position: absolute;
    left: 0;
    right: 0;
    padding: 0;
    border: 0;
    border-bottom: 1px dashed transparent;
    background: transparent;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.sis-agenda__slot--hora {
    border-bottom-color: var(--mud-palette-table-lines);
    border-bottom-style: solid;
}

.sis-agenda__slot:hover,
.sis-agenda__slot:focus-visible {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 10%, transparent);
    outline: none;
}

/* Destino do arraste. Sem este realce, soltar um card é adivinhação: o cursor
   fica entre duas meias horas e ninguém sabe onde ele vai cair. */
.sis-agenda__slot--alvo {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 22%, transparent);
    border: 1px dashed var(--mud-palette-primary);
}

.sis-agenda__card {
    position: absolute;
    display: flex;
    overflow: hidden;
    padding: 0;
    border: 1px solid var(--mud-palette-lines-default);
    border-left: 4px solid var(--sis-agenda-accent, var(--mud-palette-info));
    border-radius: 6px;
    background-color: color-mix(in srgb, var(--sis-agenda-accent, var(--mud-palette-info)) 14%, var(--mud-palette-surface));
    cursor: grab;
    transition: box-shadow .12s ease;
}

.sis-agenda__card:hover {
    box-shadow: 0 2px 10px rgba(0, 0, 0, .35);
    z-index: 1;
}

.sis-agenda__card:active {
    cursor: grabbing;
}

.sis-agenda__card--atrasada {
    border-color: var(--mud-palette-error);
}

/* Encerrada fica em segundo plano — continua visível (é o histórico do dia),
   mas não disputa atenção com o que ainda vai acontecer. */
.sis-agenda__card--encerrada {
    opacity: .72;
}

.sis-agenda__card-abrir {
    display: flex;
    flex-direction: column;
    gap: 1px;
    flex: 1 1 auto;
    min-width: 0;
    padding: 3px 6px;
    border: 0;
    background: transparent;
    color: var(--mud-palette-text-primary);
    text-align: left;
    cursor: pointer;
}

.sis-agenda__card-topo {
    display: flex;
    align-items: baseline;
    gap: 6px;
    min-width: 0;
}

.sis-agenda__card-hora {
    font-size: .7rem;
    font-weight: 700;
    color: var(--sis-agenda-accent, var(--mud-palette-text-secondary));
    white-space: nowrap;
}

.sis-agenda__card-numero {
    font-size: .68rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

/* min-width:0 na cadeia inteira: sem ele o nome longo ALARGA o card em vez de
   truncar, e o card estouraria a coluna do dia. */
.sis-agenda__card-cliente,
.sis-agenda__card-tecnico,
.sis-agenda__card-equipamento {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sis-agenda__card-cliente {
    font-size: .78rem;
    font-weight: 600;
}

/* ── Colunas da visão POR TÉCNICO ────────────────────────────────────────────
   Mesma grade da diária/semanal — o que muda é o significado da coluna. O
   cabeçalho troca "dia + número" por "nome + carga do dia". */
.sis-agenda__tecnico-nome {
    font-size: .82rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

/* A carga do dia: quantos atendimentos aquele técnico tem. É o número que
   decide o remanejamento, e por isso fica no cabeçalho e não escondido. */
.sis-agenda__tecnico-carga {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 20px;
    padding: 0 6px;
    border-radius: 999px;
    background-color: var(--mud-palette-action-default-hover);
    color: var(--mud-palette-text-secondary);
    font-size: .72rem;
    font-weight: 600;
}

/* A coluna SEM RESPONSÁVEL é a fila do que precisa ser distribuído — some do
   cinza do fundo de propósito, para o olho ir nela primeiro. */
.sis-agenda__dia-nome--sem-tecnico .sis-agenda__tecnico-nome {
    color: var(--mud-palette-warning);
}

.sis-agenda__coluna--sem-tecnico {
    background-color: color-mix(in srgb, var(--mud-palette-warning) 6%, transparent);
}

/* Bloco curto (menos de ~1 h): sem a linha do equipamento. Ela sairia CORTADA ao
   meio, que é pior que ausente — parece defeito de renderização. Foi a captura
   quem viu, num atendimento de 45 minutos. */
.sis-agenda__card--compacto .sis-agenda__card-equipamento {
    display: none;
}

/* No bloco curto o espaço é de TRÊS linhas apertadas — hora, cliente e técnico.
   O número da O.S. sai (é o dado que menos se procura na agenda: quem olha o
   calendário procura horário, cliente e quem atende) e as entrelinhas encostam.
   Foi a captura de um atendimento de 45 minutos que mostrou o corte. */
.sis-agenda__card--compacto .sis-agenda__card-abrir {
    gap: 0;
    padding: 1px 6px;
}

.sis-agenda__card--compacto .sis-agenda__card-numero {
    display: none;
}

.sis-agenda__card--compacto .sis-agenda__card-topo,
.sis-agenda__card--compacto .sis-agenda__card-cliente,
.sis-agenda__card--compacto .sis-agenda__card-tecnico {
    line-height: 1.15;
}

.sis-agenda__card-equipamento {
    font-size: .72rem;
    color: var(--mud-palette-text-secondary);
}

/* O técnico responsável — a terceira linha do card, e a que SOBREVIVE quando o
   bloco é curto: "quem atende" decide mais do que "o que veio" na hora de
   remanejar o dia. */
.sis-agenda__card-tecnico {
    display: flex;
    align-items: center;
    gap: 3px;
    font-size: .72rem;
    color: var(--mud-palette-text-primary);
}

.sis-agenda__card-tecnico .mud-icon-root {
    font-size: .85rem;
    flex: 0 0 auto;
    color: var(--mud-palette-text-secondary);
}

/* O botão de remarcar só aparece no hover/foco: num card de 30 minutos ele
   ocuparia metade da altura útil, e o que precisa ser lido é o cliente. */
.sis-agenda__card-remarcar {
    flex: 0 0 auto;
    align-self: flex-start;
    opacity: 0;
    transition: opacity .12s ease;
}

.sis-agenda__card:hover .sis-agenda__card-remarcar,
.sis-agenda__card-remarcar:focus-visible {
    opacity: 1;
}

/* ---------------------------- visão MENSAL ---------------------------- */
.sis-agenda-mes__cabecalho,
.sis-agenda-mes {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
}

.sis-agenda-mes__dia-nome {
    padding: 6px 4px;
    text-align: center;
    font-size: .74rem;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.sis-agenda-mes__celula {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-height: 108px;
    padding: 4px;
    border: 1px solid var(--mud-palette-table-lines);
    overflow: hidden;
}

/* Dias de fora do mês entram para fechar a semana — apagados, mas clicáveis:
   é neles que se procura espaço quando o mês corrente está cheio. */
.sis-agenda-mes__celula--fora {
    opacity: .45;
}

.sis-agenda-mes__celula--hoje {
    border-color: var(--mud-palette-primary);
    background-color: color-mix(in srgb, var(--mud-palette-primary) 6%, transparent);
}

.sis-agenda-mes__numero {
    align-self: flex-start;
    padding: 0 4px;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--mud-palette-text-primary);
    font-size: .8rem;
    font-weight: 600;
    cursor: pointer;
}

.sis-agenda-mes__numero:hover,
.sis-agenda-mes__numero:focus-visible {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 18%, transparent);
    outline: none;
}

.sis-agenda-mes__item {
    display: flex;
    align-items: baseline;
    gap: 4px;
    width: 100%;
    padding: 1px 4px;
    border: 0;
    border-left: 3px solid var(--sis-agenda-accent, var(--mud-palette-info));
    border-radius: 4px;
    background-color: color-mix(in srgb, var(--sis-agenda-accent, var(--mud-palette-info)) 14%, var(--mud-palette-surface));
    color: var(--mud-palette-text-primary);
    font-size: .72rem;
    text-align: left;
    cursor: grab;
}

.sis-agenda-mes__item--atrasada {
    outline: 1px solid var(--mud-palette-error);
}

.sis-agenda-mes__hora {
    font-weight: 700;
    color: var(--sis-agenda-accent, var(--mud-palette-text-secondary));
    white-space: nowrap;
}

.sis-agenda-mes__texto {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   AGENDA de Atendimento (salão de beleza / clínica, /atendimento/agenda) — a
   MESMA receita da agenda de O.S. (grade, slot, card, visão por responsável e
   mensal), copiada com PREFIXO PRÓPRIO — não reusada — porque o
   SeletorDeTesteConventionTests exige que classe usada como seletor de teste
   seja aplicada por UM componente só; os testes da agenda de O.S. já
   selecionam `.sis-agenda__*`/`.sis-agenda-mes__*`, e reusar essas classes
   aqui tornaria os dois conjuntos de seletores ambíguos (mesmo raciocínio que
   fez o card do monitor de O.P. nascer `.sis-pcp-card`, não `.sis-os-card`).

   ⛔ Nada de cor cravada: tudo pela paleta do MudBlazor.
   -------------------------------------------------------------------------- */
.sis-atendimento-agenda__cabecalho {
    display: grid;
    position: sticky;
    top: 0;
    z-index: 2;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-surface);
}

.sis-atendimento-agenda__canto {
    border-right: 1px solid var(--mud-palette-lines-default);
}

.sis-atendimento-agenda__dia-nome {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: 6px;
    padding: 8px 4px;
    border-right: 1px solid var(--mud-palette-lines-default);
    color: var(--mud-palette-text-secondary);
    font-size: .78rem;
    text-transform: uppercase;
}

.sis-atendimento-agenda__dia-numero {
    font-size: 1.05rem;
    font-weight: 700;
    color: var(--mud-palette-text-primary);
}

.sis-atendimento-agenda__dia-nome--hoje,
.sis-atendimento-agenda__dia-nome--hoje .sis-atendimento-agenda__dia-numero {
    color: var(--mud-palette-primary);
}

.sis-atendimento-agenda {
    display: grid;
    overflow-x: auto;
}

.sis-atendimento-agenda__horas {
    position: relative;
    border-right: 1px solid var(--mud-palette-lines-default);
}

.sis-atendimento-agenda__hora {
    position: relative;
    border-bottom: 1px solid var(--mud-palette-table-lines);
}

.sis-atendimento-agenda__hora > span {
    position: absolute;
    top: -8px;
    right: 6px;
    font-size: .72rem;
    color: var(--mud-palette-text-secondary);
}

.sis-atendimento-agenda__coluna {
    position: relative;
    border-right: 1px solid var(--mud-palette-lines-default);
}

.sis-atendimento-agenda__coluna--hoje {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 6%, transparent);
}

.sis-atendimento-agenda__slot {
    position: absolute;
    left: 0;
    right: 0;
    padding: 0;
    border: 0;
    border-bottom: 1px dashed transparent;
    background: transparent;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.sis-atendimento-agenda__slot--hora {
    border-bottom-color: var(--mud-palette-table-lines);
    border-bottom-style: solid;
}

.sis-atendimento-agenda__slot:hover,
.sis-atendimento-agenda__slot:focus-visible {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 10%, transparent);
    outline: none;
}

.sis-atendimento-agenda__card {
    position: absolute;
    display: flex;
    overflow: hidden;
    padding: 0;
    border: 1px solid var(--mud-palette-lines-default);
    border-left: 4px solid var(--sis-atendimento-agenda-accent, var(--mud-palette-info));
    border-radius: 6px;
    background-color: color-mix(in srgb, var(--sis-atendimento-agenda-accent, var(--mud-palette-info)) 14%, var(--mud-palette-surface));
    cursor: grab;
    transition: box-shadow .12s ease;
}

.sis-atendimento-agenda__card:hover {
    box-shadow: 0 2px 10px rgba(0, 0, 0, .35);
    z-index: 1;
}

.sis-atendimento-agenda__card:active {
    cursor: grabbing;
}

.sis-atendimento-agenda__card--atrasada {
    border-color: var(--mud-palette-error);
}

.sis-atendimento-agenda__card--encerrada {
    opacity: .72;
}

.sis-atendimento-agenda__card-abrir {
    display: flex;
    flex-direction: column;
    gap: 1px;
    flex: 1 1 auto;
    min-width: 0;
    padding: 3px 6px;
    border: 0;
    background: transparent;
    color: var(--mud-palette-text-primary);
    text-align: left;
    cursor: pointer;
}

.sis-atendimento-agenda__card-topo {
    display: flex;
    align-items: baseline;
    gap: 6px;
    min-width: 0;
}

.sis-atendimento-agenda__card-hora {
    font-size: .7rem;
    font-weight: 700;
    color: var(--sis-atendimento-agenda-accent, var(--mud-palette-text-secondary));
    white-space: nowrap;
}

.sis-atendimento-agenda__card-numero {
    font-size: .68rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.sis-atendimento-agenda__card-cliente,
.sis-atendimento-agenda__card-tecnico {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sis-atendimento-agenda__card-cliente {
    font-size: .78rem;
    font-weight: 600;
}

.sis-atendimento-agenda__tecnico-nome {
    font-size: .82rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

.sis-atendimento-agenda__tecnico-carga {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 20px;
    padding: 0 6px;
    border-radius: 999px;
    background-color: var(--mud-palette-action-default-hover);
    color: var(--mud-palette-text-secondary);
    font-size: .72rem;
    font-weight: 600;
}

.sis-atendimento-agenda__dia-nome--sem-tecnico .sis-atendimento-agenda__tecnico-nome {
    color: var(--mud-palette-warning);
}

.sis-atendimento-agenda__coluna--sem-tecnico {
    background-color: color-mix(in srgb, var(--mud-palette-warning) 6%, transparent);
}

.sis-atendimento-agenda__card--compacto .sis-atendimento-agenda__card-abrir {
    gap: 0;
    padding: 1px 6px;
}

.sis-atendimento-agenda__card--compacto .sis-atendimento-agenda__card-numero {
    display: none;
}

.sis-atendimento-agenda__card--compacto .sis-atendimento-agenda__card-topo,
.sis-atendimento-agenda__card--compacto .sis-atendimento-agenda__card-cliente,
.sis-atendimento-agenda__card--compacto .sis-atendimento-agenda__card-tecnico {
    line-height: 1.15;
}

.sis-atendimento-agenda__card-tecnico {
    display: flex;
    align-items: center;
    gap: 3px;
    font-size: .72rem;
    color: var(--mud-palette-text-primary);
}

.sis-atendimento-agenda__card-tecnico .mud-icon-root {
    font-size: .85rem;
    flex: 0 0 auto;
    color: var(--mud-palette-text-secondary);
}

.sis-atendimento-agenda__card-remarcar {
    flex: 0 0 auto;
    align-self: flex-start;
    opacity: 0;
    transition: opacity .12s ease;
}

.sis-atendimento-agenda__card:hover .sis-atendimento-agenda__card-remarcar,
.sis-atendimento-agenda__card-remarcar:focus-visible {
    opacity: 1;
}

/* ---------------------------- visão MENSAL ---------------------------- */
.sis-atendimento-agenda-mes__cabecalho,
.sis-atendimento-agenda-mes {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
}

.sis-atendimento-agenda-mes__dia-nome {
    padding: 6px 4px;
    text-align: center;
    font-size: .74rem;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.sis-atendimento-agenda-mes__celula {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-height: 108px;
    padding: 4px;
    border: 1px solid var(--mud-palette-table-lines);
    overflow: hidden;
}

.sis-atendimento-agenda-mes__celula--fora {
    opacity: .45;
}

.sis-atendimento-agenda-mes__celula--hoje {
    border-color: var(--mud-palette-primary);
    background-color: color-mix(in srgb, var(--mud-palette-primary) 6%, transparent);
}

.sis-atendimento-agenda-mes__numero {
    align-self: flex-start;
    padding: 0 4px;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--mud-palette-text-primary);
    font-size: .8rem;
    font-weight: 600;
    cursor: pointer;
}

.sis-atendimento-agenda-mes__numero:hover,
.sis-atendimento-agenda-mes__numero:focus-visible {
    background-color: color-mix(in srgb, var(--mud-palette-primary) 18%, transparent);
    outline: none;
}

.sis-atendimento-agenda-mes__item {
    display: flex;
    align-items: baseline;
    gap: 4px;
    width: 100%;
    padding: 1px 4px;
    border: 0;
    border-left: 3px solid var(--sis-atendimento-agenda-accent, var(--mud-palette-info));
    border-radius: 4px;
    background-color: color-mix(in srgb, var(--sis-atendimento-agenda-accent, var(--mud-palette-info)) 14%, var(--mud-palette-surface));
    color: var(--mud-palette-text-primary);
    font-size: .72rem;
    text-align: left;
    cursor: grab;
}

.sis-atendimento-agenda-mes__item--atrasada {
    outline: 1px solid var(--mud-palette-error);
}

.sis-atendimento-agenda-mes__hora {
    font-weight: 700;
    color: var(--sis-atendimento-agenda-accent, var(--mud-palette-text-secondary));
    white-space: nowrap;
}

.sis-atendimento-agenda-mes__texto {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Alteração em lote de produtos (CatalogoProdutoLotePage): indicador de edição por LINHA e por CÉLULA.
   Cor WARNING (âmbar), não a primária do grid comum — "editado, ainda não salvo" é um estado distinto de
   "selecionado", e os dois podem coexistir na mesma tela. */
.sis-bulk-edit-scroll {
    overflow-x: auto;
}

.sis-bulk-edit-table .mud-table-row.sis-row-dirty td {
    background-color: rgba(var(--mud-palette-warning-rgb), 0.10);
}

.sis-bulk-edit-table .mud-table-row.sis-row-dirty td:first-child {
    box-shadow: inset 4px 0 0 0 var(--mud-palette-warning);
}

/* A célula do campo que mudou, além da linha — numa linha com 12 colunas editáveis, "a linha mudou" não diz
   QUAL campo; o traço embaixo do valor sim. */
.sis-bulk-edit-cell-dirty {
    box-shadow: inset 0 -3px 0 0 var(--mud-palette-warning);
}

/* ── Importador: histórico de execuções (/config/importador) ───────────────────────────────────────────── */
/* Contador do relatório. Caixa do TEMA (surface + borda + raio), nunca bloco de cor chapada: bloco pintado é
   a única coisa que não acompanha o claro/escuro. A cor entra só no NÚMERO, pelo Color do MudText. */
.sis-import-counter {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    min-width: 104px;
    padding: 8px 14px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius);
    background-color: var(--mud-palette-surface);
}

.sis-import-counter__label {
    color: var(--mud-palette-text-secondary);
    text-transform: uppercase;
    letter-spacing: .04em;
}

/* Falha diferente de zero salta na grade. Sem isto, "37" e "0" têm o mesmo peso visual e o operador só
   descobre a execução problemática abrindo uma a uma. */
.sis-import-falhas {
    color: var(--mud-palette-error);
    font-weight: 600;
}

/* ---------------------------------------------------------------------------
   Cabeçalho de MÓDULO dentro do menu de ajuda (SisTutorialHelpButton): separa
   "Vendas", "Financeiro"… na lista de outros tutoriais. É item desabilitado, e
   por isso precisa recuperar legibilidade — o cinza de "desabilitado" do
   MudBlazor apagaria o único rótulo que orienta a leitura da lista.
   --------------------------------------------------------------------------- */
.sis-ajuda-modulo {
    opacity: 1 !important;
    min-height: 28px;
    padding-top: 6px;
    padding-bottom: 2px;
    color: var(--mud-palette-text-secondary);
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    cursor: default;
}

/* ---------------------------------------------------------------------------
   Aba "Documentação" do menu Ajuda (DocumentacaoPage) — molde do .sis-pdf-viewer:
   barra de identidade + iframe ocupando o resto da tela. O site embutido é
   estático (docs/telas-doc/), publicado em wwwroot/docs/ desta RCL.
   --------------------------------------------------------------------------- */
.sis-doc-page {
    display: flex;
    flex-direction: column;
    height: calc(100dvh - 96px);
    min-height: 480px;
    gap: 8px;
    padding: 12px;
}

.sis-doc-page__bar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 16px;
    border-radius: 12px;
    flex-shrink: 0;
}

.sis-doc-page__titles {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.sis-doc-page__title {
    font-weight: 700;
}

.sis-doc-page__hint {
    color: var(--mud-palette-text-secondary);
}

.sis-doc-page__frame {
    flex: 1 1 auto;
    width: 100%;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background: #FFFFFF;
}

/* --------------------------------------------------------------------------
   Card do MONITOR de PRÉ-VENDA (a ficha do balcão)
   Mesma família do `sis-os-card` (faixa de acento à esquerda, botão nativo, cor
   só pela paleta), com UMA inversão deliberada de hierarquia: aqui o NÚMERO é o
   dado dominante, não um rótulo pequeno no canto.

   Por quê: o card da O.S. responde "o que é, de quem é e pra quando"; este
   responde "QUAL FICHA". O cliente chega ao caixa dizendo "ficha 12" e o
   operador varre o quadro procurando o 12 — se o número tiver o tamanho do
   nome do vendedor, essa varredura vira leitura, e leitura numa fila é fila
   parada. É o mesmo motivo pelo qual o número vem primeiro no ranking da busca.
   -------------------------------------------------------------------------- */
.sis-ficha-card {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
    width: 100%;
    height: 100%;
    padding: 14px 16px 14px 18px;
    border: 1px solid var(--mud-palette-lines-default);
    border-left: 6px solid var(--sis-table-accent, var(--mud-palette-lines-default));
    border-radius: var(--mud-default-borderradius, 12px);
    background-color: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    text-align: left;
    cursor: pointer;
    transition: background-color .12s ease, box-shadow .12s ease;
    -webkit-tap-highlight-color: transparent;
}

.sis-ficha-card:hover,
.sis-ficha-card:focus-visible {
    background-color: color-mix(in srgb, var(--sis-table-accent, var(--mud-palette-primary)) 10%, var(--mud-palette-surface));
    box-shadow: 0 2px 10px rgba(0, 0, 0, .35);
    outline: none;
}

.sis-ficha-card__top {
    display: flex;
    align-items: baseline;
    gap: 10px;
    min-width: 0;
}

/* O número é a informação que se procura de longe — 2.1rem contra os 1.5rem do
   card de O.S. O prefixo "FICHA" fica pequeno em cima, como no papel. */
.sis-ficha-card__number {
    font-size: 2.1rem;
    font-weight: 800;
    line-height: 1;
    color: var(--mud-palette-primary);
}

.sis-ficha-card__number::before {
    content: "FICHA ";
    display: block;
    font-size: .62rem;
    font-weight: 700;
    letter-spacing: .08em;
    line-height: 1.6;
    color: var(--mud-palette-text-secondary);
}

.sis-ficha-card__status {
    margin-left: auto;
    padding: 2px 8px;
    border: 1px solid var(--sis-table-accent, var(--mud-palette-lines-default));
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 600;
    white-space: nowrap;
    color: var(--sis-table-accent, var(--mud-palette-text-secondary));
}

.sis-ficha-card__seller {
    display: flex;
    align-items: center;
    gap: 5px;
    /* min-width:0 na cadeia inteira: sem ele o nome longo ALARGA o card em vez
       de truncar, e um card mais largo desalinha a linha inteira da grade. */
    min-width: 0;
    font-size: .9rem;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sis-ficha-card__seller .mud-icon-root {
    font-size: .95rem;
    flex: 0 0 auto;
    color: var(--mud-palette-text-secondary);
}

/* A observação CRESCE (flex:1) e é ela que alinha o rodapé — e portanto o total —
   de todos os cards da linha, sem altura cravada. Duas linhas e reticências: é
   recado de balcão, não o lugar de lê-lo inteiro. */
.sis-ficha-card__note {
    flex: 1 1 auto;
    font-size: .84rem;
    line-height: 1.35;
    color: var(--mud-palette-text-secondary);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: 2.4em;
}

.sis-ficha-card__foot {
    display: flex;
    align-items: center;
    gap: 10px;
    padding-top: 8px;
    border-top: 1px solid var(--mud-palette-table-lines);
}

.sis-ficha-card__items {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: .8rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.sis-ficha-card__items .mud-icon-root {
    font-size: .95rem;
}

.sis-ficha-card__total {
    margin-left: auto;
    font-weight: 700;
    white-space: nowrap;
}

/* Grade de itens da FICHA: rola dentro do próprio card em vez de estourar por cima dele.

   🔴 Flagrado na captura de 1024×768 (tema escuro), e só nela: a 1600px a tabela cabe. Com o card de itens
   em md=8 sobram ~500px para SEIS colunas, e a última ("Ações") saía da superfície — os botões ficavam
   pendurados fora do card, cortados. É o defeito clássico que build e bUnit não veem.

   ⚠️ Rolagem no CONTÊINER, não `table-layout: fixed` nem coluna escondida: esconder a coluna de ações
   tiraria remover/desconto/quantidade justamente do terminal mais apertado, que é onde o balcão opera. */
.sis-ficha-itens {
    overflow-x: auto;
}

/* Densidade ANTES de estrutura (ordem de sacrifício do catálogo de design): o que estourava a largura era o
   dinheiro QUEBRANDO em duas linhas ("R$" numa, "18,90" noutra) e o respiro das células. Com nowrap nos
   números e a célula mais justa, as seis colunas cabem em ~500px sem empilhar a coluna dos totais — que
   custaria ALTURA, e num terminal de balcão é a altura que falta, não a largura. */
.sis-ficha-itens td,
.sis-ficha-itens th {
    padding-left: 8px;
    padding-right: 8px;
    white-space: nowrap;
}

/* A DESCRIÇÃO é a única que pode quebrar — e deve: é ela que absorve a sobra e mantém o resto legível. */
.sis-ficha-itens td:first-child {
    white-space: normal;
    min-width: 120px;
}

/* Observação na CONSULTA de pré-vendas: uma linha, com reticências.

   ⚠️ Ela é texto livre de balcão ("Levar até o carro — item pesado. Cliente aguarda no estacionamento.") e,
   quebrando, empurrava as colunas da direita para fora da tela em 1024px — uma linha de grade com 4 alturas
   de texto e a situação inalcançável. Quem precisa do recado inteiro abre a ficha; a grade existe para
   ACHAR.

   ⛔ Não é remendo no SisDataGrid: a classe é da COLUNA desta tela. O corte de colunas do grid em 1024 é
   característica compartilhada (a Consulta de Orçamentos tem o mesmo), e mexer nele é decisão de outra
   fatia — o que se resolve aqui é a pressão que ESTA tela acrescentava. */
.sis-pre-venda-observacao {
    max-width: 260px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Tela de configuração do logotipo (/config/logotipo). */
.sis-logotipo-preview {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 260px;
    height: 140px;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 12px;
    padding: 12px;
}

.sis-logotipo-preview img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}

/* Prévia da imagem de FUNDO: mais larga (proporção perto da tela do terminal), não quadrada como o logo. */
.sis-logotipo-preview--fundo {
    width: 360px;
    height: 180px;
}

/* ACERTAR (consignação): cor de SUCESSO — é o lançamento que conclui a linha, o gesto que se repete numa
   consignação aberta. Verde, e não primária, para distinguir à primeira vista do "alterar quantidade"
   (primária) que fica ao lado e reescreve a ENTREGA em vez de registrar o que voltou. */
.sis-row-action-settle.mud-icon-button {
    color: var(--mud-palette-success);
}
.sis-row-action-settle.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-success-rgb), 0.12);
    border-color: var(--mud-palette-success);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-success-rgb), 0.28);
}

/* DESLIGAR (a pessoa saiu da empresa): cor de AVISO, a mesma família de cancelar e estornar — encerra o
   vínculo preservando o cadastro. ⛔ Não é vermelho de propósito: vermelho é excluir, que fica ao lado, e
   duas ações vermelhas vizinhas com consequências diferentes (uma preserva o histórico do que a pessoa
   lançou, a outra tira o registro de circulação) se distinguiriam só pelo tooltip. */
.sis-row-action-offboard.mud-icon-button {
    color: var(--mud-palette-warning);
}
.sis-row-action-offboard.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-warning-rgb), 0.12);
    border-color: var(--mud-palette-warning);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-warning-rgb), 0.28);
}

/* REINTEGRAR: cor de SUCESSO, como "eleger como padrão" — é restauração, a única ação que devolve algo. Ela
   nunca aparece na mesma linha que "desligar" (uma é para a conta vigente, a outra para a desligada), então
   verde e amarelo não competem: eles se ALTERNAM, e é isso que faz o estado da linha legível de longe. */
.sis-row-action-reinstate.mud-icon-button {
    color: var(--mud-palette-success);
}
.sis-row-action-reinstate.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-success-rgb), 0.12);
    border-color: var(--mud-palette-success);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-success-rgb), 0.28);
}

/* EMPRESAS DO USUÁRIO (vínculo usuário × empresas): cor de INFO, como imprimir — é gestão de alcance, nem
   correção nem remoção, e as famílias de aviso/erro dos vizinhos ficam livres para os gestos que encerram. */
.sis-row-action-companies.mud-icon-button {
    color: var(--mud-palette-info);
}
.sis-row-action-companies.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-info-rgb), 0.12);
    border-color: var(--mud-palette-info);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-info-rgb), 0.28);
}

/* VERIFICAÇÃO EM DUAS ETAPAS (segundo fator do usuário): cor PRIMÁRIA — é configuração de credencial, gesto
   de segurança e não de correção/remoção; info já pertence ao vizinho "empresas" na MESMA linha, e dois
   ícones adjacentes da mesma cor se leem como um só. */
/* HISTÓRICO DO CLIENTE (ação de linha da consulta de Pessoas): cor INFO — leitura pura, o mesmo degrau do
   "ver detalhe". ⛔ Não primary: ela fica colada em "Editar" (primary), e duas caixas primárias vizinhas se
   leem como um botão só, que é justamente o que a posição colada existe para evitar. ⛔ Nem error/warning:
   abrir um painel não muda nada. Só a COR; a caixa vem da .sis-row-action, comum a todas.

   ⚠️ A classe é PRÓPRIA e não reusa a `-view` (que tem a mesma cor) pela regra do
   SeletorDeTesteConventionTests: a `-view` é usada por botões escritos à mão em MdfePage/BoletoPage/
   ImportRunsPage, e aplicá-la aqui tornaria ambíguo o seletor de quem procura a ação do SisRowActions. */
.sis-row-action-history.mud-icon-button {
    color: var(--mud-palette-info);
}
.sis-row-action-history.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-info-rgb), 0.12);
    border-color: var(--mud-palette-info);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-info-rgb), 0.28);
}

.sis-row-action-twofactor.mud-icon-button {
    color: var(--mud-palette-primary);
}
.sis-row-action-twofactor.mud-icon-button:hover:not(.mud-disabled) {
    background-color: rgba(var(--mud-palette-primary-rgb), 0.12);
    border-color: var(--mud-palette-primary);
    box-shadow: 0 1px 3px rgba(var(--mud-palette-primary-rgb), 0.28);
}

/* O QR do cadastro do segundo fator. ⚠️ Exceção DECLARADA à regra "zero hexadecimal": QR é artefato de
   leitura ÓPTICA — a câmera espera módulos escuros sobre fundo claro, e um QR que acompanhasse o tema escuro
   (claro sobre escuro) é recusado por vários autenticadores. O cartão branco é parte do formato, como numa
   nota fiscal impressa. */
.sis-twofactor-qr {
    background: #ffffff;
    border-radius: 8px;
    padding: 12px;
    width: 216px;
    height: 216px;
    margin-inline: auto;
}
.sis-twofactor-qr svg {
    width: 100%;
    height: 100%;
    display: block;
}

/* A chave manual (Base32) — monoespaçada e quebrável, para conferir com o aparelho na mão. */
.sis-twofactor-key {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    letter-spacing: 0.08em;
    word-break: break-all;
    text-align: center;
    color: var(--mud-palette-text-primary);
    background: rgba(var(--mud-palette-primary-rgb), 0.08);
    border-radius: 6px;
    padding: 6px 10px;
}

/* A quantidade AINDA EM PODER DO CLIENTE, na grade da consignação. É a pergunta da operação — "o que está na
   rua?" —, e um número igual aos outros na mesma linha se perde entre eles. Cor de aviso, e não vermelho:
   mercadoria pendente é o estado NORMAL de uma consignação aberta, não um erro. */
.sis-consignacao-pendente {
    color: var(--mud-palette-warning);
    font-weight: 600;
}

/* Prazo VENCIDO na consulta de consignações. Vermelho, e não âmbar como a quantidade pendente: pendente é o
   estado normal de uma consignação aberta; passar do prazo combinado não é. Mesma distinção da previsão
   atrasada na consulta de O.S. */
.sis-consignacao-atrasada {
    color: var(--mud-palette-error);
    font-weight: 600;
}

/* O preço unitário DENTRO da descrição, na grade da consignação. Ele saiu da coluna própria porque as oito
   colunas (três quantidades + preço + a cobrar + ações) empurravam a coluna de Ações para fora do card em
   1024×768 — densidade antes de estrutura, na ordem do catálogo de design. Como caption, ele continua
   conferível e não disputa largura com o que muda a cada acerto. */
.sis-consignacao-preco {
    display: block;
    font-size: .78rem;
    color: var(--mud-palette-text-secondary);
}

/* A grade da consignação tem SETE colunas (três quantidades) contra seis da ficha, e o respiro do MudBlazor
   não cabe: MEDIDO em 1024×768, a tabela ocupava 725px num card de 686px e a coluna de Ações saía fora — o
   operador perdia acertar/remover no terminal mais apertado, que é onde o balcão opera.

   🔴 <b>É ESPECIFICIDADE, não presença.</b> Duas tentativas passaram batido antes de a causa ser medida: a
   classe estava no wrapper, a regra estava no arquivo servido, e o padding computado continuava 16px. Quem
   ganha é `.mud-table-dense * .mud-table-row .mud-table-cell` do MudBlazor — QUATRO classes (0,4,0), com
   `padding: 6px 24px 6px 16px`. Uma regra de duas classes perde em silêncio, e a única pista é a largura que
   não muda um pixel. Daí o seletor longo abaixo: ele precisa empatar ou vencer aquele.
   ⚠️ E os 24px à DIREITA são metade do problema — o respiro é assimétrico, e um `padding-left` sozinho não
   devolveria nada. */
.sis-consignacao-itens .mud-table-dense .mud-table-row td.mud-table-cell,
.sis-consignacao-itens .mud-table-dense .mud-table-row th.mud-table-cell,
.sis-consignacao-itens .mud-table-dense th.mud-table-cell {
    padding-left: 8px;
    padding-right: 8px;
}

/* A descrição absorve a sobra, mas com TETO: sem ele ela estica e volta a empurrar as ações para fora. */
.sis-consignacao-itens .mud-table-dense .mud-table-row td.mud-table-cell:first-child {
    max-width: 190px;
}

/* ============================================================================
   Designer de etiqueta (.sis-label-designer) — fase 5 do épico da etiqueta.
   O CHROME (palco, seleção, alça) segue o tema por variável; a SUPERFÍCIE da
   etiqueta é PAPEL — branco e preto literais DE PROPÓSITO, como um PDF: ela
   representa o objeto físico impresso e não pode escurecer junto com o tema.
   ========================================================================== */

.sis-label-designer__stage {
    overflow: auto;
    padding: 24px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius);
    background: var(--mud-palette-background-gray);
    /* O gesto é pointer em C#: sem isto o browser "arrasta a seleção" junto. */
    user-select: none;
    touch-action: none;
    min-height: 260px;
}

.sis-label-designer__canvas {
    position: relative;
    /* Papel: branco literal de propósito (ver cabeçalho do bloco). */
    background-color: #fff;
    color: #111;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .25);
    /* Grade de 5 mm (o passo vem do zoom via --sis-label-grid) — régua visual, não imprime. */
    background-image:
        linear-gradient(to right, rgba(0, 0, 0, .06) 1px, transparent 1px),
        linear-gradient(to bottom, rgba(0, 0, 0, .06) 1px, transparent 1px);
    background-size: var(--sis-label-grid, 40px) var(--sis-label-grid, 40px);
}

.sis-label-el {
    position: absolute;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: center;
    overflow: hidden;
    cursor: grab;
    border: 1px dashed transparent;
}

.sis-label-el:hover {
    border-color: rgba(var(--mud-palette-primary-rgb), .55);
}

.sis-label-el--selected {
    border: 2px solid var(--mud-palette-primary);
    cursor: grabbing;
}

.sis-label-el__texto {
    line-height: 1.1;
    white-space: pre-wrap;
    word-break: break-word;
}

/* Código de barras estilizado (listras) — representação de design, não a simbologia real. */
.sis-label-el__barcode {
    flex: 1 1 auto;
    min-height: 6px;
    background: repeating-linear-gradient(to right, #111 0 2px, transparent 2px 5px);
}

.sis-label-el__barcode-data {
    font-size: 9px;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
}

.sis-label-el__resize {
    position: absolute;
    right: -6px;
    bottom: -6px;
    width: 12px;
    height: 12px;
    border-radius: 3px;
    background: var(--mud-palette-primary);
    border: 2px solid var(--mud-palette-surface);
    cursor: nwse-resize;
}

/* ============================================================================
   PORTAL DO CONTADOR — o card de cliente do seletor (Shell/Accountant/).
   <button> de verdade (foco por teclado, papel de botão), coluna explícita por
   causa da pegadinha do Chrome com a caixa de conteúdo de <button>. Cores só
   por variável do tema — acompanha claro/escuro sem regra por modo.
   ========================================================================== */
.sis-accountant-client-card {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
    width: 100%;
    padding: 18px 16px;
    text-align: left;
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    border-left: 6px solid var(--mud-palette-primary);
    border-radius: var(--mud-default-borderradius);
    cursor: pointer;
    transition: background-color .12s ease;
}

.sis-accountant-client-card:hover:not(:disabled),
.sis-accountant-client-card:focus-visible {
    background: rgba(var(--mud-palette-primary-rgb), .08);
}

.sis-accountant-client-card:disabled {
    opacity: .6;
    cursor: default;
}

.sis-accountant-client-card__name {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.sis-accountant-client-card__meta {
    font-size: .8rem;
    color: var(--mud-palette-text-secondary);
}

/* ── Monitor de Pedidos: aviso visual de CHEGADA ─────────────────────────────────────────────────────────
   O cartão do pedido que chegou com a tela aberta pulsa até o operador abri-lo (dar ciência). A cor vem do
   token do tema (info) — funciona nos dois temas; o halo usa color-mix para não cravar rgba de um tema só. */
.sis-channel-card-new {
  border-color: var(--mud-palette-info) !important;
  animation: sis-channel-card-pulse 1.4s ease-in-out infinite;
}

@keyframes sis-channel-card-pulse {
  0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--mud-palette-info) 55%, transparent); }
  50% { box-shadow: 0 0 0 8px color-mix(in srgb, var(--mud-palette-info) 0%, transparent); }
}

/* ── HISTÓRICO DO CLIENTE (diálogo aberto pelo terceiro botão do SisLookupField) ─────────────────────────
   Toda cor sai de var(--mud-palette-*) — as duas exceções são os tiles, que recebem cor sólida do
   DashboardPalette por parâmetro (tons já medidos contra o texto branco). */

.sis-hist {
    display: flex;
    flex-direction: column;
    gap: 12px;
    min-width: 0;
}

/* Identificação: nome à esquerda, chips à direita, quebrando para baixo quando não couber. `min-width: 0` no
   filho de texto é o que impede razão social longa de empurrar os chips para fora do diálogo. */
.sis-hist-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: 8px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* auto-fit + minmax: 4 tiles no diálogo largo, 2 no quadro de 1024×768, 1 no celular — sem media query, que
   só enxergaria a janela e não a largura que o diálogo realmente recebeu. */
.sis-hist-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 10px;
}

.sis-hist-tile {
    min-width: 0;
}

/* Os dois gráficos da visão geral. minmax(280px, 1fr) empilha antes de o gráfico de colunas ficar ilegível —
   12 colunas com rótulo a 45° precisam de largura, e espremê-las apaga o eixo. */
.sis-hist-charts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 12px;
}

/* Card do tema (surface + borda + raio) — nunca bloco de cor chapada, que é a única coisa que não acompanha
   claro/escuro. */
.sis-hist-card {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background: var(--mud-palette-surface);
    height: 100%;
    min-width: 0;
}

/* Grade dentro do diálogo: teto de altura para a lista longa não empurrar as abas para fora da tela — a
   rolagem fica NA GRADE, não no diálogo inteiro. */
.sis-hist-grid {
    max-height: 320px;
    overflow-y: auto;
}

.sis-hist-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 32px 16px;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 12px;
}

/* Linha de totalização — mesma gramática do .sis-checkout-line do fechamento: rótulo à esquerda, valor à
   direita com margin-left auto e sem quebra. */
.sis-hist-total {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 12px;
    border-radius: 8px;
    background: rgba(var(--mud-palette-primary-rgb), .10);
    font-weight: 600;
    color: var(--mud-palette-text-primary);
    white-space: nowrap;
}

/* O diálogo é alto: prende a altura ao viewport e rola por dentro, senão em 1024×768 o rodapé com o botão de
   importar sai da tela e o operador não alcança a única ação da tela. `dvh` e não `vh` por causa da barra de
   endereço do navegador móvel. */
.sis-hist-dialog .mud-dialog-content {
    max-height: calc(88dvh - 140px);
    overflow-y: auto;
}

/* Prévia da FOTO do produto (aba "Foto" do cadastro). QUADRADA, ao contrário da prévia do logotipo, porque
   é o recorte em que a vitrine pública a exibe — mostrar retangular aqui e quadrada lá faria o lojista
   escolher a foto pelo enquadramento errado. */
.sis-produto-foto-preview {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 240px;
    height: 240px;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 12px;
    padding: 12px;
    text-align: center;
}

.sis-produto-foto-preview img {
    max-width: 100%;
    max-height: 100%;
    object-fit: cover;
    border-radius: 8px;
}

/* A GALERIA de fotos do produto (aba "Foto" do cadastro). auto-fill + minmax para caber 3 no diálogo largo
   e 1 no quadro estreito, sem media query — que só enxergaria a janela, e não a largura que o diálogo
   realmente recebeu. */
.sis-produto-galeria {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
    gap: 12px;
}

.sis-produto-galeria-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    min-width: 0;
}

/* A CAPA se distingue pela borda, não por ordem visual: a grade pode quebrar em qualquer largura, e "a
   primeira" deixa de ser óbvia quando ela cai sozinha numa linha. */
.sis-produto-galeria-item--capa .sis-produto-foto-preview {
    border: 2px solid var(--mud-palette-primary);
    border-style: solid;
}

.sis-produto-galeria .sis-produto-foto-preview {
    width: 100%;
    height: 170px;
}

/* --------------------------------------------------------------------------
   A tela de OPERAÇÃO da ordem de serviço, em ABAS (2026-08-18)
   O dono pediu abas "semelhante ao que o legado fazia", porque a O.S. tem
   seções demais para uma página só — eram cinco blocos empilhados em duas
   colunas, 745 linhas de markup.

   🔑 As abas do DOCUMENTO são PÍLULAS, e não as abas clássicas de slider da
   Gerência. Não é gosto: a operação da O.S. é montada DENTRO de um MudTabPanel
   da OrdemServicoGerenciaPage, então os dois níveis convivem na mesma tela.
   Com a mesma aparência, o operador leria "aba dentro de aba" e perderia qual
   nível responde ao clique; com formas diferentes, a hierarquia se lê sozinha.

   ⚠️ Classe PRÓPRIA, e não `sis-os-gerencia-tabs`: o SeletorDeTesteConventionTests
   proíbe classe de estilo aplicada por mais de um componente ser usada como
   seletor de teste, e o E2E já seleciona por aquela.
   -------------------------------------------------------------------------- */
/* ⚠️ `mud-tabs-tabbar`, e ⛔ NÃO `mud-tabs-toolbar`: o MudBlazor 8 renomeou a barra, e a classe antiga não
   existe no DOM. Escrito errado, o seletor simplesmente não casa e as pílulas nunca aparecem — sem erro de
   CSS, sem aviso, e a tela sai com as abas padrão. Medido em 2026-08-18, contra o markup renderizado. */
.sis-os-doc-tabs .mud-tabs-tabbar {
    /* A barra some: quem desenha o contorno são as próprias pílulas. */
    background: transparent;
    min-height: unset;
}

/* 🔑 O TRILHO (2026-08-18, segunda passada — dono: *"os botões estão feios e grudados, vamos deixar mais
   elegante e moderno"*). As pílulas viviam soltas sobre o fundo da página, separadas por 8px: lidas juntas,
   pareciam botões colados; lidas isoladas, não pareciam um grupo. A faixa levemente destacada em volta é o
   que resolve as duas coisas de uma vez — ela agrupa (o olho vê UM controle, não cinco botões) e permite
   ENCOSTAR as pílulas sem que elas se confundam, porque o trilho passou a ser o separador.

   É o padrão de "segmented control": o mesmo idioma dos seletores de período do iOS e do Material 3.

   ⚠️ `width: fit-content`: sem isto o trilho ocupa a LARGURA DA TELA e vira uma barra cinza atravessada,
   com as pílulas amontoadas à esquerda — o oposto do que ele existe para fazer.

   🩸 A cor vem de `color-mix` sobre o TEXTO primário, e ⛔ não de um token de superfície. Medido na captura
   (2026-08-18): com `--mud-palette-action-default-hover` o trilho aparecia no tema ESCURO e **sumia no
   CLARO** — ali ele é quase transparente sobre fundo branco —, e sem trilho as pílulas voltavam a parecer
   soltas, que é o defeito que ele existe para corrigir, visível em um tema só. Misturar com o texto é
   mode-aware **por construção**: o texto é escuro no claro e claro no escuro, então a mesma regra rende um
   cinza sutil nos dois. É a lição do `--mud-palette-gray-light` (CLAUDE.md) aplicada antes de doer. */
.sis-os-doc-tabs .mud-tabs-tabbar-inner {
    padding: 5px;
    width: fit-content;
    max-width: 100%;
    border-radius: 999px;
    background-color: color-mix(in srgb, var(--mud-palette-text-primary) 7%, transparent);
    border: 1px solid color-mix(in srgb, var(--mud-palette-text-primary) 9%, transparent);
}


.sis-os-doc-tabs .mud-tab {
    text-transform: none;
    font-weight: 600;
    font-size: .875rem;
    /* Dentro do trilho a pílula pode ser mais baixa: quem dá a área de toque é o padding do trilho. */
    min-height: 36px;
    /* 🩸 Duas coisas dão à aba do MudBlazor uma largura FIXA de 160px, e as duas precisam cair para a pílula
       ter o tamanho do rótulo dela (medido em 2026-08-18: cinco pílulas de 160px = 815px, e "Imagens" ficava
       fora da barra em 1024×768, atrás de uma seta de rolagem que ninguém percebe que existe):
         1. o CSS `.mud-tab { width: 100%; flex-shrink: 0 }` — a aba PEDE a barra inteira e se recusa a
            encolher; some com `width: auto` + `flex: 0 0 auto`, que é o que está aqui;
         2. o parâmetro `MinimumTabWidth` do `MudTabs`, default `160px`, aplicado como ESTILO INLINE em cada
            aba — ⛔ CSS nenhum o alcança, e quem o desliga é o markup (`MinimumTabWidth="0px"`).
       ⚠️ Consertar só uma delas não muda NADA na tela: foi assim que `min-width: unset` passou por correção
       e mediu-se exatamente o mesmo 160px depois. */
    width: auto;
    flex: 0 0 auto;
    padding: 0 18px;
    border-radius: 999px;
    /* ⛔ SEM borda: dentro do trilho ela vira ruído — cinco contornos empilhados num contorno maior é
       exatamente o "grudado" que o dono apontou. Quem separa as pílulas é o trilho. */
    border: none;
    /* 🩸 O VÃO entre as pílulas é MARGEM, ⛔ nunca `gap` (2026-08-27), e as duas razões são independentes.
       ① O `gap` estava declarado no `.mud-tabs-tabbar-inner`, e as pílulas são filhas do
          `.mud-tabs-tabbar-wrapper` — a regra era INERTE desde 18/08, sem erro de CSS nem aviso. O próprio
          doc do `ReguaDeAbas` já dizia que "vãos todos em zero denunciam a regra no seletor errado", e eles
          estavam em zero. Medido na ordem de produção: as três pílulas encostadas somavam exatamente a
          largura interna do trilho (83+156+134 = 373 = wrapper), "Matérias-primas" ficava com o texto colado
          na borda e o cabeçalho inteiro se lia como "curto demais para caber os três itens" — o relato do
          dono.
       ② E mudar o `gap` para o wrapper CONSERTA o vão e QUEBRA outra coisa: o MudTabs decide mostrar as
          setas de rolagem comparando a soma das abas com a largura da barra, e num trilho `fit-content`
          essas duas medidas se alimentam uma da outra — com `gap` a comparação empata e ele desenha
          DUAS SETAS onde não há transbordo nenhum (medido em 1024×768: `sw == cw` em todos os níveis, e
          ainda assim `setas 2`). A margem separa igual e fica FORA do `getBoundingClientRect` das abas que
          ele soma, então a conta dele não muda.
       ⚠️ Nas pontas ela soma ao padding do trilho, o que é o respiro que faltava justamente ali.
       Portão: ReguaDeAbas.AfirmarPilulasSeparadas + AfirmarSemSetasDeRolagem, juntos. */
    margin: 0 3px;
    opacity: 1;
    color: var(--mud-palette-text-secondary);
    transition: background-color .18s ease, color .18s ease, box-shadow .18s ease;
}

/* O hover só existe na INATIVA: na ativa ele clarearia o preenchimento e faria o botão "piscar" ao passar
   o mouse sobre a aba em que já se está. */
.sis-os-doc-tabs .mud-tab:hover:not(.mud-tab-active) {
    background-color: var(--mud-palette-action-default-hover);
    color: var(--mud-palette-text-primary);
}

/* A ATIVA é preenchida — a única marca que sobrevive a qualquer largura e aos
   dois temas. A sombra é o que a levanta do trilho: sem ela, preenchimento sobre
   fundo levemente destacado lê-se como "campo selecionado", não como aba ativa.
   O slider do MudBlazor é escondido logo abaixo: com a pílula preenchida ele
   viraria um traço solto sob um botão arredondado. */
.sis-os-doc-tabs .mud-tab.mud-tab-active {
    background-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    box-shadow: 0 1px 3px rgba(0, 0, 0, .24);
}

.sis-os-doc-tabs .mud-tab-slider {
    display: none;
}

.sis-os-doc-tabs .mud-tabs-panels {
    padding-top: 16px;
}

/* Em tela estreita as pílulas apertam um pouco, em vez de a barra virar
   rolagem horizontal. Ver o `MinimumTabWidth` no markup: sem ele nem isto
   bastaria. */
@media (max-width: 1280px) {
    .sis-os-doc-tabs .mud-tabs-tabbar-inner {
        padding: 4px;
    }

    .sis-os-doc-tabs .mud-tab {
        padding: 0 12px;
        font-size: .82rem;
        min-height: 34px;
        margin: 0 2px;
    }

    .sis-os-tab-contador {
        min-width: 18px;
        height: 18px;
        padding: 0 4px;
        margin-left: 6px;
    }
}

/* Contador dentro da pílula ("Peças e serviços · 4"). Herda a cor do texto da
   aba, então funciona preenchida e vazia sem uma segunda regra por estado. */
.sis-os-tab-contador {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    margin-left: 8px;
    border-radius: 999px;
    background-color: color-mix(in srgb, currentColor 18%, transparent);
    font-size: .72rem;
    font-weight: 700;
    line-height: 1;
}

/* --------------------------------------------------------------------------
   A BARRA DE AÇÕES da operação — totais + ciclo, sempre visível.
   ⚠️ Compartilhada: nasceu na O.S. e o ATENDIMENTO a reusa desde 2026-08-29,
   quando ele também virou abas. Classe de design system, não propriedade de
   uma tela — quem dá identidade a cada uma é o `data-testid` (`os-acoes` ×
   `atendimento-acoes`), ⛔ nunca esta classe.
   🔒 Ela fica FORA das abas de propósito: totais dentro de aba obrigariam o
   operador a trocar de aba para saber quanto está cobrando, e a faturar às
   cegas. É o mesmo princípio do rodapé do PDV.
   -------------------------------------------------------------------------- */
.sis-os-acoes {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px;
    padding: 12px 16px;
    margin-top: 16px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background-color: var(--mud-palette-surface);
}

/* Os números à esquerda, os botões à direita — e em tela estreita a linha
   quebra sem que nada saia da caixa. */
.sis-os-acoes-totais {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 20px;
    flex: 1 1 320px;
    min-width: 0;
}

.sis-os-acoes-botoes {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-left: auto;
}

.sis-os-acoes-valor {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}

.sis-os-acoes-valor__rotulo {
    font-size: .75rem;
    opacity: .75;
}

.sis-os-acoes-valor__numero {
    font-weight: 600;
    white-space: nowrap;
}

/* O TOTAL é o número que o operador procura — maior e na cor do tema. */
.sis-os-acoes-valor--total .sis-os-acoes-valor__numero {
    font-size: 1.35rem;
    font-weight: 700;
    color: var(--mud-palette-primary);
}

/* --------------------------------------------------------------------------
   A separação PEÇA × SERVIÇO na aba de lançamentos (pedido do dono).
   ⚠️ Também compartilhada com o ATENDIMENTO (2026-08-29), onde os dois grupos
   são "Serviços" e "Produtos" — e o de SERVIÇOS vem primeiro, porque no salão
   é ele o grupo cheio.
   Duas listas com subtotal próprio, no lugar de uma lista única distinguida
   só por ícone. ⚠️ Os subtotais vêm do AGREGADO (TotalProdutos/TotalServicos)
   — a tela nunca soma.
   -------------------------------------------------------------------------- */
.sis-os-grupo {
    margin-bottom: 16px;
}

.sis-os-grupo:last-child {
    margin-bottom: 0;
}

.sis-os-grupo-cabecalho {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    border-radius: 8px;
    background-color: var(--mud-palette-background-gray);
}

.sis-os-grupo-cabecalho__titulo {
    font-weight: 600;
    flex: 1 1 auto;
    min-width: 0;
}

.sis-os-grupo-cabecalho__subtotal {
    font-weight: 700;
    white-space: nowrap;
}

/* Estado vazio de UM grupo — diz a razão, não só "nada aqui". */
.sis-os-grupo-vazio {
    padding: 12px;
    opacity: .75;
    font-size: .875rem;
}

/* --------------------------------------------------------------------------
   A GALERIA de fotos da ordem (aba "Imagens"). Mesma receita da galeria do
   cadastro de produto — auto-fill + minmax para caber 4 na tela larga e 1 na
   estreita, sem media query, que só enxergaria a janela e não a largura que a
   aba recebeu.
   -------------------------------------------------------------------------- */
.sis-os-galeria {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 12px;
}

.sis-os-galeria-item {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.sis-os-foto-preview {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 170px;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 12px;
    padding: 8px;
    text-align: center;
    overflow: hidden;
}

.sis-os-foto-preview img {
    max-width: 100%;
    max-height: 100%;
    object-fit: cover;
    border-radius: 8px;
}

/* A PRIMEIRA se distingue pela borda, não por posição: a grade quebra em
   qualquer largura, e "a primeira" deixa de ser óbvia quando ela cai sozinha
   numa linha. */
.sis-os-galeria-item--primeira .sis-os-foto-preview {
    border: 2px solid var(--mud-palette-primary);
    border-style: solid;
}

.sis-os-galeria-acoes {
    display: flex;
    align-items: center;
    gap: 2px;
}

/* ── Prévia da bobina (Cabeçalho e rodapé do cupom) ───────────────────────────────────────────────
   O papel é monoespaçado por NECESSIDADE, não por estética: a prévia mostra onde o texto quebra em 40
   colunas, e com fonte proporcional as colunas não alinham — a prévia passaria a mentir sobre o que cabe. */
.sis-cupom-previa {
    border: 1px solid var(--mud-palette-lines-default);
    background: var(--mud-palette-background-grey);
}

.sis-cupom-previa__papel {
    margin: 0;
    font-family: "Cascadia Mono", "Consolas", "DejaVu Sans Mono", monospace;
    font-size: 0.78rem;
    line-height: 1.35;
    /* pre-wrap, e não pre: a prévia já quebra as linhas no C# — o wrap é a rede para a coluna estreita do
       celular, onde rolagem horizontal dentro de um card seria pior que dobrar. */
    white-space: pre-wrap;
    color: var(--mud-palette-text-primary);
}

/* ── Catálogo de produtos: o grupo de variação física ─────────────────────────────────────────────
   A variação é uma LINHA da grade, com as MESMAS colunas da base (decisão do dono, 2026-08-24:
   agrupamento por coluna, não painel expansível). O preço disso é que, sem marca nenhuma, a linha da
   variação fica indistinguível de um produto solto — as regras abaixo são o que dá o bloco.

   ⚠️ Fundo tingido a ~3% do texto primário, e ⛔ não uma cor nova: as duas variáveis já invertem com o
   tema, então a mesma regra serve claro e escuro sem uma segunda definição. É o mesmo gesto do
   .sis-row-detail, um degrau mais leve — aqui ele se repete por linha, e o degrau do painel deixaria a
   grade listrada. */
.sis-produto-linha-variacao {
    background-color: color-mix(in srgb, var(--mud-palette-text-primary) 3%, var(--mud-palette-surface));
}

/* O título do grupo: a base é o cabeçalho do bloco, e é ela que o olho procura ao percorrer a lista.
   ⛔ Peso 600, não 700: a linha continua sendo um produto como os outros — negrito cheio a leria como
   cabeçalho de tabela.

   ⚠️ O nowrap é MEDIDO, não estética: com o chevron e o chip de contagem na mesma célula, "Camiseta
   básica" quebrava em duas linhas enquanto as variações — que têm nome MAIOR — cabiam numa só. Quebrando,
   o chip desce para a linha de baixo (o container é flex-wrap), o que é legível; a descrição partida no
   meio não é. */
.sis-produto-grupo-titulo {
    font-weight: 600;
    white-space: nowrap;
}

/* A marca de filiação da variação. Ela ocupa o lugar do chevron da base — é isso que ALINHA a descrição
   da variação com a da base em vez de deixá-la 40px à esquerda —, e desenha o cotovelo que liga uma à
   outra. Puro CSS, sem caractere de texto: "└" entraria no textContent e apareceria em toda asserção de
   markup e em toda cópia de tela. */
.sis-produto-variacao-marca {
    display: inline-block;
    flex: 0 0 auto;
    width: 26px;
    height: 11px;
    /* A margem inferior é o que faz o cotovelo TERMINAR na altura do texto: sem ela o traço horizontal
       cruza o meio da descrição em vez de passar por baixo dela. */
    margin: 0 6px 7px 6px;
    border-left: 1px solid var(--mud-palette-lines-default);
    border-bottom: 1px solid var(--mud-palette-lines-default);
    border-bottom-left-radius: 4px;
}
.sis-document-tabs {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 14px;
    padding: 5px;
    overflow-x: auto;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 14px;
    background: color-mix(in srgb, var(--mud-palette-surface) 92%, var(--mud-palette-primary) 8%);
    scrollbar-width: thin;
}

.sis-document-tab {
    display: inline-flex;
    flex: 1 0 max-content;
    align-items: center;
    justify-content: center;
    min-height: 42px;
    gap: 8px;
    padding: 8px 14px;
    border: 1px solid transparent;
    border-radius: 10px;
    color: var(--mud-palette-text-secondary);
    background: transparent;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    transition: background-color 140ms ease, border-color 140ms ease, color 140ms ease, box-shadow 140ms ease;
}

.sis-document-tab:hover:not(:disabled) {
    color: var(--mud-palette-text-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, transparent);
}

.sis-document-tab:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.sis-document-tab--active {
    color: var(--mud-palette-primary);
    border-color: color-mix(in srgb, var(--mud-palette-primary) 24%, var(--mud-palette-lines-default));
    background: var(--mud-palette-surface);
    box-shadow: 0 3px 10px color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
}

.sis-document-tab__count {
    min-width: 22px;
    padding: 1px 7px;
    border-radius: 999px;
    color: inherit;
    background: color-mix(in srgb, currentColor 10%, transparent);
    font-size: .75rem;
    text-align: center;
}

.sis-document-panel[hidden] {
    display: none !important;
}

.sis-document-summary {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 16px;
    padding: 12px 16px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background-color: var(--mud-palette-surface);
}

.sis-document-summary__values {
    display: flex;
    flex: 1 1 520px;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 12px 20px;
    min-width: 0;
}

.sis-document-summary__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-left: auto;
}

.sis-document-summary__value {
    display: flex;
    flex-direction: column;
    line-height: 1.25;
}

.sis-document-summary__label {
    color: var(--mud-palette-text-secondary);
    font-size: .75rem;
}

.sis-document-summary__number {
    font-weight: 600;
    white-space: nowrap;
}

.sis-document-summary__number--action {
    display: flex;
    align-items: center;
    gap: 2px;
}

.sis-document-summary__number--action .mud-icon-button {
    margin: -8px -8px -8px 0;
}

.sis-document-summary__value--total .sis-document-summary__number {
    color: var(--mud-palette-primary);
    font-size: 1.35rem;
    font-weight: 700;
}

.sis-payment-grid__group {
    display: contents;
}

.sis-checkout-embedded__body {
    padding: 0;
}

.sis-payment-card--selected {
    border-color: var(--mud-palette-primary) !important;
    background: color-mix(in srgb, var(--mud-palette-primary) 10%, var(--mud-palette-surface)) !important;
    box-shadow: 0 0 0 2px color-mix(in srgb, var(--mud-palette-primary) 16%, transparent);
}

.sis-payment-compose {
    padding: 14px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 28%, var(--mud-palette-lines-default));
    border-radius: 12px;
    background: color-mix(in srgb, var(--mud-palette-primary) 5%, var(--mud-palette-surface));
}

.sis-payment-compose__fields {
    display: grid;
    grid-template-columns: minmax(160px, 1fr) auto;
    align-items: end;
    gap: 10px;
    margin-top: 8px;
}

/* A BARRA DE LANÇAMENTO de item (SisItemEntry), a mesma nos seis documentos do ERP.

   🔑 O número de campos VARIA — dois na venda (quantidade e valor), três na ordem de produção (mais o preço
   de venda) — e por isso as colunas do meio são geradas por `repeat()` a partir de `--sis-item-entry-campos`,
   que o componente escreve inline. Com a grade cravada em cinco colunas, a tela com um campo a mais
   empurraria o total e o botão para fora da linha, e a de um campo a menos deixaria um buraco no lugar dele. */
.sis-item-entry {
    display: grid;
    grid-template-columns:
        minmax(280px, 2.4fr)
        repeat(var(--sis-item-entry-campos, 2), minmax(120px, .8fr))
        minmax(130px, .7fr)
        auto;
    align-items: end;
    gap: 10px;
    padding: 14px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 24%, var(--mud-palette-lines-default));
    border-radius: 14px;
    background: color-mix(in srgb, var(--mud-palette-primary) 4%, var(--mud-palette-surface));
}

.sis-item-entry__product {
    min-width: 0;
}

.sis-item-entry__total {
    display: flex;
    min-height: 48px;
    flex-direction: column;
    justify-content: center;
    padding: 4px 10px;
    border-left: 1px solid var(--mud-palette-lines-default);
}

.sis-item-entry__total span {
    color: var(--mud-palette-text-secondary);
    font-size: .75rem;
}

.sis-item-entry__total strong {
    color: var(--mud-palette-text-primary);
    font-size: 1.05rem;
    white-space: nowrap;
}

/* Largura inteira, abaixo dos campos: a descrição complementar da linha.
   ⚠️ Ela vem DEPOIS do botão no DOM de propósito — num grid, um item `1 / -1` declarado antes ocuparia a
   PRIMEIRA linha e empurraria produto, quantidade e valor para baixo. A ordem do FOCO é conduzida pelo
   componente (produto → descrição → quantidade) e não depende da ordem do DOM. */
.sis-item-entry__footer {
    grid-column: 1 / -1;
}

.sis-sale-items .mud-input-control {
    min-width: 104px;
}

.sis-sale-items .mud-input-slot {
    text-align: right;
}

.sis-sale-items td:first-child {
    min-width: 220px;
}

/* 🩸 A grade de itens CORTAVA à direita em 1024×768 — medido na captura, com a coluna de AÇÕES fora da
   tela: o operador do terminal apertado perdia editar e remover item numa tela de OPERAÇÃO. O defeito é
   ANTERIOR à coluna de unidade (medido nos dois estados, com e sem ela), mas cada coluna nova come mais
   uma, então quem acrescenta a próxima paga a conta.

   ⚠️ A cura é ROLAR, ⛔ não encolher. 🩸 E `min-width: max-content` na tabela foi MEDIDO e RECUSADO: ele
   força a largura natural, e com os campos de dinheiro em 104px a tabela fica tão larga que 1024×768 passa
   a mostrar TRÊS colunas em vez de quatro — trocou "não alcança" por "não vê", que é pior de olhar. Só o
   `overflow-x` fica: a tabela comprime como sempre comprimiu e, quando ainda assim transbordar, rola.

   🔑 Comparar com a consignação: LÁ a resposta foi reduzir para sete colunas, porque a grade tem três
   quantidades e o corte já havia sido medido. As duas respostas são certas para o caso de cada uma — ⛔ o
   que não vale é acrescentar coluna sem olhar 1024×768. */
.sis-sale-items .mud-table-container {
    overflow-x: auto;
}


@media (max-width: 700px) {
    .sis-document-tabs {
        justify-content: flex-start;
    }

    .sis-document-tab {
        flex: 0 0 auto;
    }

    .sis-payment-compose__fields {
        grid-template-columns: 1fr;
    }

    .sis-item-entry {
        grid-template-columns: 1fr 1fr;
    }

    .sis-item-entry__product {
        grid-column: 1 / -1;
    }

    .sis-item-entry__total {
        border-left: 0;
        padding-left: 0;
    }
}

@media (min-width: 701px) and (max-width: 1120px) {
    .sis-item-entry {
        grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    }

    .sis-item-entry__product {
        grid-column: 1 / -1;
    }

    .sis-item-entry__total {
        border-left: 0;
        padding-left: 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .sis-document-tab {
        transition: none;
    }
}

/* ── Reentrada por sessão expirada (SisSessionReauthOverlay) ───────────────────────────────────────────
   A sessão morreu e o operador precisa entrar de novo SEM perder a tela. A camada cobre o app inteiro e
   bloqueia o toque no que está por baixo — que continua montado, e é justamente o que se está preservando.

   z-index 1500: acima de TUDO que a casca pode ter aberto no momento em que a sessão cai — diálogo do
   MudBlazor (1400), teclado numérico (1450), cartão do tour (1392). ⛔ Não baixe: overlay de sessão que
   aparece ATRÁS de um diálogo aberto deixa o operador digitando num formulário que o servidor já recusa,
   que é exatamente o defeito que ele existe para acabar.

   O fundo é opaco o bastante para dizer "isto aqui está parado" e translúcido o bastante para o operador
   reconhecer a tela dele por trás — é o que sustenta a promessa de que nada foi perdido. */
.sis-reauth-overlay {
    position: fixed;
    inset: 0;
    z-index: 1500;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: rgba(0, 0, 0, .55);
    backdrop-filter: blur(2px);
}

.sis-reauth-card {
    width: 100%;
    max-width: 420px;
    max-height: 100%;
    overflow-y: auto;
    border-radius: 12px;
    background: var(--mud-palette-surface);
}

/* --------------------------------------------------------------------------
   O que foi MONTADO na linha — "Cor: Azul · Tamanho: M", embaixo da descrição.

   🔑 A cor vem do token do tema (`--mud-palette-text-secondary`), ⛔ nunca de um cinza cravado: a grade é
   lida nos dois temas, e um cinza fixo some no escuro. O piso de contraste do grid é testado
   (SisThemesTests) e este texto obedece ao mesmo token que a descrição complementar já usa.

   ⚠️ Ele PODE quebrar em várias linhas de propósito: uma camiseta com quatro atributos não cabe numa só, e
   truncar esconderia justamente a opção que o cliente está conferindo.
   -------------------------------------------------------------------------- */
.sis-montagem-linha {
    font-size: 0.78rem;
    line-height: 1.25;
    color: var(--mud-palette-text-secondary);
    margin-top: 2px;
    white-space: normal;
}

/* ── Barra de versão nova esperando a tela ficar limpa (SisAppUpdateWatcher) ───────────────────────────
   Ela só aparece quando HÁ trabalho em andamento — com a tela limpa a troca acontece e não há o que dizer.
   Fica no rodapé, e não no topo: no topo ela empurraria a barra da casca e mexeria no layout de todas as
   telas por causa de um aviso passageiro.

   z-index 1400: acima do conteúdo e do teclado numérico do rodapé, abaixo do overlay de sessão expirada
   (1500) — sessão morta é mais urgente que versão nova, e as duas podem coexistir. */
.sis-update-bar {
    position: fixed;
    left: 50%;
    bottom: 16px;
    transform: translateX(-50%);
    z-index: 1400;
    display: flex;
    align-items: center;
    gap: 12px;
    max-width: calc(100vw - 32px);
    padding: 10px 16px;
    border-radius: 8px;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    box-shadow: 0 4px 16px rgba(0, 0, 0, .28);
    font-size: .9rem;
}

.sis-update-bar span {
    flex: 1 1 auto;
}

/* ⚠️ O rótulo do botão quebrava em duas linhas ("Atualizar / agora") e desalinhava a barra — só a CAPTURA
   mostra isso: markup, bUnit e E2E ficam verdes com o texto partido. */
.sis-update-bar .mud-button-root {
    white-space: nowrap;
    flex: 0 0 auto;
}

/* ── Portão de versão mínima (SisAppVersionGate) ───────────────────────────────────────────────────────
   Cobre o app inteiro: abaixo da versão mínima não há tela que valha a pena mostrar, e deixar o operador
   trabalhar num cliente que o servidor recusa produziria erro em cada gesto, sem dizer a causa.

   z-index 1600: acima do overlay de sessão expirada (1500). A ordem é a da urgência — sessão morta se
   resolve digitando a senha; versão velha demais não se resolve dentro do app. */
.sis-version-gate {
    position: fixed;
    inset: 0;
    z-index: 1600;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: var(--mud-palette-background);
}

.sis-version-gate__card {
    width: 100%;
    max-width: 420px;
    border-radius: 12px;
    background: var(--mud-palette-surface);
}

/* ── ABAS DOS TERMINAIS DE APP: ÍCONE **E** TEXTO nos dois ──────────────────────────────────────────
   🔑 DECISÃO DO DONO (2026-08-29): *"ícone + texto"* também no app de O.S. ⇒ ⛔ **NÃO existe mais regra
   que oculte o rótulo**, e a ausência é a decisão — quem procurar aqui o `clip-path` que escondia o texto
   na O.S. não vai achar, porque ele foi REMOVIDO, não afrouxado.

   🩸 O que a regra removida dizia, e por que ela caiu:

     app de O.S. (5 abas)          nomes LONGOS: 109+137+87+73+81 = 487 → 2 setas, só 2½ abas visíveis
     app de O.S. (5 abas)          nomes CURTOS:  70+68+93+82+89  = 402 → 2 setas, 3½ abas visíveis
     app de Atendimento (3 abas)   nomes CURTOS: cabe, ZERO setas
     barra útil no celular de 390px: 374

   ⇒ com "Geral" e "Itens" no lugar de "Atendimento" e "Peças e serviços", faltam **28px** — e o dono
   escolheu ver o texto e conviver com a seta, em vez de operar cinco ícones sem nome. ⚠️ O custo está
   aceito e é NOMEADO: `Imagens` fica atrás do `›`, e `Laudos` fica meio coberto por ele.

   ⛔ **Não devolva o ocultamento "porque não cabe"** — não caber é o estado conhecido e escolhido. E ⛔ não
   tente ganhar os 28px encurtando mais: o próximo passo inventaria abreviação que a retaguarda não usa
   (quem estoura não são os rótulos que já foram encurtados, são `Checklist`, `Laudos` e `Imagens`, que
   sempre foram curtos).

   ⚠️ O que MUDA no portão: a régua do app de O.S. deixou de exigir ZERO setas e passou a exigir que a
   primeira aba não nasça rolada para fora e que as TRÊS primeiras caibam inteiras. A do Atendimento
   continua exigindo zero — lá cabe.

   🩸 E o ÍCONE tem de continuar DENTRO do `<TabContent>`: o `Icon=` do `MudTabPanel` é IGNORADO quando há
   `TabContent` — ele substitui o conteúdo inteiro da aba. Com o ícone no parâmetro e o rótulo oculto pela
   regra que existia aqui, a barra saía COMPLETAMENTE VAZIA (medido: só o traço da aba ativa), e a régua
   dava verde, porque aba vazia cabe com folga.

   🩸 A âncora `data-tour` mora num `<span class="sis-aba">` que EMBRULHA ícone e rótulo, e ⛔ não no
   rótulo. Isso nasceu do tempo do ocultamento — sobre um elemento de 1×1 recortado, o `highlight` do
   `tutorial.js` (que mede por `getBoundingClientRect`) transformava o destaque num PONTO. Com o texto de
   volta o problema não existiria, mas o embrulho FICA: é ele que o `AbasDosAppsEspelhamOErpTests` recorta
   para extrair o rótulo de cada aba, e é o alvo certo para o dia em que um passo de tour ancorar ali. */

/* O embrulho do conteúdo da aba — e o ALVO do tour (ver acima). `inline-flex` porque ele passou a ser o
   pai do ícone e do rótulo: sem isso os dois deixam de ficar na mesma linha de base nos apps que exibem
   os dois (o Atendimento). */
.sis-app-doc-tabs .mud-tab .sis-aba {
    display: inline-flex;
    align-items: center;
}

/* ── ABAS DE APP: rótulo COMPACTO ────────────────────────────────────────────────────────────────────
   🔴 MEDIDO (2026-08-29): com o rótulo no padrão do MudBlazor, as três abas do app de Atendimento somavam
   154+219+115 = 488 numa barra de 374 — 2 setas e a primeira rolada para -194.

   🔑 O maior ganho é o `text-transform: none`: o MudBlazor põe o rótulo em CAIXA ALTA, e
   "PRODUTOS E SERVIÇOS" é bem mais largo que "Produtos e serviços". ⚠️ Isso também devolve a palavra ao
   vocabulário da retaguarda — a tela do ERP escreve em caixa mista, e a caixa alta era só do componente.

   ⚠️ Vale para os DOIS apps, e desde 2026-08-29 pelos MESMOS dois motivos: os dois exibem o rótulo, e é
   esta regra que faz "Geral · Itens · Checklist · Laudos · Imagens" somar 402px em vez de bem mais. */
.sis-app-doc-tabs .mud-tab {
    text-transform: none;
    font-size: 0.75rem;
    letter-spacing: 0;
    padding: 6px 8px;
    min-width: 0;
}

/* -------------------------------------------------------------------------
   Reordenar as opções de um atributo — a alça de arraste e o realce da linha
   de destino (ProdutoAtributoEditorDialog).

   🩸 O `draggable` mora na ALÇA e não na linha: com a linha inteira arrastável,
   selecionar texto dentro do campo Nome iniciaria o arraste e o operador não
   conseguiria corrigir uma letra. A linha é só o alvo da solta — daí o realce
   de destino ser dela e o de "estou saindo daqui" ser da alça.

   ⚠️ Cor SEMPRE por variável do tema: valor cravado some no tema escuro (a
   linha de destino ficaria realçada em cinza-claro sobre fundo escuro).
   ------------------------------------------------------------------------- */

/* ⚠️ Os nomes eram `sis-opcao-*` e foram neutralizados em 2026-08-30, quando o
   segundo consumidor chegou (o cadastro de campos personalizados da O.S.): a
   receita é de REORDENAR POR ARRASTO, não de "opção de produto", e um nome que
   carrega a origem manda a próxima tela copiar o bloco em vez de reusá-lo. */

.sis-arrasto-celula {
    width: 44px;
    padding-right: 0 !important;
    text-align: center;
    vertical-align: middle;
}

.sis-arrasto-alca {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: var(--mud-default-borderradius, 8px);
    color: var(--mud-palette-text-secondary);
    cursor: grab;
    /* O ícone não é texto a selecionar: sem isto, o duplo clique na alça marca
       o glifo e o arraste começa carregando uma seleção. */
    user-select: none;
    transition: background-color 0.15s ease-out, color 0.15s ease-out;
}

.sis-arrasto-alca:hover,
.sis-arrasto-alca:focus-visible {
    background-color: var(--mud-palette-action-default-hover);
    color: var(--mud-palette-text-primary);
}

/* A alça é foco de teclado (setas ↑ ↓ reordenam) — sem anel visível, quem
   navega por teclado não sabe em qual linha está. */
.sis-arrasto-alca:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 1px;
}

.sis-arrasto-alca:active {
    cursor: grabbing;
}

.sis-arrasto-linha--arrastando {
    opacity: 0.45;
}

/* O "vai cair aqui": uma barra na borda superior da linha de destino, e não um
   fundo inteiro — o fundo competiria com o realce de foco dos campos da linha. */
.sis-arrasto-linha--alvo > td {
    box-shadow: inset 0 2px 0 0 var(--mud-palette-primary);
}
