﻿/* ==========================================================================
   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;
}

/* ── FAVORITOS do menu ────────────────────────────────────────────────────────
   A estrela é IRMÃ do <a> do MudNavLink (ver ShellNavMenu.RenderItem) e fica por
   cima dele por posicionamento absoluto. Assim o clique NÃO borbulha para o link.

   🔴 A visibilidade tem TRÊS condições, e não uma. Uma estrela que só aparecesse
      no :hover seria inacessível: sumiria para quem usa teclado e para quem usa
      toque — e quem já marcou não teria como desmarcar.
        1. :hover da linha              → o gesto de mouse;
        2. :focus-visible da estrela    → quem navega por Tab;
        3. [data-marcado="true"]        → o item já é favorito, então a estrela é
                                          ESTADO e não pode sumir.
      ⚠️ As três continuam valendo, mas o que elas revelam mudou em 2026-09-14 —
      ver o bloco da OPACIDADE, logo abaixo: hoje a estrela aparece a 10%.
   E @media (hover: none) cobre o toque, onde hover não existe. */
.sis-nav-favorito-linha {
    position: relative;
}

/* 🔑 A estrela ocupa a COLUNA DO ÍCONE (dono, 2026-09-14: "já que submenus não têm ícones"), ⛔ não o
   canto direito. O 16px ⛔ não é gosto — é a caixa do ícone do grupo, medida no MudBlazor 8.13:
     cabeçalho de grupo  `padding: 8px 16px`        → o ícone começa em 16px
     ícone do nav        24px                       → ocupa 16 → 40px
     item dentro de grupo `padding-left: 36px` + `margin-left: 12px` do texto → o título começa em 48px
     MudIconButton Small `padding: 3px` + 18px      → 24px, a MESMA largura do ícone do grupo
   ⇒ a estrela cai exatamente sobre a coluna do ícone, com 8px de folga até o título. */
.sis-nav-favorito-linha .sis-nav-favorito-estrela {
    position: absolute;
    left: 16px;
    top: 50%;
    transform: translateY(-50%);
    opacity: 0;
    transition: opacity 120ms ease-in-out;
}

/* 🔒 A estrela é DISCRETA por DECISÃO DO DONO (2026-09-14), e ⛔ não por um contraste que ficou por medir.
   São DOIS valores, e a diferença entre eles é o ESTADO: **10% apagada · 50% marcada**.

   🩸 A medição que levou até aqui, porque ela ⛔ não deve ser refeita: a estrela apagada herda o
   `--mud-palette-action-default` do MudBlazor — cinza #757575, cor pensada para ícone sobre card BRANCO —,
   e sobre o navy desta gaveta isso mede **2,68:1**, contra 8,84:1 do título ao lado. Era, por contraste, o
   elemento mais apagado da gaveta inteira. A correção óbvia foi escrita e MOSTRADA ao dono — branco a 80%,
   âmbar claro, 8,49:1 — e ele **recusou**: *"ficou pior; prefiro cinza escuro de antes a 10%"*.

   🔑 ⇒ **Aqui discrição vence legibilidade, por escolha.** A estrela é um gesto de arrumação que o operador
   faz uma vez, ⛔ não um dado que ele precisa ler — e no menu ela concorre com os títulos, que são o que ele
   veio buscar. ⛔ Não "conserte" estes números por acessibilidade: quem os subir está desfazendo uma
   decisão, ⛔ não corrigindo um descuido. Portão: `A_estrela_e_discreta_por_decisao`.

   ⚠️ **Os dois valores nasceram um do outro:** com 10% nos DOIS estados — o primeiro desenho — a marcada
   ficava indistinguível da apagada, e o grupo Favoritos perdia a marca de que aqueles itens estão lá por
   escolha de alguém. Os 50% da marcada (dono, na mesma conversa) devolvem o estado sem devolver o peso:
   ela fica 5× mais presente que a apagada e ainda a meio caminho do cheio. ⇒ ⛔ não iguale os dois de novo
   "por simetria": a distância entre eles É a informação. */
.sis-nav-favorito-linha:hover .sis-nav-favorito-estrela,
.sis-nav-favorito-linha .sis-nav-favorito-estrela:focus-visible {
    opacity: .1;
}

/* A MARCADA vem depois e vence por ordem — mesma especificidade não fosse o atributo, que já a torna mais
   específica; a ordem aqui é redundância deliberada, ⛔ não descuido. */
.sis-nav-favorito-linha .sis-nav-favorito-estrela[data-marcado="true"] {
    opacity: .5;
}

@media (hover: none) {
    .sis-nav-favorito-linha .sis-nav-favorito-estrela {
        opacity: .1;
    }

    /* ⚠️ O bloco de toque precisa repetir a marcada: sem esta regra o `@media` (que vem depois, com a mesma
       especificidade do bloco base) baixaria a marcada para 10% no celular — e é justamente lá que o hover
       ⛔ não existe para revelá-la. */
    .sis-nav-favorito-linha .sis-nav-favorito-estrela[data-marcado="true"] {
        opacity: .5;
    }
}

/* ⚰️ Aqui havia um `padding-right: 28px` no texto do item, para o título longo não passar por baixo da
   estrela. Ele caiu com a estrela indo para a esquerda (2026-09-14): o título já começa depois dela, e o
   recuo à direita só encurtava o nome sem motivo. ⛔ Não o traga de volta junto com uma estrela à direita
   sem remedir a coluna do ícone acima. */

/* A EMPRESA ATIVA no topo da gaveta. Existe pelo CELULAR: lá a barra superior esconde o seletor
   (`d-none d-sm-flex`), e sem esta linha ninguém sabe em qual CNPJ está lançando. */
.sis-nav-empresa {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 12px 8px;
    color: #fff;
}
.sis-nav-empresa .mud-icon-root {
    opacity: .7;
    flex: 0 0 auto;
}
/* `min-width: 0` é o que permite o nome ENCOLHER dentro do flex — sem ele o texto não corta e empurra a
   largura da gaveta, que é fixa em 280px. Mesma armadilha do cartão de via da tela de impressão. */
.sis-nav-empresa__texto {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.2;
}
.sis-nav-empresa__rotulo {
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    opacity: .6;
}
/* Razão social é longa e o operador precisa reconhecê-la, não lê-la inteira: uma linha com reticências, e
   o nome completo continua no seletor da barra (desktop) e no grupo "Trocar de empresa". */
.sis-nav-empresa__nome {
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* 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;
}
/* O grupo da TELA ATUAL na faixa mini (#3318): sem texto em 68px, é o ícone que diz onde se está. Mesma
   linguagem do item ativo do MudNavLink — fundo leve + barra na borda —, em branco sobre o drawer escuro. */
.sis-nav-mini-icon.sis-nav-mini-icon--atual.mud-icon-button {
    background-color: rgba(255, 255, 255, 0.16);
    color: #fff;
    box-shadow: inset 3px 0 0 #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;
}
/* O item da TELA ATUAL dentro do flyout da faixa mini (#3318) — a mesma marca do ícone do grupo: fundo leve
   + barra na borda, em branco sobre o navy. */
.sis-nav-flyout .mud-menu-item.sis-nav-flyout-item--atual {
    background-color: rgba(255, 255, 255, 0.16);
    color: #fff;
    box-shadow: inset 3px 0 0 #fff;
    font-weight: 600;
}
.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);
}

/* 🔴 O BLOCO DE TEXTO DO CABEÇALHO ENCOLHE — e é o que impede a página inteira de rolar na horizontal.

   🩸 Medido em 2026-09-13 (#2708), no head Mock em 390×844: o bloco nascia `flex-shrink-0`, e item flex que
   não encolhe assume a largura de CONTEÚDO — o subtítulo de UMA linha virava a largura da página. 17 das 20
   telas que estouravam tinham esta causa, de 11px (Forma de pagamento) a 553px (Opções de Venda), e são
   192 as telas que passam `Subtitle=`: as que cabiam estouravam no próximo subtítulo mais longo.

   ⚠️ O estrago não parava na página. Com a página mais larga que o aparelho, o navegador alarga a viewport
   de LAYOUT (medido: `innerWidth` 554 e 943 com `clientWidth` 390), e a `.mud-appbar` — `position: fixed`,
   ancorada nessa viewport — passava a medir 943px: avatar, ajuda e "Sair" saíam pela direita. Em
   /config/vendas sobrava só o hambúrguer. ⇒ conserto de barra ⛔ não resolve estouro de página (a #2298
   consertou a barra e o corpo das telas reabriu o furo).

   🔑 `flex: 0 1 auto` é o default: no DESKTOP nada muda (o bloco continua do tamanho do conteúdo e o
   `MudSpacer` empurra as ações para a direita); o que a linha compra é o direito de ENCOLHER quando não
   couber. `min-width: 0` é o que deixa a caixa ir abaixo do min-content (o default `auto` a travaria na
   palavra mais longa), e `overflow-wrap: break-word` quebra a palavra que não couber sozinha.
   ⛔ Nada de `text-overflow: ellipsis` aqui: o subtítulo é explicação, ⛔ não rótulo — cortá-lo esconde a
   frase que a tela usa para se explicar. Portão: TelasDoErpCabemNoCelularTests (E2E, varredura). */
.sis-page-header-texto {
    min-width: 0;
    flex: 0 1 auto;
    overflow-wrap: break-word;
}

/* 🔴 O CONTEÚDO DO ALERTA ENCOLHE JUNTO COM A CAIXA — a MESMA causa do cabeçalho acima, noutro componente.

   🩸 Medido em 2026-09-13 (#2727), em /fiscal/mdfe a 390×844: a `.mud-alert` media 366px e o `scrollWidth`
   dela era 468 — o aviso de manifestos em aberto na SEFAZ transbordava a própria caixa e empurrava a página.
   O MudBlazor declara `.mud-alert-position { flex: 1; display: flex }`, e item flex nasce com
   `min-width: auto`: ele ⛔ não encolhe abaixo do conteúdo, por mais estreita que a caixa fique.

   🔑 **É regra GLOBAL de propósito, ⛔ não da tela do MDF-e.** Alerta é o componente em que o texto é longo
   por definição — quem escrever o próximo aviso ⛔ não tem como saber que precisa disto, e o defeito é mudo:
   a caixa cabe, o texto vaza, e só a captura em tela estreita mostra.

   🩸 **E a regra nasceu PELA METADE — medido em 2026-09-13, #2739.** Ela parava no `.mud-alert-message`, e
   dentro dele o MDF-e tem um `d-flex` com um `<p>` que carrega a CHAVE DE ACESSO: 44 caracteres sem espaço.
   Esse `<p>` é item flex, nasce com `min-width: auto`, e o min-content dele são os 44 caracteres — **377px
   num pai de 298**. ⚠️ `overflow-wrap: break-word` ⛔ NÃO resolve: ele autoriza a quebra mas ⛔ não reduz o
   tamanho MÍNIMO do conteúdo; quem reduz é **`anywhere`**. ⇒ a cura vale para os DESCENDENTES, ⛔ não só
   para a caixa.

   ⚠️ O resto só apareceu depois que a grade empilhada parou de ser a coisa mais larga da tela (a F1b levou
   a tabela de 473px para 364). 🔑 **Tirar o maior estouro de uma tela REVELA o seguinte** — a medição de
   "quanto falta" só vale depois de cada correção, ⛔ nunca antes. */
.mud-alert .mud-alert-position,
.mud-alert .mud-alert-message,
.mud-alert .mud-alert-message * {
    min-width: 0;
    overflow-wrap: anywhere;
}

/* -------------------------------------------------------------------------
   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;
}

/* -------------------------------------------------------------------------
   A barra de rolagem horizontal do TOPO do grid (ver grid.js,
   acoplarBarraDoTopo; o markup é do SisDataGrid.razor).

   A barra nativa mora no RODAPÉ da área rolável, e numa consulta longa o
   operador precisa descer a página inteira só para deslocar as colunas de
   volta.

   🔑 E por isso ela é PEGAJOSA: a dor da issue é ALCANCE, não posição. Uma
   faixa fixa no topo do grid só ajudaria enquanto o topo estivesse na tela —
   no meio de uma lista longa as DUAS barras ficam fora da vista. Grudada sob
   a app bar, ela segue o operador lista abaixo.

   ⛔ Nasce com altura ZERO e só cresce com transbordo: trilho permanente numa
   grade que cabe na tela é ruído, e é a mesma razão pela qual `overflow-x:
   scroll` já tinha sido recusado no container acima.

   ⚠️ Ela é IRMÃ do grid, fora do `.sis-data-grid.mud-table` — e isso é o que
   permite o sticky sem tocar no `overflow: hidden` do card: `hidden` cria
   contexto de rolagem e prenderia a faixa dentro dele (medido: `top` ia para
   -735px com a página rolada).
   ------------------------------------------------------------------------- */
.sis-grid-scroll-topo {
    position: sticky;
    top: var(--mud-appbar-height, 64px);
    z-index: 3;
    overflow-x: auto;
    overflow-y: hidden;
    height: 0;
    /* Fina e discreta, como manda o tema. ⚠️ Declarar `scrollbar-width` AQUI faz o Chromium ignorar todo
       `::-webkit-scrollbar` deste elemento — é a cicatriz registrada no bloco do `.mud-table-container`
       acima. ⇒ ⛔ não adianta acrescentar um bloco de pseudo-elemento para esta faixa: ele nasce morto.
       Quem responde pela aparência no Chromium é esta linha mais o trilho pintado abaixo. */
    scrollbar-width: thin;
    scrollbar-color: var(--mud-palette-lines-inputs) transparent;
}

