/* ============================================================================
   style.css — Engrena. Layout "sidebar navy + cards" (referência: portal
   acadêmico enviado pelo usuário em 2026-08, aprovado para adoção). Mesmo
   padrão de tema (dark/light via [data-theme], alternância manual salva em
   localStorage). A sidebar fica sempre em navy escuro nos dois temas — só o
   fundo/superfícies do conteúdo mudam entre dark e light.
   ============================================================================ */

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');

:root {
  --engrena-bg: #0d1520;
  --engrena-surface: #141d2b;
  --engrena-surface-alt: #1b2636;
  --engrena-border: #263346;
  --engrena-primary: #1e88e5;
  --engrena-primary-dark: #0b3a6e;
  --engrena-accent: #17b897;
  --engrena-accent-dark: #0e6650;
  --engrena-grey: #8b9cad;
  --text-primary: #e7edf5;
  --text-muted: #8fa0b5;
  --danger: #e5484d;
  --warning: #e5a13d;

  /* A sidebar não muda entre os temas — fica sempre navy escuro. */
  --sidebar-bg: #0b2c4d;
  --sidebar-bg-alt: #0a2540;
  --sidebar-text: #cfdcea;
  --sidebar-text-dim: #7d93ac;
  --sidebar-border: rgba(255, 255, 255, 0.09);
  --sidebar-hover: rgba(255, 255, 255, 0.07);

  --radius: 0.7rem;
  --radius-sm: 0.5rem;
  --shadow-card: 0 1px 2px rgba(8, 14, 22, 0.4);
}

:root[data-theme="light"] {
  --engrena-bg: #f5f7fa;
  --engrena-surface: #ffffff;
  --engrena-surface-alt: #eef2f6;
  --engrena-border: #dce3ea;
  --engrena-primary: #1668b0;
  --engrena-primary-dark: #0b3a6e;
  --engrena-accent: #0c6e57;
  --engrena-accent-dark: #094a3a;
  --engrena-grey: #56677a;
  --text-primary: #16212e;
  --text-muted: #5b6b7d;
  --danger: #c22e35;
  --warning: #a3670a;
  --shadow-card: 0 1px 2px rgba(16, 30, 45, 0.06);
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background-color: var(--engrena-bg);
  color: var(--text-primary);
  font-family: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
}

/* Marca d'água hexagonal global — ::before em vez de background direto no
   body porque a imagem em si é um PNG opaco claro (sem canal alfa); é a
   opacity do pseudo-elemento que faz a mistura com --engrena-bg por baixo e
   dá o efeito de textura bem leve, tanto no tema escuro quanto no claro.
   position:fixed = não rola com a página; z-index:-1 = fica atrás de TODO
   o conteúdo (cards, tabelas, inputs, sidebar, topbar já têm fundo sólido
   próprio, então o texto nunca fica por cima da textura "crua"). */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  background-image: url('../img/bg-hexagonal.png');
  background-repeat: repeat;
  opacity: 0.05;
  pointer-events: none;
}
/* No tema claro a imagem (já bem clara) fica quase invisível contra o
   --engrena-bg claro no mesmo opacity do tema escuro — precisa de mais
   opacity pra render minimamente perceptível. */
:root[data-theme="light"] body::before {
  opacity: 0.12;
}

:focus-visible { outline: 2px solid var(--engrena-primary); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--engrena-bg); }
::-webkit-scrollbar-thumb { background: var(--engrena-surface-alt); border-radius: 6px; }
::-webkit-scrollbar-thumb:hover { background: var(--engrena-border); }

a { color: inherit; }

/* ---------------------------------------------------------------------- */
/* Componentes genéricos                                                   */
/* ---------------------------------------------------------------------- */
.card {
  background-color: var(--engrena-surface);
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
}

input:not([type="radio"]):not([type="checkbox"]), select, textarea {
  background-color: var(--engrena-surface);
  border: 1px solid var(--engrena-border);
  color: var(--text-primary);
  border-radius: var(--radius-sm);
  padding: 0.55rem 0.75rem;
  font-size: 0.875rem;
  font-family: inherit;
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
  min-width: 140px;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--engrena-primary);
  box-shadow: 0 0 0 3px rgba(30, 136, 229, 0.16);
}

button {
  border-radius: var(--radius-sm);
  padding: 0.55rem 1rem;
  font-weight: 600;
  font-size: 0.85rem;
  font-family: inherit;
  transition: filter 0.15s, opacity 0.15s, border-color 0.15s, background-color 0.15s;
  cursor: pointer;
  border: 1px solid var(--engrena-primary);
  background-color: var(--engrena-primary);
  color: #ffffff;
}
button:hover { filter: brightness(1.1); }
button:disabled { opacity: 0.5; cursor: not-allowed; }

button.secondary, button.delete-btn {
  background-color: var(--engrena-surface);
  color: var(--text-primary);
  border: 1px solid var(--engrena-border);
}
button.secondary:hover { border-color: var(--engrena-primary); color: var(--engrena-primary); filter: none; }
button.delete-btn { color: var(--danger); }

/* Ações de linha de tabela (Editar/Excluir) — botões-ícone (lápis/lixeira),
   alinhados à extremidade direita da célula. */
td:has(.acoes-linha) {
  text-align: right;
}
.acoes-linha {
  display: flex;
  justify-content: flex-end;
  gap: 0.4rem;
}
button.icon-btn, a.icon-btn, span.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  background-color: transparent;
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius-sm);
  color: var(--text-muted);
  text-decoration: none;
}
button.icon-btn svg, a.icon-btn svg { width: 16px; height: 16px; }
button.icon-btn:hover, a.icon-btn:hover { filter: none; background-color: var(--engrena-surface-alt); color: var(--text-primary); }
button.icon-btn.delete-btn {
  background-color: transparent;
  color: var(--danger);
  border-color: var(--danger);
}
button.icon-btn.delete-btn:hover { background-color: var(--danger); color: #ffffff; }

/* Botões antigos de texto (Editar/Excluir) em telas que ainda não migraram
   pro padrão de ícone — mantém o visual compacto anterior. */
td button:not(.icon-btn) {
  padding: 0.35rem 0.65rem;
  font-size: 0.78rem;
}
td button.delete-btn:not(.icon-btn) {
  background-color: var(--danger);
  color: #ffffff;
  border: none;
}

/* Botão que se parece com texto normal, não com um botão — usado quando o
   próprio dado (ex.: o e-mail de acesso) é o gatilho pra editar. */
button.link-btn {
  background: none;
  border: none;
  padding: 0;
  color: inherit;
  font: inherit;
  cursor: pointer;
  text-decoration: underline dotted;
}
button.link-btn:hover { color: var(--engrena-primary); filter: none; }

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
  background-color: var(--engrena-surface);
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-top: 1rem;
  box-shadow: var(--shadow-card);
}
th {
  text-align: left;
  color: var(--text-muted);
  font-weight: 700;
  text-transform: uppercase;
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--engrena-border);
  padding: 0.7rem 0.9rem;
  background-color: var(--engrena-surface-alt);
  white-space: nowrap;
}
td {
  padding: 0.65rem 0.9rem;
  border-bottom: 1px solid var(--engrena-border);
  vertical-align: middle;
  font-variant-numeric: tabular-nums;
}
tr:last-child td { border-bottom: none; }
tbody tr:hover { background-color: var(--engrena-surface-alt); }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.7rem;
  font-weight: 700;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.badge-primary { background-color: rgba(229, 138, 46, 0.18); color: #f0aa5c; }
.badge-accent { background-color: rgba(47, 158, 119, 0.18); color: #5fd3a9; }
.badge-grey { background-color: rgba(152, 161, 168, 0.18); color: var(--engrena-grey); }
.badge-danger { background-color: rgba(229, 72, 77, 0.2); color: #ff8286; }
.badge-warning { background-color: rgba(229, 161, 61, 0.2); color: #f5bd6f; }
.status-clicavel { cursor: pointer; border: 1px dashed transparent; }
.status-clicavel:hover { border-color: currentColor; }

:root[data-theme="light"] .badge-primary { background-color: rgba(201, 112, 28, 0.12); color: #8a4e14; }
:root[data-theme="light"] .badge-accent { background-color: rgba(31, 122, 88, 0.12); color: #145940; }
:root[data-theme="light"] .badge-grey { background-color: rgba(91, 107, 122, 0.14); color: #45535f; }
:root[data-theme="light"] .badge-danger { background-color: rgba(217, 54, 62, 0.14); color: #b3272e; }
:root[data-theme="light"] .badge-warning { background-color: rgba(185, 116, 10, 0.14); color: #8a5806; }

form.inline-form {
  background: var(--engrena-surface);
  border: 1px solid var(--engrena-border);
  border-radius: 0.75rem;
  padding: 1rem;
  margin-top: 1.25rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: end;
}
form.inline-form label {
  display: flex;
  flex-direction: column;
  font-size: 0.8rem;
  color: var(--text-muted);
  gap: 0.25rem;
}

/* Campos de filtro (busca/cliente/status) tinham min-width fixo inline
   (ex.: 220px) que passava da largura da tela no celular — trava cada
   campo em 100% da linha abaixo desse ponto, ignorando o min-width. */
@media (max-width: 680px) {
  form.inline-form { flex-direction: column; align-items: stretch; }
  form.inline-form label { width: 100%; }
  form.inline-form input,
  form.inline-form select {
    width: 100%;
    max-width: 100%;
    min-width: 0 !important;
  }
}

.error { color: var(--danger); font-size: 0.85rem; min-height: 1.2em; }
.muted { color: var(--text-muted); font-size: 0.85rem; }

/* Confirmação instantânea depois de criar/salvar/excluir (ver mostrarToast()
   em api.js) — centralizada de propósito (pedido do usuário), some sozinha.
   z-index acima até de modal (100) pra aparecer mesmo salvando de dentro de um. */
.toast-sucesso {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%) scale(0.92);
  z-index: 200;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1.4rem;
  border-radius: var(--radius-sm);
  background: var(--engrena-surface);
  border: 1px solid var(--engrena-border);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.4);
  color: var(--text-primary);
  font-size: 0.92rem;
  font-weight: 600;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease;
}
.toast-sucesso.toast-sucesso-visivel {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}
.toast-sucesso-icone { font-size: 1.15rem; }

.btn-tema-toggle {
  position: fixed;
  top: 0.75rem;
  right: 0.75rem;
  z-index: 50;
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  background: var(--engrena-surface);
  border: 1px solid var(--engrena-border);
  color: var(--text-primary);
  font-size: 0.8rem;
  opacity: 0.7;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.btn-tema-toggle:hover { opacity: 1; filter: none; }

/* Quando o JS encaixa o botão de tema na topbar (ou na área do usuário do
   Painel), ele sai do posicionamento flutuante e vira só mais um controle
   na fileira — mesma posição/forma da amostra de layout aprovada. */
.btn-tema-toggle.btn-tema-toggle-embutido {
  position: static;
  top: auto;
  right: auto;
  z-index: auto;
  opacity: 1;
  border-radius: var(--radius-sm);
  margin-left: 0;
  flex-shrink: 0;
}
.btn-tema-toggle.btn-tema-toggle-embutido:hover { opacity: 1; }

/* ---------------------------------------------------------------------- */
/* Telas centralizadas (login)                                            */
/* ---------------------------------------------------------------------- */
.login-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.login-card { width: 100%; max-width: 340px; padding: 2rem; }
/* Mesmo recorte usado em .logo-crop (cabeçalho/sidebar), só maior — a
   logo-engrena.png original inclui uma tagline embutida na imagem, então o
   ícone (engrenagem+E) precisa ficar isolado via overflow:hidden + offset
   negativo, não é um simples <img> solto. */
.login-card .logo {
  width: 64px;
  height: 64px;
  overflow: hidden;
  border-radius: 1rem;
  margin: 0 auto 0.9rem;
}
.login-card .logo img {
  display: block;
  width: 134px;
  height: 134px;
  max-width: none;
  object-fit: contain;
  position: relative;
  left: -35px;
  top: -24px;
}
.login-card h1 { text-align: center; margin: 0 0 0.25rem; font-size: 1.15rem; }
.login-card p.sub { text-align: center; color: var(--text-muted); font-size: 0.85rem; margin: 0 0 1.5rem; }
.login-card form { display: flex; flex-direction: column; gap: 1rem; }
.login-card label { display: flex; flex-direction: column; gap: 0.35rem; font-size: 0.85rem; color: var(--text-muted); }
.login-card input { width: 100%; }
.login-card button { margin-top: 0.4rem; }

/* ---------------------------------------------------------------------- */
/* Dashboard — seleção de módulo                                          */
/* ---------------------------------------------------------------------- */
.dashboard-header {
  border-bottom: 1px solid var(--engrena-border);
  background-color: var(--engrena-surface);
  padding: 0 1.75rem;
  height: 68px;
  display: flex;
  align-items: center;
  gap: 0.9rem;
  box-shadow: 0 1px 3px rgba(8, 14, 22, 0.05);
  position: relative;
  z-index: 1;
}
.dashboard-header .brand { display: flex; align-items: center; gap: 0.75rem; }
.dashboard-header .brand .logo {
  width: 2.25rem; height: 2.25rem; border-radius: 0.6rem;
  background: linear-gradient(135deg, var(--engrena-primary), var(--engrena-accent));
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 0.8rem; color: #fff;
}
/* .header-icones (sino/chat) é o primeiro item "do lado direito" — o
   margin-left:auto nele empurra ele e tudo que vem depois (nome do
   usuário, Sair, tema) pro canto direito, com o gap do container
   cuidando do espaçamento pequeno entre eles. */
.dashboard-header .header-icones { display: flex; align-items: center; gap: 0.9rem; margin-left: auto; }
.dashboard-header .user-area { display: flex; align-items: center; gap: 0.9rem; flex-shrink: 0; }
.dashboard-header .user-area a, .dashboard-header .user-area button { white-space: nowrap; }
.dashboard-header .user-info { text-align: right; min-width: 0; }
.dashboard-header .user-info p { margin: 0; }
/* Email pode ser bem mais longo que "Painel de módulos" (a linha de baixo,
   que dá a largura de referência) — sem truncar, ele empurra "Minha Conta"
   e "Sair" e quebra o texto do link em duas linhas, que aí fica espremido
   por cima do botão Sair dentro dos 64px fixos do cabeçalho. */
.dashboard-header .user-info .nome {
  font-size: 0.85rem;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 220px;
}
.dashboard-header .user-info .perfil { font-size: 0.7rem; color: var(--text-muted); }
.dashboard-header .quebra-cabecalho { display: none; }

/* No celular o cabeçalho inteiro (logo + sino + chat + nome/e-mail + Sair)
   não cabia numa linha só e forçava a página inteira a rolar na
   horizontal. Logo continua exatamente no lugar/tamanho de sempre; o
   nome do usuário sobe pra dividir a primeira linha com a logo (em vez
   de ficar sozinho numa linha própria, deixando um vão vazio no canto
   superior direito); sino, chat, Sair e o alternador de tema formam uma
   segunda linha, colados entre si. O <span class="quebra-cabecalho"> é
   invisível no desktop — aqui vira o ponto de quebra de linha explícito
   entre as duas fileiras (técnica padrão flex-basis:100%). O
   .btn-tema-toggle é o mesmo botão flutuante único usado em todas as
   páginas — aqui, na Home, o theme.js já o encaixa dentro de .user-area
   (fica com a classe .btn-tema-toggle-embutido); só posicionamos ele na
   fileira certa. */
@media (max-width: 680px) {
  .dashboard-header {
    height: auto;
    flex-wrap: wrap;
    row-gap: 0.3rem;
    column-gap: 0.4rem;
    padding: 0.5rem 0.85rem;
  }
  .dashboard-header .brand { order: 1; }
  .dashboard-header .user-info {
    order: 2;
    margin-left: auto;
    line-height: 1.15;
  }
  .dashboard-header .user-info .nome {
    font-size: 0.68rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 55vw;
  }
  .dashboard-header .user-info .perfil { font-size: 0.58rem; }
  .dashboard-header .quebra-cabecalho {
    display: block;
    order: 3;
    flex-basis: 100%;
    height: 0;
  }
  .dashboard-header .header-icones {
    order: 4;
    margin-left: auto;
  }
  .dashboard-header .user-area { order: 4; }
  .dashboard-header #notificacoes-btn,
  .dashboard-header #suporte-btn {
    width: 1.65rem;
    height: 1.65rem;
    font-size: 0.75rem;
  }
  .dashboard-header #logout-btn {
    padding: 0.3rem 0.65rem;
    font-size: 0.75rem;
  }
  .dashboard-header .btn-tema-toggle-embutido {
    width: 1.65rem;
    height: 1.65rem;
  }
}

.dashboard-main {
  flex: 1;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 2.5rem 1.75rem 3rem;
}
.dashboard-main .wrap { width: 100%; max-width: 900px; }

/* Visão geral (dashboard) tem seções alinhadas à esquerda, diferente do
   título/lead centralizados de cima do grid de módulos. Bem mais larga que o
   .wrap padrão (900px) de propósito — o Painel de Módulos é a tela que mais
   se beneficia de aproveitar telas largas, ocupando o espaço disponível em
   vez de ficar espremido numa coluna central. Alinhado ao topo (não
   centralizado verticalmente) pelo mesmo motivo. */
.dashboard-main .wrap-dashboard { max-width: 1800px; text-align: left; }
.wrap-dashboard #visao-geral-bloco,
.wrap-dashboard #acoes-rapidas-bloco {
  margin-bottom: 1.75rem;
}

/* Cabeçalho de página do Painel de Módulos — dedicado, não reaproveita
   .form-section-titulo/.lead (esses são o padrão de divisor de seção de
   formulário, usado em ~24 outras telas; aqui é a tela inicial do sistema,
   pede peso de título de página, não de rótulo de campo). */
.painel-hero {
  margin-bottom: 2.25rem;
}
.painel-hero-titulo {
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0 0 0.4rem;
  color: var(--text-primary);
}
.painel-hero-lead {
  font-size: 0.92rem;
  color: var(--text-muted);
  max-width: 46rem;
  line-height: 1.55;
  margin: 0;
}

.kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.9rem;
}
.kpi-card {
  padding: 1rem 1.15rem;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s, transform 0.15s;
  display: block;
}
.kpi-card:hover { border-color: var(--engrena-primary); transform: translateY(-2px); }
.kpi-card .kpi-label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
  margin-bottom: 0.4rem;
}
.kpi-card .kpi-value {
  font-size: 1.6rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.kpi-card.kpi-alerta { border-color: var(--danger); }
.kpi-card.kpi-alerta .kpi-value { color: var(--danger); }

.acoes-rapidas {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}
.acao-rapida {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6rem 1rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--engrena-border);
  background: var(--engrena-surface);
  color: var(--text-primary);
  text-decoration: none;
  font-size: 0.85rem;
  font-weight: 600;
  transition: border-color 0.15s, color 0.15s, background-color 0.15s;
}
.acao-rapida:hover { border-color: var(--engrena-primary); color: var(--engrena-primary); background: var(--engrena-surface-alt); }
.acao-rapida-icon { font-size: 1rem; }

/* ---------------------------------------------------------------------- */
/* Programação de Atividades — quadro de técnicos + fila de OS            */
/* ---------------------------------------------------------------------- */
.layout-programacao {
  display: grid;
  grid-template-columns: 1fr 300px;
  gap: 1.25rem;
  align-items: start;
}

.fila-item {
  display: block;
  padding: 0.65rem 0.75rem;
  margin-bottom: 0.6rem;
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius-sm);
  background: var(--engrena-surface);
  cursor: grab;
  transition: border-color 0.15s, background-color 0.15s;
}
.fila-item:hover { border-color: var(--engrena-primary); background: var(--engrena-surface-alt); }
.fila-item.selecionado { border-color: var(--engrena-primary); box-shadow: 0 0 0 2px rgba(30, 136, 229, 0.25); }
.fila-item:active { cursor: grabbing; }
.fila-topo { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 0.25rem; }
.fila-item-link { display: inline-block; margin-top: 0.4rem; font-size: 0.75rem; color: var(--engrena-primary); text-decoration: none; }
.fila-item-link:hover { text-decoration: underline; }

@media (max-width: 1080px) {
  .layout-programacao { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------- */
/* Perfis e Permissões — lista de perfis + grade módulo × ação            */
/* ---------------------------------------------------------------------- */
.layout-perfis { display: grid; grid-template-columns: 260px 1fr; gap: 1.25rem; align-items: start; }
@media (max-width: 1080px) {
  .layout-perfis { grid-template-columns: 1fr; }
}

.lista-perfis-item {
  display: block; width: 100%; text-align: left; padding: 0.65rem 0.75rem;
  border-radius: var(--radius-sm); border: 1px solid transparent; background: transparent;
  cursor: pointer; color: var(--text-primary); font-size: 0.88rem; margin-bottom: 0.25rem;
  transition: background-color 0.15s, border-color 0.15s;
}
.lista-perfis-item:hover { background: var(--engrena-surface-alt); }
/* Perfil selecionado — 3 sinais (fundo tingido + borda + nome na cor
   primária) em vez de só fundo+borda, pro administrador nunca ter dúvida de
   qual perfil está editando — mesmo princípio já usado no item ativo da
   sidebar e no CTA do Painel de Módulos. */
.lista-perfis-item.active {
  background: color-mix(in srgb, var(--engrena-primary) 12%, var(--engrena-surface-alt));
  border-color: var(--engrena-primary);
}
.lista-perfis-item .perfil-nome { font-weight: 600; }
.lista-perfis-item.active .perfil-nome { color: var(--engrena-primary); }
.lista-perfis-item .perfil-meta {
  display: inline-flex;
  margin-top: 0.3rem;
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
  background: var(--engrena-surface);
  padding: 0.12rem 0.5rem;
  border-radius: 999px;
}
/* Perfil de sistema (acesso total, protegido) — mesmo tratamento visual do
   badge-primary usado no resto do app pra "atenção especial", sem inventar
   uma cor nova. */
.lista-perfis-item .perfil-meta.perfil-meta-protegido {
  color: var(--engrena-primary);
  background: color-mix(in srgb, var(--engrena-primary) 14%, transparent);
}

.grade-permissoes-wrap { overflow-x: auto; border: 1px solid var(--engrena-border); border-radius: var(--radius); }
.grade-permissoes { border-collapse: collapse; width: 100%; font-size: 0.85rem; }
.grade-permissoes th, .grade-permissoes td { padding: 0.55rem 0.7rem; border-bottom: 1px solid var(--engrena-border); }
.grade-permissoes thead th { text-align: center; font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); background: var(--engrena-surface-alt); }
.grade-permissoes thead th.coluna-modulo { text-align: left; }
.grade-permissoes th.coluna-acao { cursor: pointer; user-select: none; }
.grade-permissoes th.coluna-acao:hover { color: var(--engrena-primary); }
.grade-permissoes th.acao-so-ui { opacity: 0.55; }
.grade-permissoes th.acao-so-ui::after { content: ' *'; }
.grade-permissoes tr.linha-bloco td { background: var(--engrena-surface-alt); font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); font-weight: 700; }
.grade-permissoes tbody tr:not(.linha-bloco):hover td { background: var(--engrena-surface-alt); }
.grade-permissoes td.celula-acao { text-align: center; }
.grade-permissoes td.celula-acao input[type="checkbox"] { width: 1.05rem; height: 1.05rem; accent-color: var(--engrena-primary); cursor: pointer; }
.grade-permissoes td.celula-vazia { text-align: center; color: var(--text-muted); }
.grade-permissoes td.coluna-modulo { white-space: nowrap; font-weight: 500; }
/* Reclama a densidade própria da grade mesmo com .pilot-e3 no <body> — sem
   isto, a regra genérica ".pilot-e3 table th/td" (2 seletores de elemento)
   venceria por especificidade e inflaria o padding da matriz. */
.pilot-e3 .grade-permissoes th,
.pilot-e3 .grade-permissoes td { padding: 0.55rem 0.7rem; }

/* ---------------------------------------------------------------------- */
/* Grade de horários (planilha) — colunas de 30min, das 00:00 às 23:30    */
/* ---------------------------------------------------------------------- */
.grade-scroll { overflow-x: auto; }
table.tabela-grade {
  border-radius: 0;
  border: none;
  box-shadow: none;
  margin-top: 0;
  font-size: 0.78rem;
  border-collapse: separate;
  border-spacing: 0;
}
table.tabela-grade th, table.tabela-grade td { padding: 0; border-bottom: 1px solid var(--engrena-border); border-right: 1px solid var(--engrena-border); }
table.tabela-grade .col-tecnico {
  position: sticky;
  left: 0;
  z-index: 5;
  background: var(--engrena-surface);
  min-width: 148px;
  max-width: 148px;
  padding: 0.45rem 0.6rem !important;
  text-align: left;
  border-right: 2px solid var(--engrena-border);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
thead .col-tecnico { z-index: 6; background: var(--engrena-surface-alt); }
table.tabela-grade .col-slot {
  min-width: 26px;
  max-width: 26px;
  text-align: center;
  color: var(--text-muted);
  font-size: 0.62rem;
  font-weight: 700;
  padding: 0.5rem 0.1rem !important;
  background: var(--engrena-surface-alt);
  white-space: nowrap;
}
table.tabela-grade .col-slot-hora { border-left: 1px solid var(--engrena-border); }

/* Controle de Ponto — "Meu Ponto" (usado tanto na tela admin/shell quanto no
   Portal do Técnico, mesmas classes nos dois). */
.ponto-relogio-card { text-align: center; padding: 2rem 1rem; }
.ponto-relogio-hora { font-size: 2.5rem; font-weight: 800; font-variant-numeric: tabular-nums; letter-spacing: 0.02em; }
.ponto-relogio-data { color: var(--text-muted); text-transform: capitalize; margin-top: 0.25rem; font-size: 0.9rem; }
.ponto-btn-bater {
  width: 100%; max-width: 320px; margin: 1.5rem auto 0; display: block;
  padding: 1rem; font-size: 1.05rem; font-weight: 700; background: var(--engrena-accent);
}
.ponto-btn-bater:hover { background: var(--engrena-accent-dark); }
.ponto-btn-bater:disabled { opacity: 0.6; cursor: not-allowed; }
.ponto-ultima-marcacao { margin-top: 1.25rem; font-size: 0.85rem; color: var(--text-muted); }
.ponto-sem-vinculo { text-align: center; padding: 1.5rem; color: var(--text-muted); }
.ponto-sucesso { text-align: center; padding: 0.5rem 0 1rem; }
.ponto-sucesso-titulo { font-size: 1.1rem; font-weight: 700; color: var(--engrena-accent); margin-bottom: 0.75rem; }
.ponto-sucesso-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 0.75rem; margin-bottom: 1rem; }
.ponto-sucesso-item { background: var(--engrena-surface-alt); border-radius: var(--radius-sm); padding: 0.6rem; }
.ponto-sucesso-item span { display: block; font-size: 0.68rem; text-transform: uppercase; color: var(--text-muted); margin-bottom: 0.15rem; }
.ponto-sucesso-item strong { font-size: 1rem; font-family: monospace; }
.ponto-lista-dia { margin-top: 0.5rem; }
.ponto-lista-item { display: flex; justify-content: space-between; padding: 0.5rem 0; border-bottom: 1px solid var(--engrena-border); font-size: 0.85rem; }
.ponto-lista-item:last-child { border-bottom: none; }
.ponto-aviso-intervalo { color: var(--warning); font-size: 0.78rem; white-space: nowrap; }
.ponto-alerta-intervalo {
  margin: 0.9rem 0; padding: 0.75rem 1rem; border-left: 3px solid var(--warning);
  background: rgba(229, 161, 61, 0.1); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; font-size: 0.88rem;
}
.ponto-alerta-intervalo p { margin: 0.3rem 0; }

/* "Meu Ponto" — Portal do Técnico (tp-*): visual próprio, não compartilhado
   com controle-ponto-meu.html (que mantém a lista/botão simples). */
.ponto-titulo { display: flex; align-items: center; gap: 0.55rem; }
.ponto-titulo svg { width: 1.35rem; height: 1.35rem; color: var(--engrena-accent); flex-shrink: 0; }
.ponto-banner-fechado {
  display: flex; align-items: flex-start; gap: 0.6rem; margin-bottom: 1rem;
  padding: 0.75rem 1rem; border: 1px solid var(--warning); border-radius: var(--radius);
  background: rgba(229, 161, 61, 0.1); color: var(--warning); font-size: 0.85rem;
}
.ponto-banner-fechado svg { width: 1.1rem; height: 1.1rem; flex-shrink: 0; margin-top: 0.1rem; }
/* Card de bater ponto do técnico — layout próprio (não compartilhado com
   controle-ponto-meu.html): flex column com gap uniforme entre as seções,
   em vez de margens avulsas em cada elemento. */
.tp-ponto-card { display: flex; flex-direction: column; align-items: center; gap: 1.1rem; padding: 2rem 1.5rem; }
.tp-ponto-card .ponto-status-pill,
.tp-ponto-card .ponto-colaborador,
.tp-ponto-card .ponto-relogio-icone,
.tp-ponto-card .ponto-relogio-display,
.tp-ponto-card .ponto-btn-bater { margin: 0; }
.ponto-status-pill { margin-bottom: 0.6rem; }
.ponto-colaborador { display: flex; flex-direction: column; align-items: center; gap: 0.1rem; margin-bottom: 0.85rem; }
.ponto-colaborador-nome { font-weight: 700; font-size: 0.95rem; }
.ponto-colaborador-matricula { font-size: 0.74rem; color: var(--text-muted); }
.ponto-relogio-icone {
  width: 88px; height: 88px; margin: 0 auto 0.35rem; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--engrena-surface-alt); color: var(--engrena-accent);
}
.ponto-relogio-icone svg { width: 44px; height: 44px; }
/* Com foto cadastrada, o círculo vira retângulo (proporção 3x4, mesmo padrão
   do cadastro de colaborador) — reforço visual de identidade sem o corte
   estranho que uma foto de rosto sofre dentro de um círculo pequeno. */
.ponto-relogio-icone:has(img) { width: 90px; height: 120px; border-radius: 8px; }
.ponto-relogio-icone img { width: 100%; height: 100%; object-fit: cover; border-radius: 8px; }
.ponto-relogio-display { display: flex; flex-direction: column; align-items: center; gap: 0.2rem; }
.tp-ponto-card .ponto-relogio-data { margin-top: 0; }
.ponto-btn-bater { display: flex; align-items: center; justify-content: center; gap: 0.55rem; }
.ponto-btn-bater svg { width: 1.15rem; height: 1.15rem; flex-shrink: 0; }
.tp-ponto-card .ponto-rodape-card { align-self: stretch; width: 100%; margin-top: 0; }
.ponto-rodape-card {
  margin-top: 1.25rem; padding-top: 0.85rem; border-top: 1px dashed var(--engrena-border);
  display: flex; align-items: flex-end; justify-content: space-between; gap: 0.75rem; text-align: left;
}
.tp-ponto-card .ponto-ultima-marcacao { text-align: left; }
.ponto-ultima-marcacao { font-size: 0.85rem; color: var(--text-muted); }
.ponto-proxima-acao { display: flex; flex-direction: column; gap: 0.2rem; align-items: flex-end; text-align: right; margin-left: auto; min-width: 0; }
.ponto-proxima-acao-label { font-size: 0.78rem; color: var(--text-muted); }
.ponto-proxima-acao-contagem { font-size: 1.05rem; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--engrena-accent); }
.ponto-proxima-acao.atrasado .ponto-proxima-acao-contagem { color: var(--danger); }
.ponto-proxima-acao-indisponivel { font-size: 0.76rem; color: var(--text-muted); max-width: 180px; text-align: right; }

