/* ===== 07-documento.css — itens, parcelas, stepper, fotos, visor, assinatura, campo select =====
   Fatia do antigo app.css (09/08/2026). O NÚMERO NO NOME É A POSIÇÃO NA CASCATA: é a ordem
   dos <link> no index.html, e trocá-la muda quem vence. Regra e política em 01-base.css. */

/* Frame de itens do orçamento — destaca o bloco de itens (cabeçalho + lista + total) do resto do
   formulário, que é só campos soltos. */
.itens-panel {
    margin: 0 0 1rem;
    padding: .9rem .95rem 1rem;
    background: var(--brand-tint);
    border: 1px solid #E3AFA0;
    border-radius: .8rem;
}

.itens-panel .section-header { margin-bottom: .6rem; }

.itens-panel h2 {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 800;
    color: var(--brand-dark);
}

.itens-total {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    margin-top: .75rem;
    padding-top: .6rem;
    border-top: 1px dashed #E3AFA0;
    font-weight: 700;
    color: var(--brand-dark);
}

.itens-total .value { font-size: 1.2rem; font-weight: 800; }

/* Card de item do orçamento — layout dedicado (cliente-card genérico é compartilhado com listas de
   outras entidades, e ali título+ações dividem espaço com o subtítulo na mesma linha, quebrando
   feio). Aqui título+ações ficam na 1ª linha; quantidade/preço/subtotal ocupam a 2ª linha inteira. */
.item-card {
    display: flex;
    flex-direction: column;
    gap: .35rem;
    padding: .85rem .9rem;
    border: 1px solid var(--line);
    border-radius: .7rem;
    background: #fff;
}

.item-card-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: .5rem;
}

.item-card-title { font-size: 1rem; min-width: 0; }

.item-card-actions { display: flex; gap: .25rem; flex-shrink: 0; }

.item-card-detail {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: .5rem;
    font-size: .85rem;
    color: var(--muted);
}

.item-card-detail .value { font-weight: 700; color: var(--ink); }

/* Campo criticado à mão — os sheets em que a conferência não passa pelo DataAnnotationsValidator
   (os três campos do item em Orçamento/OS, o Reagendar da Agenda, o Agendar retorno dos Lembretes).
   Quem recebe a classe é o `.field`, não o input, por duas razões:

   (a) `CampoData` fixa o próprio `class` — o `@attributes` do chamador vem ANTES no template, e em
       Razor o último atributo vence —, então classe nenhuma chega lá pelo splat. Marcando o
       wrapper, a mesma regra serve input cru, `InputQty`/`InputMoney` e `CampoData`;
   (b) o seletor precisa vencer a regra verde do Blazor de qualquer jeito. `InputQty`/`InputMoney`
       são `InputBase`: perguntam a classe ao EditContext e recebem `modified valid` — o campo não
       tem regra nenhuma no modelo, então passa por válido —, e `.valid.modified:not(...)` (três
       níveis) vence um `.invalid` de um nível só. O campo criticado ficava **verde** a partir do
       primeiro toque, isto é, o `.invalid` só pegava em campo intocado, que é quando não importa.
       Aqui são quatro níveis, e não depende da ordem do arquivo. */
.field.is-critico .input:not([type=checkbox]) {
    outline: 1px solid var(--danger);
}

/* ---- Resumo dos itens dentro do sheet de digitação (OrcamentoForm) ----
   Grade de leitura, fonte menor que a do formulário de propósito: ela confere o que já entrou, não
   compete com os campos que estão sendo preenchidos logo acima. Sem ação nenhuma nas linhas —
   editar e remover continuam nos cards da página, atrás do sheet. */
.itens-resumo {
    width: 100%;
    border-collapse: collapse;
    margin: 0 0 .5rem;
    font-size: .78rem;
    line-height: 1.25;
}

/* Colunas numéricas no tamanho do próprio conteúdo (nowrap, sem width): valor de orçamento vai de
   "90,00" a "12.500,00" e uma largura em % cortaria justamente o maior. */
.itens-resumo th,
.itens-resumo td {
    padding: .3rem .35rem;
    text-align: right;
    white-space: nowrap;
}

.itens-resumo th {
    color: var(--muted);
    font-weight: 600;
    border-bottom: 1px solid var(--line);
}

/* A descrição fica com a sobra da largura. O par width:100% + max-width:0 é o que faz o ellipsis
   funcionar dentro de tabela: sem o max-width a célula cresce com o texto (a largura da coluna é
   calculada a partir do conteúdo) e nunca há o que truncar. */