.sis-grid-scroll-topo--ativa {
    height: 10px;
    margin-bottom: 2px;

    /* 🩸 O TRILHO é desenhado AQUI, ⛔ não deixado por conta da barra do navegador — medido no Chromium
       (E2E, 2026-09-11): a barra é OVERLAY tanto com `scrollbar-width: thin` quanto com `auto`
       (offsetHeight == clientHeight nos dois), e overlay some quando ninguém está arrastando. Uma faixa
       invisível em repouso derrota o pedido que a originou: ela existe para o operador VER que dá para
       arrastar ali em cima.
       ⚠️ Depender do SO não serve: no Windows do cliente a barra costuma ser clássica e visível, e no
       headless do CI não é — o mesmo CSS entregaria duas experiências.
       ⚠️ A cor sai do TEXTO, ⛔ não de `--mud-palette-lines-default`: medido, aquela é rgb(220 225 232) e a
       55% sobre o card branco dá um trilho que ⛔ não aparece nem na captura. Pelo texto, o mesmo token
       serve aos dois temas.
       ⚠️ E a mistura é com `surface`, ⛔ não com `transparent`: grudada sob a app bar a faixa FLUTUA sobre
       as linhas da grade, e um trilho translúcido deixaria o texto delas atravessar por baixo. */
    background-color: color-mix(in srgb, var(--mud-palette-text-primary) 22%, var(--mud-palette-surface));
    border-radius: 5px;
}

/* O trilho não desenha nada: a largura dele é o que dá à faixa a MESMA extensão rolável da tabela, e é
   isso que faz o polegar ter o tamanho proporcional em vez de percorrer tudo em dois pixels. */
.sis-grid-scroll-topo__trilho {
    height: 1px;
}

/* Dentro de um diálogo quem rola é o conteúdo dele, e ⛔ não há app bar por cima — o offset da casca
   empurraria a faixa para dentro da grade. */
.mud-dialog .sis-grid-scroll-topo {
    top: 0;
}


/* 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. */

/* ────────────────────────────────────────────────────────────────────────────────────────────────────────
   CÉLULA NUMÉRICA e CÉLULA COM CAMPO (2026-09-01)

   🩸 Nasceu de uma captura da revisão de XML de entrada, onde o dono viu os itens "tortos": com dez colunas
   e um campo de busca dentro da última, o dinheiro QUEBRAVA A LINHA — "R$" numa linha e "45,90" na outra —
   e os valores à direita paravam em alturas diferentes, um por linha. Alinhar à direita não basta quando o
   conteúdo pode quebrar: o que o olho percebe é o fim da PRIMEIRA linha, e ele muda de célula para célula.

   ⛔ A regra NÃO é global por `text-align:right` inline: seria adivinhar a intenção pelo estilo. A tela
   declara a classe, e ela diz o que a célula É — número —, não como ela aparece.

   ⚠️ O `nowrap` empurra a largura, e é de propósito: quem rola é o CONTAINER da grade (o
   .mud-table-container já tem overflow local, com as sombras de rolagem logo acima), ⛔ nunca a página.
   É a mesma régua do HorizontalScrollbar da nota fiscal digitada. */
.sis-data-grid .sis-cell-numero {
    white-space: nowrap;
    text-align: right;
}

/* Grade de CONDIÇÕES de pagamento (editor de forma de pagamento).

   🩸 Nasceu de uma captura em 1024×768: com a coluna "Vencimentos (dias)" a grade foi a doze colunas, e o
   `overflow-x:auto` do container NÃO basta — sem uma largura mínima o navegador prefere ESPREMER as células
   a rolar, e os campos numéricos passaram a exibir "(" no lugar de "0,00", com a coluna "Ativo" cortada na
   borda do diálogo.

   ⚠️ O min-width vai no <table>, ⛔ não no container: é o container que rola, e dar-lhe largura mínima
   empurraria o próprio diálogo. */
.sis-condicoes-tabela table {
    min-width: 1320px;
}

/* Célula que hospeda um CAMPO (busca vinculada, numérico inline): o campo é alto e o texto das vizinhas é
   de uma linha só — sem isto, a linha inteira cresce e o texto flutua contra o campo. */
.sis-data-grid .sis-cell-campo,
.sis-data-grid td:has(.sis-lookup-field),
.sis-data-grid td:has(.mud-input-control) {
    vertical-align: middle;
}

/* 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;
}

/* =========================================================================
   NO CELULAR CADA REGISTRO É UM CARTÃO — a grade empilhada CABIA e ⛔ não se LIA
   =========================================================================

   🩸 Medido em 2026-09-13 (#2739), em Pessoas, Vendas e Contas a receber a 390×844: o vão entre dois
   registros consecutivos era **0px**, o `<tr>` ⛔ não tinha borda, margem nem fundo próprio, e a fronteira
   entre dois REGISTROS era a MESMA linha de 1px que separa dois CAMPOS do mesmo registro. Com 265 a 389px
   por registro cabem 2 a 3 por tela, e o que o operador lê é "Ações › Emissão…".

   🔑 **A causa tem DUAS metades, e a segunda é nossa.** O MudBlazor empilha em `.mud-xs-table` desenhando
   CÉLULAS (flex + `::before { content: attr(data-label) }`), e a única fronteira que ele prevê é o
   `border-bottom` da ÚLTIMA célula da linha — ou seja, ele já tentava separar registro de registro. Quem
   apagou a distinção foi a regra do Sis logo acima, que põe `border-bottom` em TODA célula: escrita para o
   modo TABELA (onde "toda célula" é "toda linha", e está certo), ela vira "toda linha de campo" no modo
   empilhado. ⇒ **regra de grade escrita sem olhar o modo empilhado erra por metade**, e o erro é mudo.

   🩸 E o achado ⛔ não veio da medição: veio de uma PERGUNTA do dono. A grade tinha entrado no "já funciona"
   do handoff porque passou na largura e nos alvos de toque. ⇒ **"cabe" ⛔ não é "se lê"** — portão de
   largura fica verde com os registros indistinguíveis, e é por isso que esta fatia ganhou portão PRÓPRIO
   (`GradeEmCartoesNoCelularTests`), que mede o VÃO entre registros.

   ⚠️ O corte é o MESMO do resto da casca (`599.98px`, o `viewport.js`), e em 768/1024 a grade continua
   TABELA — medido. ⛔ Não mexa aqui achando que alcança o terminal de 1024×768.
   📖 docs/handoff-interface-no-celular-2026-09-13.md §3 (D3b) */
@media (max-width: 599.98px) {
    /* A tabela e o corpo viram bloco: sem isto o `<tr>` com `display: block` fica sob um `table-row-group`,
       e o navegador o embrulha numa linha/célula anônima — margem e borda do cartão passam a não valer. */
    .sis-data-grid .mud-table-root,
    .sis-data-grid .mud-table-body {
        display: block;
    }

    /* ⛔ O `border-top` do corpo (do MudBlazor) some: com cartões ele vira um traço solto acima do primeiro. */
    .sis-data-grid .mud-table-body {
        border-top: none;
    }

    /* O CARTÃO. `overflow: hidden` é o que faz o raio recortar o fundo da primeira e da última linha de
       campo — sem ele o canto arredondado aparece "furado" pelo realce de seleção. */
    .sis-data-grid .mud-table-body > .mud-table-row {
        display: block;
        margin: 0 0 12px;
        border: 1px solid var(--mud-palette-lines-default);
        border-radius: var(--mud-default-borderradius, 8px);
        background-color: var(--mud-palette-surface);
        overflow: hidden;
    }

    /* 🔑 A ÚLTIMA célula ⛔ não leva separador: quem fecha o registro é a borda do cartão. É a correção da
       metade que este arquivo tinha errado — e é ela que devolve significado à linha de 1px, que volta a
       dizer só "próximo CAMPO". */
    .sis-data-grid .mud-table-body > .mud-table-row > .mud-table-cell:last-child {
        border-bottom: none;
    }

    /* O separador ENTRE CAMPOS fica mais leve que a borda do cartão — a hierarquia é o que se lê. */
    .sis-data-grid .mud-table-body > .mud-table-row > .mud-table-cell {
        border-bottom: 1px solid color-mix(in srgb, var(--mud-palette-table-lines) 45%, transparent);
    }

    /* 🔴 O `!important` aqui ⛔ não é preguiça: quem escreve a largura é um `style` INLINE, posto pela TELA
       para o modo TABELA — `width: 1%` na coluna de código, `min-width: 280px` na de nome, e assim em 93
       consultas. Regra de classe ⛔ não vence atributo inline, e sem isto a célula de código fica com **16px**
       dentro de um cartão de 364 (medido em Pessoas): o realce do registro selecionado pinta só um pedaço da
       linha, e o cartão — que é uma moldura — faz esse retalho parecer defeito de renderização.
       🔑 A largura de COLUNA ⛔ não tem sentido onde ⛔ não há colunas: no cartão cada campo é uma linha. */
    .sis-data-grid .mud-table-body > .mud-table-row > .mud-table-cell {
        width: auto !important;
        min-width: 0 !important;
        max-width: none !important;
    }

    /* ⚠️ A regra de "última LINHA sem separador" (acima, do modo tabela) ⛔ não vale aqui: no cartão cada
       registro se fecha sozinho, e sem isto o último registro perderia os separadores INTERNOS dele. */
    .sis-data-grid .mud-table-body > .mud-table-row:last-child > .mud-table-cell {
        border-bottom: 1px solid color-mix(in srgb, var(--mud-palette-table-lines) 45%, transparent);
    }

    .sis-data-grid .mud-table-body > .mud-table-row:last-child > .mud-table-cell:last-child {
        border-bottom: none;
    }

    /* O RÓTULO do campo (o `::before` do MudBlazor) recua para um papel de apoio: quem o operador lê é o
       VALOR. Sem isto o rótulo repetido a cada registro disputa a leitura com o dado. */
    .sis-data-grid .mud-table-body > .mud-table-row > .mud-table-cell::before {
        color: var(--mud-palette-text-secondary);
        font-weight: 400;
        flex: 0 0 auto;
    }

    /* A célula de AÇÕES vira RODAPÉ do cartão: fundo tênue e os ícones à direita, para o gesto ficar no
       mesmo lugar em todos os cartões. */
    .sis-data-grid .mud-table-body > .mud-table-row > .mud-table-cell:last-child {
        background-color: color-mix(in srgb, var(--mud-palette-table-lines) 18%, transparent);
    }

    /* 🔑 A célula de EXPANDIR (a do `HierarchyColumn`) ⛔ não tem `data-label` — é a única assim, e sem isto
       ela ocupa uma linha inteira do cartão só com o chevron, que foi justamente o que virava "separador por
       acidente" no defeito original. Compacta, ela lê como o canto do cartão. */
    .sis-data-grid .mud-table-body > .mud-table-row > .mud-table-cell:not([data-label]) {
        justify-content: flex-end;
        padding-top: 2px;
        padding-bottom: 2px;
        border-bottom: none;
        min-height: 0;
    }

    /* ⚠️ O realce de seleção pintava a célula; no cartão ele pinta o CARTÃO, senão o registro selecionado
       aparece como um retângulo dentro de outro. */
    .sis-data-grid .mud-table-body > .mud-table-row.sis-grid-row-selected {
        border-color: var(--mud-palette-primary);
    }

    /* ⛔ A barra de rolagem horizontal do topo ⛔ não tem função com cartões (nada rola para o lado) e
       ⚠️ ela é `position: sticky`: deixada viva, some com um pedaço do primeiro cartão. */
    .sis-data-grid .sis-grid-scroll-topo {
        display: none;
    }
}

/* -------------------------------------------------------------------------
   O "ORDENAR POR" DO CELULAR (#2761) — a barra que devolve a ordenação onde o
   cabeçalho não existe.

   🩸 Abaixo de 600px o MudBlazor esconde o `<thead>` inteiro para empilhar os
   registros. O cabeçalho é o ÚNICO lugar de onde se ordena ⇒ a capacidade
   sumia sem aviso: sem botão apagado, sem mensagem — só deixava de existir.
   Medido: 126 telas usam o SisDataGrid, NENHUMA declara `SortMode.None`, e são
   96 colunas com `Sortable="true"` além das que herdam o default.

   🔑 A barra é ESCONDIDA por padrão e revelada só aqui, ⛔ nunca o contrário:
   escrita como `display: flex` com um `display: none` no `@media` do terminal,
   qualquer folha carregada depois — ou um `@media` que não casasse — a deixaria
   VISÍVEL no desktop, que é o lado caro do erro (ali o cabeçalho já ordena, e
   dois controles para o mesmo fim discordam).

   ⚠️ O corte é o MESMO do cartão e do resto da casca (`599.98px`, o
   `viewport.js`). ⛔ Não o mude sozinho: em 768 e 1024 a grade continua tabela,
   e a barra apareceria sobre um cabeçalho que já faz o serviço.
   📖 docs/handoff-interface-no-celular-2026-09-13.md §3 (D3c) */