/* ---- Card "Status de Conformidade" (aba AFD/AEJ) -----------------------
   Grid simples de rótulo/valor, reaproveitando .badge-* já existente pra
   marcar status (✓ operacional / indisponível). Sem paleta nova. */
.ponto-conformidade-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 0.9rem 1.4rem; margin-top: 0.9rem;
}
.ponto-conformidade-item { display: flex; flex-direction: column; gap: 0.25rem; }
.ponto-conformidade-item span {
  font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-muted);
}
.ponto-conformidade-item strong { font-size: 0.9rem; }

.ponto-perfil-rep { display: flex; gap: 0.5rem; align-items: center; margin-top: 0.3rem; }
.ponto-perfil-rep .badge { cursor: default; }
.ponto-perfil-rep .badge-futuro { opacity: 0.55; }

.ponto-cert-detalhes { margin-top: 1rem; }
.ponto-cert-detalhes > summary {
  cursor: pointer; font-size: 0.82rem; color: var(--text-muted);
  list-style: none; padding: 0.25rem 0;
}
.ponto-cert-detalhes > summary::-webkit-details-marker { display: none; }
.ponto-cert-detalhes > summary::after { content: ' ▾'; }
.ponto-cert-detalhes[open] > summary::after { content: ' ▴'; }
.ponto-cert-detalhes dl {
  display: grid; grid-template-columns: minmax(120px, 30%) 1fr; gap: 0.4rem 0.8rem;
  margin: 0.6rem 0 0; font-size: 0.82rem;
}
.ponto-cert-detalhes dt { color: var(--text-muted); }
.ponto-cert-detalhes dd { margin: 0; word-break: break-all; }

/* ---- Espelho — um card por dia (Fase D.1), no lugar da antiga tabela de
   3 colunas — evita tabela horizontal gigantesca com os campos novos da
   Apuração (períodos, intervalos, ocorrências). Reaproveita os tokens de
   cor já usados no resto do módulo, sem paleta nova. */
.ponto-espelho-dias { display: flex; flex-direction: column; gap: 0.85rem; margin-top: 0.9rem; }
.ponto-espelho-dia {
  border: 1px solid var(--engrena-border); border-radius: var(--radius-sm);
  background: var(--engrena-surface-alt); padding: 0.9rem 1.1rem;
}
.ponto-espelho-dia-cabecalho {
  display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.6rem;
  font-weight: 700; text-transform: capitalize;
}
.ponto-espelho-dia-corpo { display: flex; flex-direction: column; gap: 0.55rem; font-size: 0.85rem; }
.ponto-espelho-secao-titulo {
  display: block; font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--text-muted); margin-bottom: 0.2rem;
}
.ponto-espelho-marcacao { display: inline-flex; align-items: center; gap: 0.3rem; margin-right: 0.6rem; }
.ponto-espelho-marcacao.desconsiderada { text-decoration: line-through; color: var(--text-muted); }
.ponto-espelho-resumo-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 0.5rem 1.2rem; padding: 0.5rem 0; border-top: 1px dotted var(--engrena-border); border-bottom: 1px dotted var(--engrena-border);
}
.ponto-espelho-resumo-item span { display: block; font-size: 0.68rem; text-transform: uppercase; color: var(--text-muted); }
.ponto-espelho-resumo-item strong { font-variant-numeric: tabular-nums; }
.ponto-espelho-ocorrencia { color: var(--warning); }

/* Card "Registro de Marcações" — .card sozinho não tem padding (ver base
   .card), então precisa da própria classe pra não colar título/filtros/
   tabela nas bordas do card. */
.tp-registro-card { padding: 1.5rem 1.25rem; margin-top: 1.25rem; }

/* Cabeçalho "Registro de Marcações": título centralizado (stretch, ocupa a
   largura toda) e período+filtro num bloco à direita que não excede a
   largura do card — min-width:0 é essencial pra permitir que o flex-wrap
   dos filtros funcione em vez de forçar overflow horizontal. */
.tp-registro-cabecalho { display: flex; flex-direction: column; gap: 0.75rem; margin-bottom: 0.6rem; width: 100%; min-width: 0; }
.tp-registro-titulo { text-align: center; font-size: 1.05rem; font-weight: 800; margin: 0; }
.tp-registro-periodo-filtro { display: flex; flex-direction: column; align-items: flex-end; gap: 0.4rem; width: 100%; min-width: 0; }
.tp-registro-filtros { display: flex; flex-wrap: nowrap; align-items: center; justify-content: flex-end; gap: 0.6rem; font-size: 0.8rem; max-width: 100%; }
.tp-registro-filtros label { display: flex; align-items: center; gap: 0.35rem; color: var(--text-muted); white-space: nowrap; min-width: 0; }
.tp-registro-filtros select { padding: 0.35rem 0.5rem; font-size: 0.8rem; max-width: 100%; min-width: 0; }
/* Abaixo de 680px "Mês"/"Ano" por extenso + os dois <select> não cabem lado
   a lado — o rótulo some (só visual; aria-label no <select> mantém a
   informação pra leitor de tela), já que o valor escolhido ("Agosto",
   "2026") já é autoexplicativo dentro de "Registro de Marcações". */
@media (max-width: 680px) {
  .tp-registro-filtro-rotulo { display: none; }
  .tp-registro-filtros { gap: 0.4rem; }
  .tp-registro-filtros select { font-size: 0.76rem; padding: 0.35rem 0.4rem; }
}