.itens-resumo .resumo-desc {
    width: 100%;
    max-width: 0;
    text-align: left;
    overflow: hidden;
    text-overflow: ellipsis;
}

.itens-resumo tbody td { border-bottom: 1px solid var(--line); }
.itens-resumo .value { font-weight: 700; color: var(--ink); }
.itens-resumo .resumo-rotulo { text-align: left; color: var(--muted); }

.itens-resumo tfoot td {
    border-top: 1px solid var(--line);
    padding-top: .45rem;
    font-weight: 700;
}

/* Linha que está aberta nos campos acima (sheet em modo "Editar item") — sem esta marca, a grade
   mostra os valores de ANTES da edição e não há como saber qual das linhas eles são. */
.itens-resumo tr[aria-current] td { background: var(--brand-tint); }

/* ---- Parcelamento do recebimento (RecebimentoForm, modo "Parcelado") ----
   As linhas do plano reusam o .item-card do orçamento, mas cada uma carrega DOIS campos editáveis
   (valor e vencimento) em vez de texto: pelo ADR 0010 cada parcela é um recebimento independente, e
   negociação desigual ("500 agora, 250 e 250") é rotina. Lado a lado enquanto couber; empilhados no
   celular estreito, porque um <input type="date"> não encolhe abaixo da largura do seu próprio
   formato e espremê-lo corta o ano. */
.parcela-campos {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
}

.parcela-campo {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    flex: 1 1 9rem;
    min-width: 0;
}

.parcela-campo label {
    font-size: .78rem;
    color: var(--muted);
}

.parcela-campo .input { margin-bottom: 0; }

/* ---- Prévia do recebimento mensal (RecebimentoForm, modo "Todo mês") ----
   Não reusa o .item-card do parcelamento porque aqui não há campo editável: no mensal as linhas são
   iguais por definição (o que varia é a data), e ajustar um mês específico se faz depois, no card
   dele — cada linha nasce um recebimento comum. São até 12, e como cartões de dois campos elas
   empurrariam o Salvar para bem longe do polegar; em uma linha cada, a lista inteira cabe na tela. */
.plano-mensal {
    list-style: none;
    margin: 0 0 .5rem;
    padding: 0;
    border: 1px solid var(--line);
    border-radius: .7rem;
    overflow: hidden;
    background: var(--bg);
}

.plano-mensal li {
    display: flex;
    align-items: baseline;
    gap: .5rem;
    padding: .45rem .6rem;
    border-bottom: 1px solid var(--line);
    font-size: .9rem;
}

.plano-mensal li:last-child { border-bottom: none; }
.plano-mensal .plano-mes { color: var(--muted); min-width: 4.5rem; }
.plano-mensal .plano-data { flex: 1 1 auto; }
.plano-mensal .value { font-weight: 700; }

/* Passo a passo do número de parcelas. Alvo de toque de 44px nas duas pontas (a mão que segura o
   celular no cliente é uma só) e o valor no meio com largura fixa, para o texto não empurrar os
   botões de lugar ao passar de "9 parcelas" para "10 parcelas". */
.stepper {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .25rem;
    border: 1px solid var(--line);
    border-radius: .7rem;
    background: var(--bg);
    margin-bottom: .35rem;
}

.stepper-valor {
    flex: 1 1 auto;
    text-align: center;
    font-weight: 700;
    color: var(--ink);
}

/* Seletor de modo do recebimento: são 4 opções desde o mensal, e "Vou receber depois" não cabe num
   quarto de linha a 360px — viraria três linhas de texto, deixando o grupo MAIS alto do que a grade
   2x2 que a alternativa produz. A quebra continua acontecendo dentro do chip, sem espremer a fonte
   de todo chip-group do app. */
.chip-group-modo {
    display: grid;
    grid-template-columns: 1fr 1fr;
}

.chip-group-modo .chip {
    font-size: .88rem;
    line-height: 1.15;
    text-align: center;
    padding: .5rem .35rem;
}

/* Divisórias da grade. O .chip separa por border-right, que numa única fileira basta; em duas
   fileiras é o :last-child de lá que erra — ele zera a borda do 4º chip, não a do 2º, que é quem
   encosta na borda direita da barra. */
.chip-group-modo .chip:nth-child(2n) { border-right: none; }
.chip-group-modo .chip:nth-child(-n+2) { border-bottom: 1px solid var(--line); }