.sis-grid-ordenar {
    display: none;
}

@media (max-width: 599.98px) {
    /* `relative` é o que ancora o painel da lista — ele é filho, ⛔ não popover. */
    .sis-grid-ordenar {
        position: relative;
        display: flex;
        align-items: center;
        gap: 2px;
        /* Encosta no primeiro cartão sem colar: o cartão já traz 12px de vão entre registros. */
        margin-bottom: 4px;
    }

    /* ⚠️ O texto ⛔ não pode ser cortado no meio de um nome de coluna comprido ("Data de emissão"), e
       ⛔ não pode empurrar a seta para fora da tela: o botão encolhe e o rótulo trunca com reticências. */
    .sis-grid-ordenar-botao {
        min-width: 0;
        flex: 0 1 auto;
        overflow: hidden;
        text-transform: none;
    }

    .sis-grid-ordenar-botao .mud-button-label {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* 🔑 O alvo de toque tem PISO de 44px — a régua de dedo da frente do celular. O `Size.Small` do
       MudBlazor dá 30px, que é alvo de mouse. ⛔ Não troque por padding: o ícone ficaria descentrado. */
    .sis-grid-ordenar-sentido {
        min-width: 44px;
        min-height: 44px;
        flex: 0 0 auto;
    }

    /* O fundo que fecha a lista ao tocar FORA dela. ⚠️ `fixed` cobrindo o viewport inteiro, ⛔ não
       `absolute`: o toque pode cair em qualquer ponto da tela, inclusive fora da grade. */
    .sis-grid-ordenar__fundo {
        position: fixed;
        inset: 0;
        z-index: 1200;
    }

    /* ⚠️ `z-index` ACIMA do fundo — senão o primeiro toque em cada item cairia no fundo e só fecharia
       a lista, e o controle pareceria não responder. */
    .sis-grid-ordenar__painel {
        position: absolute;
        top: calc(100% + 2px);
        left: 0;
        z-index: 1201;
        min-width: 200px;
        /* ⚠️ ⛔ Não pode passar da tela: com muitas colunas os últimos itens ficariam inalcançáveis. */
        max-width: calc(100vw - 32px);
        max-height: 60vh;
        overflow-y: auto;
        padding: 4px 0;
        border: 1px solid var(--mud-palette-lines-default);
        border-radius: var(--mud-default-borderradius, 8px);
        background-color: var(--mud-palette-surface);
        box-shadow: var(--mud-elevation-8);
    }

    .sis-grid-ordenar__item {
        display: flex;
        align-items: center;
        /* 🩸 `justify-content` EXPLÍCITO, e ⛔ não é redundância com o default: medido no navegador, um
           `<button>` com `display: flex` chega aqui com `justify-content: center` — vem de um reset de
           terceiro, ⛔ não do CSS desta barra. Sem esta linha os títulos das colunas aparecem CENTRADOS
           (medido: o título começava em 104px de um item que começa em 13px), e a lista fica com cara de
           caixa de diálogo em vez de menu. ⚠️ `text-align: left` ⛔ NÃO resolve: num container flex quem
           posiciona os filhos é o `justify-content`; o `text-align` só alinha o texto DENTRO do span, que
           tem a largura do próprio texto. */
        justify-content: flex-start;
        gap: 8px;
        width: 100%;
        /* 🔑 O mesmo piso de 44px do alvo de toque — aqui ele vale por LINHA da lista. */
        min-height: 44px;
        padding: 0 16px 0 8px;
        border: 0;
        background: none;
        color: var(--mud-palette-text-primary);
        font: inherit;
        text-align: left;
        cursor: pointer;
    }

    .sis-grid-ordenar__item:hover,
    .sis-grid-ordenar__item:focus-visible {
        background-color: var(--mud-palette-action-default-hover);
    }

    .sis-grid-ordenar__item--ativa .sis-grid-ordenar__titulo {
        font-weight: 500;
        color: var(--mud-palette-primary-text, var(--mud-palette-text-primary));
    }

    /* 🔑 Largura FIXA mesmo vazia: é ela que alinha os títulos das colunas numa coluna só. Sem isso, a
       linha com seta ficaria deslocada das demais e a lista pareceria desalinhada a cada ordenação. */
    .sis-grid-ordenar__seta {
        display: inline-flex;
        flex: 0 0 auto;
        justify-content: center;
        width: 24px;
        color: var(--mud-palette-primary);
    }

    .sis-grid-ordenar__titulo {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .sis-grid-ordenar__risco {
        margin: 4px 0;
        border: 0;
        border-top: 1px solid var(--mud-palette-lines-default);
    }

    .sis-grid-ordenar__vazio {
        margin: 0;
        padding: 8px 16px;
        color: var(--mud-palette-text-secondary);
    }
}

/* -------------------------------------------------------------------------
   O QUE NÃO ENCOLHE NO CELULAR — chip e combo (#2781)

   🩸 As duas famílias que sobraram na fila do portão de largura, e as duas têm a MESMA forma: um controle
   que se dimensiona pelo TEXTO que carrega, sem teto. Enquanto o texto é curto ninguém vê; com um texto
   real do cliente, a página inteira desliza para o lado.

   ⚠️ Elas moram aqui, no CSS da RCL, e ⛔ não nas duas telas que estouram hoje: o `nowrap` é do MudBlazor,
   então a tela que nascer amanhã com um chip de texto longo já nasce com o defeito. Corrigir as duas rotas
   da fila fecharia a fila e ⛔ não a família.
   📖 docs/handoff-interface-no-celular-2026-09-13.md §3 (D3d, D6) */
@media (max-width: 599.98px) {
    /* 🩸 CHIP com `white-space: nowrap` (do MudBlazor). Medido: `/access/usuarios` tinha um chip de
       **238px** ("6 de 8 usuários (2 aguardando aceite)") empurrando a página 8px, e no `/fiscal/mdfe` o
       chip pede **390px** numa caixa de 272.
       ⚠️ `height: auto` anda JUNTO e ⛔ não é enfeite: o MudChip tem altura FIXA — deixando o texto quebrar
       sem soltar a altura, a segunda linha vaza para fora da pílula, que é trocar um defeito por outro. */
    .mud-chip {
        max-width: 100%;
        height: auto;
        min-height: 24px;
    }

    .mud-chip .mud-chip-content {
        white-space: normal;
        overflow-wrap: anywhere;
    }

    /* 🩸 COMBO que se dimensiona pelo RÓTULO SELECIONADO. Medido no `/config/vendas`: o item
       "Expedição 100x150 (envio) (100,00 × 150,00 mm)" faz o `mud-select` pedir **450px** numa caixa de
       **332** — 89px de estouro, o maior da fila.
       🔑 São DUAS metades e só valem juntas: o `max-width` impede o controle de passar do pai, e o
       `min-width: 0` no slot é o que permite ao flex ENCOLHER — sem ele o `min-content` do texto (que é
       `nowrap`) continua sendo o piso, e o `max-width` ⛔ não tem efeito.
       ⚠️ O texto vira reticências, ⛔ não quebra: rótulo de combo em duas linhas muda a altura do campo e
       desalinha o formulário inteiro. */
    /* 🔴 O `!important` ⛔ não é preguiça — é a MESMA armadilha do cartão da grade (#2739): quem escreve a
       largura aqui é um `style` INLINE, posto pela TELA. Medido no `/config/vendas`:
       `Style="max-width: 460px"` num combo — **460px numa tela de 390**. Regra de classe ⛔ não vence
       atributo inline, e sem o `!important` a cura fica escrita e inerte (foi o que aconteceu na primeira
       versão desta regra: o primeiro combo da tela obedeceu, o segundo — o que tinha o style — ⛔ não, e o
       estouro continuou nos mesmos 89px).
       🔑 A régua geral: **largura fixa em PIXELS escrita para o desktop é dívida no celular** — 460, 280 e
       180px são medidas de uma tela que ⛔ não existe no aparelho. Enquanto elas viverem em `style` inline,
       só o `!important` as alcança. */
    .mud-input-control,
    .mud-select {
        max-width: 100% !important;
    }

    .mud-select .mud-input-slot {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
    }
}

/* -------------------------------------------------------------------------
   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;
}

/* A célula inteira: a pilha de texto à ESQUERDA e o gesto do boleto à direita.
   ⚠️ O ícone fica AO LADO, ⛔ não embaixo: empilhado, ele engordaria as 50
   linhas da grade — o mesmo motivo do `line-height` curto logo acima. */
.sis-cobranca-linha {
    display: flex;
    align-items: center;
    gap: 4px;
}

/* (#3405) A coluna Status do Contas a Receber: o chip do status e o de VENCIDO lado a lado, ⛔ nunca
   empilhados — empilhar dobraria a altura das linhas vencidas numa grade que já teve de caber (#1939). */
.sis-status-titulo {
    display: flex;
    align-items: center;
    flex-wrap: nowrap;
    gap: 4px;
}

.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);
}

/* NOTA FISCAL (reimprimir o DANFE): cor INFO, e a diferença para o secundário do pedido e do cupom é
   deliberada. Os três entregam um documento da venda, mas só este tem valor perante o fisco e só ele
   aparece em algumas linhas — a cor própria é o que faz o operador reparar que aquela venda emitiu, sem
   precisar passar o mouse. ⛔ Não é error: reimprimir não destrói nada nem toca a SEFAZ. */
.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);
}

/* 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;
}

/* Destaque (favorito) do cardápio — #3164.

   A estrela é IRMÃ do card e fica SOBRE ele, no canto. Ela não pode ser filha do <button> do card
   (elemento interativo dentro de <button> é HTML inválido), e não pode ocupar espaço no fluxo — com
   `position: static` ela empurraria o nome e os cards com e sem estrela teriam alturas diferentes. */
.sis-product-slot {
    position: relative;
    height: 100%;
}

.sis-product-slot__star {
    position: absolute;
    top: 4px;
    right: 4px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* 28px é o alvo de toque mínimo que ainda cabe no canto de um card de 92px de altura. */
    width: 28px;
    height: 28px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.sis-product-slot__star:hover,
.sis-product-slot__star:focus-visible {
    background-color: var(--mud-palette-action-default-hover);
    outline: none;
}

/* A marca de quem só LÊ o destaque: mesma posição, sem alvo de toque e sem cursor de clique — ela
   explica a ordem da grade, não oferece um gesto que o servidor recusaria. */
.sis-product-slot__star--lido {
    cursor: default;
    pointer-events: none;
}

/* O nome recua para não passar por baixo da estrela. ⚠️ O recuo vale para TODO card, com estrela ou
   sem: aplicado só a quem tem, o nome quebraria em pontos diferentes de card para card e a grade
   pareceria desalinhada. */
.sis-product-card__name {
    padding-right: 24px;
}

/* -------------------------------------------------------------------------
   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;
}

/* 👥 Cabeçalho de grupo da lista de itens (visão "agrupar por pessoa" da comanda).
   Fundo chapado em vez de borda: com borda, dois grupos seguidos desenhariam duas linhas coladas à
   divisória do item anterior, e a lista passaria a parecer uma grade. */
.sis-tab-group {
    display: flex;
    align-items: center;
    margin-top: 8px;
    padding: 6px 8px;
    border-radius: 8px;
    background-color: color-mix(in srgb, var(--mud-palette-primary) 10%, transparent);
    color: var(--mud-palette-primary);
}

.sis-tab-group:first-child {
    margin-top: 0;
}

.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;
}

/* Páginas DESENHADAS pelo sistema (app Android — o WebView não desenha PDF num iframe). Mesma regra do
   quadro: preenche o pai posicionado, e ROLA — é a lista inteira do documento. O fundo cinza separa as folhas
   brancas, que são imagens com fundo já pintado de branco pelo renderer. */
.sis-pdf-viewer__paginas {
    position: absolute;
    inset: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    padding: 12px;
    background: var(--mud-palette-background-gray);
}

.sis-pdf-viewer__pagina {
    display: block;
    width: 100%;
    max-width: 900px;
    height: auto;
    box-shadow: 0 1px 4px rgba(0, 0, 0, .25);
}

.sis-pdf-viewer__mais {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 8px 0 16px;
}

.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;
    /* Coluna 1: o campo. Coluna 2: o "x" que limpa o VÍNCULO (só existe com vínculo). Colunas 4, 5 e 6:
       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.

       🩸 E foi exatamente isto em 2026-09-01: o "x" entrou como sexto filho e a sexta coluna não veio
       junto, então num lookup com os quatro gestos o "ver cadastro" ia para a linha de baixo. Quem pegou
       foi o ColunasDoLookupAcompanhamOsBotoesTests, ⛔ não a suíte de componente — que é o motivo escrito
       deste portão existir. */
    grid-template-columns: minmax(0, 1fr) auto auto auto auto auto;
    align-items: end;
    column-gap: 4px;
    width: 100%;
    position: relative;
}

