/* ============================================================
   MARCENARIA APP — ESTILO BASE
   Identidade: "desenho técnico de marcenaria"
   Tipografia com peso de régua/esquadro + azul-projeto de destaque
   + tom madeira nos acentos + números em monoespaçada
   ============================================================ */

/* As fontes sao declaradas no <head> de cada pagina, com preconnect.
   Um @import aqui obrigaria o navegador a baixar e interpretar esta
   folha inteira antes de sequer descobrir a URL das fontes. */

:root {
  /* cores base */
  --bg: #EFEDE6;
  --bg-panel: #FFFFFF;
  --ink: #2A2420;
  --ink-soft: #6B6258;
  --line: #DAD5C9;

  /* acento principal: azul-projeto (blueprint) */
  --accent: #1F5A5E;
  --accent-hover: #164548;
  --accent-soft: #E4EEEE;

  /* acento secundário: madeira */
  --wood: #C17D3F;
  --wood-hover: #A8692F;
  --wood-soft: #F5E6D3;
  /* variante só para TEXTO sobre --wood-soft (ou outro fundo claro): o
     --wood original dá 2.73:1 nesse par, abaixo do mínimo WCAG AA de
     4.5:1 para texto normal. --wood-hover chega a 3.63:1, ainda abaixo.
     Este tom mantém o matiz de madeira e passa em 4.82:1. Não mexe em
     --wood nem --wood-hover -- esses continuam corretos para fundo
     sólido com texto branco (.btn-wood, .subtab-btn.active). */
  --wood-text: #8F5726;

  /* status do orçamento */
  --status-pending: #C17D3F;
  --status-pending-soft: #F5E6D3;
  --status-pending-text: var(--wood-text); /* mesmo par de cor do wood, mesma correção */
  --status-approved: #3F7A52;
  --status-approved-soft: #E3EFE5;
  --status-declined: #9C3F32;
  --status-declined-soft: #F3E3E0;
  --status-declined-hover: #7E332A;

  /* texto sobre fundo escuro ou colorido.
     Estes tons apareciam repetidos como literais (#F4F2EA em 5 lugares,
     #fff em 9): fora dos tokens, mudar a identidade obrigava a caçar
     hexadecimal por toda a folha, que é justamente o que os tokens
     existem para evitar. */
  --on-dark: #F4F2EA;        /* texto principal sobre o cabeçalho */
  --on-dark-soft: #D8D3C6;   /* itens de menu em repouso */
  --on-dark-dim: #B9B2A5;    /* etiquetas e legendas no escuro */
  --on-accent: #FFFFFF;      /* texto sobre acento, status e madeira */

  /* tipografia */
  --font-display: 'Zilla Slab', serif;
  --font-body: 'IBM Plex Sans', sans-serif;
  --font-mono: 'IBM Plex Mono', monospace;

  /* forma */
  --radius: 10px;
  --radius-sm: 6px;
  --shadow: 0 1px 2px rgba(42,36,32,0.06), 0 4px 14px rgba(42,36,32,0.07);
  --shadow-lg: 0 8px 30px rgba(42,36,32,0.16);
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 .5em 0;
}

/* :not(.btn) é obrigatório aqui. Sem ele, "a:hover" (especificidade 0,1,1)
   vence o "color" de .btn-primary (0,1,0) e o texto do link-botão assume a
   MESMA cor do fundo no hover -- o botão fica aparentemente vazio. */
a:not(.btn) { color: var(--accent); text-decoration: none; }
a:not(.btn):hover { color: var(--accent-hover); }

/* link estilizado como botão herda a cor da própria variante do botão */
a.btn { text-decoration: none; }

.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* ============================================================
   HEADER / MENU ESTÁTICO
   ============================================================ */
.app-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--ink);
  color: var(--on-dark);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 28px;
  /* 72px e não 64: logo de marcenaria costuma ser "empilhada" (símbolo em
     cima, nome embaixo), e a 30px de altura o nome virava um borrão. Com
     72px a marca respira sem o cabeçalho virar uma faixa. */
  min-height: 64px;
  /* NÃO quebrar: com flex-wrap:wrap o navegador joga o bloco do usuário
     para uma segunda linha ANTES de encolher a marca -- a quebra tem
     prioridade sobre o encolhimento no flexbox. Em nowrap, quem cede é
     a marca (que trunca), e o menu fica sempre numa linha só. */
  flex-wrap: nowrap;
  gap: 16px;
  box-shadow: var(--shadow);
}

.app-header .brand {
  display: flex;
  align-items: baseline;
  gap: 8px;
  /* o nome da marcenaria é livre e pode ser longo ("BIGODE MÓVEIS
     PLANEJADOS E PORTAS" tem 33 caracteres). Sem teto, ele empurrava o
     menu para uma segunda linha em telas de 1280 e 1366px. */
  /* sem teto fixo: a marca ocupa o que precisa e SÓ encolhe quando falta
     espaço de verdade. Um max-width fixo cortaria o nome até em tela
     grande, onde sobra espaço. Quem não cede é o menu (flex-shrink:0). */
  min-width: 0;
  flex: 0 1 auto;
}

/* a marca é um link para a tela inicial de quem está logado */
a.brand:not(.btn),
a.brand:not(.btn):hover { color: var(--on-dark); text-decoration: none; }

/* ------------------------------------------------------------
   Logo da marcenaria no cabeçalho (a mesma dos PDFs, §4.9)

   Sobre uma PLACA CLARA de propósito: o cabeçalho é escuro e logo de
   marcenaria costuma ser marrom, preta ou vinho -- sobre o fundo escuro
   metade delas sumiria, e não dá para pedir a cada cliente uma versão
   clara da própria marca.

   A altura manda; a largura sai por proporção, com teto: logo quadrada e
   logo em faixa comprida ocupam a mesma altura, e nenhuma empurra o menu
   para a segunda linha.
   ------------------------------------------------------------ */
.brand-placa {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  padding: 6px 12px;
  border-radius: 10px;
  background: var(--on-dark);
}

/* 48px de altura: é o maior tamanho que cabe no cabeçalho de 72px com
   respiro em cima e embaixo. Abaixo disso, a linha fina de um logo
   empilhado ("MARCENEIRO", a assinatura) deixa de ser legível e a marca
   parece uma miniatura esquecida no canto. */
.brand-logo {
  display: block;
  height: 40px;
  max-width: 200px;
  width: auto;
  /* contain: logo fora de proporção encolhe inteira em vez de ser cortada */
  object-fit: contain;
}

/* a partir daqui o menu precisa do espaço de volta -- e quem cede é a
   marca, como já acontecia com o nome escrito */
@media (max-width: 1250px) {
  .brand-logo { height: 36px; max-width: 170px; }
}
@media (max-width: 1050px) {
  .brand-placa { padding: 5px 10px; }
  .brand-logo { height: 32px; max-width: 140px; }
}

.app-header .brand-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 17px;
  letter-spacing: .2px;
  color: var(--on-dark);
  border-bottom: 2px dashed var(--wood);
  padding-bottom: 2px;
  /* corta com reticências em vez de quebrar a linha; o nome completo
     fica no title, ao passar o mouse */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

/* a etiqueta "Orçamentos" some em tela apertada: é informação redundante
   (o usuário sabe onde está) e custava ~110px de largura */
.app-header .brand-tag {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--on-dark-dim);
  text-transform: uppercase;
  letter-spacing: 1px;
  white-space: nowrap;
}

/* em tela apertada some primeiro a etiqueta, depois o texto do usuário --
   nessa ordem, porque são as informações menos necessárias. O menu é o
   último a ceder. */
@media (max-width: 1500px) {
  .app-header .brand-tag { display: none; }
}
@media (max-width: 1050px) {
  .app-header .brand-name { font-size: 16px; }
  .app-nav a { padding: 8px 9px; }
}

.app-nav {
  display: flex;
  align-items: center;
  gap: 2px;
  /* o menu NUNCA quebra em duas linhas: com 8 itens de tamanhos
     diferentes, a quebra deixava uns em cima e outros embaixo.
     Quem cede espaço é a marca (que trunca), não o menu. */
  flex-wrap: nowrap;
  flex-shrink: 0;
}

.app-nav a {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 13.5px;
  color: var(--on-dark-soft);
  padding: 8px 11px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
  transition: background .15s ease, color .15s ease;
}

.app-nav a:hover {
  background: rgba(244,242,234,0.08);
  color: var(--on-dark);
}

.app-nav a.active {
  background: var(--accent);
  color: var(--on-accent);
}

/* ============================================================
   USUÁRIO LOGADO (canto direito do cabeçalho)
   ============================================================ */
.usuario-bloco { position: relative; }

.usuario-botao {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 5px 10px 5px 5px;
  border: 1px solid rgba(244,242,234,.18);
  border-radius: 100px;
  background: transparent;
  color: var(--on-dark);
  cursor: pointer;
  font-family: var(--font-body);
  transition: background .15s ease, border-color .15s ease;
}

.usuario-botao:hover { background: rgba(244,242,234,.08); border-color: rgba(244,242,234,.35); }

.usuario-avatar {
  width: 28px;
  height: 28px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 14px;
}

.usuario-info { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.2; }
.usuario-nome { font-size: 13px; font-weight: 600; max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.usuario-papel { font-family: var(--font-mono); font-size: 10px; color: var(--on-dark-dim); text-transform: uppercase; letter-spacing: .5px; }

.usuario-menu {
  display: none;
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 210px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  z-index: 120;
}

.usuario-menu.aberto { display: block; }

.usuario-menu a,
.usuario-menu button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 11px 15px;
  border: none;
  background: none;
  font-family: var(--font-body);
  font-size: 13.5px;
  color: var(--ink);
  cursor: pointer;
  border-bottom: 1px solid var(--line);
}

.usuario-menu a:last-child,
.usuario-menu button:last-child { border-bottom: none; }
.usuario-menu a:hover,
.usuario-menu button:hover { background: var(--bg); color: var(--ink); }

.usuario-menu-sair { color: var(--status-declined) !important; font-weight: 600; }
.usuario-menu-sair:hover { background: var(--status-declined-soft) !important; }

/* fica só o avatar: libera ~140px e evita truncar o nome da marcenaria */
@media (max-width: 1250px) {
  .usuario-info { display: none; }
  .usuario-botao { padding: 5px; }
}

/* celular/tablet estreito: aí sim o cabeçalho quebra e o menu rola na
   horizontal dentro dele -- 8 itens não cabem de jeito nenhum */
@media (max-width: 780px) {
  .app-header { flex-wrap: wrap; row-gap: 8px; padding: 8px 16px; }
  .app-nav {
    order: 3; width: 100%;
    overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .app-nav::-webkit-scrollbar { display: none; }
}

.usuario-bloco { flex-shrink: 0; }

/* ============================================================
   MENU SUPERIOR (computador, acima de 780px)

   O cabeçalho é fixo no alto (sticky, definido lá em cima): o menu está
   sempre à mão, mesmo no meio de uma tabela longa. Links soltos e GRUPOS
   que só abrem por clique (ui.js, initMenuGrupos). Dez telas viraram cinco
   entradas, e a largura toda da janela fica para o conteúdo.

   No celular nada disto vale: o menu some e a barra inferior (bloco
   CELULAR) assume.
   ============================================================ */
@media (min-width: 781px) {
  .app-nav {
    margin-right: auto;     /* o menu cola na marca; o usuário fica na ponta direita */
    margin-left: 12px;
    gap: 4px;
  }

  .app-nav .nav-link,
  .app-nav .nav-grupo-botao {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 9px 14px;
    border: 0;
    border-radius: var(--radius-sm);
    background: none;
    color: var(--on-dark-soft);
    font-family: var(--font-body);
    font-weight: 500;
    font-size: 14px;
    white-space: nowrap;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
  }
  .app-nav .nav-link:hover,
  .app-nav .nav-grupo-botao:hover,
  .app-nav .nav-grupo.aberto > .nav-grupo-botao {
    background: rgba(244,242,234,0.10);
    color: var(--on-dark);
  }
  .app-nav .nav-link.active,
  .app-nav .nav-grupo.ativo > .nav-grupo-botao {
    background: var(--accent);
    color: var(--on-accent);
  }

  .nav-seta { width: 14px; height: 14px; transition: transform .15s ease; }
  .nav-grupo.aberto .nav-seta { transform: rotate(180deg); }

  .nav-grupo { position: relative; }

  .nav-submenu {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    min-width: 230px;
    padding: 6px;
    background: var(--bg-panel);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    z-index: 130;
  }
  .nav-submenu[hidden] { display: none; }

  /* a regra geral .app-nav a é para o fundo escuro; aqui o fundo é claro */
  .app-nav .nav-submenu .nav-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border-radius: var(--radius-sm);
    color: var(--ink);
    font-size: 14px;
    font-weight: 500;
  }
  .app-nav .nav-submenu .nav-item svg { width: 18px; height: 18px; flex-shrink: 0; color: var(--ink-soft); }
  .app-nav .nav-submenu .nav-item:hover { background: var(--bg); color: var(--ink); }
  .app-nav .nav-submenu .nav-item.active { background: var(--accent-soft); color: var(--accent); }
  .app-nav .nav-submenu .nav-item.active svg { color: var(--accent); }

  /* o alerta de contas vencendo fica junto do rótulo */
  .app-nav .nav-link .nav-alerta { margin-left: 2px; }

  .app-main { max-width: 1360px; }
}

/* janela média: menos folga, e some o texto do usuário e a etiqueta da marca */
@media (min-width: 781px) and (max-width: 1050px) {
  .app-header { padding: 8px 14px; gap: 8px; }
  .app-nav { margin-left: 4px; gap: 2px; }
  .app-nav .nav-link,
  .app-nav .nav-grupo-botao { padding: 8px 9px; font-size: 13px; }
  .app-header .brand-tag { display: none; }
}

/* ============================================================
   LAYOUT DE CONTEÚDO
   ============================================================ */
.app-main {
  max-width: 1280px;
  margin: 0 auto;
  padding: 28px;
}

.page-title-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
}

.page-title-row h1 {
  font-size: 24px;
}

.page-title-row .subtitle {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink-soft);
  text-transform: uppercase;
  letter-spacing: .5px;
  margin-top: 2px;
}

/* ============================================================
   BARRA DE PESQUISA + AÇÃO (padrão usado em Clientes/Orçamentos/Materiais)
   ============================================================ */
.toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 20px;
}

/* ------------------------------------------------------------
   Dados da empresa
   ------------------------------------------------------------ */
.empresa-colunas {
  display: grid;
  /* a logo e uma coluna estreita e o cadastro uma larga: os campos de
     endereco precisam de espaco, a imagem nao */
  grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}

@media (max-width: 860px) {
  .empresa-colunas { grid-template-columns: minmax(0, 1fr); }
}