/* Fotos da ordem de serviço (S8) — grade de miniaturas com botão de remover sobreposto. */
.foto-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
    gap: .5rem;
    margin-bottom: .75rem;
}

.foto-thumb {
    position: relative;
    aspect-ratio: 1;
    border-radius: .5rem;
    overflow: hidden;
    border: 1px solid var(--line);
    background: #fff;
}

.foto-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* A miniatura inteira é o gatilho do visor. Botão, e não <div @onclick>, porque é o que dá foco,
   Enter/Espaço e anúncio de leitor de tela de graça — mas aí precisa perder o estilo nativo e
   voltar a ser uma moldura. Irmão do .foto-thumb-remove, nunca pai: botão dentro de botão é HTML
   inválido, e o que o navegador faz com isso varia. */
.foto-thumb-abrir {
    display: block;
    width: 100%;
    height: 100%;
    padding: 0;
    border: none;
    background: none;
    cursor: zoom-in;
}

.foto-thumb-remove {
    position: absolute;
    top: .2rem;
    right: .2rem;
    background: rgba(0, 0, 0, .55);
    color: #fff;
}

/* Visor de foto em tela cheia (VisorFotos). Preto opaco de propósito: não há nada de útil por
   baixo, e fundo translúcido faria a foto competir com a tela. Um degrau acima dos sheets (30/31),
   porque a miniatura pode ser tocada de dentro de um. */
.visor {
    position: fixed;
    inset: 0;
    z-index: 40;
    display: flex;
    flex-direction: column;
    background: #000;
}

.visor-topo {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    padding: .5rem .75rem;
    padding-top: max(.5rem, env(safe-area-inset-top));
    color: #fff;
}

.visor-contador {
    font-size: .9rem;
    color: rgba(255, 255, 255, .85);
}

.visor-btn {
    color: #fff;
    background: rgba(255, 255, 255, .12);
}

.visor-btn:hover { background: rgba(255, 255, 255, .22); }

/* min-height: 0 é o que permite a imagem encolher dentro do flex — sem ele o item flex assume o
   tamanho natural da foto (1280px) e o topo/rodapé saem da tela em vez de a imagem caber. */
.visor-palco {
    flex: 1;
    min-height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: .5rem;
}

.visor-palco img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}

.visor-navegacao {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 2rem;
    padding: .75rem;
    padding-bottom: max(.75rem, env(safe-area-inset-bottom));
}

/* Texto livre que o prestador escreveu em várias linhas (o "O que foi feito" do comprovante). Sem
   pre-wrap o HTML colapsa as quebras e a lista que ele digitou vira um parágrafo corrido. */
.texto-longo { white-space: pre-wrap; }

/* Assinatura do cliente final (S8) — canvas de desenho e preview do PNG salvo. */
.assinatura-canvas {
    width: 100%;
    max-width: 100%;
    height: auto;
    aspect-ratio: 600 / 220;
    border: 1px dashed var(--line);
    border-radius: .5rem;
    background: #fff;
    touch-action: none;
    margin-bottom: .6rem;
}

.assinatura-preview {
    width: 100%;
    max-width: 320px;
    border: 1px solid var(--line);
    border-radius: .5rem;
    background: #fff;
    margin-bottom: .6rem;
}

/* Resumo de seleção (cliente/equipamento já escolhidos) */
.picker-summary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    padding: .75rem .85rem;
    border: 1px solid var(--line);
    border-radius: .7rem;
    background: #fff;
}

/* Campo de escolha entre opções fixas (CampoSelect) — mesmo desenho do .picker-summary, porque é o
   mesmo gesto: um resumo tocável que abre a lista num BottomSheet. Aqui o elemento é um <button>
   (todo o campo abre o sheet), então precisa neutralizar o estilo nativo de botão e voltar ao
   alinhamento de campo de formulário. */
.campo-select {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .5rem;
    width: 100%;
    padding: .75rem .85rem;
    border: 1px solid var(--line);
    border-radius: .7rem;
    background: #fff;
    font: inherit;
    color: var(--ink);
    text-align: left;
    cursor: pointer;
}

.campo-select:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.campo-select:active { background: var(--surface-2, #f6f5f2); }
.campo-select:disabled { opacity: .6; cursor: default; }

.campo-select > .icon { flex: 0 0 auto; color: var(--muted); }

/* O valor escolhido quebra em vez de estourar o botão (rótulos como "Refrigeração e
   ar-condicionado" não cabem em 360px). */
.campo-select-valor { min-width: 0; }
.campo-select-placeholder { min-width: 0; color: var(--muted); }