/* -------------------------------------------------------------------------
   O LOOKUP NO CELULAR (#2813) — o campo para de virar "Cl…"

   🩸 Medido em 390×844: o `<input>` do campo *Cliente* da venda tinha **55 px** e o rótulo saía cortado.
   ⛔ Os botões ⛔ não estavam fora da tela — eles cabiam; quem ⛔ não cabia era o campo.

   🔑 A causa tem DUAS metades, e a segunda ⛔ não estava no handoff:
     1. os quatro botões consomem 164 px (4 × 36 + gaps) numa linha só; e
     2. a TELA declara `xs-8` no MudGrid — o lookup recebe 8 de 12 colunas **também no celular**, ou seja
        227 px de 340. No desktop 8/12 são ~800 px e os mesmos 164 px somem no meio.
   ⇒ o `xs-8` ⛔ não é erro da tela: é uma proporção que só faz sentido acima de certa largura. Corrigir
   aqui, no componente, alcança as telas de hoje E as que nascerem — e ⛔ não obriga a revisar `xs-*`
   uma a uma.

   🩸 O DESENHO É A SEGUNDA VERSÃO, e a primeira foi REPROVADA PELO DONO: *"os ícones do lookup de cliente
   ficaram desalinhados"*. Ela punha o campo e a lupa na linha 1 e os três opcionais na linha 2, cada botão
   numa COLUNA declarada — e o resultado ficava esparramado, porque as colunas deixam BURACO: o `limpar` só
   existe com vínculo, então a coluna dele ficava vazia e a lupa aparecia sozinha no canto direito, enquanto
   o `criar novo` caía no canto esquerdo da linha de baixo. ⇒ **coluna fixa por botão ⛔ não agrupa botão
   opcional; ela reserva lugar para quem pode não vir.**

   ✅ O desenho de agora: o CAMPO ocupa a linha inteira (`grid-column: 1 / -1`, e assim ele fica com os
   ~227 px do contêiner, ⛔ não com 130) e os botões viram um GRUPO CONTÍGUO na linha de baixo, alinhados à
   esquerda. As quatro faixas de 36 px mais um `1fr` no fim são o que mantém o quinto botão colado no
   quarto: sem o `1fr`, a última faixa sobraria de largura e o grupo abriria um vão.

   ⚰️ AQUI HAVIA UM `justify-self: start`, e o defeito plantado provou que ele ⛔ NÃO FAZIA FALTA: quebrando
   o seletor dele de propósito, o arranjo ⛔ não se mexeu. O motivo é que quem estica na faixa `1fr` é o
   WRAPPER do tooltip — o `MudIconButton` dentro dele mantém os 36 px e fica encostado à esquerda do
   wrapper. ⇒ a regra protegia contra um estrago que ⛔ não acontece. 🔑 Regra de CSS cuja justificativa
   escrita é falsa é pior que regra ausente: ela ensina errado a quem vier depois.

   ⚠️ O TETO É DE CINCO BOTÕES por construção (4 faixas + a `1fr`). Botão número seis quebraria numa
   terceira linha, e o portão do arranjo REPROVA isso de propósito — quem acrescentar um sexto acrescenta
   a faixa aqui, do mesmo jeito que o bloco do desktop já cobra.

   🔑 O `order` do `limpar` é o que impede o grupo de PULAR: ele entra no DOM antes da lupa, então sem isso
   escolher um cliente empurraria todos os outros botões 40 px para a direita, na cara do operador. O helper
   vem depois dele para ⛔ não se meter no meio do grupo.

   ⚠️ O `:has(> …)` ⛔ não é preciosismo: cada botão vem embrulhado num `<MudTooltip>`, então o filho DIRETO
   do grid é o wrapper e o `data-tour` está no NETO. A primeira versão usou `> [data-tour=…]` e a regra
   ⛔ NUNCA aplicou — sem erro, sem aviso, e com o portão de fonte verde.
   🩸 ESTE BLOCO CHEGOU À DEV NUM SEGUNDO PR (#2813, 2026-09-15), e o motivo fica escrito porque o
   estado intermediário era PIOR que o defeito original: o PR #2824 foi mergeado com a PRIMEIRA versão
   (as colunas declaradas), o redesenho foi empurrado para a branch DEPOIS do merge, e ninguém o levou
   adiante. ⇒ por 24 h a dev serviu exatamente o arranjo que o dono reprovou. ⚠️ Quem reler isto e achar
   que as colunas eram mais simples: elas foram medidas, mostradas ao dono e RECUSADAS.
   📖 docs/handoff-interface-no-celular-2026-09-13.md §3 (D3) */
@media (max-width: 599.98px) {
    .sis-lookup-field {
        grid-template-columns: repeat(4, 36px) 1fr;
        row-gap: 4px;
    }

    /* O campo é o primeiro filho e ocupa a linha inteira — é ele que precisa de largura. */
    .sis-lookup-field > *:first-child {
        grid-column: 1 / -1;
    }

    /* O `limpar` ao FIM do grupo, e o texto de ajuda depois dele. */
    .sis-lookup-field > [data-tour="sis-lookup-limpar"],
    .sis-lookup-field > *:has(> [data-tour="sis-lookup-limpar"]) {
        order: 1;
    }

    .sis-lookup-field > .sis-lookup-helper {
        order: 2;
    }
}

/* 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;
}

/* O CÓDIGO do produto na linha lançada (2026-09-04, #1888).
   Largura MÍNIMA e alinhado à direita: sem isso cada linha começa a descrição num ponto diferente, e a
   coluna de números deixa de ser lida como coluna. `flex: 0 0 auto` para ele não encolher quando a
   descrição é longa — é o campo mais curto e o primeiro que o flex sacrificaria; e `min-width` em vez de
   `width` para o código de cinco dígitos não ser cortado. */
.sis-os-item-codigo {
    flex: 0 0 auto;
    min-width: 48px;
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-secondary);
}

.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;
}

/* =====================================================================================================
   Recorte de imagem — SisImageCropDialog
   =====================================================================================================

   O XADREZ do palco não é enfeite: ele revela o que é TRANSPARENTE no arquivo, e transparência é
   justamente o que a conversão para JPEG vai achatar em branco. Sem ele o operador só descobre no
   documento impresso. */
.sis-crop {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 220px;
    padding: 8px;
    border-radius: 8px;
    overflow: hidden;
    background-color: var(--mud-palette-background-grey);
    background-image:
        linear-gradient(45deg, rgba(128, 128, 128, 0.18) 25%, transparent 25%),
        linear-gradient(-45deg, rgba(128, 128, 128, 0.18) 25%, transparent 25%),
        linear-gradient(45deg, transparent 75%, rgba(128, 128, 128, 0.18) 75%),
        linear-gradient(-45deg, transparent 75%, rgba(128, 128, 128, 0.18) 75%);
    background-size: 16px 16px;
    background-position: 0 0, 0 8px, 8px -8px, -8px 0;
}

/* `line-height: 0` e `inline-block` porque a seleção é posicionada SOBRE a <img>: qualquer respiro entre a
   caixa do palco e a imagem desloca o retângulo dos pixels que ele diz recortar.

   `touch-action: none` é o que faz o arraste funcionar no TABLET — sem ele o navegador entende o gesto como
   rolagem, engole o pointermove e o recorte não sai do lugar (e nada no desktop denuncia isso). */
.sis-crop__palco {
    position: relative;
    display: inline-block;
    line-height: 0;
    touch-action: none;
}

.sis-crop__img {
    display: block;
    max-width: 100%;
    max-height: 46vh;
    user-select: none;
    -webkit-user-drag: none;
}

/* O escurecimento de fora vem do `box-shadow` de raio enorme — é o que o `.sis-crop { overflow: hidden }`
   recorta. Quatro divs de sombra dariam o mesmo desenho com quatro vezes mais estado para manter. */
.sis-crop__sel {
    position: absolute;
    box-sizing: border-box;
    border: 1px solid #fff;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.65), 0 0 0 9999px rgba(0, 0, 0, 0.5);
    cursor: move;
}

.sis-crop__handle {
    position: absolute;
    width: 12px;
    height: 12px;
    background: #fff;
    border: 1px solid rgba(0, 0, 0, 0.65);
    border-radius: 2px;
}

.sis-crop__handle--nw { top: -6px; left: -6px; cursor: nwse-resize; }
.sis-crop__handle--n { top: -6px; left: calc(50% - 6px); cursor: ns-resize; }
.sis-crop__handle--ne { top: -6px; right: -6px; cursor: nesw-resize; }
.sis-crop__handle--e { top: calc(50% - 6px); right: -6px; cursor: ew-resize; }
.sis-crop__handle--se { bottom: -6px; right: -6px; cursor: nwse-resize; }
.sis-crop__handle--s { bottom: -6px; left: calc(50% - 6px); cursor: ns-resize; }
.sis-crop__handle--sw { bottom: -6px; left: -6px; cursor: nesw-resize; }
.sis-crop__handle--w { top: calc(50% - 6px); left: -6px; cursor: ew-resize; }

.sis-crop__barra {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 8px;
}

/* 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;
}

/* Marcador do elemento de IMAGEM no palco do designer.
   ⚠️ É MARCADOR, ⛔ não prévia: o desenho depende do cadastro da empresa, que o designer não carrega — e uma
   prévia que buscasse o logotipo faria a caixa vazia da empresa sem logo parecer defeito do editor.
   Tracejado pelo mesmo motivo do card "disponível" do catálogo: diz "aqui vai algo" sem competir com o que
   já está desenhado. */
.sis-label-el__imagem {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-height: 0;
    overflow: hidden;
    border: 1px dashed var(--mud-palette-lines-inputs);
    border-radius: 3px;
    color: var(--mud-palette-text-secondary);
    font-size: 8px;
    line-height: 1;
}

.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 {
    /* 🩸 CENTRA as pílulas na vertical (#2840, olho do dono: *"o menu da ordem de serviço ficou com um
       padding estranho"*). Medido antes: **5 px acima e 9 abaixo** no computador, **5 e 19** no celular —
       as pílulas encostadas no topo, com uma faixa vazia embaixo.

       🔑 A altura do trilho é imposta de FORA, e é por isso que ⛔ não se conserta com padding: o MudBlazor
       põe `min-height: 48px` aqui, e no celular as setas de rolagem esticam o trilho para 58. A sobra muda
       com a largura da tela ⇒ número fixo acertaria uma e erraria as outras. O que vale em todas é dividir
       a sobra, seja ela qual for.

       🔴 É `align-items`, ⛔ NUNCA `justify-content` — e o caminho até esta linha é a lição. O trilho é
       flex de **LINHA** (medido no navegador: `display=flex dir=row`), então o eixo vertical é o CRUZADO e
       quem o comanda é o `align-items`.

       🩸 A primeira tentativa escreveu `justify-content: center`, a partir de um `grep -o` no
       `MudBlazor.min.css` que devolveu:

           .mud-tabs-tabbar-inner{flex-direction:column}

       ⚠️ O `grep -o` CORTOU O SELETOR ANCESTRAL. A regra inteira é
       `.mud-tabs-tabbar.mud-tabs-vertical .mud-tabs-tabbar-inner` — ela vale só para aba VERTICAL, que ⛔
       não é o nosso caso. ⇒ **medição que perde o contexto ⛔ não é medição**, e quem desfez o engano foi
       rodar o portão: os números vieram IDÊNTICOS (5/9), que é a assinatura de regra inerte.

       ⚠️ Por que o defeito só aparece ABAIXO de 1281px: o `@media` logo adiante encolhe a pílula para
       `min-height: 34px` e o padding para 4. Aí a caixa de conteúdo do trilho (48 − 2 de borda − 8 de
       padding = 38) fica MAIOR que a pílula (34), e os 4 px de sobra caem embaixo. Acima de 1280 a pílula
       tem 36 e a caixa tem 36 — enchem exatamente, e por isso ali sempre esteve simétrico (6/6).

       ⚠️ Isto alcança as QUATRO telas que usam a classe (O.S., Atendimento, Ordem de Produção e Nota
       Fiscal) — ela é design system de DOCUMENTO, ⛔ não da O.S., e o portão mede as quatro. */
    align-items: center;
    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;
}

/* (2026-09-15, #2988) A MESMA área, quando o resumo é um painel EM COLUNA — o caso da consignação.
   🔑 Ela reusa a classe de propósito: o gesto que conclui o documento é o mesmo conceito nas duas telas, e
      dois nomes fariam a próxima mudança de tema acertar uma e esquecer a outra.
   ⚠️ O que muda é só o que a horizontal ⛔ não precisa: o respiro ACIMA (ali o empurrão é o `margin-left`)
      e a borda que separa o botão dos números — sem ela, ele encosta no total e se lê como parte dele. */
.sis-document-summary__actions--empilhado {
    margin-left: 0;
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.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;
    /* 🩸 A linha se alinha pelo TOPO DOS CONTROLES, ⛔ nunca pelo fim da célula (issue #2896). Era
       `align-items: end`, e com ele a barra saía TORTA em toda tela cujo lookup tem texto de ajuda: a
       célula do produto é mais ALTA que as vizinhas, porque o `SisLookupField` desenha a ajuda como uma
       segunda linha do grid dele (`.sis-lookup-helper`, `grid-column: 1 / -1`). Bottom-alinhando a célula
       INTEIRA, quem encostava no fim era a FRASE — e o campo do produto subia a altura dela. Medido no
       navegador, na aba Itens da O.S.: produto em Y=298 contra Y=321 de quantidade e valor, 23 px de
       desvio, que é exatamente a linha de ajuda.
       ⚠️ Invisível na venda, que ⛔ não passa `HelperText` ao lookup — portão escrito só sobre ela ficaria
       verde com o defeito de pé.
       🔑 `start` é a resposta CERTA, e ⛔ não "tirar a ajuda do fluxo": a segunda linha da barra é a
       descrição complementar (`.sis-item-entry__footer`), então ajuda fora do fluxo cai POR CIMA dela.
       Aqui a ajuda continua empurrando a própria célula para baixo, sem mover ninguém — e de quebra a
       mensagem de erro de um campo numérico passou a crescer para BAIXO em vez de erguer o campo.
       Portão: AlinhamentoDaBarraDeLancamentoTests (E2E, em pixels — bUnit é cego para isto). */
    align-items: start;
    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;
}