.logo-area {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 130px;
  margin-bottom: 16px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  /* xadrez discreto: mostra a transparencia de um PNG, que sobre fundo
     branco daria a impressao de que a logo tem um retangulo branco */
  background-color: var(--bg);
  background-image:
    linear-gradient(45deg, var(--bg-panel) 25%, transparent 25%, transparent 75%, var(--bg-panel) 75%),
    linear-gradient(45deg, var(--bg-panel) 25%, transparent 25%, transparent 75%, var(--bg-panel) 75%);
  background-size: 16px 16px;
  background-position: 0 0, 8px 8px;
}

.logo-atual {
  max-width: 100%;
  max-height: 150px;
  height: auto;
}

.logo-vazia {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}

/* ------------------------------------------------------------
   Navegador de mês (Financeiro: fora do filtro "Em aberto")
   ------------------------------------------------------------ */
.mes-nav {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
  padding: 10px 14px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

/* largura mínima para o rótulo não "pular" ao trocar de mês:
   "MAIO DE 2026" é bem mais curto que "SETEMBRO DE 2026", e sem isso
   as setas mudariam de lugar a cada clique */
.mes-nav-rotulo {
  min-width: 210px;
  text-align: center;
  font-family: var(--font-display);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--ink);
}

.mes-nav .btn-icone svg { width: 16px; height: 16px; }

/* o "Este mês" fica encostado à direita, separado das setas: é uma ação
   de atalho, não faz parte da navegação passo a passo */
.mes-nav #mesHoje { margin-left: auto; }

.mes-nav #mesHoje:disabled {
  opacity: .45;
  cursor: default;
}

@media (max-width: 560px) {
  .mes-nav-rotulo { min-width: 0; flex: 1; font-size: 14px; }
}

/* ------------------------------------------------------------
   Agenda financeira (Financeiro: lista única em ordem de data,
   com pagar e receber juntos -- formato de extrato bancário)
   ------------------------------------------------------------ */
.agenda-dia { margin-bottom: 18px; }
.agenda-dia:last-child { margin-bottom: 0; }

.agenda-dia-cabecalho {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px 16px;
  padding: 4px 2px 8px;
}

.agenda-dia-titulo {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}

.agenda-dia-totais {
  display: flex;
  gap: 14px;
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
}

.agenda-total.receber { color: var(--status-approved); }
.agenda-total.pagar   { color: var(--status-declined); }

/* cada dia é sua própria table.data-table (thead pequeno repetido) --
   é o que mantém o card do celular funcionando (§7.1: os rótulos vêm do
   thead), sem herdar sticky nem larguras de uma tabela única gigante */
.agenda-tabela { margin-bottom: 0; }

.search-box {
  position: relative;
  flex: 1;
  max-width: 420px;
}

.search-box input {
  width: 100%;
  padding: 10px 14px 10px 38px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-panel);
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ink);
  outline: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}

.search-box input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.search-box .search-icon {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  width: 16px;
  height: 16px;
  color: var(--ink-soft);
  pointer-events: none;
}

.autocomplete-list {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  /* ~6 sugestões de uma linha (42px) ou ~4 de duas linhas (nomes longos);
     o resto rola. O endpoint devolve até 10, e uma lista comprida cobrindo
     meia tela fica desagradável. */
  max-height: 252px;
  overflow-y: auto;
  z-index: 50;
  display: none;
}

.autocomplete-list.open { display: block; }

/* Flex, e NUNCA float, para o valor da direita.
   Com "float:right" o valor sai do fluxo: quando o rótulo é comprido
   ("MDF CARVALHO AMERICANO 15MM") ele não cabe na mesma linha, desce, e
   como o float não conta para a altura do item, o preço acaba invadindo
   a linha de baixo -- foi exatamente o desalinhamento relatado.
   Em flex os dois são itens da mesma linha: o rótulo encolhe com
   reticências e o valor fica sempre à frente dele, à direita.

   Bônus: garantindo uma linha por item, a altura fica previsível e o
   max-height acima (5 x 42px) volta a mostrar 5 sugestões de verdade. */
.autocomplete-list .item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 14px;
  cursor: pointer;
  border-bottom: 1px solid var(--line);
  font-size: 14px;
}

/* rótulo (id + nome): quebra em até DUAS linhas e só então corta.
   Em linha única o que identifica o material ("TREND 0,8" x "TREND 1,5",
   a espessura, a cor) fica justamente no fim do nome e sumia atrás das
   reticências: duas sugestões diferentes pareciam iguais. O nome completo
   também vai no title, para o que passar de duas linhas. */
.autocomplete-list .item .item-rotulo {
  min-width: 0;
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  line-height: 1.35;
  overflow-wrap: anywhere;
}

/* valor da direita: nunca encolhe nem quebra */
.autocomplete-list .item .item-extra {
  margin-left: auto;
  flex-shrink: 0;
  white-space: nowrap;
  color: var(--ink-soft);
  font-size: 13px;
  /* alinha o valor à primeira linha do nome, não ao meio do bloco */
  line-height: 1.35;
}

.autocomplete-list .item:last-child { border-bottom: none; }
.autocomplete-list .item:hover,
.autocomplete-list .item.highlighted { background: var(--accent-soft); }

.autocomplete-list .item .id-tag {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--ink-soft);
  margin-right: 6px;
}

.autocomplete-list .empty {
  padding: 14px;
  font-size: 13px;
  color: var(--ink-soft);
  text-align: center;
}

/* ============================================================
   BOTÕES
   ============================================================ */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border: none;
  border-radius: var(--radius);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  transition: background .15s ease, transform .1s ease;
  white-space: nowrap;
}

.btn:active { transform: scale(0.98); }

/* O atributo hidden é só um display:none do navegador, e o display do .btn
   (e do ".toolbar > .btn" no celular) passava por cima dele: o JS escondia o
   "+ Novo Ambiente" de orçamento aprovado e ele continuava na tela -- e
   clicar dava erro do servidor. Com !important, hidden volta a esconder. */
.btn[hidden] { display: none !important; }

.btn-primary { background: var(--accent); color: var(--on-accent); }
.btn-primary:hover { background: var(--accent-hover); }

.btn-wood { background: var(--wood); color: var(--on-accent); }
.btn-wood:hover { background: var(--wood-hover); }

.btn-ghost { background: transparent; color: var(--ink); border: 1px solid var(--line); }
.btn-ghost:hover { background: var(--bg); }

.btn-danger { background: var(--status-declined); color: var(--on-accent); }
.btn-danger:hover { background: var(--status-declined-hover); }

.btn-sm { padding: 6px 12px; font-size: 13px; }

/* botão só de ícone — para ações repetidas linha a linha, onde um botão
   com texto rouba largura da tabela e polui visualmente.
   Exige sempre aria-label + title: sem texto, o ícone é a única pista. */
.btn-icone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}

.btn-icone svg {
  width: 15px;
  height: 15px;
  display: block;
}

/* o vermelho só aparece na intenção (hover/foco), não em repouso --
   evita uma coluna de alertas vermelhos gritando na tabela inteira */
.btn-icone:hover {
  color: var(--status-declined);
  border-color: var(--status-declined);
  background: var(--status-declined-soft);
}

.btn-icone:focus-visible {
  outline: none;
  color: var(--status-declined);
  border-color: var(--status-declined);
  box-shadow: 0 0 0 3px var(--status-declined-soft);
}

.btn-icone:active { transform: scale(0.94); }

/* ============================================================
   PAINÉIS / CARDS
   ============================================================ */
.panel {
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.panel-header {
  padding: 16px 20px;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

/* overflow-x: as colunas de dado usam width:1% + nowrap e não encolhem
   abaixo do próprio conteúdo. Sem esta contenção, uma tabela larga vaza
   para fora do cartão em painel estreito. Aqui ela rola dentro do painel
   e a PÁGINA nunca rola na horizontal. */
.panel-body { padding: 20px; overflow-x: auto; }

/* mesma proteção dentro de modais (lista de compras, detalhes do cliente) */
.modal-body { overflow-x: auto; }

/* Um item de grid não encolhe abaixo do conteúdo enquanto min-width for
   "auto" -- é o que empurrava o painel do dashboard para fora da coluna. */
.dash-grid > .panel,
.ambiente-lista > .ambiente-card,
.dash-cards > .dash-card { min-width: 0; }

/* card com "marca de medição" no topo — assinatura visual do sistema */
.measure-card {
  position: relative;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 18px 20px;
}

.measure-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 20px;
  right: 20px;
  height: 3px;
  background: repeating-linear-gradient(
    90deg,
    var(--wood) 0px, var(--wood) 8px,
    transparent 8px, transparent 14px
  );
}

/* ============================================================
   TABELAS
   ============================================================ */
table.data-table {
  width: 100%;
  border-collapse: collapse;
  /* 13px no conteúdo: o cabeçalho tem 11px, e 14px deixava a diferença
     grande demais. Os títulos ficam como estão. */
  font-size: 13px;
}

table.data-table th {
  text-align: left;
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--ink-soft);
  padding: 10px 14px;
  border-bottom: 2px solid var(--line);
}

table.data-table td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
  /* explícito (e não o "start" herdado) para bater com o th e permitir
     auditar o alinhamento das colunas de forma confiável */
  text-align: left;
}

table.data-table tbody tr:hover { background: var(--bg); }

table.data-table tbody tr.row-highlight {
  background: var(--accent-soft);
  transition: background 1.2s ease;
}

/* ------------------------------------------------------------
   ALINHAMENTO DE COLUNA — regra única de todo o sistema.

   Bloco da ESQUERDA (texto): identificador, nome, descrição, badge.
   Bloco da DIREITA (dado):   número, data, ações.

   Nunca intercale: uma coluna de texto depois de uma numérica cria
   zigue-zague e é o que faz a tabela parecer desalinhada. Se precisar
   de uma coluna de texto no fim, reordene as colunas.
   ------------------------------------------------------------ */

/* Todas as colunas de dado usam width:1%, que no table-layout automático
   significa "encolha até o conteúdo". A folga sobra para as colunas de
   texto, que é onde ela é útil. Sem isso, um número de 8px fica boiando
   na borda de uma coluna de 104px -- a causa real do desalinhamento. */

/* DINHEIRO e medidas com decimais: à direita, para as casas decimais
   alinharem umas sob as outras. É o único bloco que não centraliza. */
table.data-table td.num,
table.data-table th.num {
  font-family: var(--font-mono);
  text-align: right;
  width: 1%;
  white-space: nowrap;
}

/* CONTAGENS inteiras e medidas de largura uniforme (3, 12, 15mm):
   centralizadas sob o título -- não há decimal para alinhar. */
table.data-table td.col-qtd,
table.data-table th.col-qtd {
  font-family: var(--font-mono);
  text-align: center;
  width: 1%;
  white-space: nowrap;
}

/* DATAS: todas têm a mesma largura (dd/mm/aaaa), então centralizar
   fica equilibrado e o título não foge para a borda. */
table.data-table td.col-data,
table.data-table th.col-data {
  font-family: var(--font-mono);
  text-align: center;
  width: 1%;
  white-space: nowrap;
}

/* BADGES de situação: centralizados sob o título */
table.data-table td.col-status,
table.data-table th.col-status {
  text-align: center;
  width: 1%;
  white-space: nowrap;
}

/* identificador: ancora a linha, fica à esquerda e ocupa o mínimo */
table.data-table td.col-id,
table.data-table th.col-id {
  font-family: var(--font-mono);
  text-align: left;
  width: 1%;
  white-space: nowrap;
}

table.data-table td.col-acoes,
table.data-table th.col-acoes { text-align: right; white-space: nowrap; width: 1%; }

/* ============================================================
   PAGINAÇÃO (10 registros por página)
   ============================================================ */
.paginacao {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

.paginacao-info { font-size: 12px; color: var(--ink-soft); }

.paginacao-botoes { display: flex; gap: 4px; }

.pag-btn {
  min-width: 30px;
  height: 30px;
  padding: 0 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-panel);
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--ink);
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.pag-btn:hover:not(:disabled):not(.ativa) { border-color: var(--accent); color: var(--accent); }

.pag-btn.ativa {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
  font-weight: 600;
}

.pag-btn:disabled { opacity: .4; cursor: not-allowed; }

/* ============================================================
   BADGES DE STATUS
   ============================================================ */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 100px;
  font-size: 12px;
  font-weight: 600;
  font-family: var(--font-body);
}

.badge::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
}

.badge-pending { background: var(--status-pending-soft); color: var(--status-pending-text); }
.badge-approved { background: var(--status-approved-soft); color: var(--status-approved); }
/* ------------------------------------------------------------
   Juntar orçamentos (modal da tela do orçamento): um cartão por
   orçamento do cliente, com os ambientes marcáveis embaixo
   ------------------------------------------------------------ */
.juntar-orc {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  margin-bottom: 12px;
  overflow: hidden;
}
.juntar-orc.bloqueado { opacity: .6; }
.juntar-orc-topo {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: var(--bg);
  cursor: pointer;
}
.juntar-orc-nome { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.juntar-orc-nome strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.juntar-orc-valor { font-weight: 600; white-space: nowrap; }
.juntar-motivo { padding: 6px 14px 0; }
.juntar-ambs { padding: 6px 14px 10px; }
.juntar-amb {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 0 7px 26px;
  border-bottom: 1px solid var(--line);
  font-size: 13.5px;
  cursor: pointer;
}
.juntar-amb:last-child { border-bottom: none; }
.juntar-amb.bloqueado { cursor: default; }
.juntar-amb-nome { flex: 1; min-width: 0; }
.juntar-orc input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--accent); flex-shrink: 0; }
.juntar-rodape .juntar-resumo { margin-right: auto; font-size: 13px; color: var(--ink-soft); }

/* realizado = aprovado com o serviço concluído: o mesmo verde, cheio --
   é o fim do caminho, e precisa se distinguir do aprovado ao bater o olho */
.badge-realizado { background: var(--status-approved); color: var(--on-accent); }
.badge-realizado::before { background: var(--on-accent); }
.badge-declined { background: var(--status-declined-soft); color: var(--status-declined); }

/* ============================================================
   MODAL
   ============================================================ */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(42,36,32,0.45);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 200;
  padding: 20px;
}

.modal-overlay.open { display: flex; }

/* ------------------------------------------------------------
   Variante PAINEL LATERAL
   Para o modal que precisa conviver com o conteúdo atrás -- o caso é a
   escolha de ferragens, feita OLHANDO o desenho para contar quantas
   dobradiças e corrediças o móvel leva. Uma caixa centralizada tapava
   justamente o desenho.

   Sem escurecer o fundo e sem capturar clique: o desenho continua
   legível e continua respondendo a zoom e arrasto com o painel aberto.
   Em troca, não existe "clicar fora para fechar" -- fecha no ×, no
   Concluir ou no Esc.
   ------------------------------------------------------------ */