.tp-ponto-mes { margin-top: 1.1rem; }
.tp-ponto-mes:first-child { margin-top: 0; }
.tp-ponto-mes-titulo {
  font-size: 0.88rem; font-weight: 700; margin: 0 0 0.4rem; padding-bottom: 0.35rem;
  border-bottom: 2px solid var(--engrena-border);
}
.tp-ponto-tabela-wrap { overflow-x: auto; }
.tp-ponto-tabela-wrap table.tabela-responsiva { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
.tp-ponto-tabela-wrap th {
  text-align: left; padding: 0.5rem 0.75rem; font-size: 0.68rem; text-transform: uppercase;
  letter-spacing: 0.03em; color: var(--text-muted); border-bottom: 1px solid var(--engrena-border); white-space: nowrap;
}
.tp-ponto-tabela-wrap td { padding: 0.5rem 0.75rem; border-bottom: 1px solid var(--engrena-border); white-space: nowrap; }
.tp-ponto-tabela-wrap tr:last-child td { border-bottom: none; }
.tp-ponto-cel { display: inline-flex; align-items: center; gap: 0.35rem; font-variant-numeric: tabular-nums; }
.tp-ponto-cel-icone {
  flex: 0 0 auto; width: 22px; height: 22px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; background: var(--engrena-surface-alt);
}
.tp-ponto-cel-icone svg { width: 12px; height: 12px; }
.tp-ponto-cel-icone.entrada { color: var(--engrena-accent); }
.tp-ponto-cel-icone.intervalo { color: var(--warning); }
.tp-ponto-cel-icone.saida { color: var(--text-muted); }

/* Abaixo de 680px, o .tabela-responsiva genérico empilha cada <td> como um
   card cheio (rótulo em cima do valor) — pra "Registro de Marcações" isso
   tirava o alinhamento entre colunas (rótulos com alturas diferentes fazem
   os horários começarem em alturas diferentes) e não escala se um dia tiver
   mais de 3-4 marcações. Em vez de reconstruir isso em flex, a tabela some
   ao layout de tabela de verdade — colunas sempre alinhadas na mesma linha
   pelo próprio navegador — e o wrapper (.tp-ponto-tabela-wrap, que já tem
   overflow-x:auto) ganha rolagem horizontal quando as colunas não cabem,
   em vez de quebrar ou estourar. */
@media (max-width: 680px) {
  .tp-ponto-tabela-wrap table.tabela-responsiva { display: table; width: auto; min-width: 100%; }
  .tp-ponto-tabela-wrap .tabela-responsiva thead { display: table-header-group; }
  .tp-ponto-tabela-wrap .tabela-responsiva tbody { display: table-row-group; }
  .tp-ponto-tabela-wrap .tabela-responsiva tr { display: table-row; }
  .tp-ponto-tabela-wrap .tabela-responsiva th,
  .tp-ponto-tabela-wrap .tabela-responsiva td {
    display: table-cell; white-space: nowrap; text-align: center;
  }
  .tp-ponto-tabela-wrap .tabela-responsiva th:first-child,
  .tp-ponto-tabela-wrap .tabela-responsiva td[data-label="Data"] { text-align: left; }
  .tp-ponto-tabela-wrap .tabela-responsiva td::before { content: none; }
}

tr.linha-inconsistente td {
  background: color-mix(in srgb, var(--danger) 12%, transparent);
}

tr.linha-equipe td {
  background: var(--engrena-surface-alt);
  color: var(--text-muted);
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0.35rem 0.6rem !important;
  position: static;
}

tr.linha-total-tecnico td { border-top: 1px solid var(--engrena-border); padding-top: 0.3rem !important; padding-bottom: 0.5rem !important; }

.slot-vazio { height: 44px; cursor: pointer; transition: background-color 0.1s; }
.slot-vazio:hover { background: var(--engrena-surface-alt); }
.slot-dragover { background: rgba(30, 136, 229, 0.22) !important; }

.slot-bloco {
  height: 44px;
  cursor: pointer;
  padding: 0 0.35rem !important;
  vertical-align: middle;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-weight: 700;
}
/* Estado real da alocação (ver estadoAlocacao em programacao-atividades.js):
   "pendente" (tom escuro/neutro, ninguém iniciou ainda) -> "em_execucao"
   (tom claro, preenchendo da esquerda pra direita conforme o tempo passa
   desde o clique real em Iniciar) -> "concluida" (tom de sucesso, sólido). */
.slot-bloco.bloco-pendente { background: rgba(30, 136, 229, 0.22); color: var(--engrena-primary); }
.slot-bloco.bloco-em_execucao { color: #ffffff; }
.slot-bloco.bloco-em_execucao .cell-num { text-shadow: 0 1px 2px rgba(0,0,0,0.35); }
.slot-bloco.bloco-concluida { background: rgba(23, 184, 151, 0.2); color: var(--engrena-accent); }
.slot-bloco:hover { filter: brightness(1.15); }

/* Bloco de ausência (Atestado/Falta) — ocupa a linha inteira do técnico no
   dia (não tem horário/duração, é o dia todo), com cor própria pra não ser
   confundido com um bloco de OS/tarefa. */
.slot-bloco-ausencia {
  height: 44px;
  cursor: pointer;
  padding: 0 0.6rem !important;
  vertical-align: middle;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-weight: 700;
  text-align: left;
}
.slot-bloco-ausencia.ausencia-atestado { background: rgba(229, 72, 77, 0.18); color: #ff8286; }
.slot-bloco-ausencia.ausencia-falta { background: rgba(229, 161, 61, 0.18); color: #f5bd6f; }
.slot-bloco-ausencia:hover { filter: brightness(1.15); }
:root[data-theme="light"] .slot-bloco-ausencia.ausencia-atestado { background: rgba(217, 54, 62, 0.14); color: #b3272e; }
:root[data-theme="light"] .slot-bloco-ausencia.ausencia-falta { background: rgba(185, 116, 10, 0.14); color: #8a5806; }

/* Bloco de tarefa avulsa (sem OS) — mesmas cores de estado do bloco de OS
   (pendente/concluída se aplicam normalmente), só que sem o ícone ▶ de
   execução, já que tarefa avulsa não tem mão de obra vinculada. */
.slot-bloco.bloco-tarefa-pendente { background: rgba(139, 92, 246, 0.22); color: #a78bfa; }
:root[data-theme="light"] .slot-bloco.bloco-tarefa-pendente { background: rgba(109, 40, 217, 0.14); color: #6d28d9; }

@media (max-width: 768px) {
  table.tabela-grade .col-tecnico { min-width: 118px; max-width: 118px; }
}

/* ---------------------------------------------------------------------- */
/* Painel de Módulos — uma seção por módulo (cabeçalho + KPIs/ações         */
/* específicas dele), em vez de um grid genérico de cards + bloco solto de */
/* "ações rápidas" misturando tudo. Módulo sem contrato pra empresa entra   */
/* esmaecido/não clicável (mas continua visível — funciona como vitrine do  */
/* que o sistema oferece).                                                 */
/* ---------------------------------------------------------------------- */
/* Colunas fixas (3 / 2 / 1 conforme a largura), não auto-fit — com um número
   sempre igual de módulos (6), colunas fixas dão cards com a mesma largura
   de verdade em vez do auto-fit reagir ao conteúdo de cada um. A altura de
   cada card é igualada pelo stretch padrão do grid (cada linha estica pro
   tamanho do maior item dela — ver .modulo-secao/.modulo-secao-corpo). */
.modulos-lista {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.75rem;
}
@media (max-width: 1180px) {
  .modulos-lista { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 680px) {
  .modulos-lista { grid-template-columns: 1fr; }
}

.modulo-secao {
  padding: 1.6rem 1.7rem;
  transition: border-color 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
  display: flex;
  flex-direction: column;
  height: 100%;
}
.modulo-secao:not(.inativo):hover {
  border-color: var(--engrena-primary);
  transform: translateY(-3px);
  box-shadow: 0 14px 30px rgba(8, 14, 22, 0.16);
}
:root[data-theme="light"] .modulo-secao:not(.inativo):hover {
  box-shadow: 0 14px 30px rgba(16, 30, 45, 0.09);
}

.modulo-secao-cabecalho {
  display: flex;
  align-items: center;
  gap: 1rem;
}
.modulo-secao-cabecalho .modulo-icon {
  flex-shrink: 0;
  width: 3.1rem;
  height: 3.1rem;
  border-radius: 0.85rem;
  background: color-mix(in srgb, var(--engrena-primary) 13%, var(--engrena-surface-alt));
  color: var(--engrena-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
}
.modulo-secao-cabecalho .modulo-icon svg { width: 1.55rem; height: 1.55rem; }
.modulo-secao-texto { flex: 1; min-width: 0; }
.modulo-secao-titulo { font-weight: 700; font-size: 1.02rem; margin: 0; letter-spacing: -0.005em; }
.modulo-secao-desc { font-size: 0.78rem; color: var(--text-muted); margin: 0.2rem 0 0; line-height: 1.45; }
.modulo-secao-entrar {
  flex-shrink: 0;
  font-size: 0.76rem;
  font-weight: 700;
  color: var(--engrena-primary);
  text-decoration: none;
  white-space: nowrap;
  padding: 0.42rem 0.9rem;
  border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--engrena-primary) 38%, transparent);
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.modulo-secao-entrar:hover {
  background: var(--engrena-primary);
  color: #ffffff;
  border-color: var(--engrena-primary);
}

.modulo-secao-corpo {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  /* margin-top:auto empurra o corpo pro rodapé do card — com todos os cards
     da linha esticados pra mesma altura (stretch padrão do grid), isso evita
     que um card com menos KPIs/ações fique com o conteúdo "flutuando" perto
     do cabeçalho e um vazio estranho embaixo. */
  margin-top: auto;
  padding-top: 1.1rem;
  border-top: 1px solid var(--engrena-border);
}
.modulo-secao-kpis { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.modulo-kpi {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.5rem 0.85rem;
  background: var(--engrena-surface-alt);
  border-radius: var(--radius-sm);
  min-width: 6.5rem;
  flex: 1 1 6.5rem;
  text-decoration: none;
  color: inherit;
}
.modulo-kpi:hover { background: var(--engrena-border); }
.modulo-kpi .valor { font-size: 1.15rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.modulo-kpi.alerta .valor { color: var(--danger); }
.modulo-kpi .rotulo { font-size: 0.65rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.03em; }
.modulo-secao-acoes { display: flex; flex-wrap: wrap; gap: 0.5rem; }
/* Botões de ação rápida do Painel de Módulos — só o ícone fica visível; o
   nome aparece como uma caixinha de texto ao passar o mouse (só aqui, não
   nas barras "acoes-rapidas" de dentro de cada módulo, que continuam com o
   texto sempre visível). */
.modulo-secao-acoes .acao-rapida {
  position: relative;
  width: 2.6rem;
  height: 2.6rem;
  padding: 0;
  justify-content: center;
  gap: 0;
  border-radius: 999px;
}
.modulo-secao-acoes .acao-rapida:hover {
  background: var(--engrena-primary);
  border-color: var(--engrena-primary);
  color: #ffffff;
}
.modulo-secao-acoes .acao-rapida-icon { font-size: 1.2rem; }
.modulo-secao-acoes .acao-rapida::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translate(-50%, 4px);
  background: #16212e;
  color: #ffffff;
  font-size: 0.7rem;
  font-weight: 600;
  white-space: nowrap;
  padding: 0.35rem 0.65rem;
  border-radius: 0.35rem;
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.25);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease, transform 0.12s ease;
  z-index: 20;
}
.modulo-secao-acoes .acao-rapida::before {
  content: '';
  position: absolute;
  bottom: calc(100% + 3px);
  left: 50%;
  transform: translate(-50%, 4px);
  border: 5px solid transparent;
  border-top-color: #16212e;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease, transform 0.12s ease;
  z-index: 20;
}
.modulo-secao-acoes .acao-rapida:hover::after,
.modulo-secao-acoes .acao-rapida:hover::before {
  opacity: 1;
  transform: translate(-50%, 0);
}

.modulo-secao.inativo {
  opacity: 0.55;
  filter: grayscale(0.4);
}
.modulo-secao.inativo .modulo-secao-cabecalho { cursor: default; }
.modulo-secao.inativo:hover { border-color: var(--engrena-border); }
.modulo-secao-bloqueado {
  flex-shrink: 0;
  font-size: 0.7rem;
  font-weight: 700;
  white-space: nowrap;
  padding: 0.35rem 0.75rem;
  border-radius: 999px;
  background: var(--engrena-surface-alt);
}

/* ---------------------------------------------------------------------- */
/* Shell interno de módulo — sidebar + topbar + conteúdo                   */
/* ---------------------------------------------------------------------- */
.app-shell {
  min-height: 100vh;
  display: flex;
  position: relative;
}

.sidebar {
  width: 248px;
  flex-shrink: 0;
  background-color: var(--sidebar-bg);
  color: var(--sidebar-text);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  z-index: 40;
}

.sidebar-header {
  padding: 1.1rem;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  border-bottom: 1px solid var(--sidebar-border);
}
.sidebar-header .logo {
  width: 2.35rem; height: 2.35rem; border-radius: var(--radius-sm);
  background: var(--engrena-primary);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 0.8rem; color: #fff; flex-shrink: 0;
}
.sidebar-header .titulos p { margin: 0; }
.sidebar-header .modulo-nome { font-size: 0.9rem; font-weight: 600; line-height: 1.2; color: #fff; }
.sidebar-header .empresa-nome { font-size: 0.7rem; color: var(--sidebar-text-dim); }

/* Logo oficial (logo-engrena.png) — clicável, volta pro Painel de Módulos.
   A imagem-fonte é um template de estoque 2048x2048 com "Brand Name" /
   "Tagline Here" escritos nela; o .logo-crop isola só o ícone da
   engrenagem+E (bounding box real do ícone medido via canvas: x:544-1502,
   y:376-1336 dentro da imagem original — daí o width/left/top abaixo). */
a.logo-link {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  transition: opacity 0.15s;
}
a.logo-link:hover { opacity: 0.75; }
.logo-crop {
  display: block;
  width: 40px;
  height: 40px;
  overflow: hidden;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}
.logo-crop img {
  display: block;
  width: 84px;
  height: 84px;
  max-width: none;
  object-fit: contain;
  position: relative;
  left: -22px;
  top: -15px;
}

.sidebar-back {
  display: block;
  padding: 0.7rem 1.1rem;
  font-size: 0.78rem;
  color: var(--sidebar-text-dim);
  text-decoration: none;
  border-bottom: 1px solid var(--sidebar-border);
}
.sidebar-back:hover { color: #fff; background: var(--sidebar-hover); }

.sidebar-nav {
  flex: 1;
  overflow-y: auto;
  padding: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.nav-link {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.6rem 0.9rem;
  border-radius: var(--radius-sm);
  color: var(--sidebar-text);
  font-size: 0.87rem;
  font-weight: 500;
  cursor: pointer;
  text-decoration: none;
  transition: background-color 0.15s, color 0.15s;
}
.nav-link:hover { background-color: var(--sidebar-hover); color: #fff; }
/* Item ativo — trilho de cor na borda + fundo levemente tingido, em vez de
   preenchimento sólido cheio (mais discreto/"executivo", mesmo princípio do
   .modulo-secao-entrar do Painel de Módulos). O trilho fica alinhado à
   borda esquerda real da sidebar (fora do padding de .sidebar-nav). */
.nav-link.active {
  background: color-mix(in srgb, var(--engrena-primary) 20%, transparent);
  color: #ffffff;
  font-weight: 600;
}
.nav-link.active::before {
  content: '';
  position: absolute;
  left: -0.75rem;
  top: 0.3rem;
  bottom: 0.3rem;
  width: 3px;
  border-radius: 0 2px 2px 0;
  background: var(--engrena-primary);
}

/* Isola visualmente um grupo de itens do resto do menu (ex.: Ponto, ainda em
   desenvolvimento) — barra dupla + selo curto logo abaixo, antes do primeiro
   item do grupo. Sidebar é sempre escura (mesma cor nos dois temas), por
   isso a cor do selo não precisa de variante para tema claro. */
.sidebar-separador-dupla {
  border-top: 3px double var(--sidebar-text-dim);
  margin: 0.5rem 0.4rem 0;
}
.sidebar-separador-label {
  margin: 0.3rem 0.9rem 0.15rem;
  font-size: 0.66rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #f5bd6f;
}

.sidebar-footer {
  border-top: 1px solid var(--sidebar-border);
  padding: 1rem;
}
.sidebar-footer .usuario-nome { font-size: 0.85rem; font-weight: 600; margin: 0 0 0.1rem; color: #fff; }
.sidebar-footer .usuario-email { font-size: 0.7rem; color: var(--sidebar-text-dim); margin: 0 0 0.7rem; word-break: break-all; }
.sidebar-footer button { width: 100%; }
.sidebar-footer button.secondary {
  background-color: var(--sidebar-hover);
  color: var(--sidebar-text);
  border-color: var(--sidebar-border);
}
.sidebar-footer button.secondary:hover { color: #fff; border-color: var(--sidebar-text-dim); }

.sidebar-backdrop { display: none; }

.content-area {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.topbar {
  min-height: 60px;
  border-bottom: 1px solid var(--engrena-border);
  background-color: var(--engrena-surface);
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0 1.5rem;
  box-shadow: 0 1px 3px rgba(8, 14, 22, 0.05);
  position: relative;
  z-index: 1;
}

.sidebar-hamburger {
  display: none;
  width: 2.2rem;
  height: 2.2rem;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-sm);
  border: 1px solid var(--engrena-border);
  background: var(--engrena-surface);
  color: var(--text-primary);
  padding: 0;
  flex-shrink: 0;
}

/* ---------------------------------------------------------------------- */
/* Responsivo — sidebar vira gaveta abaixo de 768px                       */
/* ---------------------------------------------------------------------- */
@media (max-width: 768px) {
  .sidebar-hamburger { display: flex; }
  .sidebar {
    position: fixed;
    left: -248px;
    top: 0;
    height: 100dvh;
    transition: left 0.2s ease;
    box-shadow: 4px 0 24px rgba(0, 0, 0, 0.35);
  }
  .app-shell.sidebar-aberta .sidebar { left: 0; }
  .app-shell.sidebar-aberta .sidebar-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.45);
    z-index: 39;
  }
  .page-content { padding: 1rem !important; }
  .topbar { padding: 0 1rem; }
  .form-row { flex-wrap: wrap; }
  .modal-backdrop { padding: 1.25rem 0.6rem; align-items: center; }
}
.topbar h2 { margin: 0; margin-right: auto; font-size: 1.05rem; font-weight: 700; letter-spacing: -0.005em; }

.page-content {
  flex: 1;
  overflow-y: auto;
  padding: 1.5rem;
  width: 100%;
}

table { table-layout: auto; }


/* ---------------------------------------------------------------------- */
/* Cards de status de módulo (visão geral dentro de Cadastros, se usado)   */
/* ---------------------------------------------------------------------- */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 0.75rem;
  margin-top: 1.5rem;
}
.status-card {
  background: var(--engrena-surface);
  border: 1px solid var(--engrena-border);
  border-radius: 0.75rem;
  padding: 1rem;
}
.status-card.ativo { border-left: 4px solid var(--engrena-accent); }
.status-card.inativo { border-left: 4px solid var(--danger); opacity: 0.7; }
.status-card h3 { margin: 0 0 0.25rem; font-size: 1rem; }
.status-card p { margin: 0; font-size: 0.85rem; color: var(--text-muted); }

/* ---------------------------------------------------------------------- */
/* Modal                                                                   */
/* ---------------------------------------------------------------------- */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 3rem 1rem;
  overflow-y: auto;
  z-index: 100;
}
.modal-backdrop.hidden { display: none; }
.modal-box {
  width: 100%;
  max-width: 640px;
  padding: 1.5rem;
}
.modal-box .modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
}
.modal-box .modal-header h2 { margin: 0; font-size: 1.05rem; }
.modal-box .modal-close {
  background: none;
  border: none;
  color: var(--text-muted);
  font-size: 1.1rem;
  padding: 0.2rem 0.5rem;
}
.modal-box form.inline-form { margin-top: 0; border: none; padding: 0; background: none; }

/* ---------------------------------------------------------------------- */
/* Grupo de checkboxes (filtros múltiplos)                                */
/* ---------------------------------------------------------------------- */
.checkbox-group {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
}
.checkbox-group label {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.85rem;
  color: var(--text-primary);
  cursor: pointer;
}
.checkbox-group input[type="checkbox"],
.checkbox-group input[type="radio"] {
  width: auto;
  min-width: 0;
  accent-color: var(--engrena-primary);
}
.filtros-historico {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  background: var(--engrena-surface);
  border: 1px solid var(--engrena-border);
  border-radius: 0.75rem;
  padding: 1rem 1.25rem;
  margin-bottom: 1.25rem;
}
.filtros-historico .grupo { display: flex; flex-direction: column; gap: 0.4rem; }
.filtros-historico .grupo > span { font-size: 0.75rem; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; font-weight: 600; }

/* Linha expansível da tabela de clientes */
tr.linha-expandida { background-color: var(--engrena-surface-alt); }
.expand-toggle {
  background: none;
  border: none;
  color: var(--engrena-primary);
  padding: 0;
  font-size: 0.85rem;
}
.painel-expandido td {
  background: var(--engrena-surface-alt);
  padding: 1rem;
}

/* ---------------------------------------------------------------------- */
/* Formulários de modal em linhas proporcionais (Fornecedor, Cliente,      */
/* Equipamento, NF de Entrada) — cada .form-row é uma linha com colunas de */
/* largura fixa por peso (flex-2/flex-1/flex-narrow), em vez de um        */
/* flex-wrap solto que deixava os campos com larguras desproporcionais.   */
/* ---------------------------------------------------------------------- */
.form-row {
  display: flex;
  gap: 1.25rem;
  margin-bottom: 1rem;
}
.form-row > label {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  font-size: 0.8rem;
  color: var(--text-muted);
  min-width: 0;
}
/* !important necessário: o seletor global de input (linha ~115) usa dois
   :not(), o que dá a ele mais especificidade que ".form-row > label input"
   — sem isso, campos em .flex-narrow (ex.: Nº, UF) ficam maiores que a
   coluna e sobrepõem o campo vizinho (mesmo bug identificado na Proposta). */
.form-row > label input,
.form-row > label select {
  width: 100%;
  min-width: 0 !important;
}
.form-row .flex-2 { flex: 2; }
.form-row .flex-1 { flex: 1; }
.form-row .flex-narrow { flex: 0 0 100px; }
/* Sem escopo a .form-row de propósito — campo-obrigatorio é um marcador
   genérico de "campo obrigatório" reusado em vários layouts de formulário
   (.form-grid, .pneu-form-grid-*, etc.), não só dentro de .form-row. Escopar
   a um container específico faz o asterisco silenciosamente não aparecer em
   qualquer formulário que use outro layout — bug real encontrado no modal
   "Novo pneu" (campo obrigatório sem nenhuma marcação visual) e que também
   afetava outros formulários do sistema (ex.: Colaboradores) sem que
   ninguém tivesse notado, já que o campo continuava funcionalmente
   obrigatório (validado no submit), só sem o indicador visual. */
.campo-obrigatorio::after {
  content: ' *';
  color: var(--danger);
}

.form-section-titulo {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  border-top: 1px solid var(--engrena-border);
  padding-top: 1rem;
  margin: 0.25rem 0 1rem;
}

/* ---------------------------------------------------------------------- */
/* Título/subtítulo de card — cabeçalho de um bloco de conteúdo dentro de   */
/* um .card (gráfico, tabela, painel) — NÃO tem a borda superior do        */
/* .form-section-titulo (que é pra separar seções de formulário), e não    */
/* usa <h3> puro (herda tamanho/peso padrão do navegador, destoa do resto   */
/* do app). Sempre par: título + subtítulo explicando o que o bloco mostra. */
/* ---------------------------------------------------------------------- */
.card-titulo {
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--text-primary);
  margin: 0 0 0.2rem;
}
.card-subtitulo {
  font-size: 0.76rem;
  color: var(--text-muted);
  margin: 0 0 0.85rem;
  line-height: 1.4;
}

/* Padding padrão pra um .card usado como painel de conteúdo solto (sem     */
/* tabela/grade própria já cuidando do espaçamento interno).                */
.card-pad { padding: 1.1rem; }

/* Caixa de altura fixa pra um <canvas> de gráfico — Chart.js precisa de um
   contêiner com altura definida pra responsive:true funcionar direito. */
.chart-box { position: relative; width: 100%; height: 20rem; }

/* ---------------------------------------------------------------------- */
/* Formulário em grid (Equipes e Técnicos) — linhas com número de colunas  */
/* fixo, em vez do sistema de pesos flex do .form-row.                    */
/* ---------------------------------------------------------------------- */
.modal-box.modal-box-larga { max-width: 980px; }
.form-grid {
  display: grid;
  gap: 0.75rem 1rem;
  margin-bottom: 1rem;
  align-items: end;
}
.form-grid label {
  display: flex;
  flex-direction: column;
  font-size: 0.8rem;
  color: var(--text-muted);
  gap: 0.25rem;
}
.form-grid label input, .form-grid label select { width: 100%; min-width: 0 !important; }
.form-grid button { height: 2.35rem; align-self: end; }
@media (max-width: 720px) {
  .form-grid { grid-template-columns: 1fr !important; }
}

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 0.75rem;
  margin-top: 0.5rem;
}
.modal-footer button.secondary { min-width: 100px; }

/* Modal Nova OS: Cancelar / Abrir OS dividem a largura igualmente, em vez
   de ficarem só encostados à direita com tamanhos diferentes. */
#os-form .modal-footer button { flex: 1; }

.hidden { display: none !important; }

/* ---------------------------------------------------------------------- */
/* Autocomplete (busca de equipamento/produto em Movimentações)            */
/* ---------------------------------------------------------------------- */
.autocomplete-resultados {
  margin-top: -0.75rem;
  margin-bottom: 1rem;
  max-height: 220px;
  overflow-y: auto;
  border: 1px solid var(--engrena-border);
  border-radius: 0.5rem;
  background: var(--engrena-surface-alt);
}
.autocomplete-item {
  padding: 0.5rem 0.75rem;
  font-size: 0.85rem;
  cursor: pointer;
}
.autocomplete-item:hover { background: var(--engrena-border); }
.autocomplete-vazio { padding: 0.5rem 0.75rem; font-size: 0.8rem; color: var(--text-muted); }

.item-saida {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  border: 1px solid var(--engrena-border);
  border-radius: 0.5rem;
  padding: 0.5rem 0.75rem;
  margin-bottom: 0.5rem;
}
.item-saida .item-saida-info { flex: 1; min-width: 0; }
.item-saida .item-saida-info p { margin: 0; font-size: 0.8rem; }
.item-saida .item-saida-info .muted { font-size: 0.72rem; }
.item-saida input[type="number"] { width: 90px; min-width: 0; }

/* ---------------------------------------------------------------------- */
/* Recibo de saída (impressão)                                             */
/* ---------------------------------------------------------------------- */
.recibo-print {
  background: #ffffff;
  color: #101820;
  border-radius: 0.5rem;
  padding: 1.25rem;
  font-size: 0.85rem;
}
.recibo-print table { width: 100%; border-collapse: collapse; background: #fff; color: #101820; margin: 0.75rem 0; }
.recibo-print th, .recibo-print td { border-bottom: 1px solid #ccc; padding: 0.35rem 0.4rem; text-align: left; background: #fff; }
.recibo-print th { font-size: 0.7rem; text-transform: uppercase; color: #555; }
.recibo-print .recibo-titulo { font-weight: 700; margin: 0 0 0.75rem; }
.recibo-print .recibo-total { text-align: right; font-weight: 700; margin-top: 0.5rem; }
.recibo-print .recibo-assinaturas { display: flex; flex-wrap: wrap; gap: 2rem; margin-top: 3rem; }
.recibo-print .recibo-assinatura { flex: 1; min-width: 200px; border-top: 1px solid #101820; padding-top: 0.4rem; text-align: center; font-size: 0.75rem; }

/* ---------------------------------------------------------------------- */
/* Impressão da OS — cores e tamanhos fixos (não herda tema claro/escuro   */
/* da tela; página impressa é sempre clara), pensado pra caber bem numa    */
/* folha A4.                                                               */
/* ---------------------------------------------------------------------- */
.os-print {
  background: #ffffff;
  color: #16212e;
  font-family: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
  font-size: 8.5pt;
  line-height: 1.3;
  display: flex;
  flex-direction: column;
  min-height: 770pt;
}
.os-print-cabecalho {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  background: #0b2c4d;
  color: #ffffff;
  padding: 8pt 12pt;
  border-radius: 4pt;
  margin-bottom: 8pt;
}
.os-print-marca { display: flex; align-items: center; gap: 7pt; }
.os-print-logo {
  width: 24pt;
  height: 24pt;
  border-radius: 4pt;
  background: #1e88e5;
  color: #ffffff;
  font-weight: 700;
  font-size: 8pt;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  overflow: hidden;
}
.os-print-logo.os-print-logo-img { background: #ffffff; padding: 1.5pt; }
.os-print-logo img { width: 100%; height: 100%; object-fit: contain; }
.os-print-marca-texto { display: flex; flex-direction: column; line-height: 1.2; }
.os-print-marca-texto strong { font-size: 10pt; }
.os-print-marca-texto span { font-size: 7pt; color: #cfe0f0; }
.os-print-numero { text-align: right; }
.os-print-numero > span:first-child { display: block; font-size: 11.5pt; font-weight: 700; margin-bottom: 2pt; }
.os-print-status {
  display: inline-block;
  padding: 1.5pt 7pt;
  border-radius: 20pt;
  font-size: 7pt;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  background: #dbeafe;
  color: #1d4ed8;
}
.os-print-status.os-print-status-sucesso { background: #d1fae5; color: #047857; }
.os-print-status.os-print-status-perigo { background: #fee2e2; color: #b91c1c; }

.os-print-info-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 5pt 12pt;
  padding: 6pt 10pt;
  border: 1pt solid #dce3ea;
  border-radius: 4pt;
  margin-bottom: 8pt;
}
.os-print-info-item { display: flex; flex-direction: column; gap: 1pt; min-width: 0; }
.os-print-label { font-size: 6.5pt; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: #5b6b7d; }
.os-print-info-item > span:last-child { font-weight: 600; overflow-wrap: break-word; }

.os-print-secao { margin-bottom: 7pt; break-inside: avoid; page-break-inside: avoid; }
.os-print-secao-titulo {
  font-size: 7.5pt;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #16212e;
  border-bottom: 1.5pt solid #0b2c4d;
  padding-bottom: 2pt;
  margin-bottom: 4pt;
}
.os-print-motivo {
  margin: 0;
  padding: 5pt 8pt;
  background: #f5f7fa;
  border: 1pt solid #dce3ea;
  border-radius: 4pt;
}

.os-print-imagens { display: flex; gap: 8pt; flex-wrap: wrap; }
.os-print-imagens img {
  width: 47%;
  max-height: 170pt;
  object-fit: cover;
  border: 1pt solid #dce3ea;
  border-radius: 4pt;
}

.os-print-tabela { width: 100%; border-collapse: collapse; }
.os-print-tabela th {
  text-align: left;
  font-size: 6.5pt;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: #ffffff;
  background: #0b2c4d;
  padding: 3pt 5pt;
}
.os-print-tabela th.num, .os-print-tabela td.num { text-align: right; }
.os-print-tabela td { font-size: 7.5pt; padding: 2.5pt 5pt; border-bottom: 0.75pt solid #e2e8f0; }
.os-print-tabela tbody tr:nth-child(even) { background: #f5f7fa; }
.os-print-tabela tfoot td {
  font-weight: 700;
  border-top: 1.5pt solid #0b2c4d;
  border-bottom: none;
  padding-top: 4pt;
}
.os-print-vazio { text-align: center; font-style: italic; color: #5b6b7d; padding: 6pt 5pt; }

.os-print-assinaturas { display: flex; gap: 24pt; margin-top: auto; padding-top: 16pt; break-inside: avoid; page-break-inside: avoid; }
.os-print-assinatura {
  flex: 1;
  border-top: 1pt solid #16212e;
  padding-top: 4pt;
  text-align: center;
  font-size: 7.5pt;
  color: #5b6b7d;
}
.os-print-rodape { margin-top: 8pt; padding-top: 4pt; border-top: 0.5pt solid #dce3ea; text-align: center; font-size: 6.5pt; color: #5b6b7d; }

/* ---------------------------------------------------------------------- */
/* Impressão da Proposta — mesmo padrão da impressão da OS: cores e        */
/* tamanhos fixos, independente do tema, pensado pra caber numa folha A4.  */
/* ---------------------------------------------------------------------- */
.proposta-print {
  background: #ffffff;
  color: #16212e;
  font-family: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
  font-size: 8.5pt;
  line-height: 1.3;
  display: flex;
  flex-direction: column;
  min-height: 770pt;
}
.proposta-print-cabecalho {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  background: #0b2c4d;
  color: #ffffff;
  padding: 8pt 12pt;
  border-radius: 4pt;
  margin-bottom: 8pt;
}
.proposta-print-marca { display: flex; align-items: center; gap: 7pt; }
.proposta-print-logo {
  width: 24pt;
  height: 24pt;
  border-radius: 4pt;
  background: #1e88e5;
  color: #ffffff;
  font-weight: 700;
  font-size: 8pt;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  overflow: hidden;
}
.proposta-print-logo.proposta-print-logo-img { background: #ffffff; padding: 1.5pt; }
.proposta-print-logo img { width: 100%; height: 100%; object-fit: contain; }
.proposta-print-marca-texto { display: flex; flex-direction: column; line-height: 1.2; }
.proposta-print-marca-texto strong { font-size: 10pt; }
.proposta-print-marca-texto span { font-size: 7pt; color: #cfe0f0; }
.proposta-print-numero { text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 2pt; }
.proposta-print-numero > span:first-child { font-size: 11.5pt; font-weight: 700; }
.proposta-print-status {
  display: inline-block;
  padding: 1.5pt 7pt;
  border-radius: 20pt;
  font-size: 7pt;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  background: #dbeafe;
  color: #1d4ed8;
}
.proposta-print-status.proposta-print-status-sucesso { background: #d1fae5; color: #047857; }
.proposta-print-status.proposta-print-status-perigo { background: #fee2e2; color: #b91c1c; }

.proposta-print-info-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 5pt 12pt;
  padding: 6pt 10pt;
  border: 1pt solid #dce3ea;
  border-radius: 4pt;
  margin-bottom: 8pt;
}
.proposta-print-info-item { display: flex; flex-direction: column; gap: 1pt; min-width: 0; }
.proposta-print-label { font-size: 6.5pt; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: #5b6b7d; }
.proposta-print-info-item > span:last-child { font-weight: 600; overflow-wrap: break-word; }

.proposta-print-secao { margin-bottom: 7pt; break-inside: avoid; page-break-inside: avoid; }
.proposta-print-secao-titulo {
  font-size: 7.5pt;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #16212e;
  border-bottom: 1.5pt solid #0b2c4d;
  padding-bottom: 2pt;
  margin-bottom: 4pt;
}
.proposta-print-motivo {
  margin: 0;
  padding: 5pt 8pt;
  background: #f5f7fa;
  border: 1pt solid #dce3ea;
  border-radius: 4pt;
}

.proposta-print-tabela { width: 100%; border-collapse: collapse; }
.proposta-print-tabela th {
  text-align: left;
  font-size: 6.5pt;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: #ffffff;
  background: #0b2c4d;
  padding: 3pt 5pt;
}
.proposta-print-tabela th.num, .proposta-print-tabela td.num { text-align: right; }
.proposta-print-tabela td { font-size: 7.5pt; padding: 2.5pt 5pt; border-bottom: 0.75pt solid #e2e8f0; }
.proposta-print-tabela tbody tr:nth-child(even) { background: #f5f7fa; }
.proposta-print-tabela tfoot td {
  font-weight: 700;
  border-top: 1.5pt solid #0b2c4d;
  border-bottom: none;
  padding-top: 4pt;
}
.proposta-print-vazio { text-align: center; font-style: italic; color: #5b6b7d; padding: 6pt 5pt; }

.proposta-print-totais {
  display: flex;
  flex-direction: column;
  gap: 3pt;
  width: 220pt;
  margin-left: auto;
  margin-top: auto;
  break-inside: avoid;
  page-break-inside: avoid;
  padding: 6pt 9pt;
  border: 1pt solid #dce3ea;
  border-radius: 4pt;
}
.proposta-print-totais > div { display: flex; justify-content: space-between; gap: 10pt; }
.proposta-print-totais > div span:first-child { color: #5b6b7d; }
.proposta-print-total-final {
  border-top: 1.5pt solid #0b2c4d;
  margin-top: 3pt;
  padding-top: 4pt;
  font-size: 10pt;
  font-weight: 700;
}

.proposta-print-rodape { margin-top: 8pt; padding-top: 4pt; border-top: 0.5pt solid #dce3ea; text-align: center; font-size: 6.5pt; color: #5b6b7d; }

/* ---------------------------------------------------------------------- */
/* Impressão dos Relatórios de Pessoas (Absenteísmo, Horas Extras, Horas   */
/* Trabalhadas, Comissões) — mesmo padrão visual do os-print/proposta-     */
/* print (fundo sempre claro, pensado pra A4), mas mais compacto: pode ter */
/* várias seções empilhadas no mesmo documento, então densidade importa    */
/* mais aqui do que numa OS/Proposta única.                                */
/* ---------------------------------------------------------------------- */
.rh-print {
  background: #ffffff;
  color: #16212e;
  font-family: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
  font-size: 7pt;
  line-height: 1.2;
  display: flex;
  flex-direction: column;
  min-height: 770pt;
}
.rh-print-cabecalho {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  background: #0b2c4d;
  color: #ffffff;
  padding: 5pt 9pt;
  border-radius: 3pt;
  margin-bottom: 5pt;
}
.rh-print-marca { display: flex; align-items: center; gap: 6pt; }
.rh-print-logo {
  width: 18pt;
  height: 18pt;
  border-radius: 3pt;
  background: #1e88e5;
  color: #ffffff;
  font-weight: 700;
  font-size: 7pt;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  overflow: hidden;
}
.rh-print-logo.rh-print-logo-img { background: #ffffff; padding: 1pt; }
.rh-print-logo img { width: 100%; height: 100%; object-fit: contain; }
.rh-print-marca-texto { display: flex; flex-direction: column; line-height: 1.15; }
.rh-print-marca-texto strong { font-size: 8.5pt; }
.rh-print-marca-texto span { font-size: 6pt; color: #cfe0f0; }
.rh-print-numero { text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 1pt; }
.rh-print-numero > span:first-child { font-size: 9pt; font-weight: 700; }
.rh-print-numero > span:last-child { font-size: 6pt; color: #cfe0f0; }

.rh-print-info-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2pt 10pt;
  padding: 3pt 8pt;
  border: 0.75pt solid #dce3ea;
  border-radius: 3pt;
  margin-bottom: 5pt;
}
.rh-print-info-item { display: flex; flex-direction: column; gap: 0.5pt; min-width: 0; }
.rh-print-label { font-size: 5.5pt; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: #5b6b7d; }
.rh-print-info-item > span:last-child { font-weight: 600; font-size: 7pt; overflow-wrap: break-word; }

.rh-print-secao { margin-bottom: 5pt; break-inside: avoid; page-break-inside: avoid; }
.rh-print-secao-titulo {
  font-size: 7.5pt;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: #16212e;
  border-bottom: 1.25pt solid #0b2c4d;
  padding-bottom: 1.5pt;
  margin-bottom: 2.5pt;
}
.rh-print-resumo {
  margin: 0 0 3pt;
  padding: 3pt 6pt;
  background: #f5f7fa;
  border: 0.75pt solid #dce3ea;
  border-radius: 3pt;
  display: flex;
  flex-wrap: wrap;
  gap: 2pt 12pt;
}
.rh-print-resumo-item { display: flex; flex-direction: column; gap: 0.5pt; }
.rh-print-resumo-item strong { font-size: 8pt; }
.rh-print-resumo-item span { font-size: 5.5pt; text-transform: uppercase; letter-spacing: 0.03em; color: #5b6b7d; }

.rh-print-tabela { width: 100%; border-collapse: collapse; }
.rh-print-tabela th {
  text-align: left;
  font-size: 5.5pt;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: #ffffff;
  background: #0b2c4d;
  padding: 1.5pt 4pt;
}
.rh-print-tabela th.num, .rh-print-tabela td.num { text-align: right; }
.rh-print-tabela td { font-size: 6.5pt; padding: 1.25pt 4pt; border-bottom: 0.5pt solid #e2e8f0; }
.rh-print-tabela tbody tr:nth-child(even) { background: #f5f7fa; }
.rh-print-tabela tfoot td { font-weight: 700; border-top: 1.25pt solid #0b2c4d; border-bottom: none; padding-top: 2.5pt; }
.rh-print-vazio { text-align: center; font-style: italic; color: #5b6b7d; padding: 3pt 4pt; }

.rh-print-rodape { margin-top: auto; padding-top: 2.5pt; border-top: 0.5pt solid #dce3ea; text-align: center; font-size: 5.5pt; color: #5b6b7d; }

/* Fase D.2 — detalhamento diário do Espelho de Ponto impresso/PDF: a antiga */
/* tabela de 3 colunas (Data/Marcações/Tratamentos) foi substituída por um   */
/* bloco por dia espelhando os mesmos campos da Apuração já exibidos na tela */
/* (.ponto-espelho-*, dimensionada em rem) — aqui em pt, densidade de        */
/* impressão, reaproveitando o padrão visual do rh-print.                   */
.rh-print-espelho-dia { margin-bottom: 4pt; padding: 3pt 6pt; border: 0.75pt solid #dce3ea; border-radius: 3pt; break-inside: avoid; page-break-inside: avoid; }
.rh-print-espelho-dia-cabecalho { font-size: 7pt; font-weight: 700; color: #16212e; margin-bottom: 2pt; }
.rh-print-espelho-linha { font-size: 6.5pt; margin-bottom: 1pt; }
.rh-print-espelho-rotulo { font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em; color: #5b6b7d; font-size: 5.5pt; margin-right: 3pt; }
.rh-print-espelho-marcacao.desconsiderada { text-decoration: line-through; color: #8a97a6; }
.rh-print-espelho-resumo { display: flex; flex-wrap: wrap; gap: 1.5pt 9pt; margin: 2pt 0; }
.rh-print-espelho-resumo span { font-size: 5.5pt; text-transform: uppercase; letter-spacing: 0.02em; color: #5b6b7d; }
.rh-print-espelho-resumo strong { font-size: 6.5pt; margin-left: 2pt; }
.rh-print-espelho-badge { font-size: 5.5pt; font-weight: 700; padding: 0.5pt 3pt; border-radius: 2pt; margin-left: 4pt; }
.rh-print-espelho-badge-desconsiderada { background: #fdecea; color: #b3261e; }
.rh-print-espelho-badge-incompleta { background: #fff4e0; color: #8a5a00; }

/* ---------------------------------------------------------------------- */
/* Impressão dos Relatórios Financeiros (Visão Geral, Inadimplência,       */
/* Fornecedores a Pagar, Ranking de Clientes, Custos com Pessoal) — mesmo  */
/* padrão compacto do rh-print (várias seções empilhadas no mesmo          */
/* documento, densidade importa mais que numa OS/Proposta única).          */
/* ---------------------------------------------------------------------- */
.fin-print {
  background: #ffffff;
  color: #16212e;
  font-family: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif;
  font-size: 7pt;
  line-height: 1.2;
  display: flex;
  flex-direction: column;
  min-height: 770pt;
}
.fin-print-cabecalho {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  background: #0b2c4d;
  color: #ffffff;
  padding: 5pt 9pt;
  border-radius: 3pt;
  margin-bottom: 5pt;
}
.fin-print-marca { display: flex; align-items: center; gap: 6pt; }
.fin-print-logo {
  width: 18pt;
  height: 18pt;
  border-radius: 3pt;
  background: #1e88e5;
  color: #ffffff;
  font-weight: 700;
  font-size: 7pt;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  overflow: hidden;
}
.fin-print-logo.fin-print-logo-img { background: #ffffff; padding: 1pt; }
.fin-print-logo img { width: 100%; height: 100%; object-fit: contain; }
.fin-print-marca-texto { display: flex; flex-direction: column; line-height: 1.15; }
.fin-print-marca-texto strong { font-size: 8.5pt; }
.fin-print-marca-texto span { font-size: 6pt; color: #cfe0f0; }
.fin-print-numero { text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 1pt; }
.fin-print-numero > span:first-child { font-size: 9pt; font-weight: 700; }
.fin-print-numero > span:last-child { font-size: 6pt; color: #cfe0f0; }

.fin-print-info-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2pt 10pt;
  padding: 3pt 8pt;
  border: 0.75pt solid #dce3ea;
  border-radius: 3pt;
  margin-bottom: 5pt;
}
.fin-print-info-item { display: flex; flex-direction: column; gap: 0.5pt; min-width: 0; }
.fin-print-label { font-size: 5.5pt; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: #5b6b7d; }
.fin-print-info-item > span:last-child { font-weight: 600; font-size: 7pt; overflow-wrap: break-word; }

.fin-print-secao { margin-bottom: 5pt; break-inside: avoid; page-break-inside: avoid; }
.fin-print-secao-titulo {
  font-size: 7.5pt;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: #16212e;
  border-bottom: 1.25pt solid #0b2c4d;
  padding-bottom: 1.5pt;
  margin-bottom: 2.5pt;
}
.fin-print-resumo {
  margin: 0 0 3pt;
  padding: 3pt 6pt;
  background: #f5f7fa;
  border: 0.75pt solid #dce3ea;
  border-radius: 3pt;
  display: flex;
  flex-wrap: wrap;
  gap: 2pt 12pt;
}
.fin-print-resumo-item { display: flex; flex-direction: column; gap: 0.5pt; }
.fin-print-resumo-item strong { font-size: 8pt; }
.fin-print-resumo-item strong.fin-print-negativo { color: #b91c1c; }
.fin-print-resumo-item strong.fin-print-positivo { color: #047857; }
.fin-print-resumo-item span { font-size: 5.5pt; text-transform: uppercase; letter-spacing: 0.03em; color: #5b6b7d; }

.fin-print-tabela { width: 100%; border-collapse: collapse; }
.fin-print-tabela th {
  text-align: left;
  font-size: 5.5pt;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: #ffffff;
  background: #0b2c4d;
  padding: 1.5pt 4pt;
}
.fin-print-tabela th.num, .fin-print-tabela td.num { text-align: right; }
.fin-print-tabela td { font-size: 6.5pt; padding: 1.25pt 4pt; border-bottom: 0.5pt solid #e2e8f0; }
.fin-print-tabela tbody tr:nth-child(even) { background: #f5f7fa; }
.fin-print-tabela td.fin-print-atraso-alto { color: #b91c1c; font-weight: 700; }
.fin-print-vazio { text-align: center; font-style: italic; color: #5b6b7d; padding: 3pt 4pt; }

.fin-print-rodape { margin-top: auto; padding-top: 2.5pt; border-top: 0.5pt solid #dce3ea; text-align: center; font-size: 5.5pt; color: #5b6b7d; }

/* Usado na impressão/PDF em lote (várias OS/Propostas/NFs de uma vez) —
   força cada registro a começar numa página nova, exceto o primeiro. */
.quebra-pagina-antes { break-before: page; page-break-before: always; }

/* ---------------------------------------------------------------------- */
/* Evidências fotográficas da OS — grade de miniaturas + área de           */
/* arrastar-e-soltar (que também funciona como botão pra abrir a           */
/* câmera/galeria no celular, via <input type="file" accept="image/*">).   */
/* ---------------------------------------------------------------------- */
.os-imagens-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-bottom: 0.75rem;
}
.os-imagens-grid:empty { margin-bottom: 0; }
.os-imagem-thumb {
  position: relative;
  width: 110px;
  height: 110px;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 1px solid var(--engrena-border);
  background: var(--engrena-surface);
}
.os-imagem-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.os-imagem-remover {
  position: absolute;
  top: 0.25rem;
  right: 0.25rem;
  width: 1.7rem;
  height: 1.7rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 50%;
  background: rgba(20, 24, 30, 0.62);
  color: #fff;
  font-size: 0.85rem;
  line-height: 1;
  cursor: pointer;
  padding: 0;
}
.os-imagem-remover:hover { background: var(--danger); }
.os-imagem-thumb-carregando img { opacity: 0.45; }
.os-imagem-spinner {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1.6rem;
  height: 1.6rem;
  margin: -0.8rem 0 0 -0.8rem;
  border: 3px solid rgba(255, 255, 255, 0.4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: os-imagem-girar 0.7s linear infinite;
}
@keyframes os-imagem-girar {
  to { transform: rotate(360deg); }
}
.os-imagens-dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.35rem;
  padding: 1.25rem 1rem;
  border: 1.5px dashed var(--engrena-border);
  border-radius: var(--radius-sm);
  text-align: center;
  font-size: 0.82rem;
  color: var(--text-muted);
  cursor: pointer;
  transition: border-color 0.15s, background-color 0.15s;
}
.os-imagens-dropzone:hover,
.os-imagens-dropzone.dragover {
  border-color: var(--engrena-primary);
  background: rgba(30, 136, 229, 0.08);
}
.os-imagens-dropzone-icone { font-size: 1.5rem; }
.os-imagens-dropzone.hidden { display: none; }

/* Dois botões explícitos (câmera / galeria) em vez de deixar o navegador
   escolher o que oferecer — em vários Android/iOS, um <input type=file>
   sozinho (mesmo via <label>) às vezes só abre a galeria, sem opção de
   câmera. capture="environment" no input força a câmera diretamente. */
.os-imagens-botoes {
  display: flex;
  gap: 0.75rem;
  width: 100%;
  margin-top: 0.25rem;
}
label.os-imagens-botao {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.3rem;
  padding: 0.9rem 0.6rem;
  border: 1.5px solid var(--engrena-border);
  border-radius: var(--radius-sm);
  background-color: var(--engrena-surface);
  color: var(--text-primary);
  font-size: 0.85rem;
  font-weight: 500;
  text-align: center;
  cursor: pointer;
  transition: border-color 0.15s, background-color 0.15s, color 0.15s;
}
label.os-imagens-botao .os-imagens-botao-icone { font-size: 1.4rem; }
label.os-imagens-botao:hover,
label.os-imagens-botao:active {
  border-color: var(--engrena-primary);
  color: var(--engrena-primary);
  background: rgba(30, 136, 229, 0.08);
}

/* Foto de perfil do colaborador — mesmo padrão de dois botões (câmera/
   galeria) do os-imagens-botao acima, com preview retangular (proporção
   3x4, padrão de foto de documento) ao lado. */
.colaborador-foto-secao { display: flex; gap: 1.25rem; align-items: flex-start; margin-bottom: 1.25rem; }
.colaborador-foto-preview {
  flex: 0 0 auto; width: 90px; height: 120px; border-radius: 8px; overflow: hidden;
  background: var(--engrena-surface-alt); border: 1px solid var(--engrena-border);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.7rem; font-weight: 700; color: var(--text-muted);
}
.colaborador-foto-preview img { width: 100%; height: 100%; object-fit: cover; display: block; }
.colaborador-foto-corpo { flex: 1 1 auto; min-width: 0; }
.colaborador-foto-secao.desabilitada .os-imagens-botoes { opacity: 0.5; pointer-events: none; }
@media (max-width: 480px) {
  .colaborador-foto-secao { flex-direction: column; align-items: center; text-align: center; }
}

@media print {
  @page { margin: 12mm; }
  /* body::before não é pego pelo "body *" abaixo (pseudo-elemento não é
     descendente) — sem isso a marca d'água vazaria pro PDF/impressão de
     OS, Proposta e Nota Fiscal. */
  body::before { display: none; }
  body * { visibility: hidden; }
  .print-area, .print-area * { visibility: visible; }
  .print-area {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
  }
  .no-print { display: none !important; }
}

/* Etiqueta QR do pneu (Etapa 3G-F) — cores fixas (não usa os tokens de
   tema) de propósito: precisa sair preto sobre branco tanto na tela quanto
   impressa, com o app em modo claro ou escuro. Mesmo raciocínio de
   .os-print/.proposta-print, que também usam hex fixo em vez de variáveis. */
.pneu-qr-print {
  background: #ffffff;
  color: #16181d;
  padding: 1rem;
  border-radius: 8px;
  text-align: center;
}
.pneu-qr-print h3 { color: #16181d; }
.pneu-qr-print p { color: #4a5361; font-size: 0.85rem; }
.pneu-qr-link { font-size: 0.72rem !important; color: #6b7684 !important; }

/* ---------------------------------------------------------------------- */
/* Portal do Cliente — acompanhamento executivo de OS                     */
/* ---------------------------------------------------------------------- */
.portal-hero {
  background: linear-gradient(135deg, var(--engrena-primary), var(--engrena-accent));
  border-radius: var(--radius);
  padding: 1.5rem 1.75rem;
  color: #ffffff;
  margin-bottom: 1.5rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
}
.portal-hero-info { min-width: 0; }
.portal-hero-numero { font-size: 1.5rem; font-weight: 800; margin: 0 0 0.3rem; letter-spacing: 0.01em; }
.portal-hero-sub { font-size: 0.9rem; margin: 0; opacity: 0.92; }
.portal-hero-badges { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
.portal-hero-badge {
  font-size: 0.78rem;
  font-weight: 700;
  padding: 0.4rem 0.9rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.2);
  white-space: nowrap;
}
.portal-hero-badge.portal-hero-badge-alerta { background: rgba(0, 0, 0, 0.3); }

.portal-stepper { display: flex; align-items: flex-start; margin: 0 0 1.75rem; padding: 0.25rem 0.5rem 0; }
.portal-stepper.portal-stepper-cancelado { opacity: 0.55; filter: grayscale(0.5); }
.portal-etapa { flex: 1; display: flex; flex-direction: column; align-items: center; text-align: center; position: relative; min-width: 0; }
.portal-etapa-linha { position: absolute; top: 1.15rem; left: 50%; right: -50%; height: 3px; background: var(--engrena-border); z-index: 0; }
.portal-etapa:last-child .portal-etapa-linha { display: none; }
.portal-etapa-dot {
  width: 2.35rem;
  height: 2.35rem;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.95rem;
  border: 2px solid var(--engrena-border);
  background: var(--engrena-surface);
  color: var(--text-muted);
  z-index: 1;
  transition: transform 0.2s ease, background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
.portal-etapa-label { margin-top: 0.6rem; font-size: 0.78rem; font-weight: 700; color: var(--text-muted); max-width: 130px; }
.portal-etapa-data { font-size: 0.68rem; color: var(--text-muted); margin-top: 0.2rem; }
.portal-etapa.concluida .portal-etapa-dot { background: var(--engrena-accent); border-color: var(--engrena-accent); color: #fff; }
.portal-etapa.concluida .portal-etapa-linha { background: var(--engrena-accent); }
.portal-etapa.concluida .portal-etapa-label { color: var(--text-primary); }
.portal-etapa.ativa .portal-etapa-dot { background: var(--engrena-primary); border-color: var(--engrena-primary); color: #fff; transform: scale(1.14); }
.portal-etapa.ativa .portal-etapa-label { color: var(--text-primary); }
.portal-etapa.pausada .portal-etapa-dot { background: var(--warning); border-color: var(--warning); color: #fff; }
.portal-etapa-nota-pausada { font-size: 0.65rem; font-weight: 700; color: var(--warning); margin-top: 0.15rem; text-transform: uppercase; letter-spacing: 0.03em; }

.portal-secao { margin-bottom: 1.5rem; }
.portal-secao-titulo { font-size: 0.95rem; font-weight: 700; margin: 0 0 0.85rem; }
.portal-info-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0.9rem; }
.portal-info-item { background: var(--engrena-surface-alt); border-radius: var(--radius-sm); padding: 0.85rem 1rem; }
.portal-info-item .portal-info-label {
  display: block;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
  margin-bottom: 0.3rem;
}
.portal-info-item .portal-info-valor { font-size: 1rem; font-weight: 600; }

.portal-lista-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(420px, 1fr)); gap: 1.5rem; }
.portal-lista-card {
  cursor: pointer;
  padding: 1.5rem 1.6rem;
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}
.portal-lista-card:hover { transform: translateY(-3px); box-shadow: 0 10px 28px rgba(8, 14, 22, 0.22); border-color: var(--engrena-primary); }
:root[data-theme="light"] .portal-lista-card:hover { box-shadow: 0 10px 28px rgba(16, 30, 45, 0.12); }

.portal-card-cabecalho { display: flex; justify-content: space-between; align-items: flex-start; gap: 1rem; margin-bottom: 0.25rem; }
.portal-card-numero { font-size: 1.25rem; font-weight: 800; margin: 0; letter-spacing: 0.01em; }
.portal-card-equipamento { font-size: 0.85rem; color: var(--text-muted); margin: 0.3rem 0 0; }
.portal-card-cabecalho .badge { font-size: 0.75rem; padding: 0.3rem 0.75rem; flex-shrink: 0; }

.portal-card-motivo {
  font-size: 0.82rem;
  color: var(--text-muted);
  margin: 0.9rem 0 0;
  padding-top: 0.9rem;
  border-top: 1px solid var(--engrena-border);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.portal-card-stats {
  display: flex;
  flex-wrap: wrap;
  gap: 1.1rem;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--engrena-border);
}
.portal-card-stat { display: flex; flex-direction: column; gap: 0.3rem; min-width: 90px; }
.portal-card-stat-label { font-size: 0.66rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-muted); }
.portal-card-stat-valor { font-size: 0.95rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.portal-card-stat .badge { align-self: flex-start; font-size: 0.62rem; margin-top: 0.1rem; }

/* Variante compacta do stepper executivo (mesmo componente do pop-up),
   usada dentro dos cards da lista — dots e textos menores pra caber ao
   lado das outras informações do card sem dominar o espaço. */
.portal-stepper.portal-stepper-compacto { margin: 1.1rem 0 0.4rem; }
.portal-stepper-compacto .portal-etapa-dot { width: 1.9rem; height: 1.9rem; font-size: 0.8rem; }
.portal-stepper-compacto .portal-etapa-linha { top: 0.92rem; }
.portal-stepper-compacto .portal-etapa-label { font-size: 0.66rem; margin-top: 0.4rem; }
.portal-stepper-compacto .portal-etapa-data { font-size: 0.6rem; }
.portal-stepper-compacto .portal-etapa.ativa .portal-etapa-dot { transform: scale(1.1); }

/* Cabeçalho do portal — marca da prestadora à esquerda, título centralizado,
   ações à direita. Sobrepõe o flex padrão do .topbar (que empurra tudo pra
   direita via "h2 { margin-right: auto }") com um grid de 3 colunas. */
.portal-topbar { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 1rem; }
.portal-topbar-marca { display: flex; align-items: center; gap: 0.75rem; min-width: 0; }
.portal-topbar-logo {
  width: 2.6rem;
  height: 2.6rem;
  border-radius: var(--radius-sm);
  background: var(--engrena-surface-alt);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 0.85rem;
  color: var(--engrena-primary);
  overflow: hidden;
  flex-shrink: 0;
}
.portal-topbar-logo img { width: 100%; height: 100%; object-fit: contain; }
.portal-topbar-empresa-nome { margin: 0; margin-right: 0; font-weight: 700; font-size: 0.9rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.portal-topbar-empresa-cnpj { margin: 0.1rem 0 0; font-size: 0.7rem; color: var(--text-muted); }
.portal-topbar-titulo { margin: 0; margin-right: 0; font-size: 1.05rem; text-align: center; white-space: nowrap; }
.portal-topbar-acoes { justify-self: end; }
@media (max-width: 720px) {
  .portal-topbar { grid-template-columns: auto 1fr auto; }
  .portal-topbar-titulo { display: none; }
}
/* Telas bem estreitas (celular): 3+ botões de ação não cabem mais ao lado
   da marca na mesma linha — empilha a marca acima das ações em vez de
   deixar o grid de 3 colunas sobrepor tudo dentro dos 56px do .topbar. */
@media (max-width: 480px) {
  .portal-topbar {
    grid-template-columns: 1fr;
    min-height: auto;
    padding: 0.75rem 1rem;
    row-gap: 0.6rem;
  }
  .portal-topbar-acoes { justify-self: stretch; flex-wrap: wrap; }
}

/* Nota de "última atualização" no rodapé do card da OS — canto inferior
   direito, discreta, só aparece quando já existe algum evento registrado. */
.portal-card-atualizacao {
  margin-top: 0.75rem;
  padding-top: 0.6rem;
  border-top: 1px dashed var(--engrena-border);
  font-size: 0.68rem;
  color: var(--text-muted);
  text-align: right;
  line-height: 1.4;
}
.portal-card-atualizacao strong { color: var(--text-primary); font-weight: 600; }

/* Relatório de Análise de Causa Raiz (5W2H/Ishikawa) no portal do cliente —
   apresentação "gestor de qualidade": cabeçalho com método/data, problema em
   destaque, os 6 campos do 5W2H em grid, plano de ação destacado. Ciclos
   antigos (se houver mais de uma análise na OS) ficam recolhidos num
   <details>, só o mais recente vem aberto. */
.portal-causa-raiz-intro {
  font-size: 0.82rem;
  color: var(--text-muted);
  margin: -0.35rem 0 1rem;
}
.portal-causa-raiz-card {
  background: var(--engrena-surface-alt);
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius-sm);
  padding: 1.25rem 1.4rem;
  margin-bottom: 1rem;
}
.portal-causa-raiz-cabecalho {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 1rem;
}
.portal-causa-raiz-metodo {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--engrena-primary);
  background: rgba(229, 138, 46, 0.14);
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
}
:root[data-theme="light"] .portal-causa-raiz-metodo { background: rgba(201, 112, 28, 0.12); }
.portal-causa-raiz-data { font-size: 0.72rem; color: var(--text-muted); }
.portal-causa-raiz-bloco { margin-bottom: 1.1rem; }
.portal-causa-raiz-bloco:last-child { margin-bottom: 0; }
.portal-causa-raiz-bloco-titulo {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-muted);
  margin: 0 0 0.4rem;
}
.portal-causa-raiz-problema {
  font-size: 0.92rem;
  line-height: 1.55;
  margin: 0;
  padding: 0.85rem 1rem;
  background: var(--engrena-surface);
  border-left: 3px solid var(--engrena-danger, #e5484d);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.portal-causa-raiz-5w2h {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 0.85rem;
}
.portal-causa-raiz-5w2h-item { background: var(--engrena-surface); border-radius: var(--radius-sm); padding: 0.7rem 0.9rem; }
.portal-causa-raiz-5w2h-item .rotulo { display: block; font-size: 0.62rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-muted); margin-bottom: 0.25rem; }
.portal-causa-raiz-5w2h-item .valor { font-size: 0.85rem; line-height: 1.4; }
.portal-causa-raiz-plano {
  font-size: 0.92rem;
  line-height: 1.55;
  margin: 0;
  padding: 0.85rem 1rem;
  background: var(--engrena-surface);
  border-left: 3px solid var(--engrena-accent);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
details.portal-causa-raiz-historico { margin-top: 0.5rem; }
details.portal-causa-raiz-historico > summary {
  cursor: pointer;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-muted);
  padding: 0.4rem 0;
}
details.portal-causa-raiz-historico[open] > summary { margin-bottom: 0.5rem; }

/* ---------------------------------------------------------------------- */
/* Marca d'água (rodapé) — nome do desenvolvedor + versão, em toda tela.   */
/* Fixa, discreta (baixa opacidade), não intercepta cliques.               */
/* ---------------------------------------------------------------------- */
.marca-dagua-rodape {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 40;
  text-align: center;
  font-size: 0.65rem;
  letter-spacing: 0.02em;
  color: var(--text-muted);
  opacity: 0.45;
  padding: 0.2rem 0.5rem;
  pointer-events: none;
  background: linear-gradient(to top, var(--engrena-bg, transparent) 40%, transparent);
}

/* ---------------------------------------------------------------------- */
/* Botão "Painel de Administração" — só visível pro desenvolvedor, no      */
/* canto inferior do Painel de Módulos. Fica acima da marca d'água pra     */
/* não sobrepor.                                                          */
/* ---------------------------------------------------------------------- */
.btn-admin-flutuante {
  position: fixed;
  right: 1.25rem;
  bottom: 1.75rem;
  z-index: 45;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.55rem 1rem;
  border-radius: 999px;
  background: var(--engrena-surface);
  border: 1px solid var(--engrena-border);
  color: var(--text-primary);
  font-size: 0.78rem;
  font-weight: 600;
  text-decoration: none;
  box-shadow: 0 6px 18px rgba(8, 14, 22, 0.25);
  opacity: 0.85;
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.btn-admin-flutuante:hover { opacity: 1; transform: translateY(-2px); }
:root[data-theme="light"] .btn-admin-flutuante { box-shadow: 0 6px 18px rgba(16, 30, 45, 0.14); }

/* ---------------------------------------------------------------------- */
/* Ícone de mensagem (Suporte) — canto superior direito do Painel de       */
/* Módulos, junto dos outros controles do usuário.                        */
/* ---------------------------------------------------------------------- */
.btn-suporte-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 999px;
  background: var(--engrena-surface-alt);
  border: 1px solid var(--engrena-border);
  color: var(--text-primary);
  cursor: pointer;
  flex-shrink: 0;
}
.btn-suporte-icon:hover { border-color: var(--engrena-primary); }
.btn-suporte-icon .badge-nao-lida {
  position: absolute;
  top: -0.2rem;
  right: -0.2rem;
  width: 0.7rem;
  height: 0.7rem;
  border-radius: 999px;
  background: var(--engrena-primary, #e5484d);
  border: 2px solid var(--engrena-surface);
}

/* ---------------------------------------------------------------------- */
/* Suporte — modal com formulário + histórico de mensagens/respostas.      */
/* Usado tanto no Painel de Módulos (staff) quanto no Painel de            */
/* Administração (thread por empresa).                                    */
/* ---------------------------------------------------------------------- */
.suporte-mensagem-card {
  background: var(--engrena-surface-alt);
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius-sm);
  padding: 0.9rem 1rem;
  margin-bottom: 0.85rem;
}
.suporte-mensagem-cabecalho {
  display: flex;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: 0.7rem;
  color: var(--text-muted);
  margin-bottom: 0.4rem;
}
.suporte-mensagem-texto { font-size: 0.88rem; line-height: 1.5; margin: 0; }
.suporte-resposta {
  margin-top: 0.7rem;
  padding: 0.7rem 0.9rem;
  background: var(--engrena-surface);
  border-left: 3px solid var(--engrena-accent);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.suporte-resposta-cabecalho { font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--engrena-accent); margin-bottom: 0.3rem; }
.suporte-resposta-texto { font-size: 0.85rem; line-height: 1.5; margin: 0; }
.suporte-sem-resposta { font-size: 0.75rem; color: var(--text-muted); font-style: italic; margin-top: 0.6rem; }
.suporte-responder-form { margin-top: 0.6rem; display: flex; gap: 0.5rem; align-items: flex-start; }
.suporte-responder-form textarea { flex: 1; }

/* ---------------------------------------------------------------------- */
/* Painel de Administração — abas (Empresas / Dashboard)                  */
/* ---------------------------------------------------------------------- */
.admin-tabs {
  display: flex;
  gap: 0.5rem;
  border-bottom: 1px solid var(--engrena-border);
  margin-bottom: 1.25rem;
}
.admin-tab-btn {
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  padding: 0.6rem 0.2rem;
  margin-bottom: -1px;
  font-size: 0.88rem;
  font-weight: 600;
  color: var(--text-muted);
  cursor: pointer;
}
.admin-tab-btn:hover { color: var(--text-primary); }
.admin-tab-btn.active { color: var(--engrena-primary); border-bottom-color: var(--engrena-primary); }

/* ---------------------------------------------------------------------- */
/* Card "Banco de Dados" — barra de uso/livre do plano Supabase.          */
/* ---------------------------------------------------------------------- */
.banco-dados-card { padding: 1.25rem 1.4rem; margin-bottom: 1.5rem; }
.banco-dados-barra {
  width: 100%;
  height: 0.9rem;
  border-radius: 999px;
  background: var(--engrena-surface-alt);
  overflow: hidden;
  border: 1px solid var(--engrena-border);
}
.banco-dados-barra-preenchida {
  height: 100%;
  width: 0%;
  background: var(--engrena-primary);
  border-radius: 999px;
  transition: width 0.3s ease, background 0.3s ease;
}
.banco-dados-barra-preenchida.banco-dados-alerta { background: var(--danger); }
.banco-dados-legenda {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  margin-top: 0.75rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}
.banco-dados-dot { display: inline-block; width: 0.6rem; height: 0.6rem; border-radius: 999px; margin-right: 0.4rem; vertical-align: middle; }
.banco-dados-dot-usado { background: var(--engrena-primary); }

/* ---------------------------------------------------------------------- */
/* Tabela responsiva — abaixo de 680px, cada <tr> vira um card empilhado   */
/* em vez de manter colunas com scroll horizontal apertado. Opt-in via     */
/* classe (não é o padrão de toda tabela do sistema) — usar nas telas de   */
/* campo (Ordens de Serviço, OS Detalhe, Portal do Cliente). Cada <td>     */
/* precisa de um atributo data-label="Nome da coluna" (gerado no JS que    */
/* monta a linha) pra virar o rótulo mostrado acima do valor.              */
/* ---------------------------------------------------------------------- */
@media (max-width: 680px) {
  .tabela-responsiva { border: none; box-shadow: none; background: transparent; margin-top: 0.75rem; }
  .tabela-responsiva thead { display: none; }
  .tabela-responsiva, .tabela-responsiva tbody, .tabela-responsiva tr, .tabela-responsiva td { display: block; width: 100%; }
  .tabela-responsiva tr {
    background: var(--engrena-surface);
    border: 1px solid var(--engrena-border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-card);
    margin-bottom: 0.75rem;
    padding: 0.25rem 0;
  }
  .tabela-responsiva tbody tr:hover { background: var(--engrena-surface); }
  .tabela-responsiva td {
    padding: 0.5rem 0.9rem;
    border-bottom: 1px solid var(--engrena-border);
    word-break: break-word;
  }
  .tabela-responsiva tr td:last-child { border-bottom: none; }
  .tabela-responsiva td::before {
    content: attr(data-label);
    display: block;
    font-weight: 700;
    text-transform: uppercase;
    font-size: 0.62rem;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    margin-bottom: 0.25rem;
  }
  .tabela-responsiva td .acoes-linha { flex-wrap: wrap; }
}
.banco-dados-dot-livre { background: var(--engrena-surface-alt); border: 1px solid var(--engrena-border); }

/* ---------------------------------------------------------------------- */
/* Apontamento de Horas — botões grandes de tipo + cards de lançamento,    */
/* pensados pra toque no celular (tela usada em campo).                   */
/* ---------------------------------------------------------------------- */
.tipo-registro-grupo { display: flex; gap: 0.6rem; flex-wrap: wrap; margin-bottom: 1rem; }
.tipo-registro-btn {
  flex: 1;
  min-width: 130px;
  padding: 0.9rem 0.75rem;
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius);
  background: var(--engrena-surface);
  color: var(--text-primary);
  font-size: 0.9rem;
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s, background-color 0.15s;
}
.tipo-registro-btn:hover { border-color: var(--engrena-primary); }
.tipo-registro-btn.ativo { border-color: var(--engrena-primary); background: rgba(30, 136, 229, 0.14); color: var(--engrena-primary); }

.apontamento-card {
  padding: 0.9rem 1.1rem;
  margin-bottom: 0.75rem;
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
}
.apontamento-card-topo { display: flex; align-items: center; gap: 0.75rem; }
.apontamento-card-data { font-size: 0.85rem; color: var(--text-muted); }
.apontamento-card-detalhes { display: flex; align-items: center; gap: 1rem; font-size: 0.85rem; margin-left: auto; }
.apontamento-card .delete-apontamento-btn { flex-shrink: 0; }

/* ---------------------------------------------------------------------- */
/* Central de Ajuda (ajuda.html) + botão de acesso embutido nas telas      */
/* ---------------------------------------------------------------------- */
.btn-ajuda-toggle {
  position: fixed;
  top: 0.75rem;
  right: 3rem;
  z-index: 50;
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  background: var(--engrena-surface);
  border: 1px solid var(--engrena-border);
  color: var(--text-primary);
  font-size: 0.8rem;
  opacity: 0.7;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}
.btn-ajuda-toggle:hover { opacity: 1; filter: none; }
.btn-ajuda-toggle.btn-ajuda-toggle-embutido {
  position: static; top: auto; right: auto; z-index: auto; opacity: 1;
  border-radius: var(--radius-sm); margin-left: 0; flex-shrink: 0;
}
.btn-ajuda-toggle.btn-ajuda-toggle-embutido:hover { opacity: 1; }

.ajuda-sobre {
  background-color: var(--engrena-surface);
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 1.4rem 1.6rem;
  margin-bottom: 1.75rem;
}
.ajuda-sobre .ajuda-lista-campos { max-width: 40ch; }

.ajuda-busca-wrap { margin-bottom: 1.25rem; }
.ajuda-busca-wrap input {
  width: 100%; max-width: 420px; font-size: 0.95rem;
  padding: 0.6rem 0.9rem;
}
.ajuda-busca-contagem { font-size: 0.78rem; color: var(--text-muted); margin-top: 0.4rem; }

.ajuda-toc { list-style: none; margin: 0; padding: 0; }
.ajuda-toc li { margin: 0; }
.ajuda-toc a.ajuda-toc-modulo {
  display: block; font-weight: 700; font-size: 0.86rem; color: var(--text-primary);
  text-decoration: none; padding: 0.55rem 0.75rem 0.15rem;
}
.ajuda-toc a.ajuda-toc-tela {
  display: block; font-size: 0.8rem; color: var(--text-muted); text-decoration: none;
  padding: 0.3rem 0.75rem 0.3rem 1.4rem; border-left: 2px solid transparent; margin-left: 0.75rem;
}
.ajuda-toc a.ajuda-toc-tela:hover, .ajuda-toc a.ajuda-toc-modulo:hover { color: var(--engrena-primary); border-left-color: var(--engrena-primary); }

.ajuda-modulo { margin-bottom: 3rem; scroll-margin-top: 1rem; }
.ajuda-modulo-cabecalho {
  display: flex; align-items: baseline; gap: 0.7rem; border-bottom: 2px solid var(--text-primary);
  padding-bottom: 0.6rem; margin-bottom: 0.3rem;
}
.ajuda-modulo-num { font-weight: 700; font-size: 0.85rem; color: var(--engrena-primary); }
.ajuda-modulo-cabecalho h2 { margin: 0; font-size: 1.4rem; }
.ajuda-modulo-intro { color: var(--text-muted); max-width: 66ch; margin: 0.7rem 0 0; }

.ajuda-tela { margin-top: 2rem; padding-top: 1.6rem; border-top: 1px solid var(--engrena-border); scroll-margin-top: 1rem; }
.ajuda-tela:first-of-type { border-top: none; }
.ajuda-tela-eyebrow { font-size: 0.68rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 0.25rem; }
.ajuda-tela h3 { margin: 0 0 0.6rem; font-size: 1.1rem; }
.ajuda-tela p, .ajuda-tela ul, .ajuda-tela ol { max-width: 66ch; }
.ajuda-tela li { margin-bottom: 0.35rem; }

.ajuda-onde {
  display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.78rem; color: var(--text-muted);
  background: var(--engrena-surface-alt); border: 1px solid var(--engrena-border);
  padding: 0.28rem 0.6rem; border-radius: var(--radius-sm); margin-bottom: 0.9rem;
}
.ajuda-onde strong { color: var(--text-primary); }

.ajuda-campo {
  color: var(--engrena-primary); background: rgba(30, 136, 229, 0.12);
  padding: 0.04rem 0.32rem; border-radius: 3px; white-space: nowrap; font-size: 0.92em;
}
.ajuda-botao {
  display: inline-flex; align-items: center; gap: 0.25rem; font-weight: 600; font-size: 0.92em;
  color: var(--text-primary); background: var(--engrena-surface-alt); border: 1px solid var(--engrena-border);
  padding: 0.05rem 0.45rem; border-radius: var(--radius-sm);
}

.ajuda-nota, .ajuda-alerta {
  max-width: 66ch; margin: 1rem 0; padding: 0.75rem 1rem; border-left: 3px solid var(--engrena-primary);
  background: rgba(30, 136, 229, 0.08); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; font-size: 0.92rem;
}
.ajuda-alerta { border-left-color: var(--warning); background: rgba(229, 161, 61, 0.1); }

.ajuda-fluxo { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin: 1rem 0 1.2rem; }
.ajuda-fluxo .arrow { color: var(--text-muted); }

.ajuda-lista-campos { list-style: none; padding: 0; margin: 0.8rem 0; max-width: 66ch; }
.ajuda-lista-campos li { display: grid; grid-template-columns: minmax(140px, 32%) 1fr; gap: 0.8rem; padding: 0.45rem 0; border-bottom: 1px dotted var(--engrena-border); font-size: 0.92rem; }
.ajuda-lista-campos li:last-child { border-bottom: none; }
.ajuda-lista-campos .fnome { font-weight: 600; color: var(--text-primary); }
.ajuda-lista-campos .freq { color: var(--danger); font-weight: 700; }
.ajuda-lista-campos .fdesc { color: var(--text-muted); }

.ajuda-chip-row { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.8rem 0 1.1rem; }
.ajuda-chip { font-size: 0.78rem; font-weight: 600; background: var(--engrena-surface-alt); border: 1px solid var(--engrena-border); padding: 0.32rem 0.65rem; border-radius: var(--radius-sm); }

.ajuda-tabela-wrap { overflow-x: auto; max-width: 66ch; margin: 0.8rem 0; }
.ajuda-tabela-wrap table { border-collapse: collapse; width: 100%; font-size: 0.85rem; }
.ajuda-tabela-wrap th, .ajuda-tabela-wrap td { text-align: left; padding: 0.45rem 0.6rem; border-bottom: 1px solid var(--engrena-border); }
.ajuda-tabela-wrap th { color: var(--text-muted); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em; }

.ajuda-subtitulo { font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); margin: 1.3rem 0 0.2rem; }

.ajuda-tela-destacada { animation: ajudaDestaque 2.4s ease-out; }
@keyframes ajudaDestaque {
  0% { background: rgba(30, 136, 229, 0.16); box-shadow: 0 0 0 1px rgba(30, 136, 229, 0.3); border-radius: var(--radius-sm); }
  100% { background: transparent; box-shadow: none; }
}

.ajuda-oculto { display: none !important; }
.ajuda-sem-resultado { color: var(--text-muted); font-size: 0.9rem; padding: 2rem 0; }

@media (max-width: 900px) {
  .ajuda-layout { grid-template-columns: 1fr !important; }
}

/* ============================================================================
   Portal do Técnico (tecnico.html / tecnico-os.html) — mobile-first de
   propósito: telas próprias, sem shell.js/sidebar, no mesmo espírito do
   Portal do Cliente (ver .portal-* acima). Base pensada pra 360-390px de
   largura; o grid da lista só ganha colunas extras a partir de telas largas.
   ============================================================================ */
.tecnico-body { min-height: 100%; }

.tecnico-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: 0.9rem 1rem;
  background-color: var(--engrena-surface);
  border-bottom: 1px solid var(--engrena-border);
  position: sticky;
  top: 0;
  z-index: 5;
}
.tecnico-topbar-marca { display: flex; align-items: center; gap: 0.65rem; flex-shrink: 0; }
.tecnico-topbar-avatar {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: var(--engrena-surface-alt); color: var(--text-muted);
}
.tecnico-topbar-avatar svg { width: 18px; height: 18px; }
.tecnico-topbar-avatar img { width: 100%; height: 100%; object-fit: cover; }
.tecnico-topbar-info { text-align: right; margin-right: 0.4rem; }
.tecnico-topbar-saudacao { margin: 0; font-weight: 700; font-size: 0.95rem; }
.tecnico-topbar-data { margin: 0.1rem 0 0; font-size: 0.72rem; color: var(--text-muted); text-transform: capitalize; }
.tecnico-voltar { font-size: 0.9rem; font-weight: 600; text-decoration: none; color: var(--text-primary); }

/* Ações do lado direito da topbar (Sair + tema/ajuda, embutidos ali por
   theme.js/ajudaBotao.js — ver seletor .tecnico-topbar-acoes nesses arquivos).
   min-width:0 + flex-wrap: em telas estreitas (avatar+saudação+data+Sair+
   tema+ajuda não cabem numa linha só) os itens quebram pra 2ª linha em vez
   de espremer a logo (.tecnico-topbar-marca) até sumir atrás deles. */
.tecnico-topbar-acoes { display: flex; align-items: center; flex-wrap: wrap; justify-content: flex-end; gap: 0.5rem; min-width: 0; }

.tecnico-main { max-width: 720px; margin: 0 auto; padding: 1rem 1rem 3rem; }
.tecnico-main-os { padding-top: 1.1rem; }
.tecnico-titulo { font-size: 1.3rem; margin: 0.2rem 0 1rem; }

.tecnico-ponto-link {
  display: flex; align-items: center; justify-content: center; gap: 0.5rem;
  text-align: center; padding: 1.2rem; margin-bottom: 1rem;
  font-weight: 700; font-size: 1.1rem; text-decoration: none; color: var(--text-primary);
  border: 1px solid var(--engrena-border); transition: border-color 0.15s;
}
.tecnico-ponto-link:hover { border-color: var(--engrena-accent); }
.tecnico-ponto-link-icone { font-size: 1.9rem; line-height: 1; }

.tecnico-produtividade-card {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.9rem 1.1rem; margin-bottom: 1rem;
}
.tecnico-produtividade-label { font-size: 0.85rem; color: var(--text-muted); }
.tecnico-produtividade-valor { font-size: 1.4rem; font-weight: 700; color: var(--engrena-accent); }

.tecnico-filtros { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 0.7rem; }
.tecnico-chip {
  border: 1px solid var(--engrena-border);
  background: var(--engrena-surface);
  color: var(--text-muted);
  border-radius: 999px;
  padding: 0.4rem 0.9rem;
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
}
.tecnico-chip:hover { filter: none; border-color: var(--engrena-primary); }
.tecnico-chip.ativo { background: var(--engrena-primary); border-color: var(--engrena-primary); color: #fff; }

.tecnico-lista-grid { display: grid; grid-template-columns: 1fr; gap: 0.9rem; margin-top: 1rem; }
@media (min-width: 640px) {
  .tecnico-lista-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .tecnico-lista-grid { grid-template-columns: repeat(3, 1fr); }
}

.tecnico-os-card { padding: 1.1rem; cursor: pointer; display: flex; flex-direction: column; gap: 0.3rem; }
.tecnico-os-card:hover { border-color: var(--engrena-primary); }

/* Estado vazio com borda e ícone — antes era um parágrafo solto sem nenhum
   limite visual, lendo como a tela quebrada em vez de "sem OS agora". Mesmo
   tratamento do Controle de Pneus (.tp-estado-vazio). */
.tecnico-estado-vazio {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 0.6rem; margin-top: 1rem; padding: 2.8rem 1.5rem; color: var(--text-muted);
  border: 1px dashed var(--engrena-border); border-radius: var(--radius);
}
.tecnico-estado-vazio-icone { width: 3rem; height: 3rem; color: var(--text-muted); opacity: 0.55; }
.tecnico-estado-vazio-titulo { margin: 0; font-size: 1rem; font-weight: 700; color: var(--text-primary); }
.tecnico-estado-vazio-texto { margin: 0; font-size: 0.85rem; max-width: 22rem; line-height: 1.5; }
.tecnico-os-card-topo { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.tecnico-os-card-numero { margin: 0; font-size: 1.05rem; font-weight: 700; }
.tecnico-os-card-cliente { margin: 0.15rem 0 0; font-weight: 600; }
.tecnico-os-card-equipamento { margin: 0; color: var(--text-muted); font-size: 0.88rem; }
.tecnico-os-card-servico { margin: 0.3rem 0 0; font-size: 0.88rem; }
.tecnico-os-card-rodape { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.5rem; flex-wrap: wrap; }
.tecnico-os-card-prazo { font-size: 0.8rem; color: var(--text-muted); }
.tecnico-btn-abrir {
  margin-top: 0.6rem;
  width: 100%;
  padding: 0.75rem;
  font-size: 0.95rem;
  font-weight: 700;
}

/* Tela de execução da OS */
.tecnico-os-hero { background: var(--engrena-surface); border: 1px solid var(--engrena-border); border-radius: var(--radius); padding: 1.1rem; margin-bottom: 1rem; }
.tecnico-os-hero-topo { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.tecnico-os-hero-numero { margin: 0; font-size: 1.3rem; font-weight: 700; }
.tecnico-os-hero-cliente { margin: 0.5rem 0 0; font-weight: 600; }
.tecnico-os-hero-equipamento { margin: 0.15rem 0 0; color: var(--text-muted); }
.tecnico-os-hero-prazo { margin: 0.5rem 0 0; font-size: 0.85rem; color: var(--text-muted); }

.tecnico-secao { background: var(--engrena-surface); border: 1px solid var(--engrena-border); border-radius: var(--radius); padding: 1.1rem; margin-bottom: 1rem; }
.tecnico-secao h2 { margin: 0 0 0.7rem; font-size: 1rem; }
.tecnico-secao-destaque { border-color: var(--engrena-primary); }
.tecnico-motivo { margin: 0; white-space: pre-wrap; line-height: 1.5; }
.tecnico-cancelada { color: var(--danger); font-weight: 600; }

.tecnico-stepper { display: flex; align-items: center; }
.tecnico-etapa { display: flex; flex-direction: column; align-items: center; gap: 0.3rem; flex: 0 0 auto; }
.tecnico-etapa-dot {
  width: 32px; height: 32px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--engrena-surface-alt); border: 2px solid var(--engrena-border);
  font-size: 0.85rem; font-weight: 700; color: var(--text-muted);
}
.tecnico-etapa.concluida .tecnico-etapa-dot { background: var(--engrena-accent); border-color: var(--engrena-accent); color: #fff; }
.tecnico-etapa.ativa .tecnico-etapa-dot { background: var(--engrena-primary); border-color: var(--engrena-primary); color: #fff; }
.tecnico-etapa-label { font-size: 0.72rem; color: var(--text-muted); text-align: center; }
.tecnico-etapa.ativa .tecnico-etapa-label { color: var(--text-primary); font-weight: 600; }
.tecnico-etapa-linha { flex: 1 1 auto; height: 2px; background: var(--engrena-border); margin: 0 0.3rem 1.4rem; }

.tecnico-linha-registro { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; padding: 0.5rem 0; border-bottom: 1px solid var(--engrena-border); font-size: 0.88rem; }
.tecnico-linha-registro:last-of-type { border-bottom: none; }

.tecnico-sessao-aberta {
  margin-top: 0.7rem; padding: 0.8rem;
  background: rgba(229, 161, 61, 0.12); border: 1px solid var(--warning);
  border-radius: var(--radius-sm);
  display: flex; flex-direction: column; gap: 0.6rem; align-items: flex-start;
  font-size: 0.88rem;
}
.tecnico-sessao-aberta button { width: 100%; }

.tecnico-btn-acao {
  display: inline-flex; align-items: center; justify-content: center;
  width: 100%; margin-top: 0.7rem;
  padding: 0.75rem; font-weight: 700; font-size: 0.92rem;
  cursor: pointer; text-align: center;
}
.tecnico-btn-secundario { background: var(--engrena-surface-alt); color: var(--text-primary); border: 1px solid var(--engrena-border); }

.tecnico-fotos-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.7rem; margin-bottom: 0.5rem; }
.tecnico-foto-thumb { position: relative; aspect-ratio: 4 / 3; border-radius: var(--radius-sm); overflow: hidden; border: 1px solid var(--engrena-border); }
.tecnico-foto-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.tecnico-foto-remover {
  position: absolute; top: 0.35rem; right: 0.35rem;
  width: 30px; height: 30px; padding: 0; border-radius: 50%;
  background: rgba(13, 21, 32, 0.75); color: #fff;
}
.tecnico-fotos-botoes { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 0.5rem; }
.tecnico-fotos-botoes .tecnico-btn-acao { margin-top: 0; }

.tecnico-form { display: flex; flex-direction: column; gap: 0.7rem; margin-top: 0.8rem; }
.tecnico-form label { display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.85rem; }
.tecnico-form-botoes { display: flex; gap: 0.6rem; }
.tecnico-form-botoes button { flex: 1; padding: 0.7rem; }

#tecnico-observacao { width: 100%; resize: vertical; }

.tecnico-prazo-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 0.6rem;
  padding: 0.8rem 1rem; margin-bottom: 1rem; border-radius: var(--radius);
  font-weight: 700; font-size: 0.9rem;
  background: var(--engrena-surface); border: 1px solid var(--engrena-border);
}
.tecnico-prazo-banner-urgente {
  background: color-mix(in srgb, var(--danger) 16%, var(--engrena-surface));
  border-color: var(--danger); color: var(--danger);
}

.tecnico-btn-finalizar {
  width: 100%; padding: 1rem; font-size: 1.02rem; font-weight: 700;
  background: var(--engrena-accent); margin-bottom: 1rem;
}
.tecnico-btn-finalizar:hover { background: var(--engrena-accent-dark); }
.tecnico-concluido-msg {
  text-align: center; font-weight: 700; color: var(--engrena-accent);
  padding: 1rem; margin-bottom: 1rem;
  background: var(--engrena-surface); border: 1px solid var(--engrena-accent); border-radius: var(--radius);
}

.tecnico-timeline { display: flex; flex-direction: column; gap: 0.6rem; }
.tecnico-timeline-item { display: flex; flex-direction: column; gap: 0.1rem; font-size: 0.85rem; padding-bottom: 0.6rem; border-bottom: 1px solid var(--engrena-border); }
.tecnico-timeline-item:last-child { border-bottom: none; padding-bottom: 0; }
.tecnico-timeline-hora { font-size: 0.72rem; color: var(--text-muted); }

@media (min-width: 768px) {
  .tecnico-os-card, .tecnico-secao, .tecnico-os-hero { padding: 1.3rem; }
}

/* ---------------------------------------------------------------------- */
/* Banner de alerta genérico — generalização do .tecnico-prazo-banner pra   */
/* fora do Portal do Técnico (usado em Frota > Abastecimentos: leitura      */
/* regressiva, acima da capacidade, origem emergencial). Sem badge          */
/* piscante, sem vermelho pra evento não-crítico — .alerta-banner-info é o  */
/* padrão neutro; -atencao/-critico só quando o dado exige mesmo.           */
/* ---------------------------------------------------------------------- */
.alerta-banner {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.75rem 1rem;
  margin-bottom: 1rem;
  border-radius: var(--radius);
  font-size: 0.85rem;
  line-height: 1.4;
  background: var(--engrena-surface);
  border: 1px solid var(--engrena-border);
}
.alerta-banner-icone { flex-shrink: 0; font-size: 1rem; line-height: 1.3; }
/* §3 — o aviso só sai quando o usuário disser que leu. Sem este botão ele
   ficava na tela sem caminho de saída, até outra ação sobrescrevê-lo. */
.alerta-banner-fechar {
  flex-shrink: 0; align-self: flex-start;
  background: none; border: none; padding: 0 0.2rem; margin: -0.15rem -0.3rem 0 0;
  font-size: 1.25rem; line-height: 1; cursor: pointer;
  color: inherit; opacity: 0.65;
}
.alerta-banner-fechar:hover { opacity: 1; }
.alerta-banner-fechar:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; border-radius: 3px; }
.alerta-banner-texto { flex: 1; }
.alerta-banner-info { border-color: var(--engrena-primary); }
.alerta-banner-atencao {
  background: color-mix(in srgb, var(--warning) 12%, var(--engrena-surface));
  border-color: var(--warning);
}
.alerta-banner-critico {
  background: color-mix(in srgb, var(--danger) 10%, var(--engrena-surface));
  border-color: var(--danger);
}

/* ---------------------------------------------------------------------- */
/* Card de contexto do ativo — mostrado ao selecionar o veículo/equipamento */
/* no formulário de Novo Abastecimento (Frota). Grade simples reaproveitando */
/* os mesmos tokens do .kpi-card, sem nenhum componente novo de verdade.    */
/* ---------------------------------------------------------------------- */
.ativo-contexto-card {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 0.6rem 1.25rem;
  padding: 0.9rem 1.1rem;
  margin-bottom: 1rem;
  background: var(--engrena-surface-alt);
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius);
}
.ativo-contexto-item { display: flex; flex-direction: column; gap: 0.15rem; }
.ativo-contexto-label { font-size: 0.65rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); }

/* ---------------------------------------------------------------------- */
/* Timeline vertical de ciclos de vida do pneu (Etapa 3G-E) — cada ciclo é */
/* um ponto ligado por uma linha; mais recente primeiro. Sem biblioteca.   */
/* ---------------------------------------------------------------------- */
.ciclo-timeline { display: flex; flex-direction: column; }
.ciclo-timeline-item { position: relative; padding: 0 0 1.2rem 1.6rem; border-left: 2px solid var(--engrena-border); }
.ciclo-timeline-item:last-child { border-left-color: transparent; padding-bottom: 0; }
.ciclo-timeline-dot {
  position: absolute; left: -0.5rem; top: 0.15rem;
  width: 0.85rem; height: 0.85rem; border-radius: 50%;
  background: var(--engrena-surface); border: 2px solid var(--engrena-primary);
}
.ciclo-timeline-item.ciclo-encerrado .ciclo-timeline-dot { border-color: var(--engrena-border); }
.ciclo-timeline-titulo { font-weight: 700; margin-bottom: 0.2rem; }
.ciclo-timeline-meta { font-size: 0.8rem; color: var(--text-muted); }
.ciclo-timeline-acoes { margin-top: 0.4rem; display: flex; gap: 0.6rem; flex-wrap: wrap; }
.ativo-contexto-valor { font-size: 0.88rem; font-weight: 600; color: var(--text-primary); }

/* ============================================================================
   Central Visual de Pneus (Etapa 3G-H2) — chassi dinâmico gerado por
   componentes (nunca imagem fixa), painel de pneu selecionado, estoque
   disponível. Namespace .pneu-chassi-* isolado, reaproveita 100% os tokens
   de cor/raio/sombra/fonte já existentes (--engrena-*, --radius*, Inter) —
   nenhuma cor ou fonte nova introduzida. Modo configuração (3G-H1) não foi
   redesenhado aqui, só recebe polimento leve pontual (ver frota-pneus.js).
   ============================================================================ */

.pneu-chassi-central {
  background: var(--engrena-surface);
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius);
  min-width: 0;
}

.pneu-chassi-vazio-aviso { text-align: center; padding: 2.5rem 1rem; color: var(--text-muted); }

/* ============================================================================
   RENDERER SVG DO CHASSI + COMPOSIÇÃO DA CENTRAL (Etapa 3G-H2.1.3).
   Substitui o bloco da H2.1.2 (não empilha overrides — mandato §84).
   Convergência às duas referências aprovadas: pneu com friso horizontal e aro,
   contorno colorido por estado, longarinas largas com travessas/rebites,
   diferencial esférico, cabeçalho com breadcrumb, KPIs com ícone, painel com
   miniatura e ações 2×2, estoque com miniaturas.

   NOTA SOBRE COR (exceção deliberada, mantida da H2.1.2): borracha e aço usam
   paleta física FIXA, não tokens de tema — um pneu é escuro nos dois temas.
   As faixas contrastam contra o surface escuro (#141d2b) e contra o branco.
   Precedente no projeto: .pneu-qr-print e .os-print também fixam cor por serem
   "material". Todo o resto (etiquetas, contornos de estado, chrome) usa tokens.
   ============================================================================ */

/* ---- (1) Palco e SVG ---------------------------------------------------- */
/* min-width:0 + max-width:100% são obrigatórios: sem eles o min-width do SVG
   estica o palco, o overflow-x dele nunca ativa e o corte acaba acontecendo lá
   em cima no .page-content (bug encontrado no viewport 375 durante a H2.1.3). */
.pneu-chassi-palco {
  display: flex;
  justify-content: center;
  overflow-x: auto;
  min-width: 0;
  max-width: 100%;
  padding: 0;
}
.pneu-chassi-svg {
  width: 100%;
  max-width: 860px;
  min-width: 520px;
  height: auto;
  display: block;
}
.pneu-chassi-central { padding: 1rem 1rem 0.6rem; }

/* ---- (2) Estrutura: longarinas, travessas, rebites, bico ---------------- */
/* §31 — presença vem de profundidade (sombra + alma + arestas), não largura. */
.pn-longarina-sombra { fill: rgba(6, 10, 15, 0.34); }
.pn-longarina { fill: #6f7a86; stroke: rgba(10, 14, 20, 0.85); stroke-width: 1.3; }
/* Perfil U: abas claras nas bordas, alma rebaixada (mais escura) no meio. */
.pn-longarina-aba { fill: url(#pnAcoV); }
.pn-longarina-alma { fill: rgba(22, 29, 38, 0.34); }
.pn-longarina-aresta { stroke: rgba(10, 14, 20, 0.7); stroke-width: 1.4; }
.pn-travessa { fill: url(#pnAcoH); stroke: rgba(14, 19, 26, 0.7); stroke-width: 1.1; }
.pn-travessa-face { fill: rgba(255, 255, 255, 0.16); }
/* §33 — substitui o X decorativo: travessa intermediária + esquadros de canto */
.pn-travessa-int { fill: url(#pnAcoH); stroke: rgba(14, 19, 26, 0.6); stroke-width: 1; opacity: 0.9; }
.pn-esquadro { fill: #6d7783; stroke: rgba(14, 19, 26, 0.5); stroke-width: 0.9; opacity: 0.72; }
.pn-bico { fill: url(#pnAcoH); stroke: rgba(14, 19, 26, 0.65); stroke-width: 1.1; opacity: 0.94; }
.pn-rebite { fill: rgba(18, 24, 32, 0.55); stroke: rgba(255, 255, 255, 0.16); stroke-width: 0.7; }

/* ---- (3) Eixo: tubo, diferencial, cubos --------------------------------- */
.pn-tubo-sombra { fill: rgba(6, 10, 15, 0.3); }
.pn-tubo { fill: url(#pnAcoH); stroke: rgba(14, 19, 26, 0.72); stroke-width: 1.2; }
.pn-tubo-face { fill: rgba(255, 255, 255, 0.18); }
/* §29 — o diferencial ganha pescoços, tampa, núcleo e brilho para ler como
   peça acoplada ao tubo, não como elipse sobreposta. */
.pn-dif-pescoco { fill: url(#pnAcoH); stroke: rgba(14, 19, 26, 0.6); stroke-width: 1.1; }
.pn-diferencial { fill: url(#pnDif); stroke: rgba(14, 19, 26, 0.82); stroke-width: 1.5; }
.pn-dif-tampa { fill: rgba(255, 255, 255, 0.07); stroke: rgba(14, 19, 26, 0.5); stroke-width: 1.6; }
.pn-dif-nucleo { fill: rgba(14, 19, 26, 0.45); }
.pn-dif-parafuso { fill: rgba(14, 19, 26, 0.52); }
.pn-dif-brilho { fill: none; stroke: rgba(255, 255, 255, 0.4); stroke-width: 2.4; stroke-linecap: round; }
/* §30 — eixo simples deixa de ser cápsula minúscula */
.pn-alojamento { fill: url(#pnAcoV); stroke: rgba(14, 19, 26, 0.72); stroke-width: 1.3; }
.pn-alojamento-face { fill: rgba(255, 255, 255, 0.16); }
/* Árvore de transmissão + juntas universais */
.pn-cardan-sombra { fill: rgba(6, 10, 15, 0.3); }
.pn-cardan { fill: url(#pnAcoV); stroke: rgba(14, 19, 26, 0.7); stroke-width: 1.2; }
.pn-cardan-brilho { fill: rgba(255, 255, 255, 0.28); }
.pn-junta { fill: url(#pnAcoH); stroke: rgba(14, 19, 26, 0.75); stroke-width: 1.2; }
.pn-junta-pino { fill: rgba(14, 19, 26, 0.55); }

/* Feixe de molas: liga visualmente o eixo à longarina */
.pn-mola-sombra { fill: rgba(6, 10, 15, 0.28); }
.pn-mola { fill: url(#pnAcoV); stroke: rgba(14, 19, 26, 0.72); stroke-width: 1.2; }
.pn-mola-folha { fill: rgba(255, 255, 255, 0.1); stroke: rgba(14, 19, 26, 0.4); stroke-width: 0.9; }
.pn-mola-brilho { fill: rgba(255, 255, 255, 0.3); }
.pn-mola-grampo { fill: rgba(14, 19, 26, 0.5); }

/* Tambor de freio: o volume que faltava entre o tubo e a roda */
.pn-tambor-sombra { fill: rgba(6, 10, 15, 0.34); }
.pn-tambor { fill: url(#pnAcoV); stroke: rgba(14, 19, 26, 0.85); stroke-width: 1.4; }
.pn-tambor-face { fill: rgba(255, 255, 255, 0.14); }

/* §28 — cubo com flange, coroa de parafusos e núcleo */
.pn-cubo { fill: url(#pnAcoV); stroke: rgba(14, 19, 26, 0.82); stroke-width: 1.4; }
.pn-cubo-face { fill: rgba(255, 255, 255, 0.17); }
.pn-cubo-flange { fill: none; stroke: rgba(14, 19, 26, 0.5); stroke-width: 1.8; }
.pn-cubo-parafuso { fill: rgba(14, 19, 26, 0.5); }
.pn-cubo-centro { fill: rgba(14, 19, 26, 0.58); }
.pn-eixo-inativo { opacity: 0.42; }

/* ---- (4) O pneu --------------------------------------------------------- */
.pn-sombra { fill: rgba(6, 10, 15, 0.4); }
.pn-corpo { fill: url(#pnBorracha); stroke: #0f1319; stroke-width: 1.4; }
/* §24 — recortes da banda com opacidade variável (definida inline por bloco),
   em colunas defasadas: leitura de desenho de banda, não de grade. */
.pn-sipe { stroke: #0c1015; stroke-linecap: round; }
.pn-canal { stroke: #0a0d12; opacity: 0.92; stroke-linecap: round; }
/* Pneu de LADO (estoque): banda curva à esquerda, face da roda com aro à
   direita. É a única vista em que o aro aparece — na vista de cima do chassi
   a banda de rodagem cobre a roda inteira. */
.pn-lat-chao { fill: rgba(6, 10, 15, 0.18); }
.pn-lat-carcaca { fill: #0d1218; }
.pn-lat-bloco { fill: #3f4a57; }
.pn-lat-sipe { stroke: #141a21; stroke-width: 0.7; opacity: 0.85; }
.pn-lat-canal { fill: none; stroke: #0a0e13; stroke-width: 1.6; opacity: 0.95; }
.pn-lat-ombro { fill: none; stroke: rgba(0, 0, 0, 0.5); stroke-width: 1.6; }
.pn-lat-letra { fill: none; stroke: rgba(255, 255, 255, 0.09); stroke-width: 1.8; }
.pn-lat-talao { fill: none; stroke: rgba(0, 0, 0, 0.5); stroke-width: 2.2; }
.pn-lat-valvula { stroke: #2b333d; stroke-width: 2.2; stroke-linecap: round; }
.pn-lat-janela { fill: #1c232b; }
.pn-lat-porca { fill: #2d353f; }
/* non-scaling-stroke: o grupo do aro é achatado por scale(), e sem isto o
   contorno ficaria fino de um lado e grosso do outro. */
.pn-lat-cubo { fill: #b9c4d0; stroke: #3d4650; stroke-width: 1; vector-effect: non-scaling-stroke; }
.pn-lat-cubo-centro { fill: #5d6773; }

/* §26 — flancos com mais contraste + sombra interna dá espessura */
.pn-flanco { fill: #0b0e13; opacity: 0.95; }
.pn-sombra-interna { fill: none; stroke: rgba(0, 0, 0, 0.45); stroke-width: 2.6; }
.pn-brilho { fill: #ffffff; opacity: 0.1; }

/* Contorno por estado — o pneu é sempre o mesmo desenho; o que muda é o anel */
.pn-contorno { fill: none; stroke-width: 2.6; }
.pn-roda-ocupada .pn-contorno { stroke: var(--engrena-accent); opacity: 0.9; }
.pn-roda-selecionada .pn-contorno { stroke: var(--engrena-primary); stroke-width: 3.4; opacity: 1; }
.pn-roda-vazia .pn-contorno,
.pn-roda-inativa .pn-contorno { stroke: none; }

/* Vazio: silhueta completa do mesmo pneu, tracejada, com "+" central */
.pn-fantasma {
  fill: var(--engrena-primary); fill-opacity: 0.05;
  stroke: var(--engrena-primary); stroke-width: 2.4; stroke-dasharray: 8 6; opacity: 0.75;
}
.pn-fantasma-mais-bg { fill: var(--engrena-primary); opacity: 0.14; }
.pn-fantasma-mais { stroke: var(--engrena-primary); stroke-width: 2.6; stroke-linecap: round; opacity: 0.95; }
.pn-roda-vazia:hover .pn-fantasma { opacity: 1; fill-opacity: 0.12; }

/* Inativo: silhueta + hachura */
.pn-inativo-base { fill: var(--engrena-surface-alt); stroke: var(--engrena-grey); stroke-width: 2.2; opacity: 0.6; }
.pn-inativo-hachura { color: var(--engrena-grey); opacity: 0.6; }

/* ---- (5) Roda: alvo, foco, hover ---------------------------------------- */
.pn-roda { cursor: pointer; transition: transform 170ms ease; }
.pn-roda-inativa { cursor: default; }
.pn-alvo { fill: transparent; }
.pn-roda:hover:not(.pn-roda-inativa) { transform: translateY(-3px); }
.pn-roda:focus { outline: none; }
.pn-roda:focus-visible .pn-alvo {
  fill: none; stroke: var(--engrena-primary); stroke-width: 2.6; stroke-dasharray: 6 4;
}

/* ---- (6) Etiquetas dentro do SVG ---------------------------------------- */
/* §34/§35/§36 — o viewBox encolheu (largura agora sai da geometria real), então
   cada unidade já renderiza maior; o acréscimo aqui é o ajuste fino para o
   código da POSIÇÃO dominar o código do pneu, e para o rótulo do eixo ser lido
   de imediato. */
.pn-cod-pos { font-family: inherit; font-size: 17px; font-weight: 700; fill: var(--text-primary); }
.pn-cod-pneu { font-family: inherit; font-size: 13px; font-weight: 600; fill: var(--engrena-accent); }
.pn-cod-vazio { font-family: inherit; font-size: 13px; font-weight: 500; fill: var(--text-muted); }
.pn-cod-inativo { font-family: inherit; font-size: 13px; font-weight: 500; fill: var(--engrena-grey); }

.pn-eixo-label-titulo { font-family: inherit; font-size: 16px; font-weight: 700; fill: var(--text-primary); }
.pn-eixo-label-linha { font-family: inherit; font-size: 12px; font-weight: 500; fill: var(--text-muted); }
.pn-eixo-label-inativo { opacity: 0.5; }

.pn-pill { fill: var(--engrena-primary); opacity: 0.16; }
.pn-pill-txt {
  font-family: inherit; font-size: 11.5px; font-weight: 700;
  letter-spacing: 0.08em; fill: var(--engrena-primary);
}
.pn-seta { fill: var(--engrena-primary); }
.pn-marcha-txt {
  font-family: inherit; font-size: 12px; font-weight: 700;
  letter-spacing: 0.09em; fill: var(--engrena-primary);
}
/* 3G-H2.7 — o rótulo tem duas redações porque tem dois espaços disponíveis.
   No mobile as legendas do SVG sobem de 12px para 19px em unidades de viewBox
   (para continuarem legíveis quando o desenho encolhe), mas o x de partida
   (CX + 22) e o do "DIREITA" (largura - 108) continuam calculados para 12px.
   A 19px a frase cresce ~58% e invade a área do DIREITA — que no mobile perde
   a pílula de fundo e fica só texto sobre texto. A seta já comunica o sentido;
   no mobile a palavra "FRENTE" basta. */
.pn-marcha-curto { display: none; }

/* ---- (7) Miniatura reutilizável ----------------------------------------- */
/* H2.1.4 §5/§6 — a geometria do pneu é compartilhada com o chassi, mas o
   TAMANHO é sempre definido pelo contexto e nunca herdado. O <svg> já sai do JS
   com width/height explícitos; estas regras são o segundo cinto de segurança,
   porque um <svg> sem dimensão own cresce até a largura do contêiner (era o que
   transformava a miniatura do painel num pôster de ~300x640px). */
/* A roda de lado é desenhada num viewBox quadrado — largura = altura. */
.pneu-mini { display: block; flex: 0 0 auto; max-width: 100%; }
.pneu-mini-detalhe { width: 86px; height: 86px; }
.pneu-mini-estoque { width: 46px; height: 46px; }

/* ---- (8) Cabeçalho da central ------------------------------------------- */
/* Três níveis de texto empilhados sem respiro liam como um bloco só. O ritmo
   vertical agora cresce do topo para baixo (breadcrumb → título → subtítulo) e
   cada nível tem tamanho/peso/cor distintos, para a hierarquia ser lida antes
   do conteúdo. */
/* .card global não tem padding — cada tela dá o seu. Sem isto o cabeçalho fica
   encostado nas quatro bordas: texto na borda esquerda, botão na direita. */
.pneu-cab-bloco { padding: 1.15rem 1.35rem 1.25rem; }

.pneu-breadcrumb {
  display: flex; align-items: center; gap: 0.35rem; flex-wrap: wrap;
  /* Menor e mais apagado que o subtítulo: é navegação, não informação. */
  font-size: 0.72rem; color: var(--text-muted); opacity: 0.85;
  margin-bottom: 0.85rem; letter-spacing: 0.01em;
}
.pneu-breadcrumb a { color: var(--text-muted); text-decoration: none; }
.pneu-breadcrumb a:hover { color: var(--engrena-primary); text-decoration: underline; }
.pneu-breadcrumb span[aria-current] { color: var(--text-primary); font-weight: 600; }

/* O botão alinha pela linha do TÍTULO, não pelo centro do bloco inteiro: com
   center ele descia 13px e ficava flutuando entre título e subtítulo. */
.pneu-cab-linha {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 1rem 2rem; flex-wrap: wrap;
}
/* flex-basis auto: a identidade encosta no próprio conteúdo em vez de esticar
   por toda a coluna e deixar o botão órfão do outro lado. */
.pneu-cab-identidade { min-width: 0; flex: 1 1 auto; }
.pneu-cab-titulo {
  margin: 0; font-size: 1.45rem; font-weight: 700; line-height: 1.2;
  letter-spacing: -0.01em;
  display: flex; align-items: center; gap: 0.55rem; flex-wrap: wrap;
}
.pneu-cab-badge { font-size: 0.7rem; vertical-align: middle; }
/* Peso 500 e um respiro maior separam o subtítulo do título sem competir. */
.pneu-cab-sub {
  margin: 0.55rem 0 0; font-size: 0.83rem; font-weight: 500;
  color: var(--text-muted); line-height: 1.45;
}
/* -5px sobe o botão (38px) para o centro óptico do título (28px), mantendo o
   alinhamento de topo do flex. */
.pneu-cab-acoes {
  display: flex; gap: 0.5rem; flex-wrap: wrap; align-items: center;
  flex: 0 0 auto; margin-top: -0.3rem;
}
.pneu-cab-acoes button { height: 2.35rem; }

/* ---- (9) KPIs em faixa com ícone ---------------------------------------- */
.pneu-kpi-faixa {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11.5rem, 1fr));
  gap: 0.7rem;
  margin-bottom: 1rem;
}
.pneu-kpi {
  display: flex; align-items: center; gap: 0.7rem;
  padding: 0.7rem 0.85rem;
}
.pneu-kpi-icone {
  flex: 0 0 auto; width: 2.2rem; height: 2.2rem; border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.05rem; line-height: 1;
}
.pneu-kpi-icone-neutro { background: rgba(139, 156, 173, 0.16); color: var(--engrena-grey); }
.pneu-kpi-icone-ok { background: rgba(23, 184, 151, 0.16); color: var(--engrena-accent); }
.pneu-kpi-icone-info { background: rgba(30, 136, 229, 0.16); color: var(--engrena-primary); }
.pneu-kpi-icone-muted { background: rgba(139, 156, 173, 0.12); color: var(--text-muted); }
.pneu-kpi-corpo { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
.pneu-kpi-label { font-size: 0.7rem; color: var(--text-muted); font-weight: 600; }
.pneu-kpi-valor { font-size: 1.5rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.pneu-kpi-helper { font-size: 0.7rem; color: var(--text-muted); }

/* ---- (10) Layout de 2 colunas ------------------------------------------- */
.pneu-chassi-layout {
  display: grid;
  /* §47 — 23rem dá folga ao painel sem estrangular o chassi; §48 diz que
     legibilidade do painel vale mais que preservar a proporção anterior. */
  grid-template-columns: minmax(0, 1fr) 23rem;
  gap: 1rem;
  align-items: start;
}
@media (max-width: 1180px) {
  .pneu-chassi-layout { grid-template-columns: 1fr; }
}
.pneu-chassi-sidebar { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }
.pneu-chassi-painel {
  background: var(--engrena-surface);
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius);
  padding: 0.95rem;
  animation: pneuPainelEntrada 180ms ease;
}
@keyframes pneuPainelEntrada {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ---- (11) Painel do pneu selecionado ------------------------------------ */
.pneu-painel-titulo {
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--text-muted); margin: 0 0 0.75rem;
}
.pneu-painel-titulo-contador { color: var(--text-muted); font-weight: 600; }
/* §4/§45 — a altura do header (e do painel) é governada pelo CONTEÚDO. A
   miniatura entra como item de largura fixa que não cresce nem encolhe, e o
   bloco de texto fica com min-width:0 para poder truncar em vez de empurrar. */
.pneu-painel-header { display: flex; gap: 0.8rem; align-items: center; margin-bottom: 0.9rem; }
.pneu-painel-header-info { min-width: 0; flex: 1 1 auto; }
/* §8/§9 — identificador nunca quebra verticalmente; se a lateral apertar, ele
   reduz de tamanho de forma controlada e, no limite, trunca com reticências. */
.pneu-painel-codigo {
  display: block; font-size: clamp(1rem, 4.2vw, 1.25rem); font-weight: 700;
  color: var(--text-primary); text-decoration: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pneu-painel-codigo:hover { color: var(--engrena-primary); }
.pneu-painel-local {
  font-size: 0.78rem; color: var(--text-muted); margin-top: 0.1rem;
  overflow-wrap: anywhere;
}
.pneu-painel-badges { display: flex; gap: 0.3rem; flex-wrap: wrap; margin-top: 0.35rem; }

.pneu-carac-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
  background: var(--engrena-border);
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin-bottom: 0.9rem;
}
.pneu-carac { background: var(--engrena-surface); padding: 0.5rem 0.6rem; min-width: 0; }
.pneu-carac-rot { font-size: 0.66rem; color: var(--text-muted); margin-bottom: 0.1rem; }
/* 3G-H2.5 — o valor QUEBRA em vez de truncar. Truncar aqui apagava
   informação que o gestor precisa ler inteira: "Continental Conti Hybrid HS3"
   virava "Continental Conti H..." e "15,8 mm — sem sulco inicial" virava
   "15.8 mm — sem sulc...". A célula tem min-width:0 e a grade é de 2 colunas,
   então quebrar em duas linhas não desalinha nada. */
.pneu-carac-val {
  font-size: 0.84rem; font-weight: 600;
  overflow-wrap: anywhere; line-height: 1.3;
}
/* Detalhe entre parênteses ao lado do valor: mesma linha quando cabe, quebra
   junto quando não cabe. Peso e tamanho menores para o valor principal
   continuar sendo o que se lê primeiro. */
.pneu-carac-det { font-size: 0.72rem; font-weight: 500; color: var(--text-muted); }

.pneu-painel-bloco { margin-bottom: 0.9rem; }
.pneu-painel-bloco:last-child { margin-bottom: 0; }
/* 3G-H2.5 — fronteira de seção. O espaçamento padrão de 0,9rem (14px) separa
   bem dois blocos de texto, mas fica visualmente apertado quando o bloco
   anterior termina em cards com borda: o título encosta neles. Usado onde
   começa um conteúdo de natureza diferente — o cálculo derivado, e não mais
   um atributo do pneu. */
.pneu-painel-bloco-sep {
  margin-top: 1.15rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--engrena-border);
}
.pneu-painel-bloco-titulo {
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--text-muted); margin-bottom: 0.4rem;
}
.pneu-painel-bloco-helper { text-transform: none; letter-spacing: 0; font-weight: 500; opacity: 0.8; }
.pneu-painel-linha { display: flex; justify-content: space-between; gap: 0.6rem; font-size: 0.85rem; padding: 0.15rem 0; }
.pneu-painel-linha span:first-child { color: var(--text-muted); }
.pneu-painel-linha span:last-child { font-weight: 600; text-align: right; }
.pneu-painel-vazio { color: var(--text-muted); font-size: 0.88rem; text-align: center; padding: 1.4rem 0.5rem; }

/* 3G-H2.7 — linha que quebra (flex), não grade auto-fit.
   Histórico: a coluna mínima subiu de 88px para 104px para caber a data
   completa da última aferição. Não resolveu, e a medição explica por quê: com
   auto-fit e mínimo de 104px, o painel de 336px acomoda TRÊS colunas (3x104 +
   2x8 = 328). Cada card fica com 107px, o que deixa 85px úteis para o valor —
   e "18/08/2026" a 1,05rem com tabular-nums ocupa 100px. Transbordava 15px
   sempre que havia pressão registrada, porque é a pressão que leva a grade de
   dois para três cards. Aumentar o mínimo não adiantaria: para caber, cada
   card precisaria de ~124px, e três deles não cabem em 336px de jeito nenhum.
   Grade de duas colunas fixas também não serve: no tablet o painel tem 694px e
   duas colunas viram cards de 343px com "120 PSI" perdido no meio.
   Com flex e base de 124px o comportamento sai certo em qualquer largura sem
   media query: em 336px cabem dois por linha (164px cada) e o terceiro ocupa a
   linha inteira; em 694px os três cabem lado a lado (~226px cada). A base de
   124px é justamente o mínimo em que a data completa cabe — 100px de texto
   mais o padding. */
.pneu-painel-metricas { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.pneu-painel-metrica {
  flex: 1 1 124px; min-width: 0;
  background: var(--engrena-surface-alt); border: 1px solid var(--engrena-border);
  border-radius: var(--radius-sm); padding: 0.55rem 0.6rem; text-align: center;
}
.pneu-painel-metrica-label {
  font-size: 0.63rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--text-muted); margin-bottom: 0.2rem;
}
.pneu-painel-metrica-valor { font-size: 1.05rem; font-weight: 700; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }

.pneu-condicao-vazia {
  padding: 0.85rem; background: var(--engrena-surface-alt);
  border: 1px dashed var(--engrena-border); border-radius: var(--radius-sm); text-align: center;
}
.pneu-condicao-vazia-titulo { margin: 0; font-size: 0.82rem; font-weight: 600; color: var(--text-primary); }
.pneu-condicao-vazia-texto { margin: 0.2rem 0 0.6rem; font-size: 0.76rem; color: var(--text-muted); }

/* Ações em grid 2×2 (referência) */
.pneu-acoes-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; margin-bottom: 0.8rem; }
.pneu-acoes-grid button { height: 2.4rem; }
.pneu-painel-acoes { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.6rem; }
.pneu-painel-ficha {
  display: block; text-align: center; font-size: 0.8rem;
  color: var(--engrena-primary); text-decoration: none; font-weight: 600;
}
.pneu-painel-ficha:hover { text-decoration: underline; }

/* ---- (12) Estoque com miniaturas ---------------------------------------- */
.pneu-estoque-lista { display: flex; flex-direction: column; gap: 0.4rem; max-height: 21rem; overflow-y: auto; }
.pneu-estoque-card {
  display: flex; align-items: center; gap: 0.65rem;
  background: var(--engrena-surface-alt);
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius-sm);
  padding: 0.45rem 0.6rem;
  min-width: 0; text-decoration: none; color: inherit;
  transition: border-color 150ms ease;
}
.pneu-estoque-card:hover { border-color: var(--engrena-primary); }
.pneu-estoque-card-info { min-width: 0; flex: 1 1 auto; line-height: 1.3; }
/* §9 — identificadores e medidas não quebram verticalmente */
.pneu-estoque-card-codigo { font-weight: 700; font-size: 0.84rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Marca/modelo quebra em vez de truncar: "Continental Conti Hybrid HS3"
   estourava por apenas 3px e perdia o modelo, que é o que distingue um SKU
   do outro na hora de escolher o pneu. O código interno acima continua
   truncando — ele é identificador, não pode quebrar em duas linhas. */
.pneu-estoque-card-detalhe { font-size: 0.73rem; color: var(--text-muted); overflow-wrap: anywhere; line-height: 1.3; }
.pneu-estoque-card-medida { font-size: 0.7rem; color: var(--text-muted); opacity: 0.8; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pneu-estoque-vazio { color: var(--text-muted); font-size: 0.85rem; text-align: center; padding: 1rem 0.5rem; }

/* ---- (13) Legenda compacta ---------------------------------------------- */
.pneu-chassi-legenda {
  display: flex; flex-wrap: wrap; gap: 0.45rem 1.1rem;
  padding: 0.7rem 0 0.2rem; margin-top: 0.5rem;
  border-top: 1px solid var(--engrena-border);
  font-size: 0.74rem; color: var(--text-muted);
}
.pneu-chassi-legenda-item { display: flex; align-items: center; gap: 0.4rem; }
.pneu-chassi-legenda-marca { width: 0.8rem; height: 0.8rem; border-radius: 3px; flex: 0 0 auto; }
.legenda-ocupada { background: var(--engrena-accent); }
.legenda-vazia { background: none; border: 2px dashed var(--engrena-primary); }
.legenda-inativa { background: var(--engrena-grey); opacity: 0.5; }
.legenda-selecionada { background: none; border: 2px solid var(--engrena-primary); }
/* 3G-H2.8 — segunda linha de legenda, só para as faixas da barra de banda.
   Sem borda superior própria: ela é continuação da legenda de estados, não
   um bloco novo. */
.pneu-chassi-legenda-banda { border-top: none; padding-top: 0.1rem; margin-top: 0; }
.pneu-chassi-legenda-rotulo { font-weight: 600; }
/* Amostra no formato da própria barra (larga e baixa), não quadrada — assim a
   associação com o desenho é imediata. */
.pneu-chassi-legenda-barra { width: 1.5rem; height: 0.42rem; border-radius: 3px; flex: 0 0 auto; }
.legenda-banda-ok { background: var(--engrena-primary); opacity: 0.85; }
.legenda-banda-alerta { background: var(--warning); opacity: 0.95; }
.legenda-banda-critico { background: var(--danger); }

.pneu-chassi-orientacao { display: none; }

/* ---- (13b) Modo configuração (H2.1.6) ----------------------------------- */
/* A configuração passou de "cards de CRUD" para editor visual: o chassi é o
   objeto, a lateral dá contexto e ações do item SELECIONADO. §66/§67 — quase
   nenhuma borda: separação vem de espaço, fundo e estado de seleção. */
.pn-eixo-alvo {
  fill: transparent; cursor: pointer;
  transition: fill 140ms ease;
}
.pn-eixo-alvo:hover { fill: rgba(30, 136, 229, 0.07); }
.pn-eixo-alvo-sel { fill: rgba(30, 136, 229, 0.12); }
.pn-eixo-alvo:focus { outline: none; }
.pn-eixo-alvo:focus-visible {
  fill: rgba(30, 136, 229, 0.12);
  stroke: var(--engrena-primary); stroke-width: 2; stroke-dasharray: 6 4;
}

.pneu-config-estrutura { display: flex; flex-direction: column; gap: 0.15rem; }
.pneu-estrutura-item {
  display: grid; grid-template-columns: 1fr auto; align-items: center;
  gap: 0.15rem 0.5rem; width: 100%; text-align: left;
  background: transparent; border: none; border-radius: var(--radius-sm);
  padding: 0.5rem 0.6rem; cursor: pointer; color: var(--text-primary);
  height: auto; font: inherit;
}
.pneu-estrutura-item:hover { background: var(--engrena-surface-alt); }
.pneu-estrutura-item-sel { background: rgba(30, 136, 229, 0.13); }
.pneu-estrutura-nome { font-size: 0.88rem; font-weight: 700; white-space: nowrap; }
.pneu-estrutura-sub {
  grid-column: 1 / 2; font-size: 0.74rem; color: var(--text-muted); font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pneu-estrutura-badge { grid-row: 1 / 3; align-self: center; font-size: 0.66rem; }
.pneu-estrutura-add {
  margin-top: 0.4rem; width: 100%; height: 2.3rem;
  font-size: 0.84rem;
}

.pneu-config-kicker {
  margin: 0; font-size: 0.7rem; font-weight: 600; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.05em;
}
.pneu-config-titulo {
  margin: 0.1rem 0 0.7rem; font-size: 1.15rem; font-weight: 700;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Propriedades como lista de definição: sem card, sem borda por item (§67) */
.pneu-config-props { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem 0.8rem; margin: 0 0 0.9rem; }
.pneu-config-props > div { min-width: 0; }
.pneu-config-props dt { font-size: 0.68rem; color: var(--text-muted); margin-bottom: 0.1rem; }
.pneu-config-props dd {
  margin: 0; font-size: 0.85rem; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pneu-config-inativa { color: var(--engrena-grey); }

.pneu-config-rotulo {
  margin: 0 0 0.35rem; font-size: 0.68rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted);
}
.pneu-config-chips { display: flex; flex-wrap: wrap; gap: 0.3rem; margin-bottom: 0.9rem; }
.pneu-config-chip {
  background: var(--engrena-surface-alt); border: none; color: var(--text-primary);
  border-radius: 999px; padding: 0.25rem 0.65rem; height: auto;
  font-size: 0.76rem; font-weight: 700; cursor: pointer; white-space: nowrap;
  font-family: inherit;
}
.pneu-config-chip:hover { background: rgba(30, 136, 229, 0.18); }
.pneu-config-chip-inativa { color: var(--engrena-grey); text-decoration: line-through; }

.pneu-config-acoes { display: flex; flex-direction: column; gap: 0.45rem; }
.pneu-config-acoes button { height: 2.4rem; width: 100%; }
/* §30 — inativar não fica gritando na tela: entra atrás de um disclosure. */
.pneu-config-mais { margin-top: 0.7rem; }
.pneu-config-mais > summary {
  cursor: pointer; font-size: 0.76rem; color: var(--text-muted);
  list-style: none; padding: 0.2rem 0;
}
.pneu-config-mais > summary::-webkit-details-marker { display: none; }
.pneu-config-mais > summary::after { content: ' ▾'; }
.pneu-config-mais[open] > summary::after { content: ' ▴'; }
.pneu-config-mais button { width: 100%; height: 2.3rem; margin-top: 0.35rem; }

/* ---- Histórico do pneu (migration_077) ---------------------------------- */
/* Timeline vertical com fio à esquerda. Somente leitura — é auditoria. */
.pneu-historico { list-style: none; margin: 0; padding: 0 0 0 1rem; border-left: 2px solid var(--engrena-border); }
.pneu-historico-item { position: relative; padding: 0 0 1.1rem 0.9rem; }
.pneu-historico-item:last-child { padding-bottom: 0; }
.pneu-historico-item::before {
  content: ''; position: absolute; left: -1.42rem; top: 0.3rem;
  width: 0.7rem; height: 0.7rem; border-radius: 50%;
  background: var(--engrena-primary); border: 2px solid var(--engrena-surface);
}
.pneu-historico-cabecalho { display: flex; justify-content: space-between; gap: 0.7rem; flex-wrap: wrap; }
.pneu-historico-acao { font-weight: 700; font-size: 0.88rem; }
.pneu-historico-data { font-size: 0.76rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.pneu-historico-autor { font-size: 0.76rem; color: var(--text-muted); margin-top: 0.1rem; overflow-wrap: anywhere; }
.pneu-historico-selo-tecnico { margin-left: 0.5rem; font-size: 0.66rem; padding: 0.1rem 0.45rem; vertical-align: middle; }
.pneu-historico-detalhe { font-size: 0.78rem; margin-top: 0.25rem; }
/* Justificativa recuada e citada: é texto que alguém escreveu, não campo. */
.pneu-historico-justificativa {
  font-size: 0.78rem; margin-top: 0.3rem; padding: 0.4rem 0.55rem;
  background: var(--engrena-surface-alt); border-radius: var(--radius-sm);
  border-left: 2px solid var(--engrena-border); line-height: 1.4;
}

/* ---- Estimativa de vida restante do pneu (3G-H2.5) ---------------------- */
/* Neutro de propósito: é uma projeção, não um alerta. Pintar de vermelho ou
   verde sugeriria um julgamento ("está bom"/"está ruim") que só a política de
   troca da empresa pode fazer — e ela ainda não existe no modelo. */
.pneu-proj {
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.7rem;
  background: var(--engrena-surface);
}
.pneu-proj-linha { display: flex; flex-direction: column; gap: 0.1rem; }
.pneu-proj-linha + .pneu-proj-linha {
  margin-top: 0.5rem; padding-top: 0.5rem;
  border-top: 1px solid var(--engrena-border);
}
.pneu-proj-valor {
  font-size: 1.1rem; font-weight: 700; color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}
.pneu-proj-detalhe { font-size: 0.72rem; color: var(--text-muted); line-height: 1.35; }
.pneu-proj-premissa {
  margin: 0.55rem 0 0; font-size: 0.7rem; line-height: 1.4;
  color: var(--text-muted);
}
/* Único caso com cor: o pneu já alcançou o piso legal — aí não é projeção,
   é um fato que exige ação. */
.pneu-proj-atingiu {
  border-color: var(--warning);
  background: color-mix(in srgb, var(--warning) 12%, var(--engrena-surface));
}
.pneu-proj-atingiu .pneu-proj-premissa { color: var(--text); font-weight: 600; }

/* ---- Compatibilidade de medida pneu x eixo (3G-H2.4) -------------------- */
/* Aviso, não erro: o formulário continua utilizável (basta escolher um pneu
   compatível), então usa a paleta de atenção e não a de falha. */
/* Usa o token --warning já existente (definido nos dois temas), no mesmo
   padrão de .ajuda-alerta: a cor semântica fica na borda e no fundo, e o
   texto herda --text — assim continua legível em claro e escuro sem uma
   segunda paleta pra manter. */
.pneu-aviso {
  margin: 0.4rem 0 0; padding: 0.55rem 0.7rem;
  font-size: 0.8rem; line-height: 1.45;
  border-radius: 6px;
  border: 1px solid var(--warning);
  background: color-mix(in srgb, var(--warning) 12%, var(--engrena-surface));
  color: var(--text);
}
/* Texto de apoio abaixo de um campo de formulário. */
.pneu-campo-ajuda {
  display: block; margin-top: 0.25rem;
  font-size: 0.75rem; line-height: 1.4; color: var(--text-muted);
  font-weight: 400;
}
/* Opção de pneu barrada pela medida: visível (para não virar chamado de
   "sumiu"), legível, e claramente indisponível. */
select option:disabled { color: var(--text-muted); font-style: italic; }

/* ---- Sulco de entrada no modal de Aplicar pneu -------------------------- */
/* Classe própria (e não .pneu-config-mais) de propósito: aquela regra estica
   TODO button descendente pra 100% de largura, o que arrebentaria o "Remover"
   de cada linha de ponto de sulco. */
.pneu-sulco-opcional { margin-top: 0.2rem; }
.pneu-sulco-opcional > summary {
  cursor: pointer; font-size: 0.82rem; color: var(--text-muted);
  list-style: none; padding: 0.25rem 0;
}
.pneu-sulco-opcional > summary::-webkit-details-marker { display: none; }
.pneu-sulco-opcional > summary::after { content: ' ▾'; }
.pneu-sulco-opcional[open] > summary::after { content: ' ▴'; }
.pneu-sulco-ajuda {
  font-size: 0.76rem; color: var(--text-muted);
  margin: 0.1rem 0 0.6rem; line-height: 1.4;
}
#aplicar-sulco-adicionar-btn { margin-top: 0.35rem; }

/* ---- (13d) Desgaste da banda ------------------------------------------- */
/* Cor NEUTRA de propósito: sem sulco mínimo cadastrado, pintar de vermelho
   seria afirmar "troque este pneu" a partir de um limite que ninguém definiu.
   A barra informa o consumo; o julgamento fica com quem opera. */
/* 3G-H2.6 — classe renomeada de .pn-banda-uso para .pn-banda-restante junto
   com a inversão do sentido da barra. Manter o nome antigo apontando para o
   significado oposto seria a armadilha clássica de leitura de código daqui a
   seis meses. O trilho é a borracha original; o preenchimento é o que resta. */
.pn-banda-trilho { fill: rgba(139, 156, 173, 0.30); }
.pn-banda-restante { fill: var(--engrena-primary); opacity: 0.85; }
/* 3G-H2.8 — faixas de cor por borracha restante. Tokens semânticos já
   definidos nos dois temas, então o contraste acompanha claro/escuro sem uma
   segunda paleta. A opacidade sobe nas faixas de atenção: quanto pior o pneu,
   mais a barra chama atenção, mesmo sendo mais curta. */
.pn-banda-alerta { fill: var(--warning); opacity: 0.95; }
.pn-banda-critico { fill: var(--danger); opacity: 1; }

/* ---- (13c) Arrastar e soltar pneus -------------------------------------- */
.pn-roda-ocupada, .pneu-estoque-card { touch-action: none; }
.pn-arrastando, .pn-arrastando * { cursor: grabbing !important; user-select: none; }
/* O fantasma leva a figura do pneu junto do código: a sensação é de estar
   carregando a peça, não arrastando uma etiqueta. Levemente inclinado, como
   algo suspenso pela mão. */
.pn-ghost {
  position: fixed; top: 0; left: 0; z-index: 9999; pointer-events: none;
  display: flex; align-items: center; gap: 0.4rem;
  background: var(--engrena-primary); color: #fff;
  padding: 0.28rem 0.6rem 0.28rem 0.35rem; border-radius: 999px;
  font-size: 0.76rem; font-weight: 700; white-space: nowrap;
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.42);
  transform-origin: top left;
  rotate: -4deg;
}
.pn-ghost-pneu { width: 20px; height: 26px; flex: 0 0 auto; display: block; }
/* Alvo possível: anel tracejado discreto. Alvo sob o cursor: preenchido. */
.pn-alvo-valido .pn-alvo {
  fill: rgba(30, 136, 229, 0.10);
  stroke: var(--engrena-primary); stroke-width: 2.2; stroke-dasharray: 7 5;
}
.pn-alvo-ativo .pn-alvo {
  fill: rgba(30, 136, 229, 0.26);
  stroke: var(--engrena-primary); stroke-width: 3.2; stroke-dasharray: none;
}
.pn-alvo-valido-estoque {
  outline: 2px dashed var(--engrena-primary); outline-offset: 4px; border-radius: var(--radius-sm);
}
.pn-alvo-valido-estoque.pn-alvo-ativo {
  outline-style: solid; background: rgba(30, 136, 229, 0.08);
}
@media (prefers-reduced-motion: reduce) { .pn-ghost { box-shadow: none; } }

/* ---- (14) Skeleton + motion --------------------------------------------- */
.pneu-skeleton {
  background: linear-gradient(90deg, var(--engrena-surface-alt) 25%, var(--engrena-border) 37%, var(--engrena-surface-alt) 63%);
  background-size: 400% 100%; animation: pneuSkeleton 1.4s ease infinite; border-radius: var(--radius-sm);
}
@keyframes pneuSkeleton { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
@media (prefers-reduced-motion: reduce) {
  .pneu-skeleton { animation: none; }
  .pneu-chassi-painel { animation: none; }
  .pn-roda { transition: none; }
  .pn-roda:hover:not(.pn-roda-inativa) { transform: none; }
}

/* ---- (15) Responsivo ---------------------------------------------------- */
/* §16 — em telas largas o card do chassi cresce e o teto de 860px deixava o
   desenho ocupando só ~70% dele. O teto sobe junto para o conjunto continuar
   dominando a coluna. */
@media (min-width: 1600px) {
  .pneu-chassi-svg { max-width: 1000px; }
}
@media (max-width: 1420px) {
  .pneu-chassi-svg { max-width: 760px; }
}
/* Mobile (§75/§76): em vez de rolagem horizontal, o desenho ESCALA para caber
   e os rótulos longos saem — o detalhe do pneu vem no painel logo abaixo. Os
   textos que ficam sobem de tamanho em unidades de viewBox para continuarem
   legíveis depois da redução de escala. */
@media (max-width: 760px) {
  .pneu-chassi-central { padding: 0.8rem 0.35rem 0.5rem; }
  .pneu-chassi-svg { min-width: 0; }
  .pneu-cab-titulo { font-size: 1.15rem; }
  .pneu-acoes-grid { grid-template-columns: 1fr; }
  .pneu-carac-grid { grid-template-columns: 1fr; }

  /* Tamanhos em unidades de viewBox. O viewBox encolheu de 1000 fixo para a
     largura real da geometria (~780–860), então cada unidade já renderiza
     maior — os valores caíram na mesma proporção para não estourarem. */
  .pn-cod-pos { font-size: 26px; }
  .pn-cod-pneu, .pn-cod-vazio, .pn-cod-inativo { display: none; }
  .pn-eixo-label-titulo { font-size: 23px; }
  .pn-eixo-label-linha { display: none; }
  .pn-pill-txt, .pn-marcha-txt { font-size: 19px; }
  .pn-pill { display: none; }
  .pn-marcha-longo { display: none; }
  .pn-marcha-curto { display: block; }

  /* §51/§52 — a miniatura do painel também precisa encolher no mobile; sem
     isto ela herdaria a altura do desktop e voltaria a dominar o painel. */
  .pneu-mini-detalhe { height: 72px; }
}

/* ============================================================================
   Etapa 3G-H2.1.1 — fechamento objetivo. Organizado por bloco na ordem do
   mandato §55: (1) page/KPI, (2) toolbar, (3) formulários/modais locais,
   (4) wizard, (5) chassi/painel, (6) responsivo, (7) motion.
   Continua namespaced .pneu-*, zero token novo, zero classe global alterada.
   ============================================================================ */

/* ---- (1) Page / KPI ------------------------------------------------------ */
/* Colunas de largura FIXA (não 1fr): com um único KPI, o .kpi-grid original
   esticava o card por toda a largura da tela — visualmente fraco (§3). */

/* ---- (2) Toolbar --------------------------------------------------------- */
/* Ações do chassi na mesma linha de base: mesma altura, mesmo alinhamento,
   primária e secundárias juntas (§23/§35). */
.pneu-toolbar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.pneu-toolbar > button { height: 2.3rem; }

/* ---- (3) Formulários e modais locais ------------------------------------- */
.pneu-modal-helper {
  margin: -0.5rem 0 1rem;
  font-size: 0.8rem;
  color: var(--text-muted);
  line-height: 1.45;
}
/* Grid de 2 e 3 colunas com larguras iguais e labels alinhados — substitui o
   .form-row flex nos formulários locais de Pneus, onde a proporção por peso
   deixava campos desiguais (§8/§23). */
.pneu-form-grid-2,
.pneu-form-grid-3 {
  display: grid;
  gap: 0.9rem 1rem;
  margin-bottom: 1rem;
}
.pneu-form-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.pneu-form-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.pneu-form-grid-2 > label,
.pneu-form-grid-3 > label,
.pneu-campo-full {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  font-size: 0.8rem;
  color: var(--text-muted);
  min-width: 0;
}
/* !important pelo mesmo motivo documentado em .form-row: o seletor global de
   input usa dois :not(), vencendo em especificidade. */
.pneu-form-grid-2 > label input,
.pneu-form-grid-2 > label select,
.pneu-form-grid-3 > label input,
.pneu-form-grid-3 > label select,
.pneu-campo-full input,
.pneu-campo-full select,
.pneu-campo-full textarea {
  width: 100%;
  min-width: 0 !important;
}
/* Altura idêntica entre input e select: o select renderiza ~2px mais alto que
   o input com o mesmo padding (altura de linha nativa do controle), o que
   deixava a linha 2 do grid desalinhada da linha 1 (§25). */
.pneu-form-grid-2 > label input:not([type="checkbox"]),
.pneu-form-grid-2 > label select,
.pneu-form-grid-3 > label input:not([type="checkbox"]),
.pneu-form-grid-3 > label select,
.pneu-campo-full input:not([type="checkbox"]),
.pneu-campo-full select {
  height: 2.35rem;
  padding-top: 0;
  padding-bottom: 0;
}
/* Observações e afins: label ACIMA, campo em largura total — antes o textarea
   ficava inline ao lado do texto do label (§10). */
.pneu-campo-full { margin-bottom: 1rem; }
.pneu-label-opcional { color: var(--text-muted); font-weight: 400; }

/* Checkbox com título + helper próprios, não uma frase solta quebrando no
   meio do formulário (§9/§26). */
.pneu-check-bloco {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  padding: 0.75rem 0.85rem;
  margin-bottom: 1rem;
  background: var(--engrena-surface-alt);
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius-sm);
}
.pneu-check-bloco input[type="checkbox"] {
  width: auto;
  min-width: 0;
  margin-top: 0.15rem;
  accent-color: var(--engrena-primary);
  flex: 0 0 auto;
}
.pneu-check-titulo { display: block; font-size: 0.85rem; font-weight: 600; color: var(--text-primary); cursor: pointer; }
.pneu-check-helper { margin: 0.2rem 0 0; font-size: 0.76rem; color: var(--text-muted); line-height: 1.4; }

/* Divisor semântico de seção dentro de um formulário longo (§19-22). */
.pneu-form-secao {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  border-top: 1px solid var(--engrena-border);
  padding-top: 0.85rem;
  margin: 0.5rem 0 0.8rem;
}
.pneu-form-secao:first-child { border-top: none; padding-top: 0; margin-top: 0; }

/* ---- (4) Wizard ---------------------------------------------------------- */
/* Card de opção clicável (origem, produto) — precisa PARECER selecionável e
   ter estado de seleção óbvio (§16/§34-35). */
.pneu-opcao-card {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  width: 100%;
  text-align: left;
  padding: 0.7rem 0.85rem;
  background: var(--engrena-surface);
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-family: inherit;
  font-weight: 400;
  font-size: 0.85rem;
  cursor: pointer;
  transition: border-color 150ms ease, background-color 150ms ease;
}
.pneu-opcao-card:hover { filter: none; border-color: var(--engrena-primary); background: var(--engrena-surface-alt); }
.pneu-opcao-card-corpo { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; flex: 1 1 auto; }
.pneu-opcao-card-titulo { font-weight: 600; }
.pneu-opcao-card-meta { font-size: 0.76rem; color: var(--text-muted); }
.pneu-opcao-card-check {
  flex: 0 0 auto;
  width: 1.3rem; height: 1.3rem;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 0.75rem; font-weight: 700;
  border: 1px solid var(--engrena-border);
  color: transparent;
}
.pneu-opcao-selecionada { border-color: var(--engrena-primary); background: var(--engrena-surface-alt); }
.pneu-opcao-selecionada .pneu-opcao-card-check { background: var(--engrena-primary); border-color: var(--engrena-primary); color: #fff; }

/* Bloco de estado (controle individual necessário / ativado / bloqueado) —
   ícone + título + texto + CTA, em vez de parágrafo solto com botão (§17). */
.pneu-estado-bloco {
  display: flex;
  align-items: flex-start;
  gap: 0.8rem;
  padding: 1rem;
  background: var(--engrena-surface-alt);
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius-sm);
}
.pneu-estado-icone { flex: 0 0 auto; font-size: 1.2rem; line-height: 1.3; }
.pneu-estado-titulo { margin: 0; font-size: 0.9rem; font-weight: 600; color: var(--text-primary); }
.pneu-estado-texto { margin: 0.25rem 0 0; font-size: 0.82rem; color: var(--text-muted); line-height: 1.5; }
.pneu-estado-ok { border-color: var(--engrena-accent); }
.pneu-estado-ok .pneu-estado-icone { color: var(--engrena-accent); font-weight: 700; }
.pneu-estado-bloqueado { border-color: var(--danger); }

/* Resumo da confirmação agrupado por seção (§24). Cada grupo é seu próprio
   card com borda — antes as 4 seções eram só um título seguido de linhas
   dentro de uma grade comum, sem nada separando "Origem e produto" de
   "Identificação" além do espaço; ficavam lidas como um bloco só. */
.pneu-resumo-grade {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 0.9rem;
}
.pneu-resumo-grupo {
  background: var(--engrena-surface-alt);
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius);
  padding: 0.85rem 1rem;
}
.pneu-resumo-grupo-titulo {
  font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text-muted); margin-bottom: 0.6rem;
}
/* Itens empilhados (rótulo em cima, valor embaixo) em vez de lado a lado —
   sobrevive a qualquer combinação de rótulo curto/valor longo sem espremer. */
.pneu-resumo-itens { display: flex; flex-direction: column; gap: 0.55rem; }
.pneu-resumo-pendente {
  margin: 0.9rem 0 0;
  padding: 0.6rem 0.75rem;
  font-size: 0.78rem;
  color: var(--text-muted);
  background: var(--engrena-surface-alt);
  border-left: 3px solid var(--warning);
  border-radius: var(--radius-sm);
  line-height: 1.45;
}

/* Stepper mobile — só aparece abaixo de 560px (§25). */
.pneu-stepper-mobile { display: none; }
.pneu-stepper-mobile-contador { font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--engrena-primary); }
.pneu-stepper-mobile-titulo { display: block; font-size: 0.95rem; font-weight: 600; margin-top: 0.15rem; }

/* ---- (5) Chassi / painel ------------------------------------------------- */
/* Código do pneu completo sempre que couber — truncar "PN-0000…" por padrão
   destrói a identificação (§31). O title do botão continua como fallback. */

/* Condição sem aferição: bloco próprio, não uma linha perdida (§33). */


/* ---- (6) Responsivo ------------------------------------------------------ */
@media (max-width: 720px) {
  .pneu-form-grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .pneu-form-grid-2,
  .pneu-form-grid-3 { grid-template-columns: 1fr; }
  .pneu-stepper { display: none; }
  .pneu-stepper-mobile { display: block; margin-bottom: 0.9rem; }
}

/* ---- Campos de leitura com referência e variação (odômetro/horímetro) ----- */
/* A referência é o valor do EQUIPAMENTO, fonte única alimentada por
   Abastecimentos e por Pneus. A variação existe porque o backend barra leitura
   menor, mas não tem trava para leitura absurdamente maior — mostrar o delta
   deixa o erro de digitação visível sem inventar um limite de salto. */
.leitura-campo { display: flex; flex-direction: column; }
.leitura-rotulo {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.6rem; flex-wrap: wrap;
}
.leitura-ref {
  font-size: 0.72rem; font-weight: 500; color: var(--text-muted);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.leitura-ref-vazia { font-style: italic; opacity: 0.75; }
.leitura-delta {
  display: block; min-height: 1.05rem; margin-top: 0.25rem;
  font-size: 0.73rem; line-height: 1.3; color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
/* 3G-H2.8 — a dica de variação só existe depois que o usuário digita. Enquanto
   está vazia, o min-height acima reservava 21px em branco, e somados aos 16px
   da .form-row davam 43px entre o campo de leitura e o de Pressão — o dobro do
   espaçamento usado entre os demais campos. Vazia, a dica some; quando ganha
   texto volta com a reserva original. O deslocamento acontece só enquanto se
   digita naquele campo, e é de uma linha. */
.leitura-delta:empty { display: none; }
.leitura-delta-avanco { color: var(--text-muted); }
.leitura-delta-regressiva { color: #c2410c; font-weight: 500; }
:root[data-theme="dark"] .leitura-delta-regressiva { color: #fb923c; }

/* ---- Ficha do pneu: densidade e hierarquia ------------------------------- */
/* Problema que resolve: cada seção era um .card branco contendo um
   .ativo-contexto-card cinza — dois contêineres para o mesmo conteúdo, com
   uma faixa branca sobrando embaixo do cinza. Aqui o cinza vira o corpo da
   seção, encostado nas bordas internas do card, e some a faixa órfã. */
#detalhe-conteudo .card-titulo {
  font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--text-muted); margin-bottom: 0.55rem;
}
#detalhe-resumo, #detalhe-localizacao,
#detalhe-identificacao-view > .ativo-contexto-card { margin-bottom: 0; }

/* Grade fluida: as colunas se acomodam à largura real em vez de estourar em
   5 e jogar a sexta sozinha na linha de baixo. */
.ativo-contexto-card {
  display: grid; gap: 0.85rem 1.4rem;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
}
.ativo-contexto-item-largo { grid-column: 1 / -1; }
.ativo-contexto-item-largo .ativo-contexto-valor { max-width: 62ch; }

/* Ações da seção deixam de flutuar soltas no rodapé do card. */
#identificacao-abrir-btn, #observacao-abrir-btn { margin-top: 0.9rem; }

@media (max-width: 640px) {
  .ativo-contexto-card { grid-template-columns: 1fr 1fr; }
}

/* ==========================================================================
   Pneus — padrão de espaçamento dos cards
   --------------------------------------------------------------------------
   CAUSA RAIZ: a classe global `.card` define fundo, borda, raio e sombra e
   NENHUM padding. Cada tela do sistema depende de alguém lembrar de aplicar
   padding inline; onde esqueceram, título e botão ficam a 1px da borda.
   Medido nesta tela: 5 de 27 cards com padding 0 e folga mínima de 1px.

   Corrigido com escopo NO MÓDULO DE PNEUS, não em `.card` global — mexer na
   classe base alteraria todas as telas do ERP de uma vez, o que está fora do
   que foi pedido e não teria como ser verificado aqui.

   Padding inline existente continua vencendo (especificidade de style
   attribute), então cards já espaçados não ganham padding dobrado.
   ========================================================================== */
#secao-lista > .card,
#secao-detalhe .card,
#secao-chassi .card,
#detalhe-conteudo .card {
  padding: 1.15rem 1.3rem 1.25rem;
}

/* O rodapé de ações deixa de flutuar colado no fim do card: ganha uma
   separação real do conteúdo acima, alinhada à esquerda como o resto. */
#detalhe-conteudo .card > button.secondary,
#detalhe-conteudo .card > form > .modal-footer {
  margin-top: 1rem;
}
#detalhe-conteudo .card > button.secondary { margin-bottom: 0; }

/* Abas com aparência de aba, não de fila de botões soltos. */
#detalhe-conteudo .card + .card { margin-top: 1rem; }

@media (max-width: 640px) {
  #secao-lista > .card,
  #secao-detalhe .card,
  #secao-chassi .card,
  #detalhe-conteudo .card {
    padding: 1rem 1.05rem 1.1rem;
  }
}



/* ---- Instrumentos de medição (odômetro, horímetro, pressão) -------------
   Os três ficam numa faixa só: é uma passagem única do técnico no pneu, com os
   três instrumentos na mão. Antes a pressão morava num bloco separado abaixo,
   o que obrigava a percorrer o modal para completar uma medição só. */
.instr-faixa {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin-bottom: 0.5rem;
}
/* display:contents dissolve o wrapper: os campos viram itens diretos da faixa,
   sem perder os ids que o JS usa para mostrar/esconder cada grupo. */
.instr-sub { display: contents; }
.instr-sub.hidden { display: none; }
.instr-campo {
  flex: 1 1 158px;
  min-width: 0;
  margin: 0;
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--engrena-border);
  border-radius: 8px;
  background: var(--engrena-surface);
  /* space-between encosta os inputs na base: a pressão não tem a linha de
     'Última leitura' que odômetro e horímetro têm, e sem isso o campo dela
     flutuaria acima dos vizinhos na mesma faixa. */
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.instr-campo input[type="text"].instr-valor {
  width: 100%;
  /* O min-width global de 140px estoura a faixa em telas muito estreitas. */
  min-width: 0;
  box-sizing: border-box;
  margin: 0.25rem 0 0;
  padding: 0.32rem 0.5rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}
/* O ícone imita o mostrador real para que o campo seja achado pelo instrumento
   antes de ser lido pelo rótulo. */
.instr-icone {
  width: 17px;
  height: 17px;
  flex: 0 0 auto;
  color: var(--engrena-primary);
  vertical-align: -3px;
  margin-right: 0.3rem;
}
.instr-campo .leitura-rotulo { align-items: center; }
.instr-campo .leitura-nome { display: inline-flex; align-items: center; }

/* ---- Mapa de sulcos P1/P2/P3 (migration_079) ---------------------------
   O pneu fica DO LADO dos campos, não acima: cada ranhura desenhada aponta,
   por uma seta, para o campo daquela medida. O técnico está com o paquímetro
   numa ranhura específica e precisa achar o campo dela sem contar de cima
   para baixo.

   O alinhamento entre ranhura e campo é geométrico, não ajustado a olho:
   .sulco-mapa-pontos tem três linhas de grid IGUAIS (1fr cada), então seus
   centros caem exatamente em 1/6, 3/6 e 5/6 da altura; o SVG, estirado à mesma
   altura com preserveAspectRatio="none", tem as ranhuras nessas mesmas frações.
   Vale em qualquer altura — inclusive quando um aviso longo estica as linhas.

   A borracha é preta nos dois temas: cor fixa, não token. Um pneu cinza-claro
   no tema claro não se parece com um pneu, e o desenho existe justamente para
   ser reconhecido de relance. */
.sulco-mapa {
  --pneu-borracha: #24272c;
  --pneu-ranhura: #0e1013;
  --pneu-aresta: #3b414a;
  display: grid;
  grid-template-columns: 92px 1fr;
  gap: 0 0.35rem;
  align-items: stretch;
  padding: 0.5rem;
  border: 1px solid var(--engrena-border);
  border-radius: 10px;
  background: var(--engrena-bg);
}
.sulco-mapa-pneu {
  position: relative;
  min-height: 208px;
}
.sulco-mapa-svg { display: block; width: 100%; height: 100%; }
.sulco-mapa-lado {
  position: absolute;
  left: 0;
  right: 0;
  text-align: center;
  font-size: 0.53rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  color: rgba(255, 255, 255, 0.62);
  pointer-events: none;
}
.sulco-mapa-lado-topo { top: 5px; }
.sulco-mapa-lado-base { bottom: 5px; }
/* O código sobre a ranhura. Fica em HTML, e não dentro do SVG, porque o SVG é
   estirado sem manter proporção — texto ali sairia deformado. Encosta na borda
   direita para a seta parecer sair de dentro do próprio marcador. */
.sulco-mapa-marca {
  position: absolute;
  right: -5px;
  transform: translateY(-50%);
  min-width: 28px;
  padding: 0.1rem 0.28rem;
  border-radius: 5px;
  background: var(--engrena-primary);
  color: #fff;
  font-size: 0.66rem;
  font-weight: 700;
  line-height: 1.25;
  text-align: center;
  box-shadow: 0 1px 5px rgba(0, 0, 0, 0.5);
  pointer-events: none;
}
.sulco-mapa-marca-off { background: #6b727c; }

.sulco-mapa-pontos { display: grid; grid-template-rows: repeat(3, 1fr); }
.sulco-linha {
  display: flex;
  align-items: center;
  min-width: 0;
  padding: 2px 0;
}
/* A seta que liga a ranhura ao campo. Centrada na linha por align-items, o que
   a põe na mesma fração de altura da ranhura correspondente. */
.sulco-seta {
  position: relative;
  flex: 0 0 14px;
  height: 2px;
  background: var(--engrena-primary);
}
.sulco-seta::after {
  content: '';
  position: absolute;
  right: -1px;
  top: -4px;
  border-left: 7px solid var(--engrena-primary);
  border-top: 5px solid transparent;
  border-bottom: 5px solid transparent;
}
.sulco-linha-off .sulco-seta { background: var(--engrena-grey); opacity: 0.5; }
.sulco-linha-off .sulco-seta::after { border-left-color: var(--engrena-grey); }
/* Cada ponto é um cartão fechado: sem isso o texto de referência de um ponto
   flutua logo acima do título do ponto seguinte e parece pertencer a ele. */
.sulco-linha-corpo {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.3rem 0.45rem;
  border: 1px solid var(--engrena-border);
  border-radius: 7px;
  background: var(--engrena-surface);
}
.sulco-linha-invalida .sulco-linha-corpo { border-color: var(--danger); }
.sulco-linha-off .sulco-linha-corpo { background: transparent; border-style: dashed; }
.sulco-linha-titulo { font-size: 0.75rem; font-weight: 600; color: var(--text-primary); }
.sulco-linha-campo { display: flex; align-items: center; gap: 0.3rem; }
.sulco-mapa .sulco-linha-campo input.sulco-profundidade {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
  padding: 0.24rem 0.45rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-size: 0.9rem;
  font-weight: 600;
}
.sulco-unidade { flex: 0 0 auto; font-size: 0.72rem; color: var(--text-muted); }
.sulco-remover-btn {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 1px solid var(--engrena-border);
  border-radius: 5px;
  background: transparent;
  color: var(--text-muted);
  font-size: 0.95rem;
  line-height: 1;
  cursor: pointer;
}
.sulco-remover-btn:hover:not(:disabled) { border-color: var(--danger); color: var(--danger); }
/* Desabilitado quando é o último ponto medido: uma aferição de sulco sem
   nenhuma medida não é uma aferição de sulco. O title explica o porquê. */
.sulco-remover-btn:disabled { opacity: 0.3; cursor: not-allowed; }
.sulco-linha-vazio { margin: 0; font-size: 0.72rem; color: var(--text-muted); }
.sulco-restaurar-btn {
  margin-left: 0.3rem;
  padding: 0;
  border: none;
  background: none;
  color: var(--engrena-primary);
  font-size: 0.72rem;
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
}
.sulco-linha-off .sulco-linha-titulo { color: var(--text-muted); font-weight: 500; }

/* O aviso não bloqueia o envio — o banco é quem recusa. A borda só antecipa,
   pra ninguém preencher o modal inteiro antes de descobrir. */
.sulco-ref { line-height: 1.25; margin: 0; font-size: 0.68rem; }
.sulco-ref-alerta { color: var(--danger); font-weight: 600; }

@media (max-width: 460px) {
  .sulco-mapa { grid-template-columns: 66px 1fr; padding: 0.35rem; }
  .sulco-mapa-marca { font-size: 0.6rem; min-width: 24px; padding: 0.08rem 0.2rem; }
  .sulco-seta { flex-basis: 9px; }
  .sulco-linha-corpo { padding: 0.26rem 0.35rem; }
  .instr-campo { flex-basis: 100%; }
}

/* ---- Docas de destino no chassi (3G-H2.14) ------------------------------
   Quatro alvos de soltura logo abaixo do desenho, um por destino que o backend
   aceita. Ficam sempre visíveis, e não só durante o arrasto: quem nunca
   arrastou nada precisa DESCOBRIR que o recurso existe. */
.pn-docas {
  margin-top: 0.6rem;
  padding-top: 0.6rem;
  border-top: 1px dashed var(--engrena-border);
}
.pn-docas-dica {
  margin: 0 0 0.45rem;
  font-size: 0.72rem;
  color: var(--text-muted);
}
.pn-docas-tira {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}
.pn-doca {
  flex: 1 1 118px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.15rem;
  padding: 0.5rem 0.35rem;
  border: 1.5px dashed var(--engrena-border);
  border-radius: 9px;
  background: var(--engrena-surface);
  text-align: center;
  transition: border-color 140ms ease, background-color 140ms ease, transform 140ms ease;
}
.pn-doca-icone {
  width: 26px;
  height: 26px;
  color: var(--text-muted);
  transition: color 140ms ease;
}
.pn-doca-titulo { font-size: 0.78rem; font-weight: 600; color: var(--text-primary); }
.pn-doca-ajuda { font-size: 0.66rem; color: var(--text-muted); line-height: 1.25; }
/* Durante o arrasto as docas acendem: sem isso o usuário não sabe que soltar
   ali faz alguma coisa. */
.pn-docas-ativas .pn-doca.pn-alvo-valido {
  border-style: solid;
  border-color: var(--engrena-primary);
}
.pn-docas-ativas .pn-doca.pn-alvo-valido .pn-doca-icone { color: var(--engrena-primary); }
.pn-doca.pn-alvo-ativo {
  border-color: var(--engrena-accent);
  background: var(--engrena-surface-alt);
  transform: translateY(-2px);
}
.pn-doca.pn-alvo-ativo .pn-doca-icone { color: var(--engrena-accent); }
/* Descarte é irreversível — o alvo avisa disso ao ser mirado. */
.pn-doca[data-destino="SUCATA"].pn-alvo-ativo { border-color: var(--danger); }
.pn-doca[data-destino="SUCATA"].pn-alvo-ativo .pn-doca-icone { color: var(--danger); }

/* ---- Arrasto por toque -------------------------------------------------
   touch-action NÃO se aplica a elementos filhos de SVG: só elementos que geram
   caixa o respeitam, e um <g> não gera. A declaração em .pn-roda-ocupada era
   inerte — no celular o navegador assumia o gesto como rolagem e disparava
   pointercancel, matando o arrasto antes do limiar de 6px.

   A regra tem de morar na RAIZ do SVG, que é elemento substituído e a respeita.
   Fica condicionada à classe que só existe quando dá para arrastar de verdade
   (modo operação + permissão de editar), para que em leitura a rolagem sobre o
   chassi continue normal. */
.pn-chassi-arrastavel svg { touch-action: none; }

/* No celular a legenda da banda quebrava em 1+2: o rótulo e a primeira faixa
   cabiam na linha, as outras duas caíam embaixo desalinhadas. O rótulo passa a
   ocupar a linha inteira e as três faixas formam uma linha só, dividindo a
   largura por igual. */
@media (max-width: 560px) {
  .pneu-chassi-legenda-banda { column-gap: 0.5rem; row-gap: 0.25rem; }
  .pneu-chassi-legenda-banda .pneu-chassi-legenda-rotulo { flex: 1 0 100%; }
  .pneu-chassi-legenda-banda .pneu-chassi-legenda-item {
    flex: 1 1 auto;
    justify-content: flex-start;
    font-size: 0.72rem;
    white-space: nowrap;
  }
}
.legenda-curto { display: none; }
@media (max-width: 560px) {
  .legenda-longo { display: none; }
  .legenda-curto { display: inline; }
}

/* ---- Ordem de rodízio impressa (ponto 9) --------------------------------
   Papel é preto e branco e vai para o pátio: nada aqui pode depender de cor
   para ser entendido. O destaque das posições que mudam é borda grossa, não
   fundo colorido. */
.rod-print { color: #000; font-size: 11pt; }
.rod-titulo { font-size: 15pt; margin: 0 0 0.3rem; }
.rod-subtitulo { font-size: 12pt; margin: 1rem 0 0.3rem; }
.rod-cabecalho { display: flex; flex-wrap: wrap; gap: 0 1.4rem; margin-bottom: 0.8rem; font-size: 10pt; }
.rod-esquemas { display: flex; align-items: center; gap: 0.8rem; }
.rod-esquema-bloco { flex: 1 1 0; min-width: 0; }
.rod-esquema-bloco h2 { font-size: 10pt; text-transform: uppercase; letter-spacing: 0.05em; margin: 0 0 0.3rem; }
.rod-seta-bloco { font-size: 20pt; flex: 0 0 auto; }
.rod-esquema { width: 100%; border-collapse: separate; border-spacing: 3px; }
.rod-esquema td { border: 1px solid #000; padding: 3px 2px; text-align: center; vertical-align: middle; }
.rod-eixo { border: none !important; font-size: 8.5pt; font-weight: 700; white-space: nowrap; padding: 0 4px !important; }
.rod-celula { width: 20%; }
/* Borda dupla e grossa: sobrevive a fotocópia e a impressora sem tinta. */
.rod-celula-muda { border: 2.5px double #000 !important; }
.rod-pos { display: block; font-size: 8pt; text-transform: uppercase; }
.rod-pneu { display: block; font-size: 9.5pt; font-weight: 700; font-variant-numeric: tabular-nums; }
.rod-nota { font-size: 8.5pt; margin: 0.35rem 0 0; }
.rod-tabela { width: 100%; border-collapse: collapse; font-size: 10pt; }
.rod-tabela th, .rod-tabela td { border: 1px solid #000; padding: 4px 6px; text-align: left; }
/* Quadrado para o técnico marcar no pátio conforme executa. */
.rod-check { width: 70px; height: 22px; }
.rod-assinaturas { display: flex; gap: 2.5rem; margin-top: 2rem; font-size: 9.5pt; }
.rod-assinaturas > div { flex: 1 1 0; text-align: center; }
.rod-linha-assinatura { display: block; border-top: 1px solid #000; margin-bottom: 0.25rem; }
.rod-rodape { font-size: 8pt; margin-top: 1.2rem; }
/* O tema escuro do app define cor em th/td e em vários blocos. Sem forçar aqui,
   o comprovante sai com texto claro sobre branco no papel — ilegível, e só se
   descobre depois de imprimir. Vale para os dois temas. */
.rod-print, .rod-print * { background: #fff !important; color: #000 !important; }
.rod-print .rod-celula, .rod-print .rod-tabela th, .rod-print .rod-tabela td { border-color: #000 !important; }

/* Ajustes para o comprovante caber bem na página A4 do jsPDF. A largura fixa
   evita que a captura herde a largura da janela — sem isso o mesmo documento
   sai com proporções diferentes em cada monitor. */
.rod-print { width: 186mm; }
/* O par antes/depois é a peça que se lê de relance: quebrá-la entre páginas
   destruiria a comparação, que é justamente o ponto do desenho. */
.rod-esquemas, .rod-esquema-bloco, .rod-esquema { break-inside: avoid; page-break-inside: avoid; }
.rod-tabela tr, .rod-assinaturas { break-inside: avoid; page-break-inside: avoid; }
.rod-tabela thead { display: table-header-group; }
.rod-titulo { border-bottom: 2px solid #000; padding-bottom: 0.2rem; }
.rod-cabecalho { border-bottom: 1px solid #000; padding-bottom: 0.4rem; }
.rod-tabela tbody tr:nth-child(even) td { background: #f2f2f2 !important; }

/* O desenho ganha peso sobre a tabela: ele é a peça que o técnico lê de
   relance no pátio; a tabela é conferência. Antes os dois tinham corpo
   parecido e a página lia como "duas tabelas". */
.rod-print .rod-esquema { border-spacing: 4px; }
.rod-print .rod-esquema td { padding: 7px 4px; }
.rod-print .rod-pos { font-size: 9.5pt; }
.rod-print .rod-pneu { font-size: 12pt; }
.rod-print .rod-eixo { font-size: 10pt; }
.rod-print .rod-esquema-bloco h2 { font-size: 11pt; margin-bottom: 0.45rem; }
.rod-print .rod-seta-bloco { font-size: 26pt; }
.rod-print .rod-celula-muda { border-width: 3.5px !important; }
/* Tabela recua um pouco — continua legível, deixa de competir. */
.rod-print .rod-tabela { font-size: 9pt; }
.rod-print .rod-tabela th, .rod-print .rod-tabela td { padding: 3px 5px; }
.rod-print .rod-subtitulo { font-size: 11pt; }

/* ---- Ordem de rodízio v2: cabeçalho de empresa e peso visual -------------
   A seta entre os esquemas é desenhada com bordas. A versão anterior usava o
   caractere "➜" e ele saiu como "'œ" no PDF: o jsPDF embute Helvetica com
   codificação WinAnsi, que não tem esse ponto de código. Qualquer glifo fora
   do latim básico corre o mesmo risco neste documento. */
.rod-topo {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 1rem;
  padding-bottom: 0.5rem;
  border-bottom: 2.5px solid #000;
}
.rod-marca { display: flex; align-items: center; gap: 0.6rem; }
.rod-logo { width: 46px; height: 46px; object-fit: contain; flex: 0 0 auto; }
.rod-logo-vazia { border: 1px dashed #999; border-radius: 4px; }
.rod-marca-txt { display: flex; flex-direction: column; line-height: 1.35; }
.rod-marca-txt strong { font-size: 13pt; }
.rod-marca-txt span { font-size: 8.5pt; }
.rod-doc { text-align: right; display: flex; flex-direction: column; line-height: 1.3; }
.rod-doc-tipo { font-size: 8pt; text-transform: uppercase; letter-spacing: 0.12em; }
.rod-doc-nome { font-size: 14pt; }

/* Faixa de dados do veículo: rótulo pequeno em cima, valor forte embaixo —
   assim o técnico acha a placa sem ler a linha inteira. */
.rod-dados {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.6rem;
  padding: 0.5rem 0;
  margin-bottom: 0.7rem;
  border-bottom: 1px solid #000;
}
.rod-dado { display: flex; flex-direction: column; line-height: 1.3; }
.rod-dado span { font-size: 7.5pt; text-transform: uppercase; letter-spacing: 0.08em; }
.rod-dado strong { font-size: 11pt; }

/* Seta desenhada: haste + ponta em triângulo de bordas. Zero dependência de fonte. */
.rod-seta { flex: 0 0 34px; display: flex; align-items: center; justify-content: center; }
.rod-seta i {
  display: block; position: relative;
  width: 20px; height: 3px; background: #000;
}
.rod-seta i::after {
  content: ''; position: absolute; right: -2px; top: -6px;
  border-left: 12px solid #000;
  border-top: 7.5px solid transparent;
  border-bottom: 7.5px solid transparent;
}

.rod-esquema-bloco h2 { border-bottom: 1px solid #000; padding-bottom: 0.15rem; }
.rod-pneu-linha { display: flex; align-items: center; justify-content: center; gap: 3px; }
.rod-mini { width: 11px; height: 16px; flex: 0 0 auto; }
.rod-celula-vazia { border-style: dashed !important; }
.rod-vazio { display: block; font-size: 8pt; font-style: italic; }
.rod-eixo { display: table-cell; }
.rod-eixo strong { display: block; font-size: 10pt; }
.rod-eixo span { display: block; font-size: 7.5pt; }
.rod-amostra {
  display: inline-block; width: 16px; height: 10px;
  border: 3.5px solid #000; vertical-align: -1px; margin-right: 3px;
}
.rod-td-pneu { font-weight: 700; font-variant-numeric: tabular-nums; }
.rod-assinaturas { margin-top: 2.2rem; }

/* ---- Correções do PDF real (v3) ----------------------------------------
   O PDF gerado saiu CORTADO: só o primeiro esquema, com a coluna direita
   decepada, e nada depois dele. Três causas, todas de layout:

   1. Os dois esquemas lado a lado num flex row. As tabelas internas não
      encolhem abaixo do conteúdo mínimo das células, então a linha ficou mais
      larga que a página. O conversor do jsPDF NÃO quebra o que transborda —
      ele corta, e o que vinha depois se perdeu junto.
      Solução: empilhar. Sobrava metade da página em branco justamente embaixo.

   2. letter-spacing e text-transform faziam o conversor remontar o texto letra
      a letra ("V E Í C U L O"). Removidos daqui.

   3. Largura fixa em mm brigando com a largura de captura. Passa a 100%. */
.rod-print { width: 100%; }
.rod-print * { letter-spacing: normal !important; text-transform: none !important; }

.rod-print .rod-esquemas { display: block; }
.rod-print .rod-esquema-bloco { width: 100%; margin-bottom: 0.5rem; }
/* Empilhados, a seta deixa de ser lateral: vira um separador entre os dois. */
.rod-print .rod-seta { width: 100%; height: 22px; margin: 0.2rem 0 0.5rem; }
.rod-print .rod-seta i { width: 3px; height: 16px; }
.rod-print .rod-seta i::after {
  right: auto; left: -6px; top: auto; bottom: -11px;
  border-left: 7.5px solid transparent;
  border-right: 7.5px solid transparent;
  border-top: 12px solid #000;
  border-bottom: none;
}
/* Miniatura sem SVG — o conversor descartava SVG inline. */
.rod-print .rod-mini {
  display: inline-block; width: 9px; height: 13px;
  border: 1.2px solid #000; border-radius: 2px;
  vertical-align: -2px; margin-right: 3px;
}
.rod-print .rod-esquema { table-layout: fixed; }
.rod-print .rod-pneu { font-size: 10.5pt; word-break: break-all; }

/* Voltando ao motor do navegador, o CSS de impressão volta a mandar. Estas
   regras existem porque agora é @page quem pagina, não o conversor. */
@media print {
  .rod-print { width: auto; }
  .rod-print .rod-esquemas { display: block; }
  /* Sem isto o par de esquemas pode ser partido entre páginas. */
  .rod-print .rod-esquema-bloco { break-inside: avoid; page-break-inside: avoid; }
  .rod-print .rod-topo, .rod-print .rod-dados { break-inside: avoid; }
}

/* ---- Ordem de rodízio v4: uma página, eixos alinhados ------------------
   Grade fixa: todo eixo ocupa as mesmas colunas, então o dianteiro (2
   posições) fica centrado sobre o par dos traseiros (4) em vez de se
   distribuir sozinho. */
.rod-print .rod-esquema { table-layout: fixed; width: 100%; }
.rod-print .rod-celula-nula { border: none !important; background: none !important; }

/* O documento PRECISA caber em uma página. O corpo foi reduzido no conjunto —
   reduzir só uma parte deixaria a página desequilibrada. */
.rod-print { font-size: 9.5pt; }
.rod-print .rod-esquema td { padding: 4px 3px; }
.rod-print .rod-pos { font-size: 8pt; }
.rod-print .rod-pneu { font-size: 9.5pt; }
.rod-print .rod-eixo strong { font-size: 9pt; }
.rod-print .rod-eixo span { font-size: 7pt; }
.rod-print .rod-esquema-bloco h2 { font-size: 9.5pt; margin: 0 0 0.25rem; }
.rod-print .rod-esquemas { margin-bottom: 0.2rem; }
.rod-print .rod-seta { height: 14px; margin: 0.15rem 0 0.3rem; }
.rod-print .rod-seta i { height: 10px; }
.rod-print .rod-tabela { font-size: 8.5pt; }
.rod-print .rod-tabela th, .rod-print .rod-tabela td { padding: 2.5px 5px; }
.rod-print .rod-subtitulo { font-size: 10pt; margin: 0.5rem 0 0.25rem; }
.rod-print .rod-nota { font-size: 7.5pt; }
.rod-print .rod-assinaturas { margin-top: 1.2rem; font-size: 8.5pt; }
.rod-print .rod-rodape { font-size: 7pt; margin-top: 0.6rem; }
.rod-print .rod-marca-txt strong { font-size: 12pt; }
.rod-print .rod-doc-nome { font-size: 12.5pt; }
.rod-print .rod-logo { width: 38px; height: 38px; }

/* A faixa preta no rodapé do PDF era a marca d'água do app, que o @media print
   já escondia mas voltava na captura do jsPDF. */
.rod-print::before, .rod-print::after { content: none !important; }
@media print { body::after { display: none !important; } }

/* ---- Ordem de rodízio v5: margens e eixo como cabeçalho ----------------
   O documento ficava colado no canto superior esquerdo. Margem própria centra
   o bloco na folha e dá respiro nas laterais — o @page do navegador cuida da
   margem física, esta é a interna, de composição. */
.rod-print { max-width: 176mm; margin: 0 auto; padding: 4mm 0; }

/* O eixo agora encabeça a sua faixa. Fundo sólido separa uma seção da outra
   sem precisar de linha extra. */
.rod-print .rod-eixo-cab th {
  background: #000 !important;
  color: #fff !important;
  text-align: left;
  padding: 3px 7px;
  font-size: 8.5pt;
  letter-spacing: 0;
  border: 1px solid #000 !important;
}
.rod-print .rod-lados th {
  background: #e8e8e8 !important;
  font-size: 7.5pt;
  padding: 2px 6px;
  border: 1px solid #000 !important;
  text-align: center;
}
/* Cada eixo é um tbody: nunca parte entre páginas. */
.rod-print .rod-faixa-eixo { break-inside: avoid; page-break-inside: avoid; }
.rod-print .rod-esquema { border-spacing: 0; border-collapse: collapse; }
.rod-print .rod-esquema td { border: 1px solid #000; }
.rod-print .rod-celula { padding: 5px 3px; }

/* ---- Assinaturas ancoradas no pé da página ------------------------------
   Coladas logo abaixo da tabela, elas pareciam mais uma linha do documento.
   Assinatura é fecho: pertence ao rodapé, com espaço em branco antes dela.

   O bloco vira coluna flex com a altura útil da página (A4 menos as margens
   de 12mm do @page), e as assinaturas usam margin-top:auto — descem sozinhas
   até o fim, sem número mágico que quebra quando o veículo tem mais um eixo. */
.rod-print {
  display: flex;
  flex-direction: column;
  min-height: 273mm;
}
.rod-print .rod-assinaturas {
  margin-top: auto;
  padding-top: 8mm;
}
.rod-print .rod-rodape { margin-top: 3mm; }
@media print {
  /* Na impressão o @page já reserva 12mm; a altura útil real é essa. */
  .rod-print { min-height: 265mm; }
}

/* ---- Cabeçalho do eixo sem preenchimento sólido -------------------------
   Eram seis barras pretas por página. Numa impressora de oficina isso é tinta
   ou toner que acaba rápido, e o documento é impresso todo dia. Sombreado
   claro cumpre a mesma função de separar as faixas: o que distingue a seção é
   o contraste com a célula branca ao lado, não a saturação. */
.rod-print .rod-eixo-cab th {
  background: #f0f0f0 !important;
  color: #000 !important;
  text-align: center;
  font-weight: 700;
  border: 1px solid #000 !important;
  border-bottom-width: 1.5px !important;
}

/* ---- Destaque sem deformar a grade --------------------------------------
   Marcar a posição que muda com borda mais grossa parecia inofensivo, mas com
   border-collapse a borda participa do layout: as células destacadas ficavam
   maiores e desalinhavam a tabela "Como deve ficar" em relação à "Como está
   agora" — e é a comparação entre as duas que dá sentido ao documento.

   box-shadow inset desenha o realce POR DENTRO, sem ocupar espaço. A grade das
   duas tabelas fica idêntica, e o destaque continua visível em preto e branco. */
.rod-print .rod-celula-muda {
  border-width: 1px !important;
  box-shadow: inset 0 0 0 2.5px #000;
}
/* A amostra da legenda acompanha o mesmo desenho do realce. */
.rod-print .rod-amostra {
  border: 1px solid #000;
  box-shadow: inset 0 0 0 2.5px #000;
}

/* ---- Sidebar: ícones, rodapé alinhado e modo recolhido ------------------
   O rodapé tinha e-mail longo quebrando em várias linhas e empurrando os
   botões contra a borda — "Conectado", "Minha Conta" e "Sair" ficavam quase
   sobrepostos. Agora o e-mail é truncado (o título mostra inteiro) e as ações
   ficam numa coluna com espaçamento próprio. */
.nav-link { display: flex; align-items: center; gap: 0.6rem; }
.nav-icone { flex: 0 0 1.15rem; width: 1.15rem; text-align: center; font-size: 0.95rem; line-height: 1; }
.nav-texto { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.sidebar-footer { display: flex; flex-direction: column; gap: 0.55rem; }
.sidebar-usuario { min-width: 0; }
.sidebar-footer .usuario-email {
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  word-break: normal;
}
.sidebar-acoes { display: flex; flex-direction: column; gap: 0.35rem; }
/* Sem borda própria — mesma linguagem "ghost" dos .nav-link acima (só
   fundo/hover), pra não competir visualmente com o trilho do item ativo. */
.sidebar-acao {
  display: flex; align-items: center; gap: 0.6rem;
  padding: 0.55rem 0.6rem;
  border: none;
  border-radius: var(--radius-sm);
  background: transparent;
  color: var(--sidebar-text);
  font-size: 0.82rem;
  text-decoration: none;
  cursor: pointer;
  width: 100%;
}
.sidebar-acao:hover { background: var(--sidebar-hover); color: #fff; }
.sidebar-retrair {
  display: flex; align-items: center; gap: 0.6rem;
  padding: 0.4rem 0.6rem;
  border: none; background: none;
  color: var(--sidebar-text-dim);
  font-size: 0.78rem; cursor: pointer;
}
.sidebar-retrair:hover { color: #fff; }
.sidebar-retrair-seta {
  flex: 0 0 1.15rem; width: 1.15rem; text-align: center;
  border-left: 5px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transform: rotate(180deg);
}

/* Modo recolhido: só ícones. Sem media query — é escolha do usuário, não do
   tamanho da tela; a gaveta do celular continua respondendo à largura. */
@media (min-width: 769px) {
  .app-shell.sidebar-recolhida .sidebar { width: 62px; overflow: visible; }
  .app-shell.sidebar-recolhida .nav-texto,
  .app-shell.sidebar-recolhida .sidebar-back,
  .app-shell.sidebar-recolhida .titulos,
  .app-shell.sidebar-recolhida .sidebar-usuario,
  .app-shell.sidebar-recolhida .sidebar-separador-label { display: none; }
  .app-shell.sidebar-recolhida .nav-link,
  .app-shell.sidebar-recolhida .sidebar-acao { justify-content: center; padding-left: 0; padding-right: 0; gap: 0; }
  .app-shell.sidebar-recolhida .sidebar-footer { padding: 0.6rem 0.4rem; }
  .app-shell.sidebar-recolhida .sidebar-retrair { justify-content: center; padding-left: 0; padding-right: 0; }
  .app-shell.sidebar-recolhida .sidebar-retrair-seta { transform: rotate(0deg); }
  .app-shell.sidebar-recolhida .logo-crop { margin: 0 auto; }
}

/* A área de impressão do rodízio ganhou min-height de 273mm e fundo branco para
   ancorar as assinaturas no pé da página. Fora do contexto de impressão isso
   virava um retângulo branco gigante no fim da tela — visível em Cadastro e
   Ciclos, porque o elemento vive no body, não dentro do modal.
   Só existe quando se está imprimindo. */
#reposicionar-print { display: none !important; }
@media print {
  #reposicionar-print { display: flex !important; }
}

/* ---- Duas páginas: a conta não fechava ---------------------------------
   .rod-print tinha min-height 265mm E padding 4mm em cima e embaixo. Com
   box-sizing content-box o padding SOMA: 265 + 8 = 273mm, que é exatamente a
   área útil do A4 com as margens de 12mm do @page. Qualquer arredondamento do
   navegador empurrava para a segunda página — e empurrava sempre.

   border-box faz o padding caber dentro da altura, e 250mm deixa folga real
   em vez de encostar no limite. */
.rod-print {
  box-sizing: border-box;
  min-height: 250mm;
  padding: 0;
}
@media print {
  .rod-print { min-height: 250mm; }
  /* Nada depois do documento pode gerar página extra. */
  .rod-print > *:last-child { margin-bottom: 0 !important; }
}

/* ---- Stepper do Novo pneu: as quatro classes que faltavam ---------------
   O JS já emitia .pneu-stepper-passo / -bolha / -label / -linha, mas nenhuma
   delas tinha estilo. Sem CSS, os <span> são inline puro e colavam: a saída
   virava "10Origem2Produto3Controle" — o "0" era a linha separadora, um span
   vazio que sem estilo não desenha nada e só emenda o texto ao redor.

   O fluxo não muda: cinco etapas, mesma ordem, mesma lógica de estado. */
.pneu-stepper {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.pneu-stepper-passo {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-width: 0;
}
/* A bolha carrega o número — ou o ✓ quando a etapa já passou. Círculo de
   tamanho fixo para os cinco ficarem na mesma linha de base. */
.pneu-stepper-bolha {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.45rem;
  height: 1.45rem;
  border-radius: 50%;
  border: 1.5px solid var(--engrena-border);
  background: var(--engrena-surface);
  color: var(--text-muted);
  font-size: 0.75rem;
  font-weight: 700;
  line-height: 1;
}
.pneu-stepper-label {
  font-size: 0.78rem;
  color: var(--text-muted);
  white-space: nowrap;
}
/* A linha entre as etapas: dá a leitura de percurso, não de lista solta. */
.pneu-stepper-linha {
  flex: 1 1 0.75rem;
  min-width: 0.75rem;
  height: 1.5px;
  background: var(--engrena-border);
}
/* Etapa atual: é onde o usuário está — o único ponto que pede destaque forte. */
.stepper-ativo .pneu-stepper-bolha {
  border-color: var(--engrena-primary);
  background: var(--engrena-primary);
  color: #fff;
}
.stepper-ativo .pneu-stepper-label {
  color: var(--text-primary);
  font-weight: 700;
}
/* Concluída: verde discreto. Informa progresso sem competir com a atual. */
.stepper-concluido .pneu-stepper-bolha {
  border-color: var(--engrena-accent);
  color: var(--engrena-accent);
  background: transparent;
}
.stepper-concluido .pneu-stepper-label { color: var(--text-primary); }

/* Abaixo de 560px cinco bolhas ficam ilegíveis: entra o contador textual que
   o JS já monta ("Etapa 2 de 5 · Produto"). */
@media (max-width: 560px) {
  .pneu-stepper { display: none; }
  .pneu-stepper-mobile { display: block; margin-bottom: 0.9rem; }
}

/* ---- Etapa "Produto" do Novo pneu ---------------------------------------
   O campo de busca ficava com a largura mínima do input global (140px) dentro
   de um label bloco: um retângulo pequeno perdido num modal largo. E a lista
   só existia depois de digitar — para escolher, era preciso adivinhar o termo.
   Agora o campo ocupa a linha e a lista já vem carregada: a busca vira filtro,
   não porta de entrada. */
#pneu-novo-etapa-produto > label { display: block; margin-bottom: 0.7rem; font-weight: 600; font-size: 0.85rem; }
#pneu-novo-produto-busca { width: 100%; box-sizing: border-box; margin-top: 0.3rem; }
#pneu-novo-produto-lista { min-height: 96px; }
/* Cada produto é um alvo clicável de linha inteira — em oficina se usa o dedo,
   e um item de lista estreito erra. */
#pneu-novo-produto-lista .produto-opcao-btn {
  display: block; width: 100%; text-align: left;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--engrena-border);
  border-radius: var(--radius-sm);
  background: var(--engrena-surface);
  cursor: pointer;
}
#pneu-novo-produto-lista .produto-opcao-btn:hover { border-color: var(--engrena-primary); }

/* ---- Grade de campos: alinhar pela BASE, não pelo topo ------------------
   "Fornecedor (opcional)" quebra o rótulo em duas linhas; os vizinhos ficam
   em uma. Como os labels são colunas flex crescendo de cima para baixo, o
   select do fornecedor descia e saía do alinhamento com os campos ao lado.

   justify-content: flex-end empurra o controle para a base de cada célula:
   os campos ficam na mesma linha independentemente de quantas linhas o rótulo
   ocupe. É o alinhamento que o olho procura — o de cima é o texto, o de baixo
   é onde se digita. */
.pneu-form-grid-2 > label,
.pneu-form-grid-3 > label { justify-content: flex-end; }
/* "(opcional)" deixa de disputar espaço com o nome do campo: fica menor e não
   força a quebra sozinho. */
.pneu-label-opcional {
  font-size: 0.72rem;
  font-weight: 400;
  opacity: 0.75;
  white-space: nowrap;
}
/* Respiro entre as seções — Identificação, Características, Aquisição estavam
   com o mesmo espaçamento interno e externo, e as faixas se confundiam. */
.pneu-form-secao {
  margin-top: 1.1rem;
  margin-bottom: 0.5rem;
  padding-bottom: 0.3rem;
  border-bottom: 1px solid var(--engrena-border);
}
.pneu-form-secao:first-of-type { margin-top: 0.4rem; }

/* ---- Linha "Aquisição": fornecedor precisa de mais largura --------------
   Três colunas iguais tratam "Fornecedor" como se fosse do tamanho de "Custo"
   e "Data". Mas razão social é nome longo — "TRANSPORTADORA E COMÉRCIO DE
   PNEUS SÃO JOSÉ LTDA" não cabe em um terço do modal, e select truncado obriga
   a abrir a lista só para saber o que está selecionado.

   Custo e data são campos curtos por natureza (um valor, uma data): não ganham
   nada com largura extra. O fornecedor leva o dobro. */
.pneu-form-grid-3:has(#pn-fornecedor) {
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr);
}
/* Fallback para navegador sem :has() — o seletor acima é ignorado inteiro
   nesses casos, então a classe explícita garante o mesmo resultado. */
.pneu-form-grid-aquisicao {
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1fr);
}
/* Nome longo não pode estourar a célula nem empurrar as vizinhas. */
#pn-fornecedor { width: 100%; min-width: 0; text-overflow: ellipsis; }
@media (max-width: 720px) {
  .pneu-form-grid-3:has(#pn-fornecedor),
  .pneu-form-grid-aquisicao { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   Controle de Pneus do técnico (tecnico-pneus.html) — mobile-first. O chassi
   é o MESMO desenho ilustrado da tela de gestão (mesmas classes .pn-*, já
   definidas acima) — só sem modo de configuração, arraste ou seleção: o
   técnico toca numa posição aplicada e o clique abre direto a aferição.
   ========================================================================== */
/* CAUSA RAIZ do "cards desconformes": a classe global .card só dá fundo,
   borda e sombra — ZERO padding (mesmo problema já corrigido antes na ficha
   do pneu). Sem padding próprio, o conteúdo encosta direto na borda do card
   e o card lê como uma caixa quebrada, não uma seção. Todo card desta tela
   ganha padding explícito abaixo — nenhum depende só da classe global. */
.tp-busca-card, .tp-chassi-card, .tp-disponiveis-card { padding: 1rem 1.1rem; }

/* Rótulo de seção — mesmo padrão "card-titulo" usado no resto do sistema
   (pequeno, maiúsculo, discreto): identifica a seção sem competir com o
   conteúdo abaixo dela. */
.tp-secao-titulo {
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text-muted); margin-bottom: 0.6rem;
}

.tp-busca-card { display: flex; flex-direction: column; gap: 0.5rem; position: relative; }
.tp-busca-campo { position: relative; display: flex; align-items: center; }
.tp-icone-lupa {
  /* Sem top/transform, um elemento absoluto ancora pela posição estática que
     teria no fluxo. top:50% + translateY(-50%) centraliza no eixo vertical;
     right cuida do horizontal — encostada na extremidade direita do campo. */
  position: absolute; right: 0.6rem; top: 50%; transform: translateY(-50%);
  width: 1.9rem; height: 1.9rem;
  display: flex; align-items: center; justify-content: center;
  background: none; border: none; border-radius: 50%; padding: 0; cursor: pointer;
  color: var(--text-muted);
}
.tp-icone-lupa svg { width: 1.1rem; height: 1.1rem; }
.tp-icone-lupa:hover, .tp-icone-lupa:focus-visible { background: rgba(127,127,127,0.14); color: var(--text); }
.tp-busca-campo input { width: 100%; padding-right: 2.6rem; }
.tp-busca-resultados {
  position: absolute; left: 1rem; right: 1rem; top: 100%; z-index: 5;
  margin-top: 0.4rem; background: var(--engrena-surface); border: 1px solid var(--engrena-border);
  border-radius: var(--radius); box-shadow: 0 12px 28px rgba(0,0,0,0.22);
  max-height: 60vh; overflow-y: auto;
}
.tp-busca-item {
  display: flex; flex-direction: column; gap: 0.15rem; width: 100%; text-align: left;
  padding: 0.7rem 0.9rem; border: none; border-bottom: 1px solid var(--engrena-border);
  background: transparent; color: var(--text-primary); font: inherit; cursor: pointer;
}
.tp-busca-item:last-child { border-bottom: none; }
.tp-busca-item:hover, .tp-busca-item:focus-visible { background: var(--engrena-surface-alt); }
.tp-busca-item span { font-size: 0.78rem; color: var(--text-muted); }
.tp-busca-vazia { padding: 0.85rem 0.9rem; font-size: 0.82rem; color: var(--text-muted); margin: 0; }

/* Estado vazio: ícone + título + texto, sem caixa pesada — convida a agir em
   vez de parecer um aviso de erro. */
.tp-estado-vazio {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 0.6rem; padding: 2.8rem 1.5rem; color: var(--text-muted);
  border: 1px dashed var(--engrena-border); border-radius: var(--radius);
}
.tp-icone-pneu-grande { width: 3.2rem; height: 3.2rem; color: var(--text-muted); opacity: 0.55; }
.tp-estado-vazio-titulo { margin: 0; font-size: 1rem; font-weight: 700; color: var(--text-primary); }
.tp-estado-vazio-texto { margin: 0; font-size: 0.85rem; max-width: 26rem; line-height: 1.5; }

/* Agora vive DENTRO de .tp-chassi-card, como cabeçalho da seção — a borda
   embaixo é o que separa "qual veículo" de "chassi dele", sem precisar de
   três caixas soltas empilhadas. */
.tp-veiculo-card {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; flex-wrap: wrap;
  padding-bottom: 0.9rem; margin-bottom: 0.9rem; border-bottom: 1px solid var(--engrena-border);
}
.tp-veiculo-info { display: flex; flex-direction: column; gap: 0.15rem; }
.tp-veiculo-info strong { font-size: 1.05rem; }
.tp-veiculo-info span { font-size: 0.8rem; color: var(--text-muted); }

/* Legenda pontuada por cor, mesma paleta da barra de banda desenhada no
   chassi (definida acima em .pn-banda-ok/alerta/critico). */
.tp-legenda {
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.1rem; margin-top: 1rem;
  padding-top: 0.9rem; border-top: 1px solid var(--engrena-border);
  font-size: 0.78rem; color: var(--text-muted);
}
.tp-legenda-item { display: inline-flex; align-items: center; gap: 0.4rem; }
.tp-legenda-marca { width: 0.85rem; height: 0.85rem; border-radius: 50%; display: inline-block; }
.tp-banda-ok { background: #2563eb; }
.tp-banda-alerta { background: #d97706; }
.tp-banda-critico { background: #dc2626; }
.tp-banda-desconhecida { background: #94a3b8; }

.tp-disponiveis-card { margin-top: 1.1rem; }
.tp-disponiveis-toggle {
  display: flex; align-items: center; gap: 0.75rem; width: 100%;
  background: transparent; border: none; color: var(--text-primary); font: inherit;
  padding: 0; cursor: pointer; text-align: left;
}
.tp-disponiveis-icone {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 2.3rem; height: 2.3rem; border-radius: 50%;
  background: var(--engrena-surface-alt); color: var(--engrena-accent);
}
.tp-disponiveis-icone svg { width: 1.2rem; height: 1.2rem; }
.tp-disponiveis-titulos { display: flex; flex-direction: column; gap: 0.1rem; flex: 1; min-width: 0; }
.tp-disponiveis-titulos strong { font-size: 0.92rem; }
.tp-disponiveis-titulos span { font-size: 0.78rem; color: var(--text-muted); }
.tp-disponiveis-chevron { color: var(--text-muted); font-size: 0.85rem; flex-shrink: 0; }
#tp-disponiveis-corpo { margin-top: 0.85rem; display: flex; flex-direction: column; gap: 0.6rem; }
.tp-disponiveis-lista { display: flex; flex-direction: column; gap: 0.5rem; max-height: 40vh; overflow-y: auto; }
.tp-disponivel-item {
  display: flex; flex-direction: column; gap: 0.1rem; padding: 0.6rem 0.75rem;
  border: 1px solid var(--engrena-border); border-radius: var(--radius); background: var(--engrena-surface-alt);
}
.tp-disponivel-item span { font-size: 0.78rem; color: var(--text-muted); }

/* Modal de aferição do técnico — seções divididas por um traço fino, mesma
   linguagem visual do resumo da etapa 5 do cadastro de pneu, em vez de uma
   pilha contínua de rótulo+campo sem nenhuma pausa visual. */
/* Roda de lado (mesma ilustração do painel/estoque) identificando o pneu no
   topo do modal — âncora visual em vez de só texto. */
.tp-afericao-pneu-info {
  display: flex; align-items: center; gap: 0.6rem;
  font-weight: 600; margin: 0 0 0.9rem; font-size: 1rem;
}
.tp-afericao-pneu-info .pneu-mini { flex-shrink: 0; border-radius: 6px; }
.tp-afericao-secao + .tp-afericao-secao {
  padding-top: 0.9rem; margin-top: 0.9rem; border-top: 1px solid var(--engrena-border);
}
.tp-afericao-secao-titulo {
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--text-muted); margin-bottom: 0.6rem;
}
#tp-modal-afericao label { display: block; font-size: 0.8rem; color: var(--text-muted); font-weight: 600; margin-bottom: 0.35rem; }
/* input/select não são display:block por padrão e o min-width global é só
   140px — sem isto, odômetro/horímetro/tipo ficavam do tamanho de "Pressão"
   (que É deliberadamente estreito, via .tp-campo-curto) em vez de ocupar o
   campo inteiro. */
#tp-modal-afericao input:not(.tp-campo-curto), #tp-modal-afericao select { width: 100%; }
/* Pressão, Odômetro e Horímetro na mesma linha — são três leituras curtas,
   não precisam de uma seção inteira cada. auto-fit em vez de 3 colunas fixas
   porque nem todo veículo mostra os três ao mesmo tempo (Pressão some fora
   do tipo PRESSAO/COMPLETA; Odômetro OU Horímetro somem conforme o que o
   ativo mede) — com colunas fixas, sobrar 1 de 3 deixava um vão vazio; com
   auto-fit, quem sobra ocupa a largura toda sozinho. minmax(8.5rem,1fr)
   também é o que faz a fileira virar 1 coluna em telas estreitas sem
   media query — a mesma técnica já usada no card de disponíveis/resumo. */
.tp-afericao-grid-medidas { display: grid; grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr)); gap: 0.9rem; }
/* textarea não é display:block por padrão — sem width explícito, ela ficava
   com min-width:140px num modal de 640px (medido: 201px de largura real).
   resize:none + overflow:hidden porque o crescimento é automático via JS
   (ajustarAlturaTextarea, no script da página), não pelo arrasto manual do
   canto — a alça de resize ficaria redundante e podia conflitar com o
   redimensionamento automático. */
#tp-afericao-observacoes {
  width: 100%; resize: none; overflow: hidden;
  min-height: 2.6rem; line-height: 1.4;
}

/* Movimentação de pneu do técnico (aplicar/retirar/trocar/reposicionar/
   recapagem/condenar) — mesmo padrão dos campos de aferição acima, mais o
   menu de ações e o resumo de contexto no topo de cada modal. */
.tp-movimentacao-contexto-lista {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 0.5rem 1rem; padding: 0.7rem 0.9rem; margin-bottom: 0.9rem;
  background: var(--engrena-surface-alt); border: 1px solid var(--engrena-border); border-radius: var(--radius);
  font-size: 0.85rem;
}
.tp-movimentacao-contexto-item { display: flex; flex-direction: column; gap: 0.1rem; }
.tp-movimentacao-contexto-item span { font-size: 0.65rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); }
#tp-modal-aplicar select, #tp-modal-retirar select, #tp-modal-trocar select,
#tp-modal-recapagem select, #tp-modal-aplicar textarea, #tp-modal-retirar textarea,
#tp-modal-trocar textarea, #tp-modal-reposicionar textarea, #tp-modal-recapagem textarea,
#tp-modal-condenar textarea, #tp-modal-retirar input, #tp-modal-trocar input, #tp-modal-condenar input {
  width: 100%;
}
#tp-modal-retirar textarea, #tp-modal-trocar textarea, #tp-modal-reposicionar textarea, #tp-modal-recapagem textarea {
  resize: vertical; min-height: 2.6rem;
}

/* Menu de ações — lista vertical de botões grandes, um toque cada, mesmo
   espírito mobile-first do resto do portal do técnico. */
.tp-acoes-box { max-width: 380px; }
.tp-acoes-lista { display: flex; flex-direction: column; gap: 0.5rem; }
.tp-acao-btn {
  width: 100%; text-align: left; padding: 0.85rem 1rem; font-size: 0.95rem; font-weight: 600;
  background: var(--engrena-surface-alt); color: var(--text-primary);
  border: 1px solid var(--engrena-border); border-radius: var(--radius);
}
.tp-acao-btn:hover { background: var(--engrena-surface); }
.tp-acao-btn-perigo { color: var(--danger); border-color: var(--danger); }

/* ============================================================================
   Repaginação visual — Etapa 3 (prova de conceito: Clientes, Colaboradores,
   Ordens de Serviço). Duas categorias de regra abaixo:

   1) Classes novas e genéricas (.estado-vazio*, .tabela-scroll) — não
      colidem com nada existente, então ficam disponíveis pro app inteiro
      desde já, mas só são USADAS (via HTML/JS) nestas 3 telas por ora.

   2) Regras escopadas em ".pilot-e3" (marcador no <body> das 3 telas
      piloto) — ajustam classes MUITO compartilhadas (.inline-form,
      .form-row, .form-grid, .modal-box, table) sem tocar na definição
      global delas, que é usada por ~25 outras páginas ainda não
      aprovadas para este padrão. Promover pra outra tela = só adicionar
      "pilot-e3" ao <body> dela.
   ============================================================================ */

/* --- Estado vazio de listagem ------------------------------------------- */
/* Hoje nem toda tabela tinha isso (Clientes não tinha nenhum; Colaboradores
   e Ordens de Serviço tinham a mesma string inline duplicada). Um único
   padrão visual, sem CTA (RBAC continua decidindo o que aparece de ação —
   isto aqui é só a mensagem). */
.estado-vazio {
  text-align: center;
  padding: 2.75rem 1rem;
  color: var(--text-muted);
}
.estado-vazio-titulo {
  font-weight: 600;
  color: var(--text-primary);
  margin: 0 0 0.3rem;
  font-size: 0.9rem;
}
.estado-vazio-desc { margin: 0; font-size: 0.8rem; }

/* --- Scroll horizontal de tabela larga ----------------------------------- */
/* Ordens de Serviço e Colaboradores já resolviam isso com o mesmo
   style="overflow-x:auto" inline duplicado; Clientes não tinha nada (achado
   real, não hipotético — tabela cortava a viewport sem nenhuma saída no
   celular). Vira classe única; comportamento idêntico ao que já existia
   nas duas que já tinham. */
.tabela-scroll { overflow-x: auto; }

/* --- Piloto: filtros, formulários e modais ------------------------------- */
.pilot-e3 .inline-form label {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.pilot-e3 .form-section-titulo { margin-top: 1.75rem; }
.pilot-e3 .form-row,
.pilot-e3 .form-grid { margin-bottom: 1.15rem; }
.pilot-e3 .modal-box { padding: 1.75rem; }
.pilot-e3 .modal-box .modal-header { margin-bottom: 1.25rem; }
.pilot-e3 .modal-box .modal-header h2 { font-size: 1.1rem; font-weight: 700; }

/* --- Piloto: densidade de tabela (leve, não "indiscriminada") ----------- */
.pilot-e3 table th { padding: 0.75rem 1rem; }
.pilot-e3 table td { padding: 0.7rem 1rem; }
/* Reclama a densidade própria da grade de horários (Programação de
   Atividades) mesmo com .pilot-e3 no <body> — mesmo motivo e mesmo padrão
   da guarda de .grade-permissoes acima: ".pilot-e3 table th/td" empata em
   especificidade com "table.tabela-grade th/td" e venceria por vir depois
   no arquivo, preenchendo com padding as células de 30 min e quebrando o
   alinhamento do quadro. */
.pilot-e3 .tabela-grade th,
.pilot-e3 .tabela-grade td { padding: 0; }