/* 🔴 (2026-09-15, #2987) A BARRA QUEBRA EM DUAS LINHAS QUANDO ⛔ NÃO CABE — antes ela TRANSBORDAVA.
   🩸 Medido no navegador, na consignação a 1280×800: `scrollWidth 768` contra `clientWidth 611`, com o
   botão ADICIONAR em x=1014 e o card acabando em 938 — 92 px fora, e ⛔ sem rolagem que o alcançasse.
   Grid de template fixo ⛔ não quebra: ele estoura. ⇒ o conserto é trocar o TEMPLATE quando o espaço
   ⛔ não dá, e quem responde "quanto espaço eu tenho" é o hospedeiro.

   🔑 O corte é 880 px porque o mínimo do template largo é ~824 px (280 do produto + 2 × 120 + 130 do
   total + ~106 do botão + gaps + padding); a folga de ~56 px é o que impede a troca de acontecer a um
   pixel do limite, onde ela pisca ao redimensionar.

   ⚠️ Estreito, o PRODUTO toma a linha inteira — ⛔ não é estética: ele é o campo com texto longo (nome de
   produto), e espremê-lo em 150 px é o que faz o operador não conseguir ler o que escolheu. Os numéricos,
   o total e o botão dividem a segunda linha, onde todos cabem.

   ⚠️ A DESCRIÇÃO complementar continua em `1 / -1` — ela já era linha inteira, e ⛔ nada aqui a move. */
.sis-item-entry-host {
    container-type: inline-size;
}

@container (max-width: 880px) {
    .sis-item-entry {
        grid-template-columns:
            repeat(var(--sis-item-entry-campos, 2), minmax(110px, 1fr))
            minmax(120px, .8fr)
            auto;
    }

    .sis-item-entry__product {
        grid-column: 1 / -1;
    }
}

.sis-sale-items .mud-input-control {
    min-width: 104px;
}

.sis-sale-items .mud-input-slot {
    text-align: right;
}

/* 🩸 (2026-09-22) Este min-width nasceu preso ao PRIMEIRO filho quando Descrição era a primeira coluna
   (27/08). Em 03/09 a coluna Código entrou na frente dela (issue #1888) e o seletor estrutural passou a
   mirar Código em silêncio — Código ficou largo, Descrição voltou a quebrar em várias linhas, e uma
   tentativa posterior de encolher Código por width inline não fez diferença nenhuma: min-width sempre
   vence um width menor no mesmo elemento. O respiro é da DESCRIÇÃO — por isso mora no segundo filho. */
.sis-sale-items td:nth-child(2) {
    min-width: 220px;
}

.sis-sale-items td:first-child {
    width: 1%;
    white-space: nowrap;
}

/* 🩸 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);
}

/* --------------------------------------------------------------------------
   BLOQUEIO ENQUANTO A CONEXÃO NÃO VOLTA (SisOfflineBlockOverlay, #3021).

   🔑 z-index 1600 — ACIMA do 1500 da reentrada, e a ordem é deliberada. Os dois podem estar de pé ao mesmo
   tempo (a sessão morre, e logo depois a rede cai), e ⛔ não adianta oferecer o campo de senha para quem
   ⛔ não tem como mandá-la ao servidor: com este por cima, o operador lê o motivo certo primeiro.

   ⚠️ Ele cobre o app INTEIRO de propósito (position: fixed; inset: 0). O pedido do dono é "bloqueia até a
   conexão voltar" — um aviso que deixasse a tela clicável por baixo seria um aviso, ⛔ não um bloqueio.
   -------------------------------------------------------------------------- */
.sis-offline-block {
    position: fixed;
    inset: 0;
    z-index: 1600;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
    background: rgba(0, 0, 0, .65);
    backdrop-filter: blur(2px);
}

.sis-offline-block-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. */
/* 🔑 FAIXA DE LARGURA INTEIRA, VERMELHA — decisão do dono (2026-09-02): *"quando for exibir aviso de
   atualização eu quero algo mais explícito"*, com os avisos do Evernote e do Warp como referência.

   🩸 O que ela substitui: uma pílula flutuante de 8px de raio, cor `--mud-palette-surface` (a MESMA do
   card atrás dela) e 340px de largura, no canto de baixo. Ela dizia a coisa certa e não era vista — e o
   caso em que ela aparece é justamente aquele em que a troca NÃO acontece sozinha, ou seja, o único em
   que o operador precisa saber de alguma coisa. Aviso discreto no caso raro é aviso que não cumpre.

   ⬇️ EMBAIXO, e não no topo como nos dois exemplos — a diferença é medida, não gosto: a `.mud-appbar` e a
   `.mud-drawer` são `position: fixed` ancoradas na viewport, então uma faixa no topo teria de reposicionar
   as DUAS (o drawer daqui é `ClipMode.Always`, logo o `top` dele deriva de `--mud-appbar-height`) e o
   PDV por cima. Embaixo o empurrão são duas regras, exatamente as do teclado numérico logo acima — e
   é também onde o `#blazor-error-ui` já mora, o que dá uma linguagem só para os dois avisos de sistema.

   🩸 ⚠️ A cor é o LITERAL `#b32121`, ⛔ **não** `--mud-palette-error` — e a primeira versão desta faixa
   usou a variável, com a captura mostrando por quê: no tema ESCURO o MudBlazor clareia a paleta de erro,
   a faixa saiu rosa-lavada e o botão branco quase sumiu dentro dela. Aviso que perde urgência no escuro é
   metade do produto sem o aviso.
   🔑 Aqui o literal é o certo, e o argumento é o oposto do usual: a faixa é uma BANDA PREENCHIDA, então o
   contraste é dela com o próprio texto (branco sobre vermelho, igual nos dois temas) — ⛔ não com o fundo
   da página, que é o caso em que a variável seria obrigatória. É o mesmo `#b32121` do `#blazor-error-ui` e
   do aviso de reserva dos três `index.html`: uma linguagem só para os avisos de sistema. */
.sis-update-bar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 1400;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 8px 16px;
    min-height: var(--sis-update-bar-height);
    padding: 10px 16px;
    background: #b32121;
    color: #fff;
    box-shadow: 0 -2px 16px rgba(0, 0, 0, .28);
    font-size: .95rem;
    text-align: center;
}

/* Altura reservada para o empurrão abaixo. ⚠️ É variável e não número repetido: barra e empurrão
   discordando dariam de novo o defeito que o empurrão existe para corrigir — a última linha da grade
   escondida atrás do aviso. */
:root {
    --sis-update-bar-height: 52px;
}

.sis-update-bar__msg {
    display: flex;
    align-items: center;
    gap: 8px;
    justify-content: center;
}

.sis-update-bar strong {
    font-weight: 600;
}

/* ⚠️ 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;
    background: #fff;
    color: #b32121;
    font-weight: 600;
}

.sis-update-bar .mud-button-root:hover {
    background: rgba(255, 255, 255, .85);
}

/* ---- A faixa EMPURRA a tela, não a cobre ------------------------------
   Mesmo seletor `:has()` do teclado numérico, e pela mesma razão: a faixa EXISTIR no DOM já é a única
   condição, então não há segundo estado (uma classe posta por JS) para dessincronizar.

   `.mud-main-content` cobre a casca do ERP e as dos aplicativos; `.pdv` é o terminal, que é
   `position: fixed` por conta própria e por isso recua pelo `bottom`, não por padding. Sem estas duas o
   aviso cobriria a última linha da grade e a faixa de teclas de função do PDV — justamente os controles
   de quem está no meio do documento que a barra pede para concluir. */
body:has(.sis-update-bar) .mud-main-content {
    padding-bottom: var(--sis-update-bar-height);
}

body:has(.sis-update-bar) .pdv {
    bottom: var(--sis-update-bar-height);
}

/* 🩸 A ALTURA RESERVADA é uma ESCADA, e ela veio da captura: a frase é longa de propósito (diz o estado,
   a natureza e a hora), então abaixo de ~1400px ela quebra em duas linhas e o botão desce para a terceira.
   Com a reserva fixa de uma linha, medido em 1024×768, a faixa cobria o painel de totais da venda —
   exatamente o controle de quem está no documento que ela pede para concluir.

   ⚠️ ⛔ Não "resolva" isto encurtando a frase: as três partes dela são o pedido do dono. E ⛔ não confie
   nesta escada de olho — o E2E mede, nos quatro quadros, o recuo do conteúdo CONTRA a altura real da
   faixa no navegador. */
@media (max-width: 1399.98px) {
    :root {
        --sis-update-bar-height: 112px;
    }
}

@media (max-width: 599.98px) {
    :root {
        --sis-update-bar-height: 136px;
    }

    .sis-update-bar {
        font-size: .875rem;
    }
}

/* ── 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);
}

/* ── Aparência dos relatórios (/config/aparencia-relatorios) ────────────────────────────────────────
   A prévia imita a FOLHA, não a tela: fundo branco fixo, mesmo no tema escuro. O documento sai em
   papel, e uma prévia que acompanhasse o tema mostraria um contraste que a impressora não reproduz —
   exatamente o julgamento que esta tela existe para o usuário fazer. */
.sis-aparencia-amostra {
    width: 32px;
    height: 32px;
    border-radius: 50%;
    border: 2px solid transparent;
    cursor: pointer;
    padding: 0;
    outline-offset: 2px;
}

.sis-aparencia-amostra--ativa {
    border-color: var(--mud-palette-text-primary);
}

.sis-aparencia-previa {
    background: #FFFFFF;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 4px;
    padding: 16px;
    font-size: 12px;
}

.sis-aparencia-previa__titulo {
    font-size: 16px;
    font-weight: 600;
}

/* O cabeçalho do documento comercial na prévia da aparência: o emitente à esquerda e a caixa do logo à
   direita, como no PDF. A caixa tem a largura em PORCENTAGEM da linha (a página faz a conta a partir da
   largura útil do A4), então a proporção entre logo e texto na tela é a mesma do papel. */
.sis-aparencia-cabecalho {
    display: flex;
    align-items: flex-start;
    gap: 12px;
}

.sis-aparencia-cabecalho__emitente {
    flex: 1 1 auto;
    min-width: 0;
    line-height: 1.5;
}

.sis-aparencia-cabecalho__nome {
    font-size: 15px;
    font-weight: 600;
}

/* flex-shrink: 0 — sem ele o flex encolheria a caixa para caber o texto do emitente, e a prévia deixaria
   de mostrar a diferença entre os degraus, que é exatamente o que ela existe para mostrar. */
.sis-aparencia-cabecalho__logo {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 2px;
    background: var(--mud-palette-background-grey);
    color: var(--mud-palette-text-secondary);
    font-size: 10px;
    letter-spacing: 0.08em;
}

.sis-aparencia-cabecalho__documento {
    text-align: center;
    font-size: 13px;
    font-weight: 600;
}

.sis-aparencia-previa__linha {
    border-top: 1px solid;
    margin: 6px 0 12px;
}

.sis-aparencia-previa__resumo {
    display: flex;
    justify-content: space-between;
    padding: 10px 12px;
    margin-bottom: 12px;
}

.sis-aparencia-previa__tabela {
    width: 100%;
    border-collapse: collapse;
}

.sis-aparencia-previa__tabela th,
.sis-aparencia-previa__tabela td {
    padding: 6px 8px;
    text-align: left;
}

.sis-aparencia-previa__tabela th {
    font-weight: 600;
}

.sis-aparencia-previa__tabela tbody tr {
    border-bottom: 1px solid;
}

.sis-aparencia-previa__numero {
    text-align: right;
}

.sis-aparencia-previa__rodape {
    margin-top: 12px;
    font-size: 10px;
}

/* ── Cotação de compra: mapa comparativo (2026-09-02) ──────────────────────────────────────────────
   A célula com o MENOR preço do item ganha um fundo discreto de sucesso; a célula ESCOLHIDA ganha o
   contorno. São as duas informações que o comprador lê de relance — e são separadas de propósito:
   escolher o mais caro (prazo, frete, confiança) é decisão legítima, e o mapa não pode sugerir erro. */
.sis-cotacao-mapa td.sis-cotacao-celula-melhor {
    background: color-mix(in srgb, var(--mud-palette-success) 10%, transparent);
}

.sis-cotacao-mapa td.sis-cotacao-celula-escolhida {
    box-shadow: inset 0 0 0 2px var(--mud-palette-success);
    border-radius: 6px;
}