.modal-overlay.modal-lateral {
  justify-content: flex-end;
  align-items: stretch;
  padding: 0;
  background: transparent;
  pointer-events: none;
}

.modal-overlay.modal-lateral .modal-box {
  pointer-events: auto;
  width: 100%;
  max-width: 440px;
  max-height: 100vh;
  border-radius: 0;
  box-shadow: -12px 0 34px rgba(42,36,32,0.20);
  display: flex;
  flex-direction: column;
  animation: painel-entra .18s ease-out;
}

/* só o corpo rola: cabeçalho e rodapé ficam fixos, para o botão
   "Concluir" não fugir depois de lançar oito ferragens */
.modal-overlay.modal-lateral .modal-body {
  flex: 1;
  overflow-y: auto;
  min-height: 0;
}

.modal-overlay.modal-lateral .modal-header,
.modal-overlay.modal-lateral .modal-footer { flex-shrink: 0; }

@keyframes painel-entra {
  from { transform: translateX(24px); opacity: 0; }
  to   { transform: translateX(0);    opacity: 1; }
}

/* tela estreita: não há desenho ao lado para preservar, então o painel
   ocupa tudo e vira um modal de tela cheia */
@media (max-width: 900px) {
  .modal-overlay.modal-lateral { background: rgba(42,36,32,0.45); pointer-events: auto; }
  .modal-overlay.modal-lateral .modal-box { max-width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .modal-overlay.modal-lateral .modal-box { animation: none; }
}

.modal-box {
  background: var(--bg-panel);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  width: 100%;
  max-width: 560px;
  max-height: 90vh;
  overflow-y: auto;
}

.modal-header {
  padding: 18px 22px;
  border-bottom: 1px solid var(--line);
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.modal-header h3 { margin: 0; font-size: 18px; }

.modal-close {
  background: none;
  border: none;
  cursor: pointer;
  color: var(--ink-soft);
  font-size: 20px;
  line-height: 1;
  padding: 4px;
}

.modal-body { padding: 22px; }

.modal-footer {
  padding: 16px 22px;
  border-top: 1px solid var(--line);
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  /* rótulos de botão variam de tamanho; sem wrap, um rodapé com 3 opções
     empurra o primeiro botão para fora da caixa e ele fica cortado */
  flex-wrap: wrap;
}

/* botão de modal nunca encolhe abaixo do próprio texto */
.modal-footer .btn { flex-shrink: 0; }

/* ============================================================
   FORMULÁRIOS
   ============================================================ */
.form-group { margin-bottom: 16px; }

.form-group label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 6px;
}

.form-group .hint {
  font-size: 12px;
  color: var(--ink-soft);
  margin-top: 4px;
}

.form-control {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ink);
  background: var(--bg-panel);
  outline: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}

.form-control:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.form-row {
  display: flex;
  gap: 14px;
}

.form-row .form-group { flex: 1; }

/* ============================================================
   ABAS DE CATEGORIA (Materiais) E SUB-ABAS (espessura MDF)
   ============================================================ */
.tabs-categoria {
  display: flex;
  gap: 6px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 14px;
}

.tab-btn {
  background: none;
  border: none;
  padding: 10px 16px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 14px;
  color: var(--ink-soft);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color .15s ease, border-color .15s ease;
}

.tab-btn:hover { color: var(--ink); }

.tab-btn.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

.tabs-espessura {
  display: flex;
  gap: 8px;
  margin-bottom: 18px;
}

.tabs-espessura:empty { display: none; }

.subtab-btn {
  background: var(--bg-panel);
  border: 1px solid var(--line);
  padding: 6px 14px;
  border-radius: 100px;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-soft);
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}

.subtab-btn:hover { border-color: var(--wood); }

.subtab-btn.active {
  background: var(--wood);
  border-color: var(--wood);
  color: var(--on-accent);
}

/* campos condicionais do modal (mostrados só para categoria MDF) */
.mdf-only { display: none; }
.mdf-only.show { display: block; }

/* ============================================================
   FORMULÁRIO DE PEÇA (2 linhas: Material+Descrição / Qtd+Compr.+Larg.+Botão)
   ============================================================ */
.peca-form-row1 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-bottom: 14px;
}

.peca-form-row2 {
  display: grid;
  grid-template-columns: 90px 1fr 1fr auto;
  gap: 14px;
  align-items: end;
}

.peca-form-row1 .form-group,
.peca-form-row2 .form-group { margin-bottom: 0; }

@media (max-width: 640px) {
  .peca-form-row1 { grid-template-columns: 1fr; }
  .peca-form-row2 { grid-template-columns: 1fr 1fr; }
}

/* ============================================================
   CARTÃO POR GRUPO DE MATERIAL (lista de peças de MDF)
   Cada material vira seu próprio bloco com tabela fixa de colunas --
   evita o desalinhamento de misturar linha de grupo (colspan) com
   linhas de dado numa tabela só.
   ============================================================ */
.peca-grupo {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  margin-bottom: 14px;
  overflow: hidden;
}

.peca-grupo-header {
  background: var(--bg);
  padding: 10px 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  border-bottom: 1px solid var(--line);
}

.peca-grupo-header .nome { font-weight: 600; }

/* rola horizontalmente em painel estreito em vez de amassar as colunas
   (o .peca-grupo tem overflow:hidden pro border-radius, então o scroll
   precisa ficar neste wrapper interno).
   Vertical: mostra 5 peças (cabeçalho 33px + 5 x 40px) e rola o resto. */
.peca-grupo-tabela-wrap {
  overflow-x: auto;
  overflow-y: auto;
  max-height: 233px;
}

/* ------------------------------------------------------------
   LISTA COM ROLAGEM (5 linhas visíveis)
   O cabeçalho fica grudado no topo enquanto o corpo rola -- sem isso
   o usuário perde a referência das colunas ao descer a lista.
   ------------------------------------------------------------ */
.peca-grupo-tabela-wrap thead th,
.tabela-rolavel thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  /* fundo opaco obrigatório: sem ele as linhas passam por trás do cabeçalho */
  background: var(--bg-panel);
}

/* tabela de ferragens/fitas/diversos: cabeçalho 37px + 5 linhas de 55px */
.tabela-rolavel {
  overflow-y: auto;
  overflow-x: auto;
  max-height: 312px;
  margin-top: 14px;
}

.peca-grupo-table {
  width: 100%;
  min-width: 520px;
  table-layout: fixed;
  border-collapse: collapse;
  font-size: 14px;
}

/* Larguras em px, não em %: cabeçalho e botão têm tamanho fixo em pixels,
   então porcentagem fazia o texto quebrar em umas colunas e não em outras.
   A coluna Descrição (auto) absorve toda a sobra. */
.peca-grupo-table th:nth-child(1) { width: auto; }   /* Descrição */
.peca-grupo-table th:nth-child(2) { width: 56px; }   /* Qtd */
.peca-grupo-table th:nth-child(3) { width: 104px; }  /* Compr. (m) */
.peca-grupo-table th:nth-child(4) { width: 96px; }   /* Larg. (m) */
.peca-grupo-table th:nth-child(5) { width: 100px; }  /* Área (m²) */
.peca-grupo-table th:nth-child(6) { width: 52px; }   /* ícone de remover */

.peca-grupo-table th {
  text-align: left;
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--ink-soft);
  padding: 8px 14px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap; /* impede "Larg. (m)" de quebrar em duas linhas */
}

/* coluna de ações: botão encostado na direita, sem sobrar padding duplo */
.peca-grupo-table th.col-acoes,
.peca-grupo-table td.col-acoes {
  text-align: right;
  padding-left: 0;
}

.peca-grupo-table td.col-acoes { padding-top: 4px; padding-bottom: 4px; }

/* ------------------------------------------------------------
   Cálculo rápido (tela de cálculo, migration 022): chapa direta e
   material estimado, sem lista de corte. Cabeçalho em madeira para se
   distinguir do lançamento detalhado logo abaixo.
   ------------------------------------------------------------ */
.calc-rapido .panel-header { background: var(--wood-soft); }
/* abas Cálculo detalhado / Cálculo rápido, acima dos painéis do ambiente */
.calc-abas { margin-bottom: 16px; }
.rapido-linha {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 130px auto;
  gap: 12px;
  align-items: end;
  margin-bottom: 10px;
}
.rapido-linha .form-group { margin-bottom: 0; }
.rapido-linha + .rapido-linha { padding-top: 10px; border-top: 1px dashed var(--line); }
.rapido-tabela { margin-top: 12px; }
.rapido-tabela th:nth-child(2) { width: 110px; }
.rapido-tabela th:nth-child(3) { width: 120px; }
.rapido-tabela th:nth-child(4) { width: 52px; }
.tag-estimado {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 100px;
  background: var(--wood-soft);
  color: var(--wood-text);
  font-family: var(--font-mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .5px;
}

/* duas ações por linha (editar e remover): a coluna cresce para caber as
   duas sem quebrar. Na tabela de itens a ação é a 5ª coluna, que já tem 100px */
.peca-grupo-table th:nth-child(6) { width: 84px; }
.item-grupo-tabela-wrap .peca-grupo-table th:nth-child(2) { width: 112px; } /* Qtd + unidade, também em edição */
.acoes-linha { display: inline-flex; gap: 4px; justify-content: flex-end; }

/* ------------------------------------------------------------
   Linha em edição (peça ou item já lançado): os campos ocupam a
   própria célula, com menos respiro, para caber na largura da coluna
   ------------------------------------------------------------ */
.peca-grupo-table tr.linha-editando td {
  background: var(--accent-soft);
  padding: 6px 4px;
}
.peca-grupo-table tr.linha-editando td:first-child { padding-left: 10px; }
.campo-linha.form-control {
  height: 32px;
  padding: 4px 8px;
  font-size: 13px;
}
.campo-linha + .campo-linha { margin-top: 4px; }
.campo-num.form-control { width: 100%; text-align: right; font-family: var(--font-mono); -moz-appearance: textfield; }
/* sem as setinhas do campo numérico: na coluna estreita elas cobriam o valor */
.campo-num::-webkit-outer-spin-button,
.campo-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.campo-com-unidade { display: flex; align-items: center; gap: 6px; }
.campo-com-unidade .mono { font-size: 12px; color: var(--ink-soft); }
.btn-icone.btn-icone-ok { color: var(--status-approved); border-color: var(--status-approved); }

.peca-grupo-table td {
  padding: 9px 14px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}

.peca-grupo-table tbody tr:last-child td { border-bottom: none; }
.peca-grupo-table tbody tr:hover { background: var(--bg); }

.peca-grupo-table th.num,
.peca-grupo-table td.num { font-family: var(--font-mono); text-align: right; }

.peca-grupo-total {
  background: var(--accent-soft);
  padding: 10px 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 13px;
  color: var(--ink);
}

.peca-grupo-total strong {
  color: var(--accent);
  font-size: 15px;
  font-family: var(--font-mono);
}

/* ============================================================
   GRID DE FORMULÁRIO (peças / itens) — se ajusta sozinho, nunca amassa o texto
   ============================================================ */
.form-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
  gap: 14px;
  align-items: end;
}

.form-grid .form-group { margin-bottom: 0; }

.form-group-btn {
  display: flex;
  align-items: flex-end;
}

.form-group-btn .btn {
  width: 100%;
  white-space: nowrap;
}

@media (max-width: 640px) {
  .form-grid { grid-template-columns: 1fr 1fr; }
}

/* ============================================================
   LAYOUT DE DUAS COLUNAS (tela de cálculo do ambiente)
   ============================================================ */
.calculo-layout {
  display: grid;
  grid-template-columns: minmax(320px, 1fr) minmax(380px, 1.3fr);
  gap: 24px;
  align-items: start;
}

.calculo-desenho-col {
  position: sticky;
  top: 84px; /* 64px do header + respiro */
}

/* Desconta a tira de miniaturas e a barra de ações que agora ficam
   embaixo do visualizador. Sem isso a coluna, que é sticky, fica mais
   alta que a tela e as miniaturas caem fora do campo de visão --
   justamente os controles que precisam estar sempre à mão. */
.calculo-desenho-col .desenho-viewport {
  height: calc(100vh - 300px);
  min-height: 320px;
}

@media (max-width: 960px) {
  .calculo-layout {
    grid-template-columns: 1fr;
  }
  .calculo-desenho-col {
    position: static;
  }
  .calculo-desenho-col .desenho-viewport {
    height: 380px;
  }
}

/* ============================================================
   VISUALIZADOR DE DESENHO (zoom + pan)
   ============================================================ */
.desenho-viewport {
  position: relative;
  width: 100%;
  height: 480px;
  overflow: hidden;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  cursor: grab;
}

.desenho-viewport.dragging { cursor: grabbing; }

.desenho-viewport img {
  position: absolute;
  top: 0;
  left: 0;
  max-width: none;
  transform-origin: 0 0;
  user-select: none;
  pointer-events: none;
}

/* --- galeria de ângulos --- */

/* Tira horizontal que ROLA em vez de quebrar em várias linhas: se ela
   quebrasse, um móvel com 6 ângulos empurraria o visualizador para cima
   e mudaria a altura da coluna a cada desenho novo. */
.desenho-galeria {
  display: flex;
  gap: 8px;
  margin-top: 10px;
  padding-bottom: 4px;
  overflow-x: auto;
  scrollbar-width: thin;
}

.desenho-galeria[hidden] { display: none; }

.desenho-miniatura {
  position: relative;
  flex: 0 0 auto;
  width: 76px;
  height: 58px;
  padding: 0;
  border: 2px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
  overflow: hidden;
  cursor: pointer;
  transition: border-color .15s ease, transform .1s ease;
}

.desenho-miniatura img {
  width: 100%;
  height: 100%;
  /* "contain" e não "cover": desenho técnico cortado perde justamente a
     borda com as cotas, que é o que identifica a vista */
  object-fit: contain;
  display: block;
  pointer-events: none;
}

.desenho-miniatura:hover { border-color: var(--accent); }
.desenho-miniatura:active { transform: scale(0.96); }