/* 👥 DIVIDIR A CONTA — as etiquetas de "de quem é este item" na linha do pedido.

   Mesma métrica das observações (.sis-obs-tags) de propósito: as duas são faixas de chips pequenos logo
   abaixo da descrição, e alturas diferentes fariam a linha do item dançar conforme o que ela carrega. */
.sis-item-guests {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 4px;
}

.sis-item-guests .mud-chip {
    margin: 0;
    height: 22px;
}

/* A lista de itens dentro do diálogo de divisão. O teto de altura existe porque a mesa de dez pratos
   empurraria os campos de valor e forma para fora da tela — e é neles que o gesto termina. */
.sis-split-items {
    max-height: 220px;
    overflow-y: auto;
}

/* ─── Espera de pagamento no balcão (fatia 2f) ────────────────────────────────────────────────────
   ⚠️ O QR precisa de FUNDO BRANCO em qualquer tema: leitor de QR lê contraste, e no tema escuro o SVG
   herdaria o fundo do painel e viraria ilegível — a tela pareceria certa e o cliente não conseguiria
   pagar. É o mesmo motivo pelo qual o boleto imprime em branco. */
.sis-espera-pagamento .sis-espera-qr {
    background: #fff;
    padding: 12px;
    border-radius: 8px;
    line-height: 0;
}

.sis-espera-pagamento .sis-espera-qr svg {
    width: 220px;
    height: 220px;
    display: block;
}

/* Em 1024×768 (o segundo quadro obrigatório das transacionais) o QR grande empurra as três saídas para
   fora da dobra — e a saída que some é justamente a que o operador precisa achar rápido. */
@media (max-height: 800px) {
    .sis-espera-pagamento .sis-espera-qr svg {
        width: 160px;
        height: 160px;
    }
}
/* ────────────────────────────────────────────────────────────────────────────────────────────────────────
   A LINHA DE PESSOA no resultado de busca (SisPessoaResultado, 2026-09-01)

   Três níveis de leitura, e o tamanho é o que os separa: o nome em corpo normal, os apelidos e o contato em
   corpo menor e cor secundária. ⚠️ O separador entre os campos de uma mesma linha é um "·" desenhado pelo
   CSS (::before do irmão), ⛔ nunca escrito no markup: no markup ele viraria um travessão órfão toda vez que
   o campo ao lado estivesse vazio. */
.sis-pessoa-resultado {
    display: flex;
    flex-direction: column;
    gap: 1px;
    width: 100%;
    line-height: 1.25;
}

.sis-pessoa-resultado__codigo {
    color: var(--mud-palette-text-secondary);
    margin-right: 6px;
}

.sis-pessoa-resultado__apelidos,
.sis-pessoa-resultado__contato {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    font-size: 0.78rem;
    color: var(--mud-palette-text-secondary);
}

.sis-pessoa-resultado__apelidos > span + span::before,
.sis-pessoa-resultado__contato > span + span::before {
    content: "· ";
}


/* ── Busca por tópico (Shell/Search) ────────────────────────────────────────────────────────────────────
   O diálogo e a página de resultados compartilham a MESMA lista (SisTopicSearchList), então compartilham
   também estas regras — é o que impede "ver todos" de mudar a aparência do resultado no meio do gesto.
   ⚠️ Zero hexadecimal: tudo por var(--mud-palette-*), senão o tema escuro deixa de ser servido em silêncio. */
.sis-topic-search__pagina {
    padding-block: 24px;
}

.sis-topic-search__lista {
    padding: 0;
}

.sis-topic-search__item {
    display: flex;
    align-items: flex-start;
    gap: 16px;
    padding: 12px 8px;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.sis-topic-search__item:last-child {
    border-bottom: none;
}

.sis-topic-search__item--ativo {
    background-color: rgba(var(--mud-palette-primary-rgb), .10);
    border-radius: var(--mud-default-borderradius);
}

/* min-width: 0 é o que impede a explicação longa de empurrar os botões para fora da superfície. */
.sis-topic-search__texto {
    flex: 1 1 auto;
    min-width: 0;
}

.sis-topic-search__titulo {
    display: flex;
    align-items: center;
    gap: 8px;
    font-weight: 500;
}

.sis-topic-search__tipo {
    font-size: .7rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--mud-palette-text-secondary);
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: 999px;
    padding: 0 8px;
}

.sis-topic-search__onde {
    font-size: .8rem;
    color: var(--mud-palette-text-secondary);
}

.sis-topic-search__descricao {
    font-size: .85rem;
    color: var(--mud-palette-text-primary);
    margin-top: 2px;
}

.sis-topic-search__acoes {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    flex: 0 0 auto;
}

.sis-topic-search__vazio {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    text-align: center;
    padding: 32px 16px;
    color: var(--mud-palette-text-secondary);
}

/* No celular os botões vão para baixo do texto: lado a lado, sobra ~80px para a explicação. */
@media (max-width: 700px) {
    .sis-topic-search__item {
        flex-direction: column;
        gap: 8px;
    }
}

/* =====================================================================================================
   FOCO NUM CAMPO — a busca por tópico chegando ao campo (JS: `focar` em tutorial.js).

   🩸 É um ANEL próprio, `position: fixed`, desenhado no `body` POR CIMA do campo — ⛔ nunca uma classe no
   elemento do campo. Medido no navegador: o Blazor RECRIA o nó no render seguinte à navegação, e a classe
   vai junto para um nó órfão (`mesmoNó=false` já em +0 ms). O anel vive fora da árvore do Blazor e por isso
   sobrevive ao diff.

   🔑 `pointer-events: none` é o que o mantém DECORATIVO: sem isso o anel comeria o clique do operador no
   campo que ele acabou de destacar — o oposto do que a fatia existe para fazer.

   ⚠️ Cor pelo TEMA (`--mud-palette-primary-rgb`), ⛔ nunca hexadecimal: cor cravada mata o claro/escuro em
   silêncio, e este destaque só existe para ser visto.

   ⚠️ `prefers-reduced-motion` desliga a pulsação e deixa o anel PARADO — ⛔ não o remove: quem pediu menos
   movimento continua precisando saber qual é o campo.
   ===================================================================================================== */
.sis-foco-anel {
    position: fixed;
    pointer-events: none;
    z-index: 1400;
    border-radius: var(--mud-default-borderradius, 4px);
    animation: sis-foco-pulso 0.66s ease-in-out 3;
}

@keyframes sis-foco-pulso {
    0%, 100% {
        box-shadow: 0 0 0 2px rgba(var(--mud-palette-primary-rgb), 0);
    }

    50% {
        box-shadow: 0 0 0 4px rgba(var(--mud-palette-primary-rgb), 1);
    }
}

@media (prefers-reduced-motion: reduce) {
    .sis-foco-anel {
        animation: none;
        box-shadow: 0 0 0 3px rgba(var(--mud-palette-primary-rgb), 0.9);
    }
}

/* ─── Gerenciador de NF-e: a barra de ações QUEBRA LINHA ────────────────────────────────────────────
   🩸 Medido na captura de 2026-09-04: a barra tem TREZE ações e não cabe em 1600px — o `MudToolBar` é
   flex SEM quebra e com altura fixa, então os botões do fim saíam cortados no meio da palavra
   ("Consult situaçã", "DANFE)", "Espelh"). ⚠️ O corte é pior que um botão escondido: o operador vê
   meio rótulo e conclui coisa errada sobre o que a ação faz. Em 1024×768 sumia mais da metade.
   ⛔ A saída ⛔ não é encolher a barra escondendo ação em menu: são treze gestos que dependem da
   SITUAÇÃO da nota, e o operador aprende a tela vendo quais estão habilitados. Quebrar a linha
   preserva isso. */
.sis-gerenciador-acoes {
    flex-wrap: wrap;
    height: auto;
    row-gap: 4px;
    padding-top: 6px;
    padding-bottom: 6px;
}

/* Com a barra em duas linhas, o divisor vertical entre os grupos vira um traço solto no fim da linha —
   ele separa GRUPOS de ação, e um separador que não separa nada é ruído. */
.sis-gerenciador-acoes .mud-divider-vertical {
    align-self: stretch;
}

/* =====================================================================================================
   BUSCA POR TÓPICO DENTRO DO MENU DE AJUDA (decisão do dono, 2026-09-04: "a lupa é redundante").

   🔑 A largura é FIXA e maior que a de um item comum: o menu de ajuda se dimensiona pelo item mais largo,
   e um campo que encolhe com o conteúdo faria o menu inteiro pular de tamanho a cada letra digitada.

   ⚠️ `max-height` + rolagem no bloco de RESULTADOS, ⛔ não no menu inteiro: sem isso os cinco resultados
   empurram a Central de Ajuda e o interruptor dos tours para fora da vista — que é a mesma medição que
   trouxe o interruptor para o topo em 2026-08-13.
   ===================================================================================================== */
.sis-ajuda-busca {
    padding: 8px 12px 4px;
    width: 520px;
    max-width: 92vw;
    box-sizing: border-box;
}

.sis-ajuda-busca-resultados {
    width: 520px;
    max-width: 92vw;
    max-height: 72vh;
    overflow-y: auto;
    box-sizing: border-box;
}

/* ⚠️ A lista foi desenhada para o diálogo e para a PÁGINA, que são largos: ali título, origem, descrição e
   os dois botões cabem na mesma linha. Dentro do menu isso esticava o menu inteiro para meia tela — medido
   na captura. Aqui as ações descem para baixo do texto, e a descrição fica em duas linhas. */
.sis-ajuda-busca-resultados .sis-topic-search__item {
    flex-wrap: wrap;
}

.sis-ajuda-busca-resultados .sis-topic-search__descricao {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* =====================================================================================================
   SisAvatarIniciais — o círculo de iniciais que abre a linha da pessoa na grade (molde do sisPainel,
   cores do Sis).

   🔑 Cor tirada do TEMA ATIVO, ⛔ nunca literal: `--mud-palette-primary-rgb` é publicada pelo
   MudThemeProvider, então o mesmo círculo sai no verde #28A745 do claro e no #5FD08A do escuro sem uma
   segunda regra e sem media query. As duas tintas (12% no fundo, 24% no contorno) são as MESMAS do
   .sis-page-header-icon — é o idioma de "marca em caixa" que a tela já fala.

   ⚠️ `flex: 0 0 auto` é o que impede a bolha de virar elipse: dentro do `d-flex` da célula, um nome longo
   espreme tudo que aceite encolher, e um círculo achatado se lê como defeito de renderização.
   ===================================================================================================== */
.sis-avatar-iniciais {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    width: var(--sis-avatar-size, 32px);
    height: var(--sis-avatar-size, 32px);
    border-radius: 50%;
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    line-height: 1;
    user-select: none;
    color: var(--mud-palette-primary);
    background-color: rgba(var(--mud-palette-primary-rgb), 0.12);
    border: 1px solid rgba(var(--mud-palette-primary-rgb), 0.24);
}

/* O ícone da queda (nome sem letra nenhuma) ocupa o mesmo espaço óptico das duas letras. */
.sis-avatar-iniciais .mud-icon-root {
    font-size: 1.05rem;
}

/* -------------------------------------------------------------------------
   Escolha de impressão — as opções em DUAS COLUNAS (2026-09-08, pedido do dono)
   -------------------------------------------------------------------------
   🩸 A lista era vertical, e ela cresceu: com o cupom de bobina a O.S. passou a
      ter CINCO opções, cada uma com uma frase explicando quando serve. Empilhadas,
      o diálogo virou uma coluna alta em que a última linha disputa espaço com o
      rodapé — e a decisão que o operador toma ali é uma COMPARAÇÃO, que é
      justamente o que uma coluna alta atrapalha.

   🔑 A faixa inteira (`--faixa`) NÃO é enfeite: é onde o CUPOM fica, separado das
      vias do A4. As quatro vias existem porque o equipamento FICA (uma folha
      acompanha a entrada, outra a entrega); o cupom é o outro PAPEL, e é um só.
      A grade passou a mostrar o que a decisão já dizia.

   ⚠️ Uma coluna abaixo de 600px, e ⛔ não é preferência: em duas colunas num
      celular a frase de cada opção quebraria em cinco linhas e o cartão viraria
      um parágrafo — a comparação que as colunas existem para permitir some.
   ------------------------------------------------------------------------- */
/* 🔑 Os dois NOMES, uma regra só (2026-09-14, #2453). O diálogo de escolha do caminho fiscal
   (emitir agora × abrir a nota) é o MESMO molde de forma do diálogo de vias da O.S. — cards
   clicáveis com ícone, título e a frase de quando usar —, e o dono pediu explicitamente "o mesmo
   tipo de modal".

   ⛔ Duplicar o bloco seria a divergência garantida: a primeira correção de contraste ou de
   quebra a 600px iria para um dos dois, e a captura do outro só acusaria meses depois.
   ⚠️ `sis-escolha-*` é o nome GENÉRICO e o preferido em telas novas; `sis-via-*` fica porque é o
   que o diálogo da O.S. já usa, e renomear lá seria churn sem ganho. */
.sis-escolha-grid,
.sis-via-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
}

@media (max-width: 599.98px) {
    .sis-escolha-grid,
    .sis-via-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

.sis-escolha-card,
.sis-via-card {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    width: 100%;
    height: 100%;
    padding: 12px;
    text-align: left;
    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;
}

/* 🔑 O realce é EVIDENTE, e ⛔ não um fio de borda: a decisão que se toma aqui é uma comparação entre
      cartões vizinhos, e um destaque tímido ⛔ não diz em qual deles o operador está. */
.sis-escolha-card:hover:not(:disabled),
.sis-escolha-card:focus-visible,
.sis-via-card:hover:not(:disabled),
.sis-via-card:focus-visible {
    border-color: var(--mud-palette-primary);
    background-color: rgba(var(--mud-palette-primary-rgb), .1);
    box-shadow: 0 2px 10px rgba(var(--mud-palette-primary-rgb), .22);
    transform: translateY(-1px);
}

/* ⚠️ O TECLADO ganha um anel POR CIMA do realce do mouse, ⛔ não o mesmo tratamento:
      quem navega por Tab ⛔ não tem o cursor para dizer onde está, então o estado precisa
      ser inconfundível — e ⛔ nunca `outline: none`, que apagaria a única pista que resta. */
.sis-escolha-card:focus-visible,
.sis-via-card:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* ⚠️ Quem pediu para reduzir animação ⛔ não recebe o deslocamento — o realce continua inteiro
      (borda, fundo, sombra e anel), só o movimento sai. */
@media (prefers-reduced-motion: reduce) {
    .sis-escolha-card,
    .sis-via-card {
        transition: none;
    }

    .sis-escolha-card:hover:not(:disabled),
    .sis-escolha-card:focus-visible,
    .sis-via-card:hover:not(:disabled),
    .sis-via-card:focus-visible {
        transform: none;
    }
}

/* O CUPOM, na faixa inteira — ver o porquê no comentário do bloco. */
.sis-escolha-card--faixa,
.sis-via-card--faixa {
    grid-column: 1 / -1;
}

.sis-escolha-card__icone,
.sis-via-card__icone {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background-color: rgba(var(--mud-palette-primary-rgb), .14);
}

.sis-escolha-card__titulo,
.sis-via-card__titulo {
    display: block;
    font-weight: 600;
    line-height: 1.3;
}

/* ⚠️ `min-width: 0` no filho do flex: sem ele a frase longa ⛔ não quebra e o
      cartão estoura a coluna, empurrando o vizinho para fora da grade. */
.sis-escolha-card__texto,
.sis-via-card__texto {
    min-width: 0;
}

.sis-escolha-card__descricao,
.sis-via-card__descricao {
    display: block;
    margin-top: 2px;
    font-size: .8125rem;
    line-height: 1.35;
    color: var(--mud-palette-text-secondary);
}

/* =====================================================================================================
   TELA FINAL DA VENDA (2026-09-12, #1704) — totais, a prévia do cupom e os cards Cupom / NFC-e / saída.
   UM componente para o PDV (overlay do terminal) e para o restaurante (diálogo), por isso mora AQUI e não
   no pdv.css: o restaurante não carrega aquele arquivo. Tudo por variável do tema — a tela é a mesma nos
   dois modos e nos dois hosts.
   ===================================================================================================== */

.sis-concluida {
    display: flex;
    flex-direction: column;
    gap: clamp(10px, 1.2vw, 18px);
    height: 100%;
    min-height: 0;
    padding: clamp(12px, 1.4vw, 24px);
    color: var(--mud-palette-text-primary);
}

.sis-concluida__head {
    display: flex;
    align-items: center;
    gap: 16px;
    flex: 0 0 auto;
}

.sis-concluida__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: rgba(var(--mud-palette-success-rgb), .16);
    color: var(--mud-palette-success);
    flex: 0 0 auto;
}

.sis-concluida__badge .mud-icon-root {
    color: currentColor;
}

.sis-concluida__heading {
    min-width: 0;
}

.sis-concluida__title {
    margin: 0;
    font-size: clamp(1.3rem, 2vw, 1.8rem);
    font-weight: 800;
    line-height: 1.15;
    letter-spacing: .01em;
}

.sis-concluida__subtitle {
    margin: 2px 0 0;
    color: var(--mud-palette-text-secondary);
    font-size: .95rem;
}

.sis-concluida__total {
    margin-left: auto;
    text-align: right;
    flex: 0 0 auto;
}

.sis-concluida__total-label,
.sis-concluida__caption {
    display: block;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.sis-concluida__total-value {
    display: block;
    font-size: clamp(1.6rem, 2.6vw, 2.4rem);
    font-weight: 800;
    line-height: 1.1;
    white-space: nowrap;
}

/* O corpo: resumo | prévia | cards. A prévia é a coluna que cresce — é o produto da tela. */
.sis-concluida__body {
    flex: 1 1 auto;
    min-height: 0;
    display: grid;
    grid-template-columns: minmax(200px, .9fr) minmax(0, 1.8fr) minmax(240px, 1fr);
    gap: clamp(10px, 1.2vw, 18px);
}

.sis-concluida__col {
    display: flex;
    flex-direction: column;
    gap: 10px;
    min-height: 0;
    min-width: 0;
}

.sis-concluida__resumo {
    padding: 14px 16px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 14px;
    background: var(--mud-palette-surface);
    overflow: auto;
}

.sis-concluida__list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.sis-concluida__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 0;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.sis-concluida__row-label {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sis-concluida__row-value {
    font-weight: 700;
    white-space: nowrap;
}

.sis-concluida__row--troco {
    border-bottom: 0;
    color: var(--mud-palette-success);
}

.sis-concluida__row--troco .sis-concluida__row-value {
    font-size: 1.25rem;
    font-weight: 800;
}

.sis-concluida__itens {
    margin-top: auto;
    font-size: .8rem;
    color: var(--mud-palette-text-secondary);
}

.sis-concluida__previa {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 14px;
    background: var(--mud-palette-surface);
    padding: 10px;
    overflow: hidden;
}

.sis-concluida__previa .sis-pdf-viewer {
    flex: 1 1 auto;
    min-height: 0;
}

/* O aviso da queda para o cupom comercial: a nota está autorizada e o DANFE não desenhou. É tonal, ⛔ não
   vermelho — um erro aqui ensinaria a reemitir um documento que já existe. */
.sis-concluida__previa-aviso {
    flex: 0 0 auto;
    padding: 8px 10px;
    border-radius: 10px;
    background: rgba(var(--mud-palette-warning-rgb), .12);
    color: var(--mud-palette-warning-darken);
    font-size: .8rem;
    line-height: 1.35;
}

.sis-concluida__previa-vazia {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 24px;
    text-align: center;
    color: var(--mud-palette-text-secondary);
}

/* Os cards. Superfície do tema com contorno; só o de SAÍDA é sólido — é o gesto que conclui. */
.sis-concluida__card {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    width: 100%;
    padding: 14px 16px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 14px;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    text-align: left;
    font: inherit;
}

.sis-concluida__card--aviso {
    border-color: rgba(var(--mud-palette-warning-rgb), .6);
    background: rgba(var(--mud-palette-warning-rgb), .08);
}

.sis-concluida__card--aviso .sis-concluida__card-icon {
    background: rgba(var(--mud-palette-warning-rgb), .18);
    color: var(--mud-palette-warning);
}

.sis-concluida__card-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: rgba(var(--mud-palette-primary-rgb), .14);
    color: var(--mud-palette-primary);
    flex: 0 0 auto;
}

.sis-concluida__card-icon .mud-icon-root {
    color: currentColor;
}

.sis-concluida__card-body {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
    flex: 1 1 auto;
}

.sis-concluida__card-title {
    font-weight: 800;
    line-height: 1.2;
}

.sis-concluida__card-detail {
    font-size: .8rem;
    line-height: 1.35;
    color: var(--mud-palette-text-secondary);
    overflow-wrap: anywhere;
}

.sis-concluida__card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 6px;
}

/* A saída: sólido, e é BOTÃO — foco por teclado, papel de botão no leitor, :active de toque sem JS. */
button.sis-concluida__card--primary {
    margin-top: auto;
    align-items: center;
    border-color: transparent;
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    cursor: pointer;
    transition: background .12s ease;
}

button.sis-concluida__card--primary .sis-concluida__card-icon {
    background: rgba(255, 255, 255, .18);
    color: currentColor;
}

button.sis-concluida__card--primary .sis-concluida__card-title {
    font-size: 1.05rem;
}

button.sis-concluida__card--primary .sis-concluida__card-detail {
    color: inherit;
    opacity: .85;
}

button.sis-concluida__card--primary:hover:not(:disabled),
button.sis-concluida__card--primary:focus-visible {
    background: var(--mud-palette-primary-darken);
    outline: none;
}

button.sis-concluida__card--primary:disabled {
    opacity: .6;
    cursor: not-allowed;
}

/* Num terminal de 1024×768 falta ALTURA, não largura: os cards descem para baixo do resumo e a prévia
   ganha a coluna inteira da direita. No celular, tudo em UMA coluna e a prévia com altura própria. */
@media (max-width: 1100px) {
    .sis-concluida__body {
        grid-template-columns: minmax(220px, 1fr) minmax(0, 1.6fr);
    }

    .sis-concluida__previa {
        grid-row: 1 / span 2;
        grid-column: 2;
    }

    .sis-concluida__acoes {
        grid-column: 1;
    }
}

@media (max-width: 760px) {
    .sis-concluida {
        height: auto;
        overflow: auto;
    }

    .sis-concluida__body {
        grid-template-columns: minmax(0, 1fr);
    }

    .sis-concluida__previa {
        grid-row: auto;
        grid-column: auto;
        min-height: 360px;
    }

    .sis-concluida__acoes {
        grid-column: auto;
    }

    .sis-concluida__total-value {
        font-size: 1.5rem;
    }
}

/* O diálogo do restaurante: altura fixa para a prévia ter onde crescer — sem ela o iframe do PDF mede
   zero e a tela abre só com os cards. */
.sis-concluida-dialog .sis-concluida-dialog__content {
    height: min(78vh, 760px);
    padding: 0;
}

.sis-concluida-dialog .sis-concluida-dialog__content .sis-concluida {
    height: 100%;
}

/* ══ Observação do título nas consultas de Contas a Receber / a Pagar (#2431) ═════════════════════

   🩸 A #1939 removeu colunas destas duas grades por excesso de largura (329 px medidos). O campo de
   observação aceita 1.000 caracteres e ⛔ não cabe em grade nenhuma, então a coluna é ESTREITA e
   trunca: o texto inteiro fica no `title` da célula, que é o que o navegador já sabe mostrar sem
   custar pixel.

   ⚠️ `max-width` com `overflow:hidden` só trunca porque a célula é `table-cell` de tabela com
   layout automático — sem o `max-width` o texto alargaria a coluna e empurraria Valor e Saldo para
   fora da tela em 1024×768, que é o defeito que a #1939 consertou. */
.sis-grid-observacao {
    display: block;
    max-width: 180px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: .8rem;
    color: var(--mud-palette-text-secondary);
}

/* ══ Chave de acesso no roteiro do romaneio (#2758) ═══════════════════════════════════════════════

   🩸 Medido pela CAPTURA de 2026-09-13: a chave resumida (`…` + 12 posições) quebrava em DUAS linhas,
   deixando o `…` sozinho na primeira — o operador confere esses dígitos contra o DANFE, e um número
   partido no meio é justamente o que ele ⛔ não consegue conferir de relance.

   ⚠️ O markup estava perfeito e o bUnit verde: quebra de linha ⛔ não aparece em asserção de texto. */
.sis-romaneio-chave {
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    font-size: .85rem;
}

.sis-romaneio-roteiro td {
    vertical-align: middle;
}

/* 🔒 O roteiro tem SEIS colunas mais as ações, e em 1024×768 a última — a CONFERÊNCIA, que é o assunto
   da tela depois do despacho — saía do quadro. A régua da casa para isto é uma só: tabela que não cabe
   rola em container PRÓPRIO, ⛔ nunca faz a página rolar de lado.

   ⚠️ O `min-width` é o que faz a rolagem existir: sem ele o navegador espreme as colunas até o texto
   virar uma letra por linha, que é "cabe" sem ser legível. */
.sis-romaneio-roteiro,
.sis-romaneio-disponiveis {
    overflow-x: auto;
}

.sis-romaneio-disponiveis table {
    min-width: 720px;
}

/* ⚠️ O roteiro pede MAIS que os disponíveis porque tem uma coluna a mais — a das grandezas (#2788).
   Os dois números são medidos pela captura em 1024×768, ⛔ não copiados um do outro: igualá-los
   devolveria a coluna de ações para fora do quadro, que é o defeito que esta regra conserta. */
.sis-romaneio-roteiro table {
    min-width: 880px;
}

/* 🩸 Medido pela CAPTURA em 1024×768: o endereço completo ("Rua X, 88 · Centro · Cascavel - PR · CEP
   85801000") quebrava em SEIS linhas, cada parada virava um bloco alto, só duas entregas cabiam na tela
   e a coluna de ações saía do quadro. É a mesma classe de defeito que a #1939 consertou nas grades de
   Contas a Receber/Pagar — e a cura é a mesma: a célula TRUNCA e o texto inteiro vive no `title`, que o
   navegador já sabe mostrar sem custar pixel.

   ⚠️ Invisível no bUnit: o markup é idêntico: quem vê é a captura. */