.desenho-miniatura.ativa {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.desenho-miniatura:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* número no canto: com miniaturas parecidas (frontal x traseira de um
   mesmo armário são quase idênticas), a posição é o que diferencia */
.desenho-miniatura-num {
  position: absolute;
  left: 2px;
  bottom: 2px;
  padding: 0 4px;
  border-radius: 3px;
  background: var(--ink);
  color: var(--on-dark);
  font-size: 9px;
  line-height: 14px;
}

/* barra embaixo: dica à esquerda, ações à direita */
.desenho-barra {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 10px;
}

.desenho-barra .hint { margin: 0; flex: 1; min-width: 180px; }
.desenho-acoes { display: flex; gap: 8px; flex-shrink: 0; }

/* quadro do ambiente que ainda não tem imagem: ocupa o lugar do
   visualizador, com a mesma altura, para a tela não mudar de forma */
.desenho-viewport.desenho-vazio {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 24px;
  text-align: center;
  border-style: dashed;
  cursor: default;
}
.desenho-vazio .btn { margin-top: 12px; }

/* ============================================================
   TOAST (notificações) — substitui o alert() nativo
   Fica acima do modal (z-index 200) porque uma ação dentro
   de um modal pode disparar uma notificação.
   ============================================================ */
.toast-container {
  position: fixed;
  bottom: 24px;
  right: 24px;
  z-index: 300;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-end;
  pointer-events: none; /* o container não bloqueia cliques; os toasts sim */
}

.toast {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  min-width: 280px;
  max-width: 380px;
  padding: 13px 14px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-left: 4px solid var(--ink-soft);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  font-size: 14px;
  line-height: 1.45;
  color: var(--ink);
  /* estado inicial da animação de entrada */
  opacity: 0;
  transform: translateX(16px);
  transition: opacity .22s ease, transform .22s ease;
}

.toast.visivel {
  opacity: 1;
  transform: translateX(0);
}

.toast-icone {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
  margin-top: 1px;
}

.toast-icone svg { width: 100%; height: 100%; display: block; }

.toast-texto { flex: 1; }

.toast-fechar {
  flex-shrink: 0;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--ink-soft);
  font-size: 18px;
  line-height: 1;
  padding: 0 2px;
  opacity: .6;
  transition: opacity .15s ease;
}

.toast-fechar:hover { opacity: 1; }

.toast-sucesso { border-left-color: var(--status-approved); }
.toast-sucesso .toast-icone { color: var(--status-approved); }

.toast-erro { border-left-color: var(--status-declined); }
.toast-erro .toast-icone { color: var(--status-declined); }

.toast-info { border-left-color: var(--accent); }
.toast-info .toast-icone { color: var(--accent); }

@media (max-width: 560px) {
  .toast-container { left: 16px; right: 16px; bottom: 16px; align-items: stretch; }
  .toast { min-width: 0; max-width: none; }
}

/* ============================================================
   MODAL DE CONFIRMAÇÃO — substitui o confirm() nativo
   ============================================================ */
/* 420px comportava 2 botões; com a terceira opção ("Sair sem salvar")
   os rótulos somam ~435px e o primeiro botão saía da caixa. */
.modal-confirmar .modal-box { max-width: 520px; }

.modal-confirmar .confirm-mensagem {
  margin: 0;
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-soft);
}

/* ============================================================
   BOTÃO EM CARREGAMENTO (trava anti duplo-clique)
   ============================================================ */
.btn:disabled {
  opacity: .65;
  cursor: not-allowed;
}

.btn:disabled:active { transform: none; }

.btn.is-loading::before {
  content: '';
  width: 13px;
  height: 13px;
  flex-shrink: 0;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: btn-spin .6s linear infinite;
}

@keyframes btn-spin {
  to { transform: rotate(360deg); }
}

/* respeita quem configurou o sistema para reduzir animações */
@media (prefers-reduced-motion: reduce) {
  .toast { transition: none; }
  .btn.is-loading::before { animation-duration: 2s; }
}

/* ============================================================
   ESTADO VAZIO
   ============================================================ */
.empty-state {
  text-align: center;
  padding: 60px 20px;
  color: var(--ink-soft);
}

.empty-state h3 { color: var(--ink); margin-bottom: 6px; }
.empty-state p { margin: 0 0 18px 0; font-size: 14px; }

/* ============================================================
   CONFERÊNCIA AO FINALIZAR O AMBIENTE (calculo.php)
   ============================================================ */
.modal-footer-fluxo { justify-content: space-between; flex-wrap: wrap; gap: 10px; }
.fluxo-principais { display: flex; gap: 10px; flex-wrap: wrap; }

.conferencia-totais {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
  margin-top: 20px;
  padding-top: 16px;
  border-top: 2px solid var(--line);
}

.conferencia-totais > div { display: flex; flex-direction: column; gap: 2px; }
.conferencia-totais .mono { font-size: 17px; font-weight: 600; }
.conferencia-totais .destaque { margin-left: auto; text-align: right; }
.conferencia-totais .destaque .mono { font-size: 22px; color: var(--accent); }

/* contador ao lado do nome da aba de status */
.tab-contador {
  font-family: var(--font-mono);
  font-size: 11px;
  padding: 1px 6px;
  border-radius: 100px;
  background: var(--bg);
  border: 1px solid var(--line);
  margin-left: 4px;
}

.tab-contador:empty { display: none; }

/* ============================================================
   DASHBOARD
   ============================================================ */
.dash-filtros {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}

.periodo-atalhos { display: flex; gap: 8px; flex-wrap: wrap; }
.periodo-datas { display: flex; gap: 12px; align-items: flex-end; }
.periodo-datas .form-group { margin-bottom: 0; }
.periodo-datas .form-control { max-width: 150px; }

.dash-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 14px;
  margin-bottom: 20px;
}

.dash-card {
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-top: 3px solid var(--accent);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 16px 18px;
}

.dash-card-valor {
  font-size: 24px;
  font-weight: 700;
  color: var(--ink);
  margin: 4px 0 2px;
}

.dash-card.positivo { border-top-color: var(--status-approved); }
.dash-card.positivo .dash-card-valor { color: var(--status-approved); }
.dash-card.negativo { border-top-color: var(--status-declined); }
.dash-card.negativo .dash-card-valor { color: var(--status-declined); }
.dash-card.alerta   { border-top-color: var(--status-pending); background: var(--status-pending-soft); }

/* ============================================================
   TELA INÍCIO (inicio/)
   O desenho do Studio adaptado às cores da marcenaria: o primeiro cartão
   em destaque (verde-petróleo), os outros brancos, e os painéis com
   estado vazio que diz o que fazer em vez de uma tabela em branco.
   ============================================================ */
.page-title-acoes { display: flex; gap: 10px; flex-shrink: 0; }

.inicio-cards {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
  margin-bottom: 20px;
}

a.inicio-card:not(.btn),
.inicio-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-height: 126px;
  padding: 18px 20px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  color: var(--ink);
  text-decoration: none;
  transition: transform .15s ease, box-shadow .15s ease;
}
a.inicio-card:not(.btn):hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }

.inicio-card-carregando { background: var(--bg); box-shadow: none; }

.inicio-card-rotulo {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--ink-soft);
}
.inicio-card-valor { font-size: 28px; font-weight: 600; line-height: 1.15; margin: 4px 0 2px; }
.inicio-card-detalhe { font-size: 13px; color: var(--ink-soft); }
.inicio-card-detalhe strong { color: var(--ink); }

/* o cartão de destaque: o que espera resposta do cliente */
a.inicio-card.destaque:not(.btn) { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.inicio-card.destaque .inicio-card-rotulo,
.inicio-card.destaque .inicio-card-detalhe { color: var(--on-dark-soft); }
.inicio-card.destaque .inicio-card-detalhe strong { color: var(--on-accent); }

/* contas a pagar vencendo: mesmo tom de alerta do Dashboard */
a.inicio-card.alerta:not(.btn) { background: var(--status-pending-soft); border-color: var(--status-pending); }

.texto-alerta { color: var(--status-declined); font-weight: 600; }

.inicio-painel { margin-bottom: 20px; }
.inicio-painel .panel-header h3 { margin: 0; font-size: 16px; }
.inicio-painel .panel-header .hint { margin: 2px 0 0; }

.inicio-colunas {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 20px;
}
.inicio-colunas .inicio-painel { min-width: 0; }

.inicio-legenda { display: flex; gap: 14px; flex-wrap: wrap; font-size: 12.5px; color: var(--ink-soft); }
.inicio-legenda span { display: inline-flex; align-items: center; gap: 6px; }
.inicio-legenda i { width: 9px; height: 9px; border-radius: 2px; display: inline-block; }

/* cor de cada tipo na agenda: receber = verde, pagar = vermelho,
   entrega = madeira (a cor de "fazer" do sistema) */
.cor-receber { background: var(--status-approved); }
.cor-pagar   { background: var(--status-declined); }
.cor-entrega { background: var(--wood); }

.agenda-lista { display: flex; flex-direction: column; gap: 8px; }

a.agenda-item:not(.btn) {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-left: 4px solid var(--wood);
  border-radius: var(--radius-sm);
  color: var(--ink);
  text-decoration: none;
}
a.agenda-item:not(.btn):hover { background: var(--bg); }
a.agenda-item.receber:not(.btn) { border-left-color: var(--status-approved); }
a.agenda-item.pagar:not(.btn)   { border-left-color: var(--status-declined); }

.agenda-tipo {
  flex-shrink: 0;
  width: 64px;
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--ink-soft);
}
.agenda-texto { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.agenda-texto strong,
.agenda-texto span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agenda-texto span { font-size: 12.5px; color: var(--ink-soft); }
.agenda-valor { flex-shrink: 0; font-weight: 600; }

.inicio-vazio {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 36px 16px;
  text-align: center;
  color: var(--ink-soft);
  font-size: 14px;
}
.inicio-vazio strong { color: var(--ink); font-size: 15px; }

@media (max-width: 1200px) {
  .inicio-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 1100px) {
  .inicio-colunas { grid-template-columns: minmax(0, 1fr); }
}

/* marca os números que ignoram o filtro de período */
.dash-tag {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 100px;
  background: var(--bg);
  border: 1px solid var(--line);
  font-family: var(--font-mono);
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: .5px;
  vertical-align: middle;
}

/* Grade de 12 colunas com vãos DECLARADOS, não "auto-fit".
   O auto-fit(340px) parecia flexível, mas em tela larga abria 3 colunas e
   os 5 painéis não fecham 3 linhas: o último caía sozinho ocupando 1/3 da
   largura, com dois terços vazios ao lado. Com 12 colunas os painéis são
   emparelhados 7+5 e cada linha fecha certo em qualquer largura. */
.dash-grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 18px;
  align-items: start;
}

/* Celular: tudo em coluna única. Bar chart e rosca lado a lado num
   celular seriam dois gráficos ilegíveis em vez de um legível. */
.dash-grid > .panel { grid-column: 1 / -1; }

/* Notebook: metade e metade. Como são TRÊS painéis, o marcado como
   "impar" toma a linha inteira -- deixá-lo com meia largura recriaria
   exatamente o buraco que esta grade existe para evitar. */
@media (min-width: 780px) and (max-width: 1149px) {
  .dash-painel-terco { grid-column: span 6; }
  .dash-painel-terco.impar { grid-column: 1 / -1; }
}

/* Tela cheia: os três lado a lado fecham as 12 colunas. */
@media (min-width: 1150px) {
  .dash-painel-terco { grid-column: span 4; }
}

.dash-painel-largo { grid-column: 1 / -1; }

.dash-grid .panel-header h3 { margin: 0; font-size: 16px; }

/* --- gráficos --- */
.grafico { width: 100%; height: auto; display: block; overflow: visible; }

.grafico-vazio {
  padding: 40px 20px;
  text-align: center;
  color: var(--ink-soft);
  font-size: 14px;
}

.grafico-vazio p { margin: 0; }

.grafico-legenda {
  display: flex;
  gap: 18px;
  justify-content: center;
  margin-top: 12px;
  font-size: 12px;
  color: var(--ink-soft);
}

.grafico-legenda i {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  margin-right: 6px;
}

/* rosca */
.rosca-wrap { display: flex; align-items: center; gap: 20px; flex-wrap: wrap; }
.rosca { width: 160px; height: 160px; flex-shrink: 0; }
.rosca-legenda { flex: 1; min-width: 170px; }

.rosca-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
}

.rosca-item:last-child { border-bottom: none; }
.rosca-cor { width: 10px; height: 10px; border-radius: 2px; flex-shrink: 0; }
.rosca-rotulo { flex: 1; }
.rosca-valor { font-weight: 600; }
.rosca-pct { color: var(--ink-soft); min-width: 38px; text-align: right; }

.rosca-nota {
  margin: 14px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  line-height: 1.5;
}

/* barras horizontais */
.barras-h { display: flex; flex-direction: column; gap: 10px; }

.barra-h-linha { display: flex; align-items: center; gap: 10px; font-size: 13px; }
.barra-h-rotulo { width: 96px; flex-shrink: 0; }

.barra-h-trilha {
  flex: 1;
  display: flex;
  gap: 2px;
  height: 20px;
  background: var(--bg);
  border-radius: 3px;
  overflow: hidden;
}

.barra-h-parte { height: 100%; transition: width .3s ease; }

.barra-h-valor {
  width: 96px;
  text-align: right;
  flex-shrink: 0;
  font-size: 12px;
}

@media (max-width: 640px) {
  .barra-h-rotulo { width: 70px; font-size: 12px; }
  .barra-h-valor { width: 76px; font-size: 11px; }
}

/* ============================================================
   FINANCEIRO DO CLIENTE (modal de detalhes)
   ============================================================ */
/* ------------------------------------------------------------
   Financeiro (financeiro/index.php)
   Topo: cartões de resumo (os mesmos da Início). Depois UM painel com
   tudo da lista: abas de situação, faixa de filtros, linha de totais e
   os dias. Antes eram quatro blocos soltos de alturas diferentes.
   ------------------------------------------------------------ */
.fin-cards { margin-bottom: 20px; }
.fin-cards .inicio-card { min-height: 112px; }

.fin-cabecalho { padding: 4px 20px 0; }
.fin-abas.tabs-categoria { margin-bottom: 0; border-bottom: none; }

.fin-filtros-barra {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 12px;
  padding: 14px 20px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: var(--bg);
}
.fin-filtros-barra .search-box { flex: 1 1 260px; min-width: 220px; max-width: 380px; }
/* navegador de mês dentro da faixa: sem a caixa própria que tinha solto */
.fin-filtros-barra .mes-nav {
  margin: 0;
  padding: 0;
  border: none;
  background: none;
  flex: 0 1 auto;
}
.fin-filtros-barra .mes-nav-rotulo { min-width: 170px; font-size: 15px; }
.fin-filtros-barra .mes-nav #mesHoje { margin-left: 4px; }

/* botões segmentados (Tudo / A receber / A pagar) */
.segmentado {
  display: inline-flex;
  flex-shrink: 0;
  padding: 3px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-panel);
}
.segmentado button {
  padding: 6px 14px;
  border: none;
  border-radius: var(--radius-sm);
  background: none;
  font-family: var(--font-body);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink-soft);
  cursor: pointer;
  white-space: nowrap;
}
.segmentado button:hover { color: var(--ink); }
.segmentado button.ativo { background: var(--accent); color: var(--on-accent); }
.segmentado button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* o que a lista soma, numa linha discreta */
.fin-totais {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 22px;
  padding: 10px 20px;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  color: var(--ink-soft);
}
.fin-totais[hidden] { display: none; }
.fin-totais strong { color: var(--ink); }
.fin-totais .texto-alerta strong { color: var(--status-declined); }

/* linha do lançamento */
.fin-desc { font-weight: 600; }
.fin-clipe {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  margin-left: 6px;
  font-size: 11px;
  color: var(--ink-soft);
  vertical-align: middle;
}
.fin-clipe svg { width: 13px; height: 13px; }

.fin-tipo {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .5px;
}
.fin-tipo.receber { color: var(--status-approved); }
.fin-tipo.pagar   { color: var(--status-declined); }

td.fin-valor { font-weight: 600; white-space: nowrap; }
td.fin-valor.receber { color: var(--status-approved); }
td.fin-valor.pagar   { color: var(--ink); }

/* Cada dia é uma tabela própria (o cartão do celular precisa do thead de
   cada uma), então no computador as larguras são FIXAS: com largura
   automática cada dia calculava as suas, e Tipo/Situação/Valor mudavam de
   lugar de um dia para o outro. E o cabeçalho das colunas aparece só no
   primeiro dia -- repetido em todos, virava ruído. */
@media (min-width: 781px) {
  .fin-painel .agenda-tabela { table-layout: fixed; }
  /* nas células também (e não só no th): com o thead escondido, a tabela
     fixa tira as larguras da primeira linha do corpo */
  .fin-painel .agenda-tabela :is(th, td):nth-child(1) { width: auto; }
  .fin-painel .agenda-tabela :is(th, td):nth-child(2) { width: 96px; }   /* Tipo */
  .fin-painel .agenda-tabela :is(th, td):nth-child(3) { width: 150px; }  /* Situação */
  .fin-painel .agenda-tabela :is(th, td):nth-child(4) { width: 150px; }  /* Valor */
  .fin-painel .agenda-tabela :is(th, td):nth-child(5) { width: 150px; }  /* Ações */
  .fin-painel .agenda-dia + .agenda-dia .agenda-tabela thead { display: none; }
  .fin-painel .agenda-tabela td:first-child { overflow: hidden; text-overflow: ellipsis; }
}

.fin-acoes-linha { display: inline-flex; align-items: center; gap: 6px; }
.fin-acoes-linha .btn-icone svg { width: 16px; height: 16px; }

.fin-periodo {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
}
.fin-periodo[hidden] { display: none; }
.fin-periodo .hint { white-space: nowrap; }
.fin-periodo input.form-control { width: 160px; }

/* Relatórios: botão Gerar PDF acima do resumo, encostado à direita */

/* Histórico do cliente: quantos orçamentos, fechados, aguardando, recusados */
.cliente-contagem {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
  margin-bottom: 14px;
}
.cliente-contagem > div {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 10px 6px;
  background: var(--bg);
  border-radius: var(--radius-sm);
}
.cliente-contagem strong { font-size: 20px; }
.cliente-contagem .fechados strong { color: var(--status-approved); }

/* Menu de ações da linha (Clientes). position: fixed porque, dentro da
   tabela, o overflow do .panel-body o cortaria. Acima do cabeçalho (100)
   e da barra do celular (150), abaixo dos modais (200). */
.menu-acoes {
  position: fixed;
  z-index: 160;
  min-width: 170px;
  padding: 4px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
}
.menu-acoes button {
  display: block;
  width: 100%;
  padding: 9px 12px;
  border: 0;
  border-radius: var(--radius-sm);
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
}
.menu-acoes button:hover,
.menu-acoes button:focus-visible { background: var(--bg); outline: none; }
.menu-acoes button.perigo { color: var(--status-declined); }
.btn-acoes { white-space: nowrap; }

.cliente-financeiro {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin-bottom: 22px;
}

.cliente-financeiro > div { background: var(--bg-panel); padding: 12px 14px; }
.cliente-financeiro .valor { font-size: 16px; font-weight: 600; margin-top: 2px; }
.cliente-financeiro .valor.grande { font-size: 20px; }
.cliente-financeiro .valor.recebido { color: var(--status-approved); }

.cliente-financeiro .saldo.devendo { background: var(--status-pending-soft); }
.cliente-financeiro .saldo.devendo .valor { color: var(--status-pending-text); }
.cliente-financeiro .saldo.quitado { background: var(--status-approved-soft); }
.cliente-financeiro .saldo.quitado .valor { color: var(--status-approved); }

/* prévia do saldo no modal de pagamento */
.previa-saldo {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
  padding: 12px 14px;
  margin-bottom: 16px;
  background: var(--bg);
  border: 1px dashed var(--line);
  border-radius: var(--radius-sm);
}

.previa-saldo > div { display: flex; flex-direction: column; gap: 2px; }
.previa-saldo .mono { font-size: 15px; font-weight: 600; }
.previa-saldo .destaque { font-size: 18px; color: var(--status-pending-text); }
.previa-saldo .destaque.quitado { color: var(--status-approved); }
.previa-saldo .destaque.excedente { color: var(--status-declined); }
.previa-seta { color: var(--ink-soft); font-size: 18px; }
.previa-saldo .btn { margin-left: auto; }

.detalhe-pagamentos-topo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 22px 0 10px;
}

/* ============================================================
   FINANCEIRO
   ============================================================ */

/* badge de alerta no menu */
.nav-com-alerta { position: relative; display: inline-flex; align-items: center; gap: 6px; }

.nav-alerta {
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 100px;
  background: var(--status-declined);
  color: var(--on-accent);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  line-height: 18px;
  text-align: center;
  cursor: pointer;
  /* pulso discreto: chama atenção sem piscar na cara do usuário */
  animation: alerta-pulso 2.4s ease-in-out infinite;
}

@keyframes alerta-pulso {
  0%, 100% { box-shadow: 0 0 0 0 rgba(156,63,50,.55); }
  50%      { box-shadow: 0 0 0 5px rgba(156,63,50,0); }
}

@media (prefers-reduced-motion: reduce) {
  .nav-alerta { animation: none; }
}

/* painel do alerta */
.alerta-painel {
  background: var(--bg-panel);
  border: 1px solid var(--status-declined);
  border-left: 5px solid var(--status-declined);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 18px 20px;
  margin-bottom: 20px;
}

.alerta-painel-topo {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}

.alerta-painel-topo h3 { margin: 0 0 2px 0; font-size: 19px; color: var(--status-declined); }

.alerta-conta {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 12px 0;
  border-top: 1px solid var(--line);
}

.alerta-conta-info { flex: 1; min-width: 200px; }
.alerta-conta-desc { font-weight: 600; font-size: 15px; }
.alerta-conta.vencida .alerta-conta-desc { color: var(--status-declined); }

.alerta-conta-valor {
  font-size: 20px;
  font-weight: 700;
  color: var(--ink);
}

.alerta-conta-acoes { display: flex; gap: 8px; }

/* etiqueta que diz se o nome é de cliente ou de fornecedor */
.tag-vinculo {
  display: inline-block;
  padding: 1px 6px;
  margin-right: 5px;
  border-radius: 100px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .5px;
  vertical-align: 1px;
}

.tag-vinculo.cliente    { background: var(--accent-soft); color: var(--accent); }
.tag-vinculo.fornecedor { background: var(--wood-soft);   color: var(--wood-text); }

/* alternador Pagar / Receber no formulário */
.tipo-toggle { display: flex; gap: 8px; }

.tipo-btn {
  flex: 1;
  padding: 10px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-panel);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  color: var(--ink-soft);
  cursor: pointer;
  transition: all .15s ease;
}

.tipo-btn:hover { border-color: var(--accent); }

.tipo-btn.ativo {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

.checkbox-linha {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
}

.checkbox-linha input { width: 16px; height: 16px; cursor: pointer; }

/* anexos */
.anexo-lista { display: flex; flex-wrap: wrap; gap: 8px; }

.anexo-chip {
  display: inline-block;
  padding: 5px 11px;
  border: 1px solid var(--line);
  border-radius: 100px;
  background: var(--bg);
  font-size: 12px;
  font-family: var(--font-mono);
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anexo-galeria {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 14px;
}

.anexo-card {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--bg);
}

.anexo-card img {
  width: 100%;
  height: 140px;
  object-fit: cover;
  display: block;
}

.anexo-pdf {
  height: 140px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--ink-soft);
  background: var(--bg-panel);
}

.anexo-card-rodape {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 6px 8px;
  background: var(--bg-panel);
  border-top: 1px solid var(--line);
  font-size: 11px;
}

.anexo-card-rodape span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.anexo-card-rodape .btn-icone { width: 24px; height: 24px; border: none; flex-shrink: 0; }
.anexo-card-rodape .btn-icone svg { width: 13px; height: 13px; }

/* contador sobre o ícone de clipe */
.btn-icone { position: relative; }

.anexo-contador {
  position: absolute;
  top: -5px;
  right: -5px;
  min-width: 15px;
  height: 15px;
  padding: 0 4px;
  border-radius: 100px;
  background: var(--accent);
  color: var(--on-accent);
  font-family: var(--font-mono);
  font-size: 9px;
  line-height: 15px;
  text-align: center;
}

/* linha de lançamento vencido */
table.data-table tbody tr.linha-atrasada td:first-child {
  box-shadow: inset 3px 0 0 var(--status-declined);
}

.orc-resumo-item.atrasado { background: var(--status-declined-soft); }
.orc-resumo-item.atrasado .orc-resumo-valor { color: var(--status-declined); }

/* ============================================================
   FILTROS DE RELATÓRIO
   ============================================================ */
.filtros-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 14px;
  align-items: end;
}

.filtros-grid .form-group { margin-bottom: 0; }

.filtros-acoes { display: flex; gap: 8px; grid-column: span 2; }
.filtros-acoes .btn { flex: 1 1 auto; white-space: nowrap; }

/* ============================================================
   TELA DO ORÇAMENTO (ver.php)
   ============================================================ */
.orc-topo {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 18px;
  flex-wrap: wrap;
}

.orc-topo-acoes { display: flex; gap: 8px; flex-wrap: wrap; }

.orc-resumo {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 20px;
}

.orc-resumo-item { background: var(--bg-panel); padding: 16px 18px; }
.orc-resumo-item.destaque { background: var(--accent-soft); }

.orc-resumo-valor {
  font-size: 16px;
  font-weight: 600;
  margin-top: 4px;
  color: var(--ink);
}

.orc-resumo-valor.grande { font-size: 24px; color: var(--accent); }

/* --- cartões de ambiente --- */
.ambiente-lista {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 14px;
}

.ambiente-card {
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* ambiente em espera (migration 020): fora do total, então mais apagado
   e com borda tracejada -- fica visível sem competir com os confirmados */
.ambiente-card.em-espera {
  background: var(--bg);
  border-style: dashed;
  box-shadow: none;
}
.ambiente-card.em-espera .ambiente-valor-final { color: var(--ink-soft); }

.ambientes-espera-titulo {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  margin: 24px 0 10px;
}

/* tela de cálculo de orçamento aprovado/recusado: só consulta */
.aviso-travado {
  margin-bottom: 16px;
  border-left: 3px solid var(--status-pending);
}

.ambiente-card-topo {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.ambiente-nome {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 17px;
}

.ambiente-valores {
  display: flex;
  gap: 20px;
  padding: 12px 0;
  border-top: 1px dashed var(--line);
  border-bottom: 1px dashed var(--line);
}

.ambiente-valor-final { font-size: 18px; font-weight: 700; color: var(--accent); }

.ambiente-acoes { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ambiente-acoes .btn { flex-shrink: 0; }
.ambiente-acoes .btn-icone { margin-left: auto; }

.orc-finalizar-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

.orc-status-botoes { display: flex; gap: 8px; flex-wrap: wrap; }

/* --- lista de compras --- */
.modal-box.modal-largo { max-width: 780px; }

.compras-resumo { margin-bottom: 18px; }

.compras-progresso {
  height: 8px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 100px;
  overflow: hidden;
  margin-bottom: 8px;
}

.compras-progresso-barra {
  height: 100%;
  background: var(--status-approved);
  transition: width .3s ease;
}

/* item já comprado fica recuado visualmente, sem sumir da lista */
table.data-table tbody tr.linha-comprada td { opacity: .55; }

table.data-table tfoot td {
  padding: 12px 14px;
  border-top: 2px solid var(--line);
}

/* ============================================================
   PLACEHOLDER DE MÓDULO EM CONSTRUÇÃO
   ============================================================ */
.empty-state.construcao { padding: 48px 20px 52px; }

.construcao-selo {
  display: inline-block;
  margin-bottom: 16px;
  padding: 5px 12px;
  border-radius: 100px;
  background: var(--wood-soft);
  color: var(--wood-text);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1px;
}

.construcao-lista {
  max-width: 460px;
  margin: 0 auto 24px auto;
  padding: 16px 20px;
  border: 1px dashed var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg);
  text-align: left;
}

.construcao-lista-titulo {
  font-family: var(--font-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--ink-soft);
  margin-bottom: 10px;
}

.construcao-lista ul {
  margin: 0;
  padding-left: 18px;
  font-size: 14px;
  color: var(--ink);
}

.construcao-lista li { margin-bottom: 6px; }
.construcao-lista li:last-child { margin-bottom: 0; }

.construcao-acoes {
  display: flex;
  gap: 10px;
  justify-content: center;
  flex-wrap: wrap;
}

/* ============================================================
   ORDENS DE SERVIÇO
   ============================================================ */

/* Duas situações a mais que o orçamento não tinha. Reaproveitam os
   tokens existentes em vez de inventar cor nova: madeira para o que
   está em produção (mesma cor dos botões de "fazer"), cinza para o
   que está parado -- serviço em espera não é erro, é só ausência de
   movimento, e pintá-lo de vermelho criaria urgência falsa. */
.badge-running { background: var(--wood-soft); color: var(--wood-text); }
.badge-hold    { background: var(--bg);        color: var(--ink-soft); }

/* previsão vencida num serviço que ainda não terminou */
.data-atrasada { color: var(--status-declined); font-weight: 600; }

/* seletor de situação dentro da linha da tabela: precisa caber na
   coluna de ações sem empurrar as outras colunas, por isso não usa
   .form-control (que é de largura total, feita para formulário) */
.select-situacao {
  font-family: var(--font-body);
  font-size: 12px;
  padding: 4px 6px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-panel);
  color: var(--ink);
  cursor: pointer;
  max-width: 150px;
}

.select-situacao:hover  { border-color: var(--accent); }
.select-situacao:focus  { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.select-situacao:disabled { opacity: .5; cursor: wait; }

/* .btn-icone nasceu para remover, então acende em vermelho. Numa ação
   que não destrói nada (abrir detalhes) o vermelho prometeria perigo
   onde não há -- este modificador devolve a cor de ação normal. */
.btn-icone.neutro:hover,
.btn-icone.neutro:focus-visible {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--accent-soft);
}

.btn-icone.neutro:focus-visible { box-shadow: 0 0 0 3px var(--accent-soft); }

/* resumo do orçamento no topo do modal da OS: dado só de leitura,
   para não obrigar a abrir o orçamento em outra aba só para lembrar
   de quem é o serviço */
.os-resumo {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin-bottom: 18px;
}

.os-resumo > div {
  background: var(--bg-panel);
  padding: 9px 12px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0; /* sem isto um nome longo estoura a grade */
}

.os-resumo span {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--ink-soft);
}