.sis-romaneio-endereco {
    display: block;
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (max-width: 1280px) {
    .sis-romaneio-endereco {
        max-width: 150px;
    }
}

/* ── (#2710, K5) Categoria de SISTEMA na tela de Categorias ──────────────────────────────────────
   Em cinza porque ⛔ se edita: o produto lança nela (adiantamento, cartão, cheque) e o operador só a VÊ.
   A cor é a secundária do TEMA (acompanha claro/escuro e passa no piso de contraste do grid). */
.sis-data-grid .mud-table-body tr.sis-categoria-sistema td {
  color: var(--mud-palette-text-secondary);
}

/* ══ As quatro grandezas no roteiro (#2788) ═══════════════════════════════════════════════════════

   A coluna empilha DOIS pares (peso · itens / volumes · valor) em vez de quatro colunas próprias: o
   papel é A4 paisagem e comporta nove colunas, a tela tem de caber em 1024×768, e quatro colunas
   numéricas espremeriam o ENDEREÇO — que é o que o operador confere.

   ⚠️ `tabular-nums` é o que faz os números de paradas vizinhas ficarem alinhados na vertical: com
   dígitos de larguras diferentes, uma coluna de pesos não se compara de relance. */
.sis-romaneio-grandezas {
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    font-size: .85rem;
}

/* A parada cujas grandezas alguém INFORMOU à mão fica em peso médio — é o que distingue, sem um
   segundo ícone por linha, o número conferido do número calculado. */
.sis-romaneio-grandezas [data-grandezas="informado"] {
    font-weight: 500;
}

/* A faixa de totais é o que o conferente bate contra a carroceria: separada do roteiro por uma régua,
   ⛔ não solta logo abaixo da última linha, onde se lê como mais uma parada. */
.sis-romaneio-totais {
    border-top: 1px solid var(--mud-palette-lines-default);
    font-variant-numeric: tabular-nums;
}

/* DE ONDE o documento veio, na célula da grade — o `SisDocumentoDeOrigem` (#2855).

   🔑 Ele é a SEGUNDA LINHA da célula do número, então o tamanho e a entrelinha são os que a consulta de
   vendas já media: mexer neles alarga a coluna que a #1939 mediu transbordando 198px em 1440px.

   ⚠️ A cor do link é HERDADA (`currentColor`), ⛔ nunca a primária do tema: a linha é texto secundário, e
   um link azul-vivo aqui competiria com o número da venda logo acima — que é o dado principal da célula.

   🩸 Mas ⛔ NÃO basta herdar a cor e esperar o hover: na captura de 2026-09-14 o link ficou
   INDISTINGUÍVEL de texto comum nos quatro quadros, e link que ⛔ não se anuncia é link que ninguém
   clica — a entrega falharia na prática passando em todo teste. ⇒ sublinhado PONTILHADO em repouso
   (discreto o bastante para ⛔ não competir com o número) e SÓLIDO no hover e no foco. */
.sis-documento-origem {
    font-size: .75rem;
    line-height: 1.1;
}

.sis-documento-origem__link {
    color: inherit;
    text-decoration: underline dotted;
    text-underline-offset: 2px;
    text-decoration-thickness: 1px;
}

.sis-documento-origem__link:hover,
.sis-documento-origem__link:focus-visible {
    color: var(--mud-palette-primary);
    text-decoration: underline solid;
}

/* ⚠️ O separador é `aria-hidden` no markup e decorativo aqui: quem ouve a linha num leitor de tela recebe
   dois links seguidos, ⛔ não um "ponto" entre eles. */
.sis-documento-origem__separador {
    margin: 0 .25rem;
    opacity: .6;
}

/* 📊 Vendas × Lucratividade (#2980) — a sublinha do PRODUTO, no modo analítico.
   🔑 Ela usa as mesmas colunas da linha da venda (ver o markup), então o que a distingue é só o peso: um
   fundo de baixa opacidade e o texto secundário. ⛔ Sem cor própria — a distinção é hierarquia, não estado,
   e cor aqui competiria com o vermelho do prejuízo na coluna de lucro. */
.lucratividade-item > td {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 4%, transparent);
    color: var(--mud-palette-text-secondary);
    font-size: .875rem;
}

/* ==========================================================================
   COMANDA E CARDÁPIO LADO A LADO  (#3102, 2026-09-21)

   O lançamento de itens deixou de ser uma tela à parte: o cardápio fica ao lado da comanda e não se
   desmonta. Em tela larga são duas colunas; no telefone o cardápio é uma gaveta por cima da comanda.

   🔑 A gaveta fecha com `display: none`, ⛔ nunca tirando o componente da árvore de render do Blazor —
   escondido, ele guarda a categoria, o texto buscado e o scroll; removido, volta zerado, que é o
   defeito que esta frente veio consertar.
   ========================================================================== */

/* 🔑 Quem tem largura FIXA é a COMANDA; o cardápio fica com o resto (pedido do dono, 2026-09-21).

   A primeira versão fazia o contrário — comanda em `1fr`, cardápio travado em 30rem — e o resultado era
   desproporcional: em 1600px a comanda ficava com ~820px para uma lista de itens que raramente passa de
   meia dúzia de linhas, enquanto o cardápio, que é a grade que o operador realmente percorre, ficava
   espremido em 480px e com três produtos por fileira.

   ⚠️ 36rem (576px) ⛔ não é um número escolhido no olho: é a menor largura em que a comanda ainda desenha
   a linha do item inteira — quantidade, descrição, selo da cozinha, total e os botões de ajuste — sem
   quebrar. A medição que a fixou foi a captura de 1024×768 da primeira versão, onde a comanda caiu para
   ~470px: as ações empilharam na vertical e o selo da cozinha subiu por cima da descrição. */
.sis-tab-split {
    display: grid;
    grid-template-columns: minmax(0, 36rem) minmax(0, 1fr);
    gap: 16px;
    align-items: start;
}

/* min-width: 0 nas duas colunas: sem ele um nome de produto longo (ou uma linha de item) estica a
   coluna e empurra a vizinha para fora da tela, em vez de quebrar. */
.sis-tab-split__tab {
    min-width: 0;
}

/* O cardápio acompanha a rolagem: numa mesa com trinta itens, quem rola a lista para conferir continua
   com a grade de produtos à vista. */
.sis-tab-split__menu {
    min-width: 0;
    position: sticky;
    top: 8px;
    max-height: calc(100vh - 7rem);
    display: flex;
    flex-direction: column;
}

.sis-launch-panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    max-height: 100%;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--mud-default-borderradius);
    padding: 12px;
    background: var(--mud-palette-surface);
}

.sis-launch-panel__head {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-bottom: 12px;
}

.sis-launch-panel__title {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* A grade rola DENTRO do painel. Deixar a página rolar levaria embora o cabeçalho da comanda cada vez
   que alguém procurasse um produto no fim do cardápio. */
.sis-launch-panel__grid {
    overflow-y: auto;
    min-height: 0;
    flex: 1 1 auto;
}

/* A montagem ocupa o lugar da grade, com as ações ancoradas no rodapé do painel: uma pizza com muitos
   grupos rola, e o botão que conclui não pode depender de chegar ao fim da lista. */
.sis-assembly-panel {
    display: flex;
    flex-direction: column;
    min-height: 0;
    flex: 1 1 auto;
}

.sis-assembly-panel__head {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-bottom: 8px;
}

.sis-assembly-panel__body {
    overflow-y: auto;
    min-height: 0;
    flex: 1 1 auto;
}

.sis-assembly-panel__actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    padding-top: 12px;
    border-top: 1px solid var(--mud-palette-lines-default);
    margin-top: 12px;
}

/* Em tela larga o cardápio está sempre à vista, então não há o que fechar nem o que abrir: o X do
   painel e o botão "Lançar itens" da comanda são gestos do TELEFONE e somem aqui.

   🔑 `sis-launch-trigger` tem nome PRÓPRIO, ⛔ não `sis-tab-actions__launch`: os dois botões que ela
   marca vivem em blocos diferentes (`sis-tab-actions` na gerência, `sis-waiter-actionbar` no garçom), e
   um nome BEM de um bloco aplicado dentro do outro é incoerente — além de inflar a contagem do bloco pai
   na varredura de seletores compartilhados.

   ⚠️ Quem decide isto é a folha de estilo, ⛔ não um `if` de largura no componente: a tela não pergunta
   onde está rodando. Em compensação, o bUnit (que não aplica media query) enxerga os dois elementos
   sempre — é o E2E, com viewport de verdade, que mede a regra. */
.sis-launch-panel__close,
.sis-launch-trigger {
    display: none;
}

/* 🩸 O ponto de quebra é 1280px, ⛔ não os 960px do `md` do MudBlazor, e o número saiu de MEDIÇÃO na
   captura de 1024×768: o menu lateral do ERP come 280px, então ali sobram 744px de conteúdo — as duas
   colunas cabiam na conta do CSS e a COMANDA ficava espremida em ~470px, com as ações empilhadas numa
   fileira vertical, a descrição do item quebrada em três linhas e o selo da cozinha por cima do texto.

   🔑 A régua: o ponto de quebra se mede pela ÁREA DE CONTEÚDO, ⛔ não pela janela — quem divide o espaço
   com este layout é a casca, e ela não aparece na media query. 1280 − 280 = 1000px, que é onde a comanda
   volta a respirar (≈520px) com o cardápio inteiro ao lado.

   ⚠️ Abaixo disso o cardápio é a GAVETA, que é o mesmo gesto do telefone — ⛔ não uma versão pior: ele
   continua montado atrás da comanda, com a categoria e a busca onde o operador deixou. */
@media (max-width: 1279.98px) {
    .sis-tab-split {
        display: block;
    }

    /* Fechada, a gaveta continua MONTADA e apenas invisível — ver a nota do topo deste bloco. */
    .sis-tab-split__menu {
        display: none;
        position: fixed;
        inset: 0;
        z-index: 1300;
        max-height: none;
        padding: 8px;
        background: var(--mud-palette-surface);
        overflow-y: auto;
    }

    .sis-tab-split--menu-open .sis-tab-split__menu {
        display: flex;
    }

    .sis-launch-panel {
        border: none;
        max-height: 100%;
    }

    .sis-launch-panel__close,
    .sis-launch-trigger {
        display: inline-flex;
    }
}

/* (#3304) A prévia das parcelas no diálogo de pagamento da Força de Vendas, a 390 px: com o vencimento
   EDITÁVEL a coluna da data vira um campo com o ícone do calendário, e com o padding padrão da tabela ele
   ficava cortado ("24/09/2") e o valor quebrava em duas linhas ("R$ / 1,62"). A data ocupa a sobra, o valor
   ⛔ quebra, e o padding encolhe — medido na captura do E2E, que é quem vê layout. */
.sis-fv-parcelas td {
    padding: 4px 6px !important;
}

.sis-fv-parcelas td:nth-child(2) {
    width: 100%;
}

.sis-fv-parcelas td:last-child {
    white-space: nowrap;
}

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   RESUMO FINANCEIRO (#3358): o card de total e a tabela agrupada com (+)/(−) — o idioma dos
   relatórios financeiros (docs/design-visual-telas-blazor.md §6.3).

   🔑 A linha do GRUPO é o botão inteiro (clique, Enter, espaço), e a cor do fundo vem da paleta do
   tema (mode-aware) — ⛔ não de `--mud-palette-gray-light`, que não acompanha o modo (CLAUDE.md).
   ═══════════════════════════════════════════════════════════════════════════════════════════════ */

.sis-resumo-card {
    height: 100%;
}

.sis-resumo-card__valor {
    line-height: 1.25;
    white-space: nowrap;
}

.sis-resumo-card__icone {
    flex: 0 0 auto;
    font-size: 1.75rem;
}

.sis-tabela-agrupada__grupo {
    cursor: pointer;
    user-select: none;
}

.sis-tabela-agrupada__grupo > td {
    background: var(--mud-palette-background-gray);
    border-top: 2px solid var(--mud-palette-lines-default);
}

.sis-tabela-agrupada__grupo:focus-visible > td {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -2px;
}

/* O espaçador (MudSpacer) dentro do cabeçalho do grupo empurra os totais para a direita. */
.sis-tabela-agrupada__grupo .mud-spacer {
    flex-grow: 1;
}

/* Comissões (#3424): os cards de total numa faixa que se divide por igual — sete cabem numa linha a 1600 e
   quebram em duas a 1024. `min-width: 0` deixa o card encolher em vez de empurrar o vizinho para fora. */
.sis-comissoes-card {
    flex: 1 1 170px;
    min-width: 0;
}

/* Comissões (#3493, F3): com o bônus por meta, o sintético por vendedor tem DOZE colunas — o dinheiro é
   `nowrap`, e com os 16 px de cada lado do MudBlazor a grade rolava na horizontal a 1600 (medido na captura). */
.sis-comissoes-sintetico .mud-table-cell {
    padding-left: 8px !important;
    padding-right: 8px !important;
}

/* Pedido de compra (#3351): nove colunas cabem na coluna de 8/12 a 1600 com o respiro lateral curto —
   com os 16/24 px do MudBlazor a grade transbordava e a coluna de ações saía da tela. */
.sis-pedido-compra-itens .mud-table-cell {
    padding-left: 6px !important;
    padding-right: 6px !important;
}