.os-resumo strong {
  font-size: 13px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}


/* ============================================================
   ESTOQUE (aba dentro de Materiais)
   ============================================================ */

/* Alternador Cadastro / Estoque. Fica ACIMA das abas de categoria de
   propósito: é uma troca de visão do mesmo material, hierarquicamente
   acima do filtro. Se ficasse ao lado das categorias pareceria só mais
   um filtro, e o usuário não entenderia que os preços sumiram. */
.modo-switch {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  margin-bottom: 14px;
  background: var(--bg-panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

.modo-btn {
  padding: 7px 20px;
  border: none;
  border-radius: calc(var(--radius-sm) - 2px);
  background: transparent;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink-soft);
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}

.modo-btn:hover { color: var(--ink); }

.modo-btn.ativo {
  background: var(--accent);
  color: var(--on-accent);
}

/* saldo na tabela: o número é o dado principal da tela, então pesa mais
   que o resto da linha */
.saldo-valor { font-weight: 600; }

/* abaixo do mínimo: alerta, não erro -- cor de madeira, a mesma dos
   estados "atenção" do resto do sistema */
.saldo-valor.baixo { color: var(--status-pending-text); }

/* negativo é outra coisa: significa que saiu material que nunca foi
   lançado como entrada. É inconsistência de cadastro, e merece vermelho */
.saldo-valor.negativo { color: var(--status-declined); }

.saldo-alerta {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 6px;
  border-radius: 100px;
  background: var(--status-pending-soft);
  color: var(--status-pending-text);
  font-family: var(--font-body);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .04em;
  vertical-align: 1px;
}

.saldo-alerta.negativo { background: var(--status-declined-soft); color: var(--status-declined); }

/* cabeçalho do modal de movimentação: mostra de qual material se trata
   e quanto tem hoje, para não obrigar a fechar o modal e conferir */
.mov-material {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 11px 14px;
  margin-bottom: 18px;
  background: var(--bg);
  border-radius: var(--radius-sm);
}

.mov-material-nome { font-weight: 600; font-size: 14px; }

.mov-material-saldo {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--ink-soft);
}

.mov-material-saldo strong { font-size: 16px; color: var(--ink); }

/* linhas do extrato: entrada e saída precisam ser distinguíveis de
   relance, sem ler o rótulo */
.extrato-qtd.entrada { color: var(--status-approved); }
.extrato-qtd.saida   { color: var(--status-declined); }

.extrato-origem {
  display: inline-block;
  padding: 1px 6px;
  border-radius: 100px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}

.extrato-origem.manual     { background: var(--bg);            color: var(--ink-soft); }
.extrato-origem.servico    { background: var(--accent-soft);   color: var(--accent); }
.extrato-origem.inventario { background: var(--wood-soft);     color: var(--wood-text); }
.extrato-origem.compra     { background: var(--status-approved-soft); color: var(--status-approved); }


/* ============================================================
   TELA DE CÁLCULO — apresentação dos itens lançados
   ============================================================ */

/* wrapper do autocomplete fora do .search-box (que reserva espaço para
   o ícone de lupa); aqui o campo é um form-control comum */
.campo-autocomplete { position: relative; }

/* material escolhido na lista ganha uma marca discreta: sem ela, o campo
   com texto parece igual ao campo com texto NÃO confirmado, e o usuário
   só descobre a diferença ao tentar adicionar */
.form-control.escolhido {
  border-color: var(--accent);
  background: var(--accent-soft);
  font-weight: 600;
}

/* --- resumo no cabeçalho do grupo --- */
.peca-grupo-resumo,
.item-grupo-resumo {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}

/* o número de chapas é a resposta que a tela existe para dar: ganha
   destaque de etiqueta em vez de virar mais um texto na linha */
.chapa-badge {
  padding: 3px 10px;
  border-radius: 100px;
  background: var(--accent);
  color: var(--on-accent);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

/* --- rodapé com a conta à mostra --- */
.peca-grupo-total .calc-conta {
  font-size: 13px;
  color: var(--ink);
}

/* os operadores em cor fraca deixam os NÚMEROS em primeiro plano;
   a conta é lida pelos valores, não pelos sinais */
.calc-conta .op {
  color: var(--ink-soft);
  margin: 0 3px;
}

.calc-conta strong { color: var(--accent); font-size: 15px; }

/* --- blocos de ferragem / fita / diverso --- */
.item-add-botoes {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

/* mesmo cartão dos grupos de MDF: as duas metades da tela de cálculo
   passam a ter a mesma linguagem visual */
.item-grupo {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  margin-bottom: 14px;
  overflow: hidden;
}

.item-grupo-header {
  background: var(--bg);
  padding: 10px 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: 14px;
  border-bottom: 1px solid var(--line);
}

.item-grupo-header .nome { font-weight: 600; }
.item-grupo-resumo .mono { font-size: 12px; color: var(--ink-soft); }

/* 5 linhas visíveis e o resto rola, igual à lista de corte.
   Altura derivada: cabeçalho 33px + 5 x 40px. */
.item-grupo-tabela-wrap {
  overflow-x: auto;
  overflow-y: auto;
  max-height: 233px;
}

.calc-vazio {
  padding: 26px 20px;
  text-align: center;
  color: var(--ink-soft);
  font-size: 14px;
  border: 1px dashed var(--line);
  border-radius: var(--radius-sm);
}

.calc-vazio p { margin: 0 0 4px; }
.calc-vazio p:last-child { margin: 0; }

/* ============================================================
   MODAL DE SELEÇÃO DE MATERIAL (ferragem / fita / diverso)
   ============================================================ */
.picker-busca { margin-bottom: 12px; }

/* lista sempre visível (não é dropdown): sem busca ela mostra a
   categoria inteira, que serve para quem não lembra o nome exato */
.picker-lista {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  max-height: 260px;
  overflow-y: auto;
}

.picker-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  width: 100%;
  padding: 10px 14px;
  border: none;
  border-bottom: 1px solid var(--line);
  background: var(--bg-panel);
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--ink);
  text-align: left;
  cursor: pointer;
}

.picker-item:last-child { border-bottom: none; }
.picker-item:hover { background: var(--accent-soft); }

.picker-item.ativo {
  background: var(--accent-soft);
  box-shadow: inset 3px 0 0 var(--accent);
}

/* já lançado: apagado e com etiqueta. Continua clicável de propósito --
   o clique é que dispara o aviso explicando por que não dá para repetir
   e o que fazer. Desabilitar o botão não explicaria nada. */
.picker-item.lancado { opacity: .62; }
.picker-item.lancado .picker-item-nome { text-decoration: line-through; }

.picker-tag-lancado {
  flex-shrink: 0;
  padding: 1px 7px;
  border-radius: 100px;
  background: var(--status-approved-soft);
  color: var(--status-approved);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  white-space: nowrap;
}

.picker-item-nome { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.picker-item-meta { font-size: 12px; color: var(--ink-soft); white-space: nowrap; }
.picker-item-meta .unidade { opacity: .75; }

.picker-vazio {
  padding: 22px 14px;
  text-align: center;
  font-size: 13px;
  color: var(--ink-soft);
}

/* barra do material escolhido + quantidade */
.picker-selecionado {
  display: flex;
  align-items: flex-end;
  gap: 14px;
  flex-wrap: wrap;
  margin-top: 14px;
  padding: 12px 14px;
  background: var(--bg);
  border-radius: var(--radius-sm);
  border-left: 3px solid var(--wood);
}

.picker-selecionado[hidden] { display: none; }

.picker-sel-info { flex: 1; min-width: 160px; display: flex; flex-direction: column; gap: 2px; }
.picker-sel-nome { font-weight: 600; font-size: 14px; }

.picker-sel-qtd { width: 140px; flex-shrink: 0; }
.picker-sel-qtd label { display: block; font-size: 12px; color: var(--ink-soft); margin-bottom: 4px; }
.picker-selecionado .btn { flex-shrink: 0; }

/* histórico da sessão: confirma que os anteriores entraram, sem
   precisar fechar o modal para conferir na tela de trás */
.picker-adicionados:not(:empty) {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}

.picker-add-titulo {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .06em;
  margin-bottom: 6px;
}

.picker-add-titulo .mono {
  font-size: 13px;
  font-weight: 700;
  color: var(--ink);
  text-transform: none;
  letter-spacing: 0;
}

.picker-add-linha {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 0;
  font-size: 13px;
  border-bottom: 1px dashed var(--line);
}

.picker-add-linha:last-child { border-bottom: none; }

/* o nome cede espaço; quantidade e lixeira nunca encolhem */
.picker-add-nome { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.picker-add-linha .mono { margin-left: auto; flex-shrink: 0; font-size: 12px; color: var(--ink-soft); white-space: nowrap; }
.picker-add-linha .btn-icone { flex-shrink: 0; width: 26px; height: 26px; }
.picker-add-linha .btn-icone svg { width: 13px; height: 13px; }

@media (max-width: 560px) {
  .picker-selecionado { align-items: stretch; }
  .picker-sel-qtd { width: 100%; }
  .picker-selecionado .btn { width: 100%; justify-content: center; }
}


/* ============================================================
   ACRÉSCIMOS DO AMBIENTE (vidro de terceiro, serviço avulso)
   ============================================================ */
.acrescimo-lista { display: grid; gap: 10px; }

/* cartão, e não linha de tabela: o acréscimo carrega uma observação de
   texto livre ("vidro fumê 4mm, feito pela vidraçaria X"), que numa
   célula de tabela ou estoura a largura ou fica cortada */
.acrescimo-card {
  border: 1px solid var(--line);
  border-left: 3px solid var(--wood);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
}

.acrescimo-topo {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.acrescimo-desc { font-weight: 600; font-size: 14px; }
.acrescimo-valor { font-size: 15px; font-weight: 600; white-space: nowrap; }

.acrescimo-obs {
  margin: 6px 0 0;
  font-size: 13px;
  color: var(--ink-soft);
  line-height: 1.45;
  /* respeita a quebra de linha digitada no textarea */
  white-space: pre-wrap;
}

.acrescimo-acoes {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  margin-top: 8px;
}

/* ============================================================
   COMPOSIÇÃO DO TOTAL DO AMBIENTE
   Mostra a conta inteira em linha: materiais × complexidade + acréscimos.
   Antes eram três blocos soltos e não se lia como operação.
   ============================================================ */
.totais-composicao {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 12px;
}

.totais-composicao > div {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.totais-composicao .mono { font-size: 18px; font-weight: 600; }

/* operador em cor fraca: os números é que devem saltar */
.totais-op {
  font-family: var(--font-mono);
  font-size: 18px;
  color: var(--ink-soft);
  padding-bottom: 2px;
}

.totais-multiplicador { width: 110px; flex-shrink: 0; }
.totais-multiplicador .form-control { padding: 6px 10px; font-size: 15px; }

/* o resultado é o que a tela existe para dar: empurrado para a direita
   e maior que as parcelas */
.totais-final { margin-left: auto; align-items: flex-end; text-align: right; }
.totais-final .mono { font-size: 24px; font-weight: 700; color: var(--accent); }

@media (max-width: 700px) {
  .totais-op { display: none; }          /* sem espaço, o sinal vira ruído */
  .totais-final { margin-left: 0; align-items: flex-start; text-align: left; }
}

/* ============================================================
   AJUSTE DO VALOR FECHADO DO ORÇAMENTO
   ============================================================ */
.orc-ajuste-info {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 6px;
  font-size: 12px;
  color: var(--ink-soft);
}

.orc-ajuste-info[hidden] { display: none; }

.ajuste-tag {
  padding: 1px 7px;
  border-radius: 100px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}

.ajuste-tag.desconto  { background: var(--status-declined-soft); color: var(--status-declined); }
.ajuste-tag.acrescimo { background: var(--status-approved-soft); color: var(--status-approved); }

.ajuste-motivo {
  width: 100%;
  text-align: right;
  font-style: italic;
}

#btnAjustarValor { margin-top: 8px; }

/* prévia dentro do modal */
.ajuste-composicao {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  padding: 12px 14px;
  margin-bottom: 18px;
  background: var(--bg);
  border-radius: var(--radius-sm);
}

.ajuste-composicao > div { display: flex; flex-direction: column; gap: 2px; }
.ajuste-composicao .mono { font-size: 16px; font-weight: 600; }

/* --- resumo de pagamento do orçamento (ver.php): Total · Recebido · Falta --- */
.pag-resumo {
  display: flex;
  align-items: center;
  gap: 12px 28px;
  flex-wrap: wrap;
}
.pag-resumo > div { display: flex; flex-direction: column; gap: 2px; }
.pag-resumo strong { font-size: 17px; }
.pag-resumo .btn { margin-left: auto; flex-shrink: 0; }
.pag-recebido { color: var(--status-approved); }
.pag-quitado  { color: var(--status-approved); }

/* --- calculadora da condição de pagamento (ver.php) --- */
.calc-campos { margin-top: 14px; }

/* as duas opções lado a lado, no mesmo fundo do ajuste: é o que o
   vendedor vai ler para o cliente, então fica em destaque */
.calc-resultado {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
}
.calc-opcao {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  padding: 12px 14px;
  background: var(--bg);
  border-radius: var(--radius-sm);
}
.calc-opcao strong { font-size: 16px; }

.calc-acoes {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 12px;
}
.calc-acoes .btn { flex-shrink: 0; }
.calc-acoes .hint { color: var(--status-pending-text); }

.calc-gerar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 16px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
}

/* desconto em vermelho e acréscimo em verde: a diferença precisa ser
   lida de relance antes de confirmar */
.dif-desconto  { color: var(--status-declined); }
.dif-acrescimo { color: var(--status-approved); }


/* ============================================================
   ESQUELETO DE CARREGAMENTO
   Substitui o texto "Carregando..." que existia em 14 telas.

   Um texto solto some e dá lugar a uma tabela de altura totalmente
   diferente: a tela "pula" e o olho perde a referência. O esqueleto
   ocupa aproximadamente o espaço do conteúdo que vem, então a troca é
   suave -- e a animação comunica que algo está acontecendo, coisa que
   um texto parado não faz.
   ============================================================ */
.esqueleto { padding: 4px 0; }

.esqueleto-linha {
  height: 14px;
  margin-bottom: 14px;
  border-radius: 4px;
  background: linear-gradient(
    90deg,
    var(--bg) 0%,
    var(--line) 40%,
    var(--bg) 80%
  );
  background-size: 300% 100%;
  animation: esqueleto-brilho 1.4s ease-in-out infinite;
}

.esqueleto-linha:last-child { margin-bottom: 0; }

@keyframes esqueleto-brilho {
  0%   { background-position: 100% 0; }
  100% { background-position: -100% 0; }
}

/* respeita quem desligou animação no sistema operacional: vira uma
   barra cinza estática, que ainda reserva o espaço certo */
@media (prefers-reduced-motion: reduce) {
  .esqueleto-linha { animation: none; background: var(--line); }
}

/* ============================================================
   FOCO VISÍVEL
   O sistema tinha anel de foco em 4 pontos isolados. Quem navega por
   teclado (e no balcão isso é comum: Tab entre campos com a mão suja
   de serragem) ficava sem saber onde está.

   :focus-visible, e não :focus -- o navegador só aplica quando o foco
   veio do teclado, então o clique de mouse não deixa anel sobrando.
   ============================================================ */
.btn:focus-visible,
.tab-btn:focus-visible,
.subtab-btn:focus-visible,
.modo-btn:focus-visible,
.tipo-btn:focus-visible,
.modal-close:focus-visible,
.picker-item:focus-visible,
.usuario-botao:focus-visible,
a:not(.btn):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* no cabeçalho escuro o anel verde-petróleo não aparece: usa o creme */
.app-nav a:focus-visible,
.usuario-botao:focus-visible {
  outline: 2px solid var(--on-dark);
  outline-offset: 2px;
}

.form-control:focus-visible {
  outline: none; /* o próprio :focus já desenha borda + sombra */
}


/* ============================================================
   PAINEL DE SUPORTE
   ============================================================ */

/* nome da marcenaria com o CNPJ embaixo, na mesma célula: duas colunas
   deixariam a de CNPJ quase sempre vazia */
.suporte-nome { font-weight: 600; }

/* separador dentro do formulário, quando um bloco muda de assunto
   (dados da empresa -> credencial do administrador) */
.suporte-divisor {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 22px 0 14px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--ink-soft);
}

.suporte-divisor::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--line);
}

/* linha de marcenaria desativada: apagada, mas ainda legível --
   é registro válido, não erro */
tr.linha-inativa td { opacity: .55; }
tr.linha-inativa .badge { opacity: 1; }

/* caixa da credencial recém-gerada. Fundo escuro de propósito: é uma
   informação que aparece UMA vez e precisa saltar da tela para a
   pessoa anotar antes de fechar. */
.credencial-caixa {
  display: grid;
  gap: 14px;
  padding: 18px 20px;
  background: var(--ink);
  border-radius: var(--radius-sm);
}

.credencial-caixa > div { display: flex; flex-direction: column; gap: 4px; }

.credencial-caixa .hint {
  color: var(--on-dark-dim);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .06em;
}

.credencial-caixa strong {
  color: var(--on-dark);
  font-size: 22px;
  letter-spacing: .05em;
  /* a senha vai ser lida em voz alta ou digitada por outra pessoa:
     seleção fácil ajuda mais do que qualquer enfeite */
  user-select: all;
}


/* ============================================================
   DASHBOARD — SAUDAÇÃO, AÇÕES RÁPIDAS E PRÓXIMOS VENCIMENTOS
   ============================================================ */

/* Primeira linha da primeira tela do dia: quem está usando, que dia é, e
   o que ele mais faz. O painel abre com contexto em vez de abrir com um
   filtro de período. */
.dash-saudacao {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px;
  margin-bottom: 18px;
}

.dash-saudacao h2 {
  margin: 0 0 2px;
  font-size: 22px;
}

.dash-acoes {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

/* ------------------------------------------------------------
   Cartão de indicador que leva a algum lugar

   O cartão virou <a>: ver "R$ 8.400 a pagar" e ter que caçar o Financeiro
   no menu é um passo a mais em cima de um número que já pede ação. Precisa
   sair das regras genéricas de link (a:not(.btn)), senão o texto todo
   assume a cor de acento.
   ------------------------------------------------------------ */
a.dash-card:not(.btn),
a.dash-card:not(.btn):hover { color: var(--ink); text-decoration: none; }

a.dash-card {
  display: block;
  transition: border-color .15s ease, box-shadow .15s ease, transform .1s ease;
}

a.dash-card:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow-lg);
}

a.dash-card:active { transform: scale(.995); }

/* variação contra o período anterior, no rodapé do cartão */
.dash-var {
  display: inline-block;
  margin-left: 4px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}

.dash-var.boa     { color: var(--status-approved); }
.dash-var.ruim    { color: var(--status-declined); }
.dash-var.neutra  { color: var(--ink-soft); font-weight: 500; }

/* ------------------------------------------------------------
   Próximos 15 dias
   ------------------------------------------------------------ */
.proximos-totais {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
  margin-bottom: 16px;
}

.proximos-total {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 12px 14px;
  background: var(--bg);
  border-radius: var(--radius-sm);
  /* a faixa colorida à esquerda diz de que lado o dinheiro anda, sem
     precisar de mais uma legenda */
  border-left: 3px solid var(--line);
}

.proximos-total strong { font-size: 18px; }
.proximos-total.entrada { border-left-color: var(--status-approved); }
.proximos-total.entrada strong { color: var(--status-approved); }
.proximos-total.saida { border-left-color: var(--status-declined); }
.proximos-total.saida strong { color: var(--status-declined); }

.proximos-rodape {
  display: flex;
  justify-content: flex-end;
  margin-top: 12px;
}

/* ============================================================
   CELULAR
   Tudo que muda no celular mora aqui, num bloco só, em vez de
   espalhado pelas seções de cima. O computador continua exatamente
   como era: nada abaixo vale acima de 780px, exceto as regras que
   ESCONDEM as peças exclusivas do celular.

   O limite é o mesmo 780px que o menu já usava para quebrar. Abaixo
   disso o menu de cima nunca coube, então é ali que a navegação muda.
   ============================================================ */

/* marcação de conteúdo por aparelho, usada direto nas views:
   .so-celular    -> botão de WhatsApp, aviso de "use o computador"
   .so-computador -> ação que é trabalho de mesa (criar orçamento, ambiente) */
@media (min-width: 781px) {
  .so-celular,
  .nav-celular,
  .folha-mais { display: none !important; }

  /* telefone vira link só onde dá para ligar; no computador continua texto */
  a.link-ligacao:not(.btn) { color: inherit; pointer-events: none; }
}

@media (max-width: 780px) {
  .so-computador { display: none !important; }

  /* --- cabeçalho: só a marca. Menu e usuário descem para a barra --- */
  .app-header {
    flex-wrap: nowrap;
    min-height: 58px;
    padding: 6px 16px;
    padding-top: max(6px, env(safe-area-inset-top));
  }
  .app-header .app-nav,
  .app-header .usuario-bloco { display: none; }
  .app-header .brand-name { font-size: 16px; }
  .brand-placa { padding: 4px 8px; }
  .brand-logo { height: 34px; max-width: 150px; }

  /* respiro embaixo = altura da barra inferior, senão o último cartão
     da lista fica escondido atrás dela */
  .app-main { padding: 16px 14px calc(88px + env(safe-area-inset-bottom)); }

  .page-title-row { margin-bottom: 14px; }
  .page-title-row h1 { font-size: 21px; line-height: 1.2; margin-bottom: 2px; }
  .page-title-row .subtitle { font-size: 11px; }

  /* --- barra inferior --- */
  .nav-celular {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 150;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    padding: 7px 4px calc(7px + env(safe-area-inset-bottom));
    background: var(--ink);
    box-shadow: 0 -4px 18px rgba(42,36,32,.18);
  }

  /* a mesma "marca de régua" do .measure-card, agora na borda da barra */
  .nav-celular::before {
    content: '';
    position: absolute;
    top: 0;
    left: 16px;
    right: 16px;
    height: 2px;
    background: repeating-linear-gradient(90deg, var(--wood) 0 8px, transparent 8px 14px);
    opacity: .7;
  }

  .nav-celular-item,
  a.nav-celular-item:not(.btn),
  a.nav-celular-item:not(.btn):hover {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    min-height: 52px;
    padding: 2px;
    border: none;
    background: none;
    color: var(--on-dark-dim);
    font-family: var(--font-body);
    font-size: 10.5px;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }

  .nav-celular-icone {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 30px;
    border-radius: 100px;
    transition: background .15s ease;
  }

  .nav-celular-icone svg { width: 22px; height: 22px; }

  .nav-celular-rotulo {
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .nav-celular-item.active,
  a.nav-celular-item.active:not(.btn) { color: var(--on-dark); }
  .nav-celular-item.active .nav-celular-icone { background: var(--accent); color: var(--on-accent); }

  .nav-celular-alerta {
    position: absolute;
    top: -2px;
    right: 6px;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    border-radius: 100px;
    background: var(--status-declined);
    color: var(--on-accent);
    font-family: var(--font-mono);
    font-size: 10px;
    line-height: 17px;
    text-align: center;
    box-shadow: 0 0 0 2px var(--ink);
  }

  /* --- folha "Mais" ---
     Abaixo da barra (z-index 140 x 150): o botão "Mais" continua
     visível e fecha a folha com o mesmo toque que a abriu. */
  .folha-mais:not([hidden]) {
    position: fixed;
    inset: 0;
    z-index: 140;
    display: flex;
    align-items: flex-end;
  }

  .folha-mais-fundo {
    position: absolute;
    inset: 0;
    background: rgba(42,36,32,.45);
  }

  .folha-mais-caixa {
    position: relative;
    width: 100%;
    max-height: 85vh;
    overflow-y: auto;
    padding: 8px 16px calc(84px + env(safe-area-inset-bottom));
    background: var(--bg);
    border-radius: 16px 16px 0 0;
    box-shadow: var(--shadow-lg);
    animation: folha-sobe .2s ease-out;
  }

  .folha-mais-alca {
    width: 40px;
    height: 4px;
    margin: 4px auto 14px;
    border-radius: 100px;
    background: var(--line);
  }

  .folha-mais-usuario {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 4px 4px 16px;
  }

  .folha-mais-usuario .usuario-avatar { width: 40px; height: 40px; font-size: 18px; }
  .folha-mais-usuario-texto { display: flex; flex-direction: column; min-width: 0; line-height: 1.3; }
  .folha-mais-usuario-texto span {
    font-size: 12px;
    color: var(--ink-soft);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .folha-mais-grupo {
    margin-bottom: 12px;
    overflow: hidden;
    background: var(--bg-panel);
    border: 1px solid var(--line);
    border-radius: var(--radius);
  }

  .folha-mais-rotulo {
    padding: 10px 16px 4px;
    font-family: var(--font-mono);
    font-size: 10.5px;
    letter-spacing: .5px;
    text-transform: uppercase;
    color: var(--ink-soft);
  }

  .folha-mais-link,
  a.folha-mais-link:not(.btn) {
    display: flex;
    align-items: center;
    width: 100%;
    min-height: 50px;
    padding: 0 16px;
    border: none;
    border-top: 1px solid var(--line);
    background: none;
    color: var(--ink);
    font-family: var(--font-body);
    font-size: 15px;
    text-align: left;
    cursor: pointer;
  }

  .folha-mais-grupo > .folha-mais-link:first-child,
  .folha-mais-rotulo + .folha-mais-link { border-top: none; }

  /* seta de "entra": a lista parece tocável, não texto solto */
  a.folha-mais-link::after {
    content: '';
    width: 7px;
    height: 7px;
    margin-left: auto;
    border-top: 2px solid var(--ink-soft);
    border-right: 2px solid var(--ink-soft);
    transform: rotate(45deg);
    opacity: .5;
  }

  a.folha-mais-link.active:not(.btn) { color: var(--accent); font-weight: 600; }
  .folha-mais-link.folha-mais-sair { color: var(--status-declined); font-weight: 600; }

  body.folha-aberta { overflow: hidden; }

  /* --- barra de ferramentas e abas --- */
  .toolbar { flex-wrap: wrap; gap: 10px; margin-bottom: 14px; }
  .toolbar .search-box { flex: 1 1 100%; max-width: none; }
  /* Financeiro: os dois selects dividem a linha; o período ocupa uma
     inteira, com os campos repartindo o espaço */
  /* Financeiro: busca, tipo e mês ocupam a linha inteira, um embaixo do outro */
  .fin-filtros-barra { padding: 12px 14px; }
  .fin-filtros-barra .search-box { flex: 1 1 100%; max-width: none; }
  .segmentado { flex: 1 1 100%; }
  .segmentado button { flex: 1 1 0; padding: 8px 6px; }
  .fin-filtros-barra .mes-nav { flex: 1 1 100%; }
  .fin-filtros-barra .mes-nav-rotulo { min-width: 0; flex: 1; }
  .fin-cabecalho { padding: 0 8px; overflow-x: auto; }
  .fin-totais { padding: 10px 14px; }
  /* botões do título descem para baixo dele e quebram linha, em vez de
     espremer o título (o Financeiro tem três) */
  .page-title-row { flex-wrap: wrap; }
  .page-title-acoes { flex-wrap: wrap; flex-shrink: 1; }
  /* grade: "Vencimento" em cima, as duas datas embaixo repartindo a
     largura -- em linha, o campo de data não encolhe abaixo do próprio
     tamanho e a segunda data saía cortada pela borda */
  .fin-periodo {
    flex: 1 1 100%;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center;
    gap: 6px 8px;
  }
  .fin-periodo[hidden] { display: none; }
  .fin-periodo > .hint:first-child { grid-column: 1 / -1; }
  .fin-periodo input.form-control { width: 100%; min-width: 0; }
  .toolbar > .btn { flex: 1 1 auto; justify-content: center; }

  /* abas rolam de lado em vez de quebrar: "Aguardando aprovação 3"
     sozinha já quase ocupa a largura da tela */
  .tabs-categoria {
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .tabs-categoria::-webkit-scrollbar { display: none; }
  .tab-btn { flex-shrink: 0; white-space: nowrap; padding: 10px 12px; }

  .panel-header { flex-wrap: wrap; gap: 6px; padding: 12px 14px; }
  .panel-body { padding: 14px; }

  /* --- toque: alvo de ~44px, e 16px nos campos. Abaixo de 16px o
     Safari do iPhone dá zoom na página ao focar o campo, e ela não
     volta sozinha --- */
  .btn { min-height: 42px; }
  .btn-sm { min-height: 36px; }
  .form-control,
  .search-box input,
  select,
  textarea { font-size: 16px; }

  .form-row { flex-direction: column; gap: 0; }

  /* --- modal vira folha que sobe de baixo, onde o polegar alcança --- */
  .modal-overlay { padding: 0; align-items: flex-end; }
  .modal-overlay .modal-box {
    max-width: 100%;
    max-height: 92vh;
    border-radius: 16px 16px 0 0;
  }
  .modal-header { padding: 16px 18px; }
  .modal-body { padding: 18px; }
  .modal-footer { padding: 12px 18px calc(12px + env(safe-area-inset-bottom)); }
  .modal-footer .btn { flex: 1 1 auto; justify-content: center; }

  /* acima da barra inferior */
  .toast-container { bottom: calc(80px + env(safe-area-inset-bottom)); }

  /* --- TABELA VIRA LISTA DE CARTÕES ---
     O rótulo de cada linha vem de data-label, preenchido pelo ui.js a
     partir do cabeçalho da coluna. Tabela que precisa continuar tabela
     leva .tabela-fixa. */

  /* o painel em volta some: cartão dentro de cartão é borda dobrada */
  .panel:has(> .panel-body > table.data-table:not(.tabela-fixa)) {
    background: none;
    border: none;
    box-shadow: none;
  }
  .panel-body:has(> table.data-table:not(.tabela-fixa)) { padding: 0; overflow: visible; }

  table.data-table:not(.tabela-fixa),
  table.data-table:not(.tabela-fixa) tfoot { display: block; }

  table.data-table:not(.tabela-fixa) thead { display: none; }

  table.data-table:not(.tabela-fixa) tbody { display: flex; flex-direction: column; gap: 10px; }

  table.data-table:not(.tabela-fixa) tr {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    column-gap: 8px;
    padding: 12px 14px;
    background: var(--bg-panel);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
  }

  table.data-table:not(.tabela-fixa) tbody tr:hover { background: var(--bg-panel); }
  table.data-table:not(.tabela-fixa) tfoot tr { margin-top: 10px; background: var(--bg); box-shadow: none; }

  table.data-table:not(.tabela-fixa) td {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    flex-wrap: wrap;
    column-gap: 14px;
    /* width:100% vence o width:1% das classes de coluna: no cartão cada
       célula é uma linha inteira */
    width: 100% !important;
    padding: 4px 0;
    border: none;
    font-size: 14px;
    text-align: right !important;
    white-space: normal;
  }

  table.data-table:not(.tabela-fixa) td::before {
    content: attr(data-label);
    flex-shrink: 0;
    font-family: var(--font-mono);
    font-size: 10.5px;
    letter-spacing: .5px;
    text-transform: uppercase;
    color: var(--ink-soft);
    text-align: left;
  }

  table.data-table:not(.tabela-fixa) td[data-label=""]::before { content: none; }
  table.data-table:not(.tabela-fixa) td[data-label=""] { justify-content: flex-start; text-align: left !important; }

  /* primeira linha do cartão: "#14  NOME DO PROJETO" */
  table.data-table:not(.tabela-fixa) td.col-id {
    order: -2;
    width: auto !important;
    padding: 0;
    font-size: 12px;
    color: var(--ink-soft);
  }
  table.data-table:not(.tabela-fixa) td.col-id::before {
    content: '#';
    font-size: 12px;
    letter-spacing: 0;
  }

  table.data-table:not(.tabela-fixa) td[data-principal] {
    order: -1;
    display: block;
    flex: 1 1 0;
    width: auto !important;
    min-width: 0;
    padding: 0 0 8px;
    font-size: 15px;
    font-weight: 600;
    text-align: left !important;
  }
  table.data-table:not(.tabela-fixa) td[data-principal]::before { content: none; }
  table.data-table:not(.tabela-fixa) td[data-principal] .hint { font-weight: 400; }

  table.data-table:not(.tabela-fixa) td.num { font-weight: 600; }

  /* ações: rodapé do cartão, com alvo de toque de verdade */
  table.data-table:not(.tabela-fixa) td.col-acoes {
    justify-content: flex-end;
    align-items: center;
    gap: 8px;
    margin-top: 8px;
    padding-top: 10px;
    border-top: 1px solid var(--line);
  }
  table.data-table:not(.tabela-fixa) td.col-acoes::before { content: none; }
  table.data-table:not(.tabela-fixa) td.col-acoes:empty { display: none; }
  table.data-table:not(.tabela-fixa) td.col-acoes .btn-icone { width: 40px; height: 40px; }
  table.data-table:not(.tabela-fixa) td.col-acoes .select-situacao { flex: 1 1 auto; min-height: 40px; }

  /* excluir fica no computador: no celular um toque errado ao rolar a
     lista é fácil, e nenhuma exclusão é urgente a ponto de não esperar */
  table.data-table:not(.tabela-fixa) td.col-acoes [data-excluir] { display: none; }

  /* a marca vermelha de atraso ia na borda da 1ª célula; no cartão, vai
     na borda do próprio cartão */
  table.data-table:not(.tabela-fixa) tbody tr.linha-atrasada td:first-child { box-shadow: none; }
  table.data-table:not(.tabela-fixa) tbody tr.linha-atrasada { box-shadow: inset 3px 0 0 var(--status-declined), var(--shadow); }

  .paginacao { justify-content: center; border-top: none; }
  .paginacao-info { flex-basis: 100%; text-align: center; }
  .pag-btn { min-width: 38px; height: 38px; }

  /* --- tela do orçamento --- */
  .orc-topo { flex-wrap: wrap; gap: 10px; }
  .orc-topo-acoes { width: 100%; }
  .orc-topo-acoes .btn { flex: 1 1 auto; justify-content: center; }
  .orc-resumo { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .orc-resumo-item.destaque { grid-column: 1 / -1; }
  .orc-finalizar-row { flex-direction: column; align-items: stretch; }
  .orc-status-botoes .btn { flex: 1 1 auto; justify-content: center; }
  .ambiente-lista { grid-template-columns: minmax(0, 1fr); }

  /* --- dashboard --- */
  .dash-saudacao { align-items: flex-start; gap: 10px; }
  .dash-saudacao h2 { font-size: 19px; }
  .dash-acoes { width: 100%; }
  .dash-acoes .btn { flex: 1 1 auto; justify-content: center; }
  .proximos-totais { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .proximos-rodape .btn { width: 100%; justify-content: center; }
  .dash-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  /* 16.5px e sem quebra: a 19px, em duas colunas, "R$ 24.860,00" partia
     em duas linhas e o cartão ficava com a altura de um parágrafo */
  .dash-card-valor { font-size: 16.5px; white-space: nowrap; }
  .dash-grid > * { grid-column: 1 / -1 !important; }
}

@keyframes folha-sobe {
  from { transform: translateY(24px); opacity: 0; }
  to   { transform: translateY(0);    opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .folha-mais-caixa { animation: none; }
}

/* ------------------------------------------------------------
   Ficha de contato (modal de detalhes do cliente)
   Rótulo à esquerda, valor à direita, um campo por linha.
   ------------------------------------------------------------ */
.ficha {
  margin-bottom: 18px;
  padding: 4px 14px;
  background: var(--bg);
  border-radius: var(--radius-sm);
}

.ficha-linha {
  display: flex;
  gap: 16px;
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
  font-size: 14px;
}

.ficha-linha:last-child { border-bottom: none; }

.ficha-rotulo {
  flex: 0 0 96px;
  padding-top: 2px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: .5px;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.ficha-valor { min-width: 0; overflow-wrap: anywhere; }

.ficha-acoes { display: flex; gap: 8px; margin: -8px 0 18px; }
.ficha-acoes .btn { flex: 1 1 0; justify-content: center; }
.ficha-acoes svg { width: 16px; height: 16px; }

/* Clientes no celular: o cartão é só o nome e o "Ver +", numa linha.
   Telefone, cidade, editar e WhatsApp moram no modal de detalhes --
   uma lista de 40 clientes com cinco linhas cada virava rolagem sem fim. */
@media (max-width: 780px) {
  table.data-table.tabela-clientes tr { align-items: center; flex-wrap: nowrap; }
  table.data-table.tabela-clientes td:not([data-principal]):not(.col-acoes) { display: none; }
  table.data-table.tabela-clientes td[data-principal] { padding: 0; }
  table.data-table.tabela-clientes td.col-acoes {
    width: auto !important;
    margin: 0;
    padding: 0;
    border: none;
  }
  .cliente-contagem { grid-template-columns: repeat(2, 1fr); }

  /* cálculo rápido: material numa linha, quantidade e botão embaixo */
  .rapido-linha { grid-template-columns: minmax(0, 1fr) auto; }
  .rapido-linha .rapido-principal { grid-column: 1 / -1; }

  /* Início: cartões dois a dois, menores; a legenda da agenda desce */
  .inicio-cards { gap: 10px; margin-bottom: 14px; }
  a.inicio-card:not(.btn),
  .inicio-card { min-height: 104px; padding: 14px; }
  .inicio-card-valor { font-size: 22px; }
  .inicio-painel .panel-header { flex-wrap: wrap; gap: 8px; }
  .agenda-tipo { width: auto; }
}

/* botões de contato (ligar / WhatsApp) ao lado do telefone */
.contato-acoes { display: inline-flex; align-items: center; gap: 6px; margin-top: 6px; }

/* ------------------------------------------------------------
   Tela que é trabalho de mesa (lista de corte).
   No celular mostra o aviso e esconde o resto da página, até a pessoa
   tocar em "Abrir mesmo assim" -- o ui.js põe .forcar-computador no body.

   Esconde os IRMÃOS SEGUINTES em vez de exigir um wrapper: a tela de
   cálculo não precisou ser reindentada, e modais e scripts ficam onde
   estavam. O aviso tem que ser o primeiro elemento depois do título.
   ------------------------------------------------------------ */
.aviso-computador {
  padding: 24px 20px;
  margin-bottom: 16px;
  text-align: center;
}
.aviso-computador h3 { margin-bottom: 6px; font-size: 18px; }
.aviso-computador p { margin: 0 auto 18px; max-width: 34ch; color: var(--ink-soft); font-size: 14px; }
.aviso-computador-acoes { display: flex; flex-direction: column; gap: 8px; }
.aviso-computador-acoes .btn { justify-content: center; }

@media (max-width: 780px) {
  body:not(.forcar-computador) .aviso-computador ~ :not(script):not(.modal-overlay) { display: none !important; }
  body.forcar-computador .aviso-computador { display: none !important; }
}

/* ------------------------------------------------------------
   Marca do SUPORTE (VindSistemas): símbolo na placa clara + nome.
   Em linha, não empilhada como a logo de uma marcenaria: a placa aqui
   é só o símbolo, e esticá-la na largura do menu lateral ficaria
   estranho. A etiqueta "Suporte" desce para a linha de baixo.
   ------------------------------------------------------------ */
.app-header .brand.brand-vind {
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: center;
  gap: 4px 10px;
}
.brand-vind .brand-placa { align-self: auto; padding: 6px; border-radius: 10px; }
.brand-vind .brand-placa svg { display: block; }

/* Padrão de toda listagem: busca à esquerda, ação principal à direita */
.toolbar > .btn-primary:last-child { margin-left: auto; }

/* ------------------------------------------------------------
   LISTAGENS: controles compactos e tabela com paginação sempre à vista
   (.panel-fill, medido pelo ui.js -- initPaineis)

   Antes eram cinco faixas empilhadas (busca, alternador, categorias,
   espessuras, tabela) e a paginação, no fim da tabela, ficava abaixo da
   dobra. Agora são duas linhas de controle, e o painel da tabela ocupa
   exatamente o que sobra da janela: as linhas rolam POR DENTRO dele, com o
   cabeçalho e a paginação grudados (sticky) em cima e embaixo.
   A altura vem do materiais.js (--altura-painel); sem JS o painel só
   cresce com o conteúdo, como qualquer outro.
   ------------------------------------------------------------ */
.toolbar-materiais { margin-bottom: 14px; flex-wrap: wrap; }
.toolbar-materiais .modo-switch { margin-bottom: 0; }
.toolbar-materiais-novo { margin-left: auto; }

.materiais-filtros {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px 20px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--line);
}
.materiais-filtros .tabs-categoria { border-bottom: none; margin-bottom: 0; }
.materiais-filtros .tabs-espessura { margin: 0 0 8px; flex-wrap: wrap; }

@media (min-width: 781px) {
  .panel-fill > .panel-body {
    max-height: var(--altura-painel, none);
    overflow-y: auto;
    padding-top: 0;
    padding-bottom: 0;
  }
  /* fundo opaco: as linhas passam por trás ao rolar */
  .panel-fill table.data-table thead th {
    position: sticky;
    top: 0;
    z-index: 2;
    background: var(--bg-panel);
  }
  .panel-fill .paginacao {
    position: sticky;
    bottom: 0;
    z-index: 2;
    margin-top: 0;
    padding: 12px 0;
    background: var(--bg-panel);
  }
}

/* ------------------------------------------------------------
   LISTA DE COMPRAS (modal da tela do orçamento)

   Oito colunas: não cabem nos 780px do .modal-largo. O modal próprio é
   mais largo, e a tabela fica compacta: uma linha por item (nada além do
   nome quebra), o que não é o material nunca quebra de linha, e a ação é
   um lápis + "Dar baixa" em vez de dois botões com texto.
   ------------------------------------------------------------ */
.modal-box.modal-compras { max-width: min(1040px, 96vw); }

.tabela-compras th,
.tabela-compras td { padding: 9px 8px; white-space: nowrap; }
.tabela-compras td.col-material { white-space: normal; min-width: 150px; }
.tabela-compras td.col-material .hint { margin: 1px 0 0; }
.tabela-compras td .hint { font-size: 11px; line-height: 1.3; }
.tabela-compras td.col-acoes { display: table-cell; }
.tabela-compras td.col-acoes .btn-icone { margin-right: 6px; vertical-align: middle; }

/* ------------------------------------------------------------
   TELA COMPRAS
   ------------------------------------------------------------ */
/* as abas só existem na leitura "Por orçamento"; sem isto o display:flex
   de .tabs-categoria vence o atributo hidden */
.tabs-categoria[hidden] { display: none; }

/* linha de totais entre as abas e a tabela */
.compras-total { margin: 0 0 10px; min-height: 1.2em; }

/* quem pede o material: corta com reticências em vez de empurrar a linha */
.compras-para {
  max-width: 420px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ------------------------------------------------------------
   COMPRAS: montar a compra, escolher do orçamento, registrar chegada
   ------------------------------------------------------------ */
/* material avulso: busca + quantidade + botão na mesma linha */
.compra-avulso {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 12px;
  padding: 10px 12px;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.compra-avulso[hidden] { display: none; }

/* painel de "Registrar chegada" dentro da compra */
.compra-chegada {
  margin-bottom: 14px;
  padding: 12px 14px;
  background: var(--accent-soft);
  border-radius: var(--radius-sm);
}
.compra-chegada .form-group { margin-bottom: 8px; }
.compra-chegada .hint { margin: 0; }
