/* ComprasFlow — front-end próprio (tela cheia, estilo app). */
:root{
  --bg:#eef1ec;
  --surface:#ffffff;
  --surface-2:#f5f6f2;
  --border:#dbdfd5;
  --ink:#1a231e;
  --ink-soft:#5c6b60;
  --ink-faint:#8b9890;
  --primary:#1f4b3f;
  --primary-ink:#ffffff;
  --primary-soft:#e0ece5;
  --primary-strong:#163a30;
  --accent:#c1652f;
  --accent-ink:#ffffff;
  --accent-soft:#f5e4d5;
  --success:#2f7a4f;
  --success-soft:#e2f0e6;
  --danger:#b23a3a;
  --danger-soft:#f7e3e1;
  --warn:#a9791f;
  --warn-soft:#f3ead2;
  /* Cor própria do papel "Administrador" nos Comentários da Requisição
     (ver .cf-comment-avatar/.cf-comment-role-badge mais abaixo) — Requisitante
     e Comprador reaproveitam --primary/--accent (já usados no resto do app),
     mas nenhuma cor existente sobrava pra Administrador sem repetir uma
     tonalidade já usada (--success é um verde próximo demais de --primary) ou
     usar uma cor com outro significado já fixado no app (--danger = ação
     destrutiva, --warn = pendência). */
  --role-admin:#3a5a8c;
  --role-admin-soft:#dfe6f2;
  /* Cor própria do papel "Gestor" (v2.29.15), mesmo espírito de --role-admin
     acima — Gestor é "quase Administrador" nas capacidades, mas precisa de
     cor própria nos Comentários pra não ser confundido visualmente com o
     Administrador de verdade. */
  --role-gestor:#6a4f9c;
  --role-gestor-soft:#e6e0f2;
  /* v2.35.3 — cores próprias dos 5 status da Fábrica (COT_STATUS_FABRICA_TONE
     em frontend.js), separadas de --warn/--danger/--accent/--success: esses
     4 tokens também pintam botões/avisos/badges em telas sem nenhuma relação
     com Cotação, então reaproveitá-los aqui faria qualquer um deles mudar de
     cor junto sem o usuário ter pedido. Pedido do usuário: Aguardando =
     amarelo, Sem Resposta = cinza, Não Tem = cinza (igual Sem Resposta),
     Cotado = verde claro, Comprado = roxo. Cada status tem 3 variantes:
     "-dot" (quadradinho da listagem COT-01, pode ser bem vivo — não carrega
     texto em cima) e a dupla "normal"/"-soft" (texto/fundo da pílula do
     seletor dentro da COT-02, onde o amarelo precisa ser mais escuro pra não
     perder legibilidade do texto — ver mockup aprovado). */
  --st-yellow:#8a6d0a; --st-yellow-dot:#e8b600; --st-yellow-soft:#fbf0bd;
  --st-gray:#5f6a74; --st-gray-dot:#8b96a1; --st-gray-soft:#e7eaed;
  --st-green:#1f9a5a; --st-green-dot:#30c172; --st-green-soft:#dcf5e7;
  --st-purple:#7c3aed; --st-purple-dot:#8b5cf6; --st-purple-soft:#ece4fb;
  --radius-sm:8px;
  --radius-md:14px;
  --radius-lg:20px;
  --shadow-sm:0 1px 2px rgba(20,30,24,.06);
  --shadow-md:0 8px 24px rgba(20,30,24,.10);
  --shadow-lg:0 20px 60px rgba(20,30,24,.22);
  color-scheme:light;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --bg:#10140f; --surface:#181e1a; --surface-2:#1f2620; --border:#2c352e;
    --ink:#eef1ec; --ink-soft:#a7b3ab; --ink-faint:#71807a;
    --primary:#6fbf9a; --primary-ink:#0c1f16; --primary-soft:#1e3830; --primary-strong:#8fd4b2;
    --accent:#e08a4f; --accent-ink:#241407; --accent-soft:#3a2a18;
    --success:#7ecb98; --success-soft:#1f3a2a; --danger:#e08585; --danger-soft:#3a1f1f;
    --warn:#e0c26a; --warn-soft:#3a301a;
    --role-admin:#8fa9d6; --role-admin-soft:#26344a;
    --role-gestor:#b3a0d9; --role-gestor-soft:#332a47;
    --st-yellow:#e8c84a; --st-yellow-dot:#f0cc33; --st-yellow-soft:#3d3310;
    --st-gray:#a7b0b8; --st-gray-dot:#8b96a1; --st-gray-soft:#2a2e33;
    --st-green:#6fe3a0; --st-green-dot:#3ddb84; --st-green-soft:#163a27;
    --st-purple:#b79cf0; --st-purple-dot:#9c7cf0; --st-purple-soft:#2c2140;
    --shadow-sm:0 1px 2px rgba(0,0,0,.3); --shadow-md:0 8px 24px rgba(0,0,0,.4); --shadow-lg:0 20px 60px rgba(0,0,0,.55);
  }
}

html.cf-app-active, html.cf-app-active body{ height:100%; margin:0; background:var(--bg); }
body.cf-app-body{ margin:0; }

.cf-app-fullscreen *, .cf-login-screen *{ box-sizing:border-box; }
.cf-app-fullscreen, .cf-login-screen{
  font-family:'Inter',system-ui,-apple-system,Segoe UI,sans-serif;
  font-size:14px; line-height:1.45; color:var(--ink); -webkit-font-smoothing:antialiased;
  min-height:100vh; background:var(--bg);
}
.cf-app-fullscreen h1,.cf-app-fullscreen h2,.cf-app-fullscreen h3,
.cf-login-screen h1,.brand-name{ font-family:'Manrope',Inter,system-ui,sans-serif; font-weight:800; letter-spacing:-.01em; }
.cf-app-fullscreen .mono,.cf-app-fullscreen input[type="date"],.cf-app-fullscreen input[type="number"]{
  font-family:'IBM Plex Mono',ui-monospace,monospace; font-variant-numeric:tabular-nums;
}
.cf-app-fullscreen a{ color:inherit; }
.cf-app-fullscreen button{ font-family:inherit; }
/* Pedido do usuário: todo o sistema (o app, não a tela de login) escrito em
   maiúsculas. text-transform:uppercase é uma propriedade herdada, então uma
   única regra no elemento raiz já cobre título, rótulos, tabelas, badges,
   texto digitado etc.; os campos de formulário (input/textarea/select/
   button) são reforçados explicitamente porque nem todo navegador herda
   propriedades de texto neles. Isso é só visual — quem realmente grava o
   valor em maiúsculas nos campos de texto é o listener em uppercaseInput()
   (frontend.js), pra que a busca, os relatórios e o wp-admin também vejam o
   dado já em maiúsculas, não só a tela do app. */
.cf-app-fullscreen{ text-transform:uppercase; }
.cf-app-fullscreen input,
.cf-app-fullscreen textarea,
.cf-app-fullscreen select,
.cf-app-fullscreen button{ text-transform:uppercase; }
.cf-app-fullscreen input::placeholder,
.cf-app-fullscreen textarea::placeholder{ text-transform:uppercase; }
/* v2.22.0 — pedido do usuário: e-mail, senha e endereço/URL passam a
   aceitar minúsculas normalmente, em vez de serem forçados pra maiúsculas
   como o resto do app. [data-no-upper] é o atributo que fieldHtml() (ver
   frontend.js) grava nos campos marcados com noUpper:true (hoje: Usuário,
   Senha e Endereço do módulo Acessos, e Teams do Fornecedor); .no-upper é
   a mesma exceção aplicada onde esses valores aparecem DEPOIS de salvos —
   colunas de listagem e a grade de detalhe (ver renderView()/detailItem()/
   detailItemWide() em frontend.js) — pra não mostrar em maiúsculas um
   valor que foi digitado (e continua gravado) em minúsculas. */
.cf-app-fullscreen [data-no-upper],
.cf-app-fullscreen [data-no-upper]::placeholder{ text-transform:none; }
.cf-app-fullscreen .no-upper{ text-transform:none; }
.cf-app-loading{ display:flex; align-items:center; justify-content:center; min-height:100vh; color:var(--ink-faint); font-size:14px; }

/* ---------- tela de login ---------- */
.cf-login-screen{
  display:flex; align-items:center; justify-content:center; padding:24px;
}
.cf-login-card{
  width:100%; max-width:360px; background:var(--surface); border:1px solid var(--border);
  border-radius:var(--radius-lg); box-shadow:var(--shadow-lg); padding:36px 30px;
}
.cf-login-brand{ text-align:center; margin-bottom:26px; }
.cf-login-logo{
  display:inline-flex; align-items:center; justify-content:center; width:52px; height:52px;
  border-radius:14px; background:linear-gradient(155deg,var(--primary),var(--primary-strong));
  color:var(--primary-ink); font-weight:800; font-size:18px; margin-bottom:12px;
}
.cf-login-brand h1{ font-size:20px; margin:0 0 2px; }
.cf-login-brand p{ margin:0; color:var(--ink-faint); font-size:12.5px; }
.cf-login-error{
  background:var(--danger-soft); color:var(--danger); border-radius:8px; padding:10px 12px;
  font-size:12.5px; font-weight:600; margin-bottom:16px; text-align:center;
}
/* Mensagem de sucesso (v2.29.15 — "link enviado", "senha redefinida") no
   mesmo molde de .cf-login-error acima, só trocando a cor pra --success. */
.cf-login-success{
  background:var(--success-soft); color:var(--success); border-radius:8px; padding:10px 12px;
  font-size:12.5px; font-weight:600; margin-bottom:16px; text-align:center;
}
/* "Esqueci minha senha" / "Voltar ao login" (v2.29.15) — link discreto
   centralizado abaixo do formulário/botão. */
.cf-login-link{
  display:block; text-align:center; margin-top:16px; font-size:12px; font-weight:600;
  color:var(--ink-soft); text-decoration:none;
}
.cf-login-link:hover{ color:var(--primary); text-decoration:underline; }
.cf-login-form{ display:flex; flex-direction:column; gap:6px; }
.cf-login-form label{ font-size:11.5px; font-weight:700; color:var(--ink-soft); margin-top:10px; }
.cf-login-form input{
  padding:10px 12px; border-radius:8px; border:1px solid var(--border); background:var(--surface-2);
  color:var(--ink); font-size:13.5px; outline:none;
}
.cf-login-form input:focus{ border-color:var(--primary); background:var(--surface); }
.cf-login-form button{
  margin-top:20px; padding:11px; border-radius:8px; border:none; background:var(--accent);
  color:var(--accent-ink); font-weight:700; font-size:13.5px; cursor:pointer;
}
.cf-login-form button:hover{ filter:brightness(1.06); }

/* ---------- shell do app ---------- */
#app{ display:flex; min-height:100vh; }
.sidebar{
  width:248px; flex:none; background:var(--surface); border-right:1px solid var(--border);
  display:flex; flex-direction:column; padding:20px 14px; gap:18px; position:sticky; top:0; height:100vh;
  /* v2.23.1 — a lista de módulos do menu lateral só cresceu a cada versão
     (Preços de Fábrica, Acessos, Itens Cotados, Calcular Preço de Venda...)
     e, sem rolagem própria, o conteúdo passou a ultrapassar os 100vh da
     barra lateral. Como isso não era recortado (sem overflow definido aqui,
     o padrão do navegador é "visible"), o excesso vazava para fora da
     barra e esticava a página inteira (#app/body/html) além da tela — o
     efeito observado pelo usuário foi os cabeçalhos "congelados" das
     tabelas (v2.14.0) voltando a rolar junto com o mouse, porque a PÁGINA
     TODA passou a rolar, arrastando título/busca/cabeçalho da tabela junto
     (eles nunca dependeram de position:sticky próprio — só ficavam fixos
     por estarem fora da área que rola). A barra lateral agora rola por
     conta própria quando não cabe, sem afetar o resto da página.
  */
  overflow-y:auto; overflow-x:hidden;
}
.brand{ display:flex; align-items:center; gap:10px; padding:4px 8px 10px; }
.brand-mark{
  width:34px;height:34px;border-radius:10px; background:linear-gradient(155deg,var(--primary),var(--primary-strong));
  display:flex;align-items:center;justify-content:center; color:var(--primary-ink);flex:none; box-shadow:var(--shadow-sm);
}
.brand-name{ font-size:17px; color:var(--ink); }
.brand-sub{ font-size:11px; color:var(--ink-faint); margin-top:1px; }

nav.modules{ display:flex; flex-direction:column; gap:3px; }
.nav-label{ font-size:10.5px; text-transform:uppercase; letter-spacing:.09em; color:var(--ink-faint); padding:10px 10px 4px; }
.nav-item{
  display:flex;align-items:center;gap:10px; padding:9px 10px;border-radius:var(--radius-sm);
  color:var(--ink-soft);cursor:pointer;border:1px solid transparent; font-size:13.5px;font-weight:600;
  transition:background .12s ease,color .12s ease;
}
.nav-item svg{ flex:none;width:17px;height:17px; }
.nav-item:hover{ background:var(--surface-2); color:var(--ink); }
.nav-item.active{ background:var(--primary-soft); color:var(--primary-strong); }
.nav-count{
  margin-left:auto;font-size:11px;font-weight:700; background:var(--surface-2);color:var(--ink-soft);
  border-radius:999px;min-width:20px;text-align:center;padding:1px 6px;
}
.nav-item.active .nav-count{ background:var(--surface); color:var(--primary-strong); }
/* Contador em destaque (laranja) — usado em "Avisos" e "Itens Cotados" pra
   chamar atenção pra algo que precisa de uma decisão, diferente da contagem
   neutra (cinza) do resto da navegação. */
.nav-count-alert{ background:var(--accent)!important; color:#fff!important; }
/* Contador de requisições com comentário novo (ver renderNav()/navItemHtml()
   em frontend.js) — vermelho de propósito, diferente do laranja usado em
   "Avisos"/"Itens Cotados" (uma pendência de decisão), pra ler como
   "notificação não lida", não como "ação pendente". Convive lado a lado com
   o .nav-count cinza normal (total de requisições) no mesmo item de menu. */
.nav-count-danger{ background:var(--danger)!important; color:#fff!important; }

/* Grupos do menu lateral (v2.25.0, ajustado na v2.25.1 — ver comentário
   abaixo) — Comercial/Compras/Relatórios/Gestão/Cadastros, cada um abrindo/
   fechando por conta própria (não é um acordeão exclusivo: abrir um não
   fecha os outros), pra caber mais itens sem a barra lateral rolar demais.
   Estado (aberto/fechado) fica em navGroupsOpen, guardado em localStorage —
   ver frontend.js.

   v2.25.1 — correção pedida pelo usuário depois de ver o menu real: o
   cabeçalho do grupo (ex: "COMPRAS") tinha ficado com fonte MENOR (10.5px,
   herdada do antigo rótulo passivo .nav-label) do que os itens dentro dele
   (.nav-item, 13.5px) — o oposto da hierarquia visual esperada (grupo em
   destaque, item mais discreto). Agora o cabeçalho do grupo usa o mesmo
   tamanho/peso de um item comum, com ícone próprio e a seta encostada na
   borda direita (antes ficava colada no rótulo, à esquerda); os itens DENTRO
   de um grupo (.nav-group-body .nav-item) passam a ser menores, mais leves e
   com um recuo extra à esquerda, pra ficar claro que estão "dentro" do
   grupo — só em telas largas, a barra lateral: no celular (ver
   @media max-width:820px mais abaixo) o menu continua achatado numa fileira
   de ícones, sem essa diferenciação. */
.nav-group{ display:flex; flex-direction:column; }
.nav-group-header{
  display:flex;align-items:center;gap:10px; padding:9px 10px;border-radius:var(--radius-sm);
  color:var(--ink-soft);cursor:pointer;border:1px solid transparent; font-size:13.5px;font-weight:700;
  text-transform:uppercase; letter-spacing:.02em; user-select:none;
  transition:background .12s ease,color .12s ease;
}
.nav-group-header svg{ flex:none;width:17px;height:17px; }
.nav-group-header:hover{ background:var(--surface-2); color:var(--ink); }
.nav-group-label{ flex:1; }
.nav-group-chevron{ display:flex;flex:none;margin-left:auto; transition:transform .15s ease; color:var(--ink-faint); }
.nav-group-chevron svg{ width:11px;height:11px; }
.nav-group.open .nav-group-chevron{ transform:rotate(90deg); }
.nav-group-body{ display:none; flex-direction:column; gap:2px; }
.nav-group.open .nav-group-body{ display:flex; }
@media (min-width:821px){
  /* Item dentro de um grupo: mais discreto que o cabeçalho do grupo acima
     dele e recuado, pra reforçar visualmente que pertence àquele grupo.
     Escopado a telas largas de propósito — .nav-group-body só existe dentro
     de #nav/.sidebar, que a v2.49.9 escondeu inteiro no celular (ver
     @media max-width:820px mais abaixo: o celular agora tem sua própria
     barra, .mobile-nav, com os itens de cada grupo reaproveitados só
     DENTRO da gaveta/.mobile-nav-sheet — ver essa mesma seção pro estilo
     deles lá). Esta regra continua escopada aqui por clareza (só faz
     sentido na barra lateral de verdade), embora na prática #nav já nem
     apareça mais abaixo de 821px. */
  .nav-group-body .nav-item{ padding-left:32px;font-size:12px;font-weight:500; }
  .nav-group-body .nav-item svg{ width:15px;height:15px; }
  .nav-group-body .nav-item.active{ font-weight:700; }
  /* "Nova Requisição" (v2.25.2) — é uma AÇÃO (abre o painel na hora), não uma
     tela como as outras, então ganha a cor de destaque do app pra se
     diferenciar visualmente dos demais itens do grupo Comercial. v2.29.13 —
     negrito removido (pedido explícito do usuário: "quero que fique normal,
     sem negrito") — mantém só a cor de destaque, no mesmo peso dos outros
     itens do grupo (.nav-group-body .nav-item, font-weight:500 acima). */
  .nav-group-body .nav-item[data-action="nova-requisicao"]{ color:var(--primary); font-weight:500; }
  .nav-group-body .nav-item[data-action="nova-requisicao"]:hover{ background:var(--primary-soft); }
}

/* Barra/gaveta de menu do celular (v2.49.9) — escondidas por padrão (só o
   computador é renderizado antes de 820px); @media max-width:820px, mais
   abaixo, liga as três de verdade. Ficam declaradas aqui (fora do media
   query) só pra garantir que nunca aparecem sem querer num redimensionamento
   de janela ou num navegador que ignore a media query, mesma cautela de
   sempre deste arquivo. */
.mobile-nav,.mobile-nav-backdrop,.mobile-nav-sheet{ display:none; }

.sidebar-foot{ margin-top:auto;padding-top:10px;border-top:1px solid var(--border); }
.status-pill{
  display:flex;align-items:center;gap:7px;font-size:11.5px;color:var(--ink-soft);
  padding:8px 9px;border-radius:var(--radius-sm);background:var(--surface-2);
}
.status-dot{ width:7px;height:7px;border-radius:50%;background:var(--success);flex:none; }
/* status-pill virou <button> (v2.29.15, abre "Meu Perfil") — reset do visual
   padrão de botão pra continuar idêntico ao <div> que era antes. */
button.status-pill{ border:none;width:100%;text-align:left;cursor:pointer;font:inherit; }
button.status-pill:hover{ background:var(--primary-soft); }
.theme-toggle{
  margin-top:8px;width:100%;display:flex;align-items:center;justify-content:center;gap:6px;
  padding:8px;border-radius:var(--radius-sm);border:1px solid var(--border);
  background:var(--surface);color:var(--ink-soft);font-size:12px;font-weight:600;cursor:pointer;text-decoration:none;
}
.theme-toggle:hover{ color:var(--ink); }

main.content{ flex:1;min-width:0;display:flex;flex-direction:column; }
.topbar{
  display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap;
  padding:26px 32px 18px;border-bottom:1px solid var(--border);background:var(--surface);
}
.topbar h1{ font-size:22px;margin:0 0 4px; }
/* v2.45.7 (pedido do usuário, mockup "ux-codigo-tela-no-cabecalho-mockup.html"
   aprovado): código curto da tela (ver SCREEN_CODES em frontend.js) — antes
   discreto no rodapé da barra lateral (".cf-screen-tag", removida) — agora
   junto do título de cada tela, formato "PROD-01 / Produtos". Tamanho em
   "em" (relativo à fonte do título que o contém) de propósito: o mesmo
   ".scrcode"/".scrsep" aparece tanto dentro de ".topbar h1" (listagens,
   22px) quanto dentro de ".panel-head h2" (formulários/detalhes, 18px),
   escalando sozinho com cada um, sem precisar de uma regra por tamanho. */
.scrcode{ color:var(--ink-faint);font-weight:700;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.73em;letter-spacing:.02em; }
.scrsep{ color:var(--ink-faint);font-weight:400;margin:0 7px; }
.topbar p{ margin:0;color:var(--ink-soft);font-size:13px;max-width:56ch; }
.btn{
  display:inline-flex;align-items:center;gap:7px; padding:9px 15px;border-radius:var(--radius-sm);border:1px solid transparent;
  font-size:13px;font-weight:700;cursor:pointer;white-space:nowrap; transition:filter .12s ease, background .12s ease;
}
.btn svg{ width:15px;height:15px;flex:none; }
.btn:hover{ filter:brightness(0.97); }
.btn-primary{ background:var(--accent);color:var(--accent-ink); }
.btn-primary:hover{ filter:brightness(1.06); }
.btn-ghost{ background:transparent;border-color:var(--border);color:var(--ink-soft); }
.btn-ghost:hover{ background:var(--surface-2);color:var(--ink); }
.btn-soft{ background:var(--primary-soft);color:var(--primary-strong); }
.btn-danger{ background:var(--danger);color:#fff; }
.btn-danger:hover{ filter:brightness(1.06); }
.btn-sm{ padding:6px 10px;font-size:12px;border-radius:7px; }
.btn-icon{ padding:7px;border-radius:8px;background:transparent;border:1px solid var(--border);color:var(--ink-soft); }
.btn-icon:hover{ background:var(--surface-2);color:var(--ink); }
/* Botão de Lixeira no rodapé do painel de detalhe (ver openGenericDetail() em
   frontend.js) — tingido de "perigo" o tempo todo, não só no hover, pra
   deixar claro que é uma ação destrutiva antes mesmo de encostar o mouse. */
.btn-icon.danger{ color:var(--danger);border-color:var(--danger-soft); }
.btn-icon.danger:hover{ background:var(--danger-soft);color:var(--danger);border-color:var(--danger-soft); }
/* Botão "Excluir" nas linhas da lista de fábricas de Preços de Fábrica e
   Carteira e Pendências (v2.29.12) — mesmo espírito de .btn-icon.danger
   acima, só que pro botão ghost com texto em vez de ícone sozinho. */
.btn-ghost.btn-ghost-danger{ color:var(--danger);border-color:var(--danger-soft); }
.btn-ghost.btn-ghost-danger:hover{ background:var(--danger-soft);color:var(--danger);border-color:var(--danger-soft); }
.btn[disabled]{ opacity:.5;cursor:not-allowed; }
.btn-link-danger{
  display:inline-flex;flex-direction:column;align-items:flex-start;background:none;border:none;padding:0;cursor:pointer;
}
.btn-link-danger .lbl{ display:inline-flex;align-items:center;gap:7px;color:var(--danger);font-size:12px;font-weight:700;letter-spacing:.02em;text-transform:uppercase; }
.btn-link-danger .cap{ font-size:10px;color:var(--ink-faint);margin-top:2px; }
.btn-link-danger[disabled]{ opacity:.5;cursor:not-allowed; }

.toolbar{
  display:flex;gap:10px;align-items:center;flex-wrap:wrap;
  padding:16px 32px;background:var(--surface);border-bottom:1px solid var(--border);
}
.search-box{
  display:flex;align-items:center;gap:8px; background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);
  padding:8px 12px;min-width:220px;flex:1;max-width:340px;
}
.search-box svg{ width:15px;height:15px;color:var(--ink-faint);flex:none; }
.search-box input{ border:none;background:transparent;outline:none;color:var(--ink);font-size:13px;width:100%; }
select.filter-select{
  padding:8px 30px 8px 12px;border-radius:var(--radius-sm);border:1px solid var(--border);
  background:var(--surface-2) url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none" stroke="%235c6b60" stroke-width="1.6"><path d="M5 8l5 5 5-5"/></svg>') no-repeat right 8px center/13px;
  color:var(--ink);font-size:13px;appearance:none;cursor:pointer;font-family:inherit;
}
/* Pedido do usuário (mockup for01-logo-filtros-contato-mockup.html): mesmo
   com padding igual, .search-box (uma div) e select.filter-select (um
   <select> nativo) renderizavam com alturas levemente diferentes — todo
   navegador dá ao <select> uma altura "de fábrica" própria, por causa do
   line-height padrão do elemento. Travando height+box-sizing explícitos
   nos dois, a altura fica garantidamente idêntica, não só parecida por
   coincidência do padding. 38px = a altura que os dois já tinham na
   listagem de Fornecedores (FOR-01), vira o padrão em toda a Toolbar do
   sistema, pros filtros extras (`.filter-extra`, ver frontend.js) incluídos. */
.search-box, select.filter-select{ height:38px;box-sizing:border-box; }
.toolbar-count{ font-size:12px;color:var(--ink-faint);margin-left:auto; }
/* Container dos filtros extras de um módulo (hoje só Fornecedores/FOR-01:
   Portfólio, Marcas, UF, Contato — ver cfg.filtrosExtras em frontend.js).
   display:contents faz os <select class="filter-select"> de dentro dele se
   comportarem como filhos diretos de .toolbar pro layout flex (mesmo gap,
   mesmo wrap), sem um "embrulho" a mais no meio. Vazio/escondido nos
   módulos que não definem filtrosExtras. */
.filter-extra{ display:contents; }

/* v2.47.33 — toggle "Pendentes/Todas" da tela "Req Cotadas" (ver
   renderItensCotadosLista() em assets/frontend.js). Esta tela esconde a
   .toolbar genérica (sem busca/filtro de módulo, igual 'avisos'/'cotar') e
   desenha este toggle sozinha, dentro de #viewArea, no lugar dela — não
   existia nenhum componente de abas pronto no sistema até aqui; reaproveita
   os mesmos tons (--surface-2/--primary-soft) já usados em .nav-item.active
   pra não introduzir uma cor nova. */
.cotrq-tabs{
  display:inline-flex;gap:4px;background:var(--surface-2);border:1px solid var(--border);
  border-radius:10px;padding:3px;margin-bottom:16px;
}
.cotrq-tab{
  border:none;background:transparent;padding:7px 14px;border-radius:7px;font-size:12.5px;font-weight:700;
  color:var(--ink-soft);cursor:pointer;white-space:nowrap;font-family:inherit;
}
.cotrq-tab.active{ background:var(--surface);color:var(--primary-strong);box-shadow:var(--shadow-sm); }
.cotrq-tab .n{ color:var(--ink-faint);font-weight:700;margin-left:4px; }
.cotrq-tab.active .n{ color:var(--primary-strong); }
/* Linha clicável (abre o painel de decisão ao clicar em qualquer parte dela,
   não só no botão "Ver" — pedido do usuário: "quando eu clicar na lista ou
   em visualizar"). tbody tr:hover já destaca o fundo (regra genérica da
   tabela, ver acima); só falta o cursor indicando que é clicável. */
.cotrq-row-clickable{ cursor:pointer; }

.view-area{ flex:1;padding:22px 32px 48px;overflow:auto; }
.empty-state{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:10px;padding:70px 20px;color:var(--ink-faint);text-align:center;
}
.empty-state svg{ width:42px;height:42px;opacity:.5; }
.empty-state strong{ color:var(--ink-soft);font-size:14px; }

/* ---------- tabela ---------- */
/* Pedido do usuário: em todas as tabelas do sistema, congelar título, filtro
   e cabeçalho da tabela, rolando só os dados. O título (.topbar) e o filtro
   (.toolbar) já ficam fora de .table-wrap (são elementos irmãos, antes da
   tabela), então na prática o que faltava era a PRÓPRIA tabela ficar de
   tamanho fixo, com rolagem só dentro dela, e o cabeçalho (thead) grudado no
   topo dessa rolagem. .table-wrap ganha uma altura máxima (o que sobra da
   tela, descontando o espaço já ocupado por título/filtro/margens — por
   isso o "- 300px" abaixo) e rolagem própria (overflow:auto no lugar de
   hidden — continua cortando os cantos arredondados igual antes, só que
   agora também rola quando o conteúdo não cabe); o `min-height` evita que a
   tabela fique espremida demais numa tela muito baixa. Com isso,
   `position:sticky` no `thead th` gruda o cabeçalho no topo dessa rolagem
   interna — funciona porque .table-wrap passa a ser o "ancestral com
   rolagem" mais próximo do thead. Quando a tabela é curta (poucas linhas),
   o max-height simplesmente não é atingido — a tabela fica do tamanho
   normal, sem barra de rolagem nenhuma. No celular (ver media query mais
   abaixo), a tabela vira uma lista de cartões e isso tudo é desligado, já
   que o cabeçalho já não aparece nesse layout. */
.table-wrap{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);
  overflow:auto;box-shadow:var(--shadow-sm);
  max-height:calc(100vh - 300px);min-height:260px;
}
table{ width:100%;border-collapse:collapse; }
thead th{
  text-align:left;font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;
  color:var(--ink-faint);padding:11px 16px;border-bottom:1px solid var(--border);
  background:var(--surface-2);font-weight:700;
  position:sticky;top:0;z-index:1;
  /* Feedback do usuário depois de testar ao vivo (v2.14.0): flutuando por
     cima das linhas durante a rolagem, o cabeçalho ficava sutil demais —
     só a borda de 1px embaixo não se destacava o suficiente das linhas
     passando por baixo. Uma sombra leve reforça a separação sem ficar
     pesada quando a tabela está parada (sem rolar, a sombra mal se nota,
     já que não tem nada "por baixo" ainda). */
  box-shadow:0 2px 4px rgba(20,30,24,.08);
}
/* Altura padrão de linha, em TODAS as tabelas do sistema (Fornecedores,
   Requisições, Cotações, Produtos): 30px (1px de padding + 28px de
   line-height, ambos de cima e de baixo) — pedido do usuário, mockup
   aprovado (for01-logo-filtros-contato-mockup.html), pra caber o logo de
   28px da listagem de Fornecedores (ver `tbody .avatar` logo abaixo) sem
   cortar. Era 18px (padding de 1px + line-height de 16px) até a v2.41.x;
   o logo precisou crescer primeiro, a linha só acompanhou o tamanho dele —
   os dois estão amarrados (ver thread do pedido). Texto não quebra em mais
   de uma linha (white-space:nowrap) — se o conteúdo não couber, a própria
   tabela aumenta a largura da coluna em vez de esticar a altura da linha.
   Colunas com listas muito longas (Marcas/Portfólio) continuam usando
   `.cell-truncate` (corte com "..." + tooltip) em vez de alargar sem limite,
   exceção deliberada já existente desde a v2.3.0. Exceções que NÃO seguem
   esta altura (já eram especiais antes desta mudança, por motivos próprios
   — ver os comentários de cada uma): `.perm-table tbody td` (Acessos) e
   `.preco-itens-table-wrap td` (tabelas dentro do painel de detalhe). */
tbody td{
  padding:1px 16px;border-bottom:1px solid var(--border);vertical-align:middle;
  font-size:13.3px;line-height:28px;white-space:nowrap;
}
tbody tr:last-child td{ border-bottom:none; }
tbody tr:hover{ background:var(--surface-2); }

/* Linhas verticais entre colunas (v2.29.25, pedido do usuário, mockup
   aprovado) — só na listagem de Requisições (REQ-01, ver renderView() em
   frontend.js, que só aplica esta classe quando cfg.key==='requisicoes');
   as demais tabelas do app continuam sem divisórias. Sem linha depois da
   última coluna (:not(:last-child)). */
.tabela-linhas-coluna th:not(:last-child),
.tabela-linhas-coluna td:not(:last-child){ border-right:1px solid var(--border); }
/* Cabeçalho da coluna "Comentários" (REQ-01) virou só o ícone de balão, em
   vez do texto — centralizado, do tamanho de um ícone normal de tabela (ver
   c.thContent/c.thClass em renderView(), frontend.js). */
th.th-icon{ text-align:center; }
th.th-icon svg{ width:13px;height:13px;vertical-align:middle; }

/* Coluna "Ver" (v2.34.0, pedido do usuário): o botão de Visualizar virou a
   PRIMEIRA coluna de toda tabela do sistema (era sempre a última, com
   cabeçalho vazio — ver renderView()/renderProdutosView()/
   renderClientesView()/renderTermTable()/renderCotar() em frontend.js).
   th.th-ver centraliza o rótulo "VER", e td.actions:first-child centraliza
   o botão embaixo dele — só quando .actions é a PRIMEIRA célula da linha
   (exatamente os casos que viraram "Ver"); .actions como ÚLTIMA célula
   (Carteira, Preços de Fábrica, Usuários — botões de texto como "Abrir"/
   "Editar", nunca o ícone de Visualizar) continua com o td.actions{
   text-align:right } de sempre, logo abaixo, sem mudança nenhuma. */
th.th-ver{ text-align:center; }
td.actions:first-child{ text-align:center; }

td.actions{ text-align:right; }
/* Botão de ação (Exibir/Editar) dentro de tabela: por padrão o navegador dá
   ao <button> um line-height baseado no font-size nativo dele (~17px), bem
   maior que os 16px de line-height da célula — isso fazia o botão ficar com
   ~31px de altura e esticar a linha inteira para ~35px, mesmo com o padding
   reduzido. Corrigido travando altura/largura explícitas (do tamanho da
   linha de texto) e centralizando o ícone com flex, em vez de depender do
   line-height do texto do botão.

   v2.47.42 (pedido do usuário, mockup "ver-icone-maior-mockup.html"
   aprovado — Opção A): o ícone de "Ver"/"Exibir" (1ª coluna de toda tabela
   do sistema, ver th.th-ver acima) estava pequeno demais pra enxergar/
   clicar com conforto. Foi de 16px/ícone 12px pra 22px/ícone 18px (+50%),
   mantendo o mesmo visual discreto de sempre (contornado, sem cor) — só o
   tamanho mudou. Cabe folgado dentro dos 28px de line-height da linha (ver
   comentário grande sobre a altura de 30px, mais abaixo). */
td.actions .btn-icon{
  margin-left:4px;padding:1px;border-radius:7px;
  width:22px;height:22px;box-sizing:border-box;
  display:inline-flex;align-items:center;justify-content:center;
}
td.actions .btn-icon svg{ width:18px;height:18px;flex:none; }

.cell-identity{ display:flex;align-items:center;gap:8px; }
.avatar{
  width:34px;height:34px;border-radius:9px;flex:none;object-fit:cover;
  background:var(--primary-soft);color:var(--primary-strong);
  display:flex;align-items:center;justify-content:center;font-weight:800;font-size:12.5px;
  border:1px solid var(--border);
}
/* Dentro de uma linha de tabela, o avatar padrão de 34px não cabe mais —
   encolhido pra 28px só nesse contexto, pedido do usuário, mockup aprovado
   (for01-logo-filtros-contato-mockup.html): antes (até a v2.41.x) era 14px/
   fonte 6.5px, ilegível, pra caber na linha de 18px de então; a linha
   cresceu pra 30px (ver `tbody td` acima) justamente pra acomodar este
   logo maior, sem precisar diminuí-lo mais que isso. Fora de tabela (ex:
   hero de detalhe), o próprio HTML já sobrescreve width/height inline com
   um tamanho maior, sem depender desta regra. */
tbody .avatar{ width:28px;height:28px;border-radius:8px;font-size:11px; }
.cell-identity .name{ font-weight:700;color:var(--ink); }
.cell-identity .sub, tbody .sub{ font-size:11.5px;color:var(--ink-faint); }
/* Badges dentro de tabela: versão compacta pra caber na linha de 18px, sem
   afetar o tamanho normal do badge usado fora de tabelas (detalhes, formulário). */
tbody .badge{ padding:1px 7px;font-size:10px; }

/* v2.47.5 (COT-05, pedido do usuário, mockup
   "cot05-tipo-tempo-espera-novo-mockup.html" aprovado — "aprovado, pode
   gerar os arquivos"): tempo de espera relativo ("há 12 min"/"há 2h"/"há 5
   dias") na coluna Data/Hora da fila de Cotar (ver
   requisicaoTempoEsperaInfo()/renderCotar() em frontend.js), com a data/
   hora absoluta continuando visível, só menorzinha, embaixo. A partir de 3
   dias sem ninguém assumir (.alerta — mesmo limite já usado no painel
   "Precisa de Atenção" da tela Início, inicioAtencaoItens()), o texto
   relativo fica na cor de alerta. tbody td normalmente tem
   white-space:nowrap/line-height:28px (ver regra acima) pensado pra uma
   linha só de texto; aqui a célula precisa de 2 linhas (relativo + data
   exata), então as duas ficam fora do fluxo normal da line-height via
   display:block na segunda linha. */
.tempo-espera{ display:inline-block;line-height:1.3;white-space:nowrap; }
.tempo-espera .rel{ font-weight:600; }
.tempo-espera.alerta .rel{ color:var(--danger); }
.tempo-espera .abs{ display:block;font-size:10.5px;color:var(--ink-faint); }

/* Pílula "Nova" e badge "Em Cotação" ao lado do número (COT-05): existiram
   da v2.47.5 até a v2.47.8 — removidas na v2.47.9 a pedido direto do
   usuário ("pode remover o campo de status, nova e em cotação, não vai
   precisar desse status"), depois que a coluna "FORN" (ver mais abaixo)
   passou a dar essa informação de um jeito mais direto (quantas fábricas
   já responderam). As classes .pill-nova/.badge (status) deixaram de ser
   usadas em renderCotar() — a lógica de "tempo decorrido"/alerta de 3 dias
   (.tempo-espera, logo acima) continua normalmente, só a pílula em si
   saiu.

   "Cotar mais"/"Concluir" (COT-05, v2.47.7, pedido do usuário: "não teria
   uma maneira de deixar essa requisição no meu cotar até que o comprador
   decida que ela saia" — mockup "cot05-manter-no-cotar-mockup.html"
   aprovado): enquanto a requisição já tem cotação mas ainda não foi
   concluída, a coluna de ação da fila de Cotar mostra dois botões em vez
   de um só — "Cotar mais" (reaproveita o mesmo formulário de sempre) e
   "Concluir" (ver abrirConfirmacaoConcluirCotacao() em frontend.js). Até a
   v2.47.8 eram dois <button> de TEXTO empilhados (um em cima do outro);
   v2.47.9 (pedido do usuário vendo a v2.47.8 em uso: "fica um botão em
   cima do outro... não ficou legal, substitua os botões por icones, um ao
   lado do outro" — mockup "cot05-icones-acao-coluna-fabricas-mockup.html"
   aprovado) trocou os dois por ÍCONES lado a lado (mesma moldura do ícone
   "Ver" da 1ª coluna, .btn-icon), com o texto completo só no title
   (tooltip). .btn-icon nunca tem um tamanho padrão de SVG (cada contexto
   define o próprio — ver td.actions/.panel-foot-left acima), por isso
   .cotar-actions .btn-icon svg abaixo. */
.cotar-actions{ display:inline-flex;align-items:center;gap:6px; }
.cotar-actions .btn-icon{ padding:5px; }
.cotar-actions .btn-icon svg{ width:13px;height:13px;flex:none; }
/* Cor de cada ícone — laranja/accent pra "Cotar mais" (ação mais comum,
   mesmo tom que já era o do botão de texto btn-primary) e verde/success
   pra "Concluir" (decisão final do comprador, cor "positiva" de conclusão
   — mesma família do badge-success já usado pro status "Aprovada"). Mesmo
   molde de .btn-icon.danger (acima), só com outras cores. */
.btn-icon.primary{ color:var(--accent);border-color:var(--accent-soft); }
.btn-icon.primary:hover{ background:var(--accent-soft);color:var(--accent);border-color:var(--accent-soft); }
.btn-icon.success{ color:var(--success);border-color:var(--success-soft); }
.btn-icon.success:hover{ background:var(--success-soft);color:var(--success);border-color:var(--success-soft); }

/* Coluna "FORN" (COT-05, v2.47.9, pedido do usuário: "crie uma coluna para
   mostrar o total de fabricas que já estão participando daquela cotação,
   incluindo, comprado, aguardando, não respondeu, não tem, cotado" —
   depois simplificado a pedido dele mesmo pra só o número, sem ícone/cor:
   "nos dados deixe somente os números" — mockup
   "cot05-icones-acao-coluna-fabricas-mockup.html" aprovado): só o número
   total de cotações já registradas pra aquela requisição (ver
   requisicaoFabricasResumo() em frontend.js), texto simples igual à
   coluna "Itens". O detalhe de quantas estão em cada status (Aguardando/
   Sem Resposta/Não Tem/Cotado/Comprado) continua disponível no title
   (tooltip), sem precisar de nenhuma classe/cor nova — só o cursor:default
   abaixo, pra não parecer um link ao passar o mouse num texto com title. */
.fab-total-cell{ cursor:default; }

/* Colunas de texto longo (Marcas / Portfólio): trunca com "..." e mostra a
   lista inteira no title (tooltip nativo do navegador) ao passar o mouse. */
.cell-truncate{
  display:inline-block;max-width:220px;white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;vertical-align:middle;
}
/* Traço neutro da coluna "Comentários" quando a requisição ainda não tem
   nenhum comentário — mockup aprovado: sem ícone nenhum nesse caso, só o
   traço, igual a qualquer outra célula vazia da tabela (ver `— ` já usado em
   várias colunas). */
.cell-dash{ color:var(--ink-faint); }
/* Ícone de balão + badge de não lidos da coluna "Comentários" (só em
   Requisições, ver comentariosCellHtml() em frontend.js). Botão sem borda —
   só o ícone — clicável, pra abrir a tela de comentários direto da linha. */
.cf-comment-cell{
  background:none;border:none;padding:0;cursor:pointer;color:var(--ink-soft);
  display:inline-flex;align-items:center;position:relative;
}
.cf-comment-cell:hover{ color:var(--ink); }
.cf-comment-cell svg{ width:15px;height:15px;flex:none; }
tbody .cf-comment-cell svg{ width:13px;height:13px; }
.cf-comment-badge{
  position:absolute;top:-6px;right:-8px;background:var(--danger);color:#fff;
  font-size:9px;font-weight:800;border-radius:999px;min-width:14px;height:14px;
  display:inline-flex;align-items:center;justify-content:center;padding:0 3px;
  line-height:1;box-shadow:0 0 0 2px var(--surface);
}

.badge{
  display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:999px;
  font-size:11px;font-weight:700;white-space:nowrap;
}
.badge-primary{ background:var(--primary-soft);color:var(--primary-strong); }
.badge-accent{ background:var(--accent-soft);color:var(--accent); }
.badge-muted{ background:var(--surface-2);color:var(--ink-faint);border:1px dashed var(--border); }
.badge-warn{ background:var(--warn-soft);color:var(--warn); }
.badge-success{ background:var(--success-soft);color:var(--success); }
.badge-danger{ background:var(--danger-soft);color:var(--danger); }
/* Ícone dentro de um badge (hoje só a estrela do "★ Principal" do Contato de
   Fornecedor, v2.41.0 — ver fornecedorContatoPrincipalCellHtml()/
   fornecedorContatosDetailHtml() em assets/frontend.js). Nenhum outro badge
   do sistema embute ícone, então isto não afeta os demais. */
.badge svg{ width:11px;height:11px;flex:none; }
/* v2.43.0 — mesma informação de badge-muted/badge-success/badge-danger
   acima, só que como TEXTO SIMPLES, sem a pílula (fundo/padding/raio) — só
   a cor. Pedido do usuário, mockup aprovado (prf01-logo-autocomplete-
   mockup.html): colunas "Marca"/"Validade" (listagem de Preços de Fábrica,
   PRF-01) e "Colunas" (listagem de Carteira e Pendências, CTP-01) deixaram
   de usar pílula colorida — "Validade" mantém a cor (vermelho/vencida,
   verde/válida) mesmo sem o fundo; ver precoFabricaValidadeTexto() em
   assets/frontend.js. As pílulas badge-* continuam existindo, sem mudança,
   em todos os outros lugares que já as usavam (inclusive o hero de detalhe
   da própria Preços de Fábrica, PRF-02). */
.plain-muted{ color:var(--ink-faint); }
.plain-success{ color:var(--success);font-weight:600; }
.plain-danger{ color:var(--danger);font-weight:600; }
/* v2.35.3 — pílulas dos 5 status da Fábrica (ver comentário em --st-yellow
   etc., no :root, e em COT_STATUS_FABRICA_TONE em frontend.js). Classes
   próprias (não reaproveitam badge-warn/badge-danger/badge-accent/
   badge-success acima) pra não recolorir nenhum outro badge do sistema que
   use essas mesmas classes genéricas em telas sem nenhuma relação com
   Cotação. */
.badge-st-yellow{ background:var(--st-yellow-soft);color:var(--st-yellow); }
.badge-st-gray{ background:var(--st-gray-soft);color:var(--st-gray); }
.badge-st-green{ background:var(--st-green-soft);color:var(--st-green); }
.badge-st-purple{ background:var(--st-purple-soft);color:var(--st-purple); }

/* Status da Fábrica na listagem de Cotações (COT-01, v2.32.2, mockup
   "quadradinho" aprovado pelo usuário): texto normal + um quadradinho da
   cor do status ao lado, em vez do badge/pill de fundo colorido — mesmas
   5 cores de sempre (ver COT_STATUS_FABRICA_TONE em assets/frontend.js),
   só aplicadas no quadradinho em vez do fundo inteiro da célula. Usado só
   aqui — a tela "Cotar" continua com o <select class="badge ..."> de
   sempre, sem nenhuma mudança. Prefixo "cot-" pra não colidir com o
   ".status-dot" já existente (bolinha verde "online" do status-pill do
   topo, ver linha ~266 acima — mesmo nome, propósito totalmente
   diferente). */
.cot-status-cell{ display:inline-flex;align-items:center;gap:7px;color:var(--ink);font-weight:500; }
.cot-status-dot{ width:10px;height:10px;flex:none;border-radius:3px; }
.dot-warn{ background:var(--warn); }
.dot-muted{ background:var(--ink-faint); }
.dot-danger{ background:var(--danger); }
.dot-accent{ background:var(--accent); }
.dot-success{ background:var(--success); }
/* v2.35.3 — quadradinhos dos 5 status da Fábrica, mesma ideia do bloco
   ".badge-st-*" acima: cor própria, puxando "-dot" (mais vivo que a dupla
   normal/soft da pílula, ver comentário em --st-yellow-dot etc. no :root). */
.dot-st-yellow{ background:var(--st-yellow-dot); }
.dot-st-gray{ background:var(--st-gray-dot); }
.dot-st-green{ background:var(--st-green-dot); }
.dot-st-purple{ background:var(--st-purple-dot); }

@media (max-width:820px){
  /* v2.49.9 — até aqui (v2.25.0 a v2.49.8), o celular reaproveitava a
     MESMA barra lateral do computador (.sidebar/#nav), só achatada numa
     fileira via display:contents: cada item de CADA grupo virava seu
     próprio ícone solto, um do lado do outro, numa fileira só (sem
     indicação nenhuma de que pertenciam a um grupo) — foi essa fileira
     lotada que o usuário mostrou num print e pediu um modelo de menu +
     submenu pra substituir (mockup "mobile-menu-submenu-mockup.html"
     aprovado: "aprovado, gere os arquivos para eu subir"). A correção da
     v2.49.8 (bug do item "Início" esticado) ainda vivia nessa mesma
     fileira achatada — ela deixou de existir agora que o celular usa uma
     barra PRÓPRIA (.mobile-nav, com 1 ícone por grupo — ver
     mobile-nav-group-btn mais abaixo — em vez de 1 por item), então as
     regras antigas de achatamento (display:contents nos grupos etc.) saíram
     daqui por não terem mais efeito nenhum: .sidebar simplesmente some no
     celular agora, ver logo abaixo. */
  .sidebar{ display:none; }
  .mobile-nav{
    display:flex;position:fixed;left:0;right:0;bottom:0;
    padding:8px 10px;padding-bottom:calc(8px + env(safe-area-inset-bottom,0px));
    z-index:40;border-top:1px solid var(--border);background:var(--surface);
    gap:4px;overflow-x:auto;align-items:center;
  }
  /* Mesmo tamanho compacto (ícone em cima, rótulo embaixo) pros 3 itens
     soltos (Início/Tarefas/Avisos, reaproveitados de TOPO_BLOCKS sem
     nenhuma mudança) e pro botão de cada grupo (.mobile-nav-group-btn) —
     os contadores normais (.nav-count, cinza) continuam escondidos aqui,
     igual sempre foi (sem espaço pra eles num ícone tão pequeno); só o
     contador AGREGADO do grupo (.nav-count-group, logo abaixo) aparece. */
  .mobile-nav .nav-item{
    flex-direction:column;gap:2px;font-size:9.5px;padding:6px 10px;min-width:56px;
    text-align:center;position:relative;
  }
  .mobile-nav .nav-item .nav-count{ display:none; }
  .nav-count-group{
    position:absolute;top:2px;right:7px;background:var(--accent);color:#fff;
    font-size:9px;font-weight:800;border-radius:999px;min-width:15px;height:15px;
    display:flex;align-items:center;justify-content:center;padding:0 3px;
    border:1.5px solid var(--surface);
  }

  /* Gaveta (submenu) do menu mobile — sobe do rodapé quando um
     .mobile-nav-group-btn é tocado (ver openMobileNavSheet() em
     frontend.js), com os itens reais daquele grupo (mesmo HTML que o
     computador já usa dentro de .nav-group-body, só que aqui em formato de
     lista horizontal em vez da fileira de ícones). Mesmo padrão visual de
     .backdrop/.panel (classe "open" controla opacidade/posição, nunca
     display:none) — ver comentário em frontend.js, appShellHtml(). */
  /* bottom:64px (não inset:0 cru) nos dois de propósito: a fileira de
     ícones (.mobile-nav) tem +- essa altura (mesma folga que
     main.content{padding-bottom:64px} já reserva pra ela, logo abaixo) —
     parando o fundo/a gaveta ALI, a barra de ícones continua 100% visível
     e tocável por cima, sem precisar de nenhum truque de z-index (e sem
     cobrir, por engano, o próprio ícone que a pessoa acabou de tocar). */
  .mobile-nav-backdrop{
    display:block;position:fixed;top:0;left:0;right:0;
    bottom:calc(64px + env(safe-area-inset-bottom,0px));
    background:rgba(10,14,11,.4);
    opacity:0;pointer-events:none;transition:opacity .18s ease;z-index:45;
  }
  .mobile-nav-backdrop.open{ opacity:1;pointer-events:auto; }
  .mobile-nav-sheet{
    display:block;position:fixed;left:0;right:0;
    bottom:calc(64px + env(safe-area-inset-bottom,0px));z-index:46;
    background:var(--surface);border-radius:18px 18px 0 0;box-shadow:0 -10px 30px rgba(0,0,0,.22);
    padding:10px 14px 10px;
    max-height:calc(70vh - 64px);overflow-y:auto;
    opacity:0;pointer-events:none;
    transform:translateY(16px);transition:transform .18s ease,opacity .18s ease;
  }
  /* pointer-events:none acima é o que realmente garante que a gaveta
     fechada (sem conteúdo ainda, ou já escolhido um item antes) nunca
     "rouba" o toque de quem tenta tocar na barra de ícones logo abaixo —
     o translateY sozinho não bastaria: antes do primeiro
     openMobileNavSheet(), a gaveta está vazia (sem padding de conteúdo
     nenhum), baixa demais pra o deslocamento afastá-la o suficiente. */
  .mobile-nav-sheet.open{ opacity:1;pointer-events:auto;transform:translateY(0); }
  .mobile-nav-sheet-handle{ width:34px;height:4px;border-radius:999px;background:var(--border);margin:0 auto 10px; }
  .mobile-nav-sheet-head{
    display:flex;align-items:center;gap:9px;margin-bottom:6px;padding-bottom:9px;
    border-bottom:1px solid var(--border);font-size:13.5px;
  }
  .mobile-nav-sheet-gi{
    width:28px;height:28px;border-radius:8px;display:flex;align-items:center;justify-content:center;
    flex:none;background:var(--primary-soft);color:var(--primary-strong);
  }
  .mobile-nav-sheet-gi svg{ width:15px;height:15px; }
  .mobile-nav-sheet-items{ display:flex;flex-direction:column;gap:1px; }
  /* Dentro da gaveta, cada item volta a ser uma linha horizontal (ícone +
     rótulo + contador), não o ícone compacto empilhado da fileira — vence
     por especificidade (2 classes/combinador) contra a regra genérica
     ".nav-item{...}" do celular, sem precisar de !important nem de truque
     de ordem no arquivo. */
  .mobile-nav-sheet .nav-item{
    flex-direction:row;justify-content:flex-start;gap:11px;font-size:13px;font-weight:600;
    padding:10px 6px;min-width:0;text-align:left;border-radius:9px;color:var(--ink);
  }
  .mobile-nav-sheet .nav-item svg{ width:17px;height:17px; }
  .mobile-nav-sheet .nav-item:active{ background:var(--surface-2); }
  .mobile-nav-sheet .nav-item.active{ background:var(--primary-soft);color:var(--primary-strong);font-weight:700; }
  .mobile-nav-sheet .nav-item .nav-count{ display:inline-flex;margin-left:auto; }

  .nav-label{ display:none; }
  main.content{ padding-bottom:64px; }
  .topbar,.toolbar,.view-area{ padding-left:18px;padding-right:18px; }
  /* A rolagem própria da tabela (ver .table-wrap fora deste media query) é
     coisa de tela larga, com cabeçalho de coluna visível — no celular o
     cabeçalho já some (thead{display:none} logo abaixo) e a lista de
     cartões deve rolar junto com o resto da página, como sempre rolou. */
  .table-wrap{ max-height:none;min-height:0;overflow:visible; }
  table,thead,tbody,th,td,tr{ display:block; }
  thead{ display:none; }
  tbody tr{ border-bottom:1px solid var(--border);padding:12px 4px;display:flex;flex-direction:column;gap:6px; }
  /* No celular a tabela vira uma lista de cartões (um campo por linha,
     empilhados) — a altura fixa de 18px e o white-space:nowrap do desktop
     não se aplicam aqui, senão o valor de campos mais longos vazaria da tela. */
  tbody td{
    border:none;padding:0 12px;display:flex;justify-content:space-between;gap:12px;align-items:center;
    white-space:normal;line-height:1.3;
  }
  tbody td[data-label]::before{
    content:attr(data-label);font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;
    color:var(--ink-faint);font-weight:700;flex:none;
  }
  td.actions{ justify-content:flex-end;padding-top:4px; }
  td.actions::before{ display:none; }
  /* Desfaz o tamanho fixo de 16px usado no desktop (ver comentário acima da
     regra `td.actions .btn-icon` fora do media query) — no celular o botão
     volta ao tamanho natural, maior e mais fácil de tocar. */
  td.actions .btn-icon{ padding:7px;width:auto;height:auto;display:inline-block; }
  td.actions .btn-icon svg{ width:auto;height:auto; }
  .cell-truncate{ max-width:100%;min-width:0;flex:1;text-align:right; }
  tbody .avatar{ width:34px;height:34px;border-radius:9px;font-size:12.5px; }
}

/* ---------- painel lateral ---------- */
.backdrop{
  position:fixed;inset:0;background:rgba(10,14,11,.42);opacity:0;pointer-events:none;
  transition:opacity .18s ease;z-index:50;
}
.backdrop.open{ opacity:1;pointer-events:auto; }
/* ---------- painel: modal central retangular ----------
   Era uma gaveta deslizando pela direita (position:fixed;right:0). Mudança
   pedida pelo usuário (mockup "Visualizar/Editar/Lixeira" aprovado): agora é
   um cartão centralizado na tela, fechando com escala+opacidade em vez de
   deslizar. .panel-wide/.panel-xwide continuam existindo, só a largura-base
   mudou (ver comentário em cada uma). */
.panel{
  position:fixed;top:50%;left:50%;
  width:min(640px,92vw);max-height:min(780px,88vh);
  background:var(--surface);box-shadow:var(--shadow-lg);border-radius:20px;
  transform:translate(-50%,-50%) scale(.96);opacity:0;pointer-events:none;
  transition:opacity .18s ease,transform .18s cubic-bezier(.32,.72,0,1);
  z-index:51;display:flex;flex-direction:column;overflow:hidden;
}
.panel.open{ transform:translate(-50%,-50%) scale(1);opacity:1;pointer-events:auto; }
.panel.panel-wide{ width:min(760px,94vw); }
/* 1400px -> 1480px na v2.26.5: o botão de remover produto (REQ-02) virou
   mais uma coluna na mesma linha dos outros campos do produto (ver
   .item-grid-single logo abaixo) — um pouco mais de largura evita apertar
   o resto da linha. */
.panel.panel-xwide{ width:min(1480px,97vw);max-height:min(860px,92vh); }
/* v2.47.33 — painel "Itens Cotados" da tela "Req Cotadas" (ver
   abrirItensCotadosRequisicao() em assets/frontend.js): a tabela de decisão
   não cabia confortavelmente no .panel-wide padrão (760px) — mockup
   aprovado já sinalizava isso. Mais estreito que .panel-xwide (1480px,
   pensado pra tabelas bem maiores, como a CMP-03 de 17 colunas). Limpa
   sozinha ao fechar o painel — ver closePanel().
   v2.47.34 — 980px → 1360px: "Produto/Marca/Qtd" virou "Solicitado" (1
   coluna) + "Disponível na Fábrica" (3 colunas), 6 colunas de dado viraram
   9 — testado com Playwright até caber tudo sem cortar nem precisar rolar. */
.panel.panel-cotados{ width:min(1360px,96vw); }
@media (max-width:560px){
  .panel{ width:94vw;max-height:92vh;border-radius:16px; }
}

/* ================= COT-01 (v2.48.0): agrupada por Requisição =================
   Pedido do usuário, numa sequência de mockups aprovados ("aprovado, gere os
   arquivos para eu subir"): a listagem deixou de ter 1 linha por cotação
   (produto × fábrica) e passou a ter 1 linha por REQUISIÇÃO — nem o nome da
   fábrica nem o produto aparecem mais nela ("na cot-01 também não vai mostrar
   o produto, o produto vai aparecer quando clicar em visualizar juntos com
   as fabricas"). O "Ver" (.panel-cotados acima, reaproveitado) mostra um
   card por fornecedor, rolando na horizontal ("faça em formato horizontal,
   os cards rolar horizontal") — dentro de cada card, os itens que aquele
   fornecedor cotou. Ver cotAgruparPorRequisicao()/renderCotacoesLista()/
   cotacaoAgrupadaDetailHtml() em frontend.js. */
.cot01-th-c, .cot01-td-c{ text-align:center; }
.cot01-status-stack{ display:inline-flex; align-items:center; }
.cot01-status-stack .status-ic-btn{ margin-left:-7px; border:2px solid var(--surface); box-sizing:border-box; }
.cot01-status-stack .status-ic-btn:first-child{ margin-left:0; }

/* v2.49.4 (pedido do usuário, mockup "cot04-historico-rodape-preco-linha-
   logo-mockup.html" aprovado): ".cot01-detail-layout" deixa de ser o flex
   de 3 colunas (railLeft/main/histórico) direto — passa a empilhar em
   coluna um novo ".cot01-detail-top" (que É o flex de 2 colunas de antes,
   só sem o histórico) com o histórico (".cot01-detail-hist", agora de
   largura total) embaixo. */
.cot01-detail-layout{ display:flex; flex-direction:column; gap:16px; height:100%; min-height:0; }
.cot01-detail-top{ display:flex; gap:16px; flex:1; min-height:0; }
.cot01-detail-rail{
  width:190px; flex:none; background:var(--surface-2); border:1px solid var(--border); border-radius:12px;
  padding:16px; overflow-y:auto;
}
.cot01-rail-kv{ padding-top:12px; border-top:1px solid var(--border); margin-top:12px; }
.cot01-rail-kv:first-child{ padding-top:0; border-top:none; margin-top:0; }
.cot01-rail-kv .k{ font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-faint);font-weight:700;display:block; }
.cot01-rail-kv .v{ font-size:13.5px;color:var(--ink);margin-top:3px;display:block; }
.cot01-rail-kv .v.empty{ color:var(--ink-faint);font-style:italic; }

.cot01-detail-main{ flex:1; min-width:0; display:flex; flex-direction:column; min-height:0; }
.cot01-detail-section-title{
  font-size:10.5px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--primary-strong);
  margin:0 0 10px; flex:none;
}
.cot01-forn-scroll{ display:flex; gap:12px; overflow-x:auto; padding-bottom:6px; flex:1; min-height:0; }
.cot01-forn-card{
  flex:none; width:230px; border:1px solid var(--border); border-radius:12px; overflow:hidden;
  display:flex; flex-direction:column; background:var(--surface);
}
.cot01-forn-card.ghost{ width:160px; background:var(--surface-2); }
.cot01-forn-card-head{
  display:flex; align-items:center; justify-content:space-between; gap:8px; padding:10px 12px;
  border-bottom:1px solid var(--border); background:var(--surface-2); flex:none;
}
.cot01-forn-card.ghost .cot01-forn-card-head{ border-bottom:none; background:transparent; }
/* v2.49.4 (pedido do usuário, mesmo mockup acima): logo da fábrica (ou
   iniciais, ".fabrica-logo" dentro de ".cotcard-logo-mini" — mesma dupla
   de classes já usada nos cards de COT-02/Comparativo) antes do nome, no
   topo do card. Precisa de um wrapper flex próprio porque, ao lado dela,
   o nome/subtítulo continuam empilhados (nome em cima, "X de Y itens"
   embaixo) — min-width:0 deixa o nome truncar com "..." em vez de
   espremer a logo ou vazar pra fora do card. */
.cot01-forn-head-nome{ display:flex; align-items:center; gap:8px; min-width:0; }
.cot01-forn-name{ font-weight:800; font-size:13px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.cot01-forn-sub{ font-size:10px; color:var(--ink-faint); margin-top:1px; }
.cot01-forn-card-body{ padding:8px 10px 10px; overflow-y:auto; flex:1; min-height:0; }
.cot01-forn-empty{ padding:2px 10px 10px; font-size:11.5px; color:var(--ink-faint); font-style:italic; line-height:1.4; }
.cot01-forn-faltantes{ margin-top:8px; padding-top:8px; border-top:1px dashed var(--border); font-size:10px; color:var(--ink-faint); font-style:italic; line-height:1.5; }

.cot01-item-mini{ border:1px solid var(--border); border-radius:9px; padding:8px 10px; margin-bottom:7px; }
.cot01-item-mini:last-child{ margin-bottom:0; }
.cot01-item-mini.is-vencedora{ border-color:var(--success); background:var(--success-soft); }
.cot01-item-popt{ font-size:9px; color:var(--ink-faint); font-weight:700; text-transform:uppercase; letter-spacing:.03em; display:block; margin-bottom:2px; }
.cot01-item-pname{ font-weight:700; font-size:11.5px; line-height:1.3; }
/* v2.49.4 (pedido do usuário, mesmo mockup acima): Preço e Qtd. Disp./
   Prazo, antes em 2 linhas (".cot01-item-price-row" sozinho em cima,
   ".cot01-item-meta" sozinho embaixo), passam a viver na MESMA linha —
   mesmo princípio já usado nos cards de COT-02/Comparativo. ".cot01-item-
   price-row" (classe antiga) sai de uso. */
.cot01-item-linha-preco{ display:flex; align-items:baseline; gap:8px; margin-top:4px; flex-wrap:wrap; }
.cot01-item-price{ font-weight:800; color:var(--primary-strong); font-size:13px; }
.cot01-item-meta{ font-size:9.5px; color:var(--ink-faint); }
.cot01-item-vencedora{ display:inline-block; margin-top:5px; padding:1px 7px; font-size:9.5px; }

/* v2.49.4 (pedido do usuário, mesmo mockup acima): "Histórico de
   Alterações" deixa de ser uma coluna lateral fixa (210px) e passa a ser
   um bloco de largura total, embaixo de railLeft/main (".cot01-detail-
   top", ver mais acima) — ver ".cot01-detail-layout" no começo do
   arquivo. A timeline (".cf-historico-timeline", compartilhada com
   Fornecedores/Requisições/Produtos/Referências — NÃO pode mudar a
   regra-base) ganha aqui, só dentro de ".cot01-detail-hist", uma versão
   em linha (em vez de empilhada) — cabem vários eventos lado a lado no
   espaço horizontal ganho, com rolagem lateral quando sobrar mais do que
   cabe; a linha vertical que liga os pontos (".cf-historico-item::before",
   pensada pra timeline empilhada) não faz sentido deitada, então some só
   aqui. */
.cot01-detail-hist{
  width:auto; flex:none; background:var(--surface-2); border:1px solid var(--border); border-radius:12px;
  padding:16px; overflow-y:visible;
}
.cot01-detail-hist .cf-historico-block{ margin-top:0; padding-top:0; border-top:none; background:transparent; }
.cot01-detail-hist .cf-historico-block h3{ margin:0 0 12px; font-size:12.5px; }
.cot01-detail-hist .cf-historico-timeline{ flex-direction:row; gap:18px; overflow-x:auto; padding-bottom:4px; }
.cot01-detail-hist .cf-historico-item{ flex:none; width:220px; padding-bottom:0; }
.cot01-detail-hist .cf-historico-item::before{ display:none; }
.cot01-hist-tag{
  display:inline-block; font-size:9px; font-weight:700; color:var(--primary-strong); background:var(--primary-soft);
  padding:1px 6px; border-radius:5px; margin-bottom:3px;
}

/* ===== card "Produtos da Requisição" (v2.48.1) — 1º card da fileira, antes
   dos fornecedores. Pedido do usuário vendo a tela em produção: "nesse tela
   precisa constar a lista de produto que o requisitante fez quando gerou
   essa requisição" → depois "coloque em um card para aparecer antes da
   cotação da primeira fabrica". Reaproveita .cot01-forn-card como base, só
   com borda/cabeçalho na cor principal pra não confundir com um fornecedor
   de verdade. ===== */
.cot01-forn-card.req-card{ width:250px; border-color:var(--primary); border-width:1.5px; }
.cot01-forn-card.req-card .cot01-forn-card-head{ background:var(--primary-soft); border-bottom-color:var(--primary); }
.cot01-forn-card.req-card .cot01-forn-name{ color:var(--primary-strong); }
.req-card-icon{
  width:22px; height:22px; border-radius:7px; background:var(--primary-strong); color:#fff;
  display:flex; align-items:center; justify-content:center; flex:none;
}
.req-card-icon svg{ width:13px; height:13px; }
.rp-item{ border:1px solid var(--border); border-radius:9px; padding:8px 10px; margin-bottom:7px; }
.rp-item:last-child{ margin-bottom:0; }
.rp-item .pname{ font-weight:700; font-size:11.5px; line-height:1.3; }
.rp-item .pmeta{ font-size:9.5px; color:var(--ink-faint); margin-top:2px; }
.rp-status{ display:inline-flex; align-items:center; gap:5px; font-size:9.5px; font-weight:700; margin-top:5px; }
.rp-dot{ width:7px; height:7px; border-radius:50%; flex:none; }
.rp-dot.ok{ background:var(--success); }
.rp-dot.pend{ background:var(--ink-faint); }
.rp-status.ok{ color:var(--success); }
.rp-status.pend{ color:var(--ink-faint); }

@media (max-width:860px){
  .cot01-detail-layout{ height:auto; }
  .cot01-detail-top{ flex-direction:column; }
  .cot01-detail-rail{ width:auto; }
  .cot01-forn-card{ width:220px; }
  .cot01-forn-card.req-card{ width:220px; }
}
.panel-head{
  display:flex;align-items:flex-start;justify-content:space-between;gap:10px;
  padding:22px 24px 16px;border-bottom:1px solid var(--border);flex:none;
}
.panel-head h2{ font-size:18px;margin:0 0 3px; }
.panel-head p{ margin:0;font-size:12px;color:var(--ink-faint); }
/* O formulário (<form id="recordForm">) é filho direto de .panel (que é
   flex-column), mas um <form> comum não vira container flex sozinho — sem
   esta regra, .panel-body (dentro dele) nunca ganha uma altura limitada e o
   "overflow:auto" abaixo não tem efeito nenhum: o painel simplesmente cresce
   até sair da tela quando o conteúdo é grande (como acontece com várias
   linhas de Marcas/Portfólio), sem barra de rolagem e sem acesso aos campos
   e ao botão Salvar que ficam mais abaixo. */
.panel > form{ display:flex; flex-direction:column; flex:1; min-height:0; }
.panel-body{ flex:1;overflow:auto;padding:22px 24px;min-height:0; }
.panel-foot{
  padding:14px 24px;border-top:1px solid var(--border);display:flex;align-items:center;justify-content:flex-end;gap:8px;
  background:var(--surface);flex:none;
}
/* Rodapé com dois grupos (Lixeira/Excluir Definitivamente à esquerda, Editar/
   Reativar à direita) — ver openGenericDetail()/openReferenciaDetail()/
   openRequisicaoDetail() em frontend.js. Quando só o grupo da direita tem
   conteúdo (a maioria das telas — nenhuma ação de lixeira, ex: formulário,
   Calcular Preço de Venda), a regra abaixo empurra ele pro canto sem precisar
   de um caso especial. */
.panel-foot{ justify-content:space-between; }
.panel-foot-left{ display:flex;align-items:center;gap:8px; }
.panel-foot-right{ display:flex;align-items:center;gap:8px;margin-left:auto; }
.panel-foot-caption{ font-size:10px;color:var(--ink-faint);margin-top:2px; }
.detail-inactive-banner{
  margin:0 0 20px;padding:11px 14px;border-radius:10px;background:var(--danger-soft);color:var(--danger);
  font-size:12px;display:flex;align-items:center;gap:9px;flex:none;
}
.detail-inactive-banner svg{ flex:none;width:16px;height:16px; }
.badge-inactive{ background:var(--danger-soft);color:var(--danger); }
.panel-foot-left .btn-icon svg{ width:16px;height:16px;flex:none; }
.btn-link-danger .lbl svg{ width:15px;height:15px;flex:none; }

/* Confirmação de Lixeira/Excluir Definitivamente — telas próprias no mockup
   aprovado (não um confirm() nativo do navegador), reaproveitando o mesmo
   #detailPanel encolhido pela classe .panel-confirm. */
.panel.panel-confirm{ width:min(460px,90vw); }
.confirm-body{ display:flex;flex-direction:column;align-items:center;text-align:center;gap:14px;padding:32px 28px 8px; }
.confirm-icon{ width:56px;height:56px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex:none; }
.confirm-icon svg{ width:28px;height:28px; }
.confirm-icon.tone-warn{ background:var(--warn-soft);color:var(--warn); }
.confirm-icon.tone-danger{ background:var(--danger-soft);color:var(--danger); }
.confirm-title{ font-family:'Manrope',Inter,system-ui,sans-serif;font-weight:800;font-size:17px;text-transform:uppercase;letter-spacing:-.01em; }
.confirm-title.tone-danger{ color:var(--danger); }
.confirm-text{ font-size:13px;color:var(--ink-soft);line-height:1.5; }
.confirm-actions{ padding:22px 28px 28px;display:flex;justify-content:center;gap:10px;flex:none; }

.field-grid{ display:grid;grid-template-columns:1fr 1fr;gap:14px 14px; }
/* Cabeçalho da "Nova Requisição" em 2 linhas (v2.29.23, mockup aprovado,
   substitui o .field-grid-3 da v2.29.22) — grids próprios, só usados pelo
   formulário de Requisição (ver openRequisicaoForm() em frontend.js), sem
   tocar no .field-grid genérico (continua 1fr/1fr pros outros formulários).
   Requisitante e Categoria usam o MESMO valor fixo — como ficam na 1ª
   coluna de uma linha e na 2ª coluna da outra, só largura fixa igual
   garante que fiquem alinhados/com a mesma largura nas duas linhas; fr não
   garantiria isso (fr é proporcional à coluna, não ao valor absoluto).
   v2.29.24 (pedido do usuário): aumentado de 210px para 300px, pra ficar do
   mesmo tamanho do campo "Produto" da linha de produtos (.item-grid-single,
   coluna 1.25fr — ~300px é o quanto essa coluna mede num painel largo, já
   descontando as outras colunas fixas/gap daquele grid; os dois grids têm
   proporções diferentes, então a largura bate certinho só numa janela
   grande, mas aproxima bem na maioria das telas).
   Data fica fixa e estreita (110px, só o suficiente pra "DD/MM/AAAA").
   Cliente, Tipo de Requisição e Local Cotar dividem o espaço que sobra em
   cada linha (fr) — aumentar o valor fixo de Requisitante/Categoria reduz
   proporcionalmente o espaço sobrando pra Tipo de Requisição, encolhendo o
   vão entre o chip "Urgente" e o campo Categoria. */
.requisicao-fields-top{ display:grid;grid-template-columns:300px 110px 1fr;gap:14px 14px; }
.requisicao-fields-bottom{ display:grid;grid-template-columns:1.3fr 300px 1fr;gap:14px 14px;margin-top:14px; }
.field{ display:flex;flex-direction:column;gap:5px;min-width:0; }
.field.col-2{ grid-column:1 / -1; }
@media (max-width:520px){ .field-grid{ grid-template-columns:1fr; } .requisicao-fields-top,.requisicao-fields-bottom{ grid-template-columns:1fr; } .field.col-2{ grid-column:auto; } }
.field label{ font-size:11.5px;font-weight:700;color:var(--ink-soft); }
.field .hint{ font-size:11px;color:var(--ink-faint); }
.field input[type="text"],.field input[type="email"],.field input[type="tel"],
.field input[type="date"],.field input[type="number"],.field textarea,.field select{
  padding:9px 11px;border-radius:8px;border:1px solid var(--border);background:var(--surface-2);
  color:var(--ink);font-size:13.3px;outline:none;width:100%;
}
.field textarea{ min-height:72px;resize:vertical;font-family:inherit; }
.field input:focus,.field select:focus,.field textarea:focus{ border-color:var(--primary);background:var(--surface); }
.field.invalid input,.field.invalid select,.field.invalid textarea{ border-color:var(--danger);background:var(--danger-soft); }
.field .error-msg{ font-size:11px;color:var(--danger);display:none; }
.field.invalid .error-msg{ display:block; }
/* Campo gerado pelo servidor, nunca digitado (type:'auto' — ver fieldHtml()
   em assets/frontend.js; hoje só o Código da Tabela de Vendas, v2.27.0): só
   o texto mais apagado e o cursor de "bloqueado" — o fundo já é igual ao de
   um campo comum sem foco (var(--surface-2) na regra acima), de propósito,
   pra não parecer quebrado/vazio antes de salvar. */
.field input:disabled{ color:var(--ink-faint);cursor:not-allowed; }
/* Checkbox genérico (type:'checkbox' — ver fieldHtml() em assets/frontend.js;
   hoje só "Cálculo Manual" da Tabela de Vendas, v2.27.1): o rótulo do campo
   (field.label, ex: "Cálculo Manual") continua em cima, igual aos outros
   tipos — aqui só o checkbox + o texto explicativo (field.checkboxLabel) lado
   a lado, clicáveis como um todo. */
.checkbox-field{ display:flex;align-items:flex-start;gap:8px;font-size:12.5px;font-weight:400;color:var(--ink);cursor:pointer;line-height:1.4; }
.checkbox-field input[type="checkbox"]{ width:16px;height:16px;flex:none;margin-top:1px;accent-color:var(--primary);cursor:pointer; }
.currency-input{ display:flex;align-items:center;border:1px solid var(--border);border-radius:8px;background:var(--surface-2);overflow:hidden; }
.currency-input span{ padding:0 0 0 11px;color:var(--ink-faint);font-size:12.5px; }
.currency-input input{ border:none!important;background:transparent!important;flex:1; }

/* Campo de lista (Marcas Representadas / Portfólio do Fornecedor, FOR-02) —
   v2.48.5, pedido do usuário vendo a tela em produção (print real com 9
   marcas, uma por linha): "vamos organizar melhor essa parte das marcas,
   pode colocar uma na frete da outra para aproveita os espaços, os campos
   das marcas já cadastradas por ser do tamanho do nome da marca, pode fazer
   isso para marcas e portfolio". Mockup aprovado, e numa 2ª rodada o botão
   de remover (até então uma caixa própria do lado do campo) foi encolhido a
   pedido do usuário: "esse icone para excuir pode ser bem menor, esta
   ocupando muito espaço [...] veja outra forma para excluir". Aprovado com
   "aprovado, pode gerar os arquivos".
   Era uma lista em coluna, cada item numa linha inteira (input ocupando
   100% da largura + botão "×" quadrado do lado, próprio com borda/fundo).
   Agora cada item vira um "chip" — texto + "×" embutido no mesmo pacote
   arredondado, sem caixa própria —, do tamanho do próprio texto (largura
   recalculada a cada letra digitada, ver cfSizeChipInput() em frontend.js),
   lado a lado, quebrando linha sozinho quando não cabe mais. */
.cf-chip-wrap{ display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px; }
.cf-chip{
  display:inline-flex;align-items:center;
  background:var(--surface-2);border:1px solid var(--border);border-radius:999px;
  padding:5px 5px 5px 12px;transition:border-color .12s ease,background .12s ease;
}
.cf-chip:focus-within{ border-color:var(--primary);background:var(--surface); }
/* v2.48.6 — correção de bug visto pelo usuário já em produção (print real):
   várias marcas apareciam com o texto cortado dentro do chip (ex: "ALE",
   "BR", "CHAN" em vez do nome completo), algumas até em branco. Causa:
   ".field input[type=\"text\"]" (a regra genérica de todo input de texto
   dentro de um .field, mais acima neste arquivo) tem MAIS especificidade
   CSS que ".cf-chip-input" sozinha (duas classes/atributos + 1 tipo contra
   uma classe só) — então o padding:9px 11px/border/background daquela
   regra genérica continuavam vencendo por baixo dos panos, mesmo com
   padding:0/border:none declarados aqui. Isso roubava ~24px da largura
   calculada por cfSizeChipInput() (que assume largura só de texto, sem
   padding/borda nenhuma) — sobrava menos espaço do que o texto precisava,
   cortando as últimas letras (ou, em nomes curtos, cortando tudo). Os
   !important abaixo (só nessas propriedades — nunca em "width", que
   continua controlada pelo JS a cada letra digitada) garantem que o chip
   sempre vença essa regra genérica, não importa a ordem das regras no
   arquivo. */
.cf-chip-input{
  border:none!important;background:transparent!important;outline:none;padding:0!important;margin:0;
  border-radius:0!important;font-size:13.3px;color:var(--ink);width:60px;min-width:18px;
}
.cf-chip-remove{
  flex:none;width:18px;height:18px;margin-left:3px;border-radius:50%;border:none;
  background:transparent;color:var(--ink-faint);font-size:13px;line-height:1;cursor:pointer;
  display:flex;align-items:center;justify-content:center;
}
.cf-chip-remove:hover{ background:var(--danger-soft);color:var(--danger); }
.cf-list-add-btn{ align-self:flex-start; }

/* ---- campo de Contatos (v2.41.0, Fornecedor — mockup aprovado) ----
   Um cartão por pessoa, com cabeçalho (numeração + estrela "Principal" +
   remover) e uma grade de 6 sub-campos. Ver contatosFieldBlock()/
   renderContatosField() em assets/frontend.js. */
.cf-contatos-wrap{ display:flex;flex-direction:column;gap:12px;margin-bottom:8px; }
.empty-contatos{ color:var(--ink-faint);font-size:13px;font-style:italic;margin:0; }
.contato-card{
  border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface-2);
  padding:12px 14px;
}
.contato-card.is-principal{ border-color:var(--warn);background:var(--warn-soft); }
.contato-card-head{ display:flex;align-items:center;gap:8px;margin-bottom:10px; }
.contato-card-num{ font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-faint);font-weight:700;flex:1; }
.star-btn{
  display:inline-flex;align-items:center;gap:5px;padding:5px 10px;border-radius:999px;
  border:1px solid var(--border);background:var(--surface);color:var(--ink-soft);font-size:11.5px;
  font-weight:700;cursor:pointer;flex:none;
}
.star-btn svg{ width:13px;height:13px;flex:none; }
.star-btn.is-on{ background:var(--warn);border-color:var(--warn);color:#fff; }
.star-btn:not(.is-on):hover{ background:var(--surface-2); }
.contato-card .btn-icon{ flex:none; }
.contato-card .btn-icon svg{ width:14px;height:14px;flex:none; }
.contato-fields{ display:grid;grid-template-columns:1fr 1fr;gap:10px 14px; }
.contato-subfield{ display:flex;flex-direction:column;gap:4px; }
.contato-subfield label{ font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-faint);font-weight:700; }
@media (max-width:520px){ .contato-fields{ grid-template-columns:1fr; } }

/* ---- Contatos no painel "Visualizar" do Fornecedor (openGenericDetail(),
   fornecedorContatosDetailHtml()) ---- */
.contatos-detail-section{ margin-top:22px; }
.contatos-detail-title{ margin:0 0 10px;font-size:13px;color:var(--ink-faint);text-transform:uppercase;letter-spacing:.05em;font-weight:700; }
.contatos-detail-grid{ display:grid;grid-template-columns:1fr 1fr;gap:12px; }
@media (max-width:520px){ .contatos-detail-grid{ grid-template-columns:1fr; } }
.contato-view-card{ border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface-2);padding:12px 14px; }
.contato-view-card.is-principal{ border-color:var(--warn);background:var(--warn-soft); }
.cvc-head{ display:flex;align-items:center;gap:8px;flex-wrap:wrap; }
.cvc-nome{ font-weight:700;color:var(--ink); }
.cvc-depto{ font-size:12px;color:var(--ink-faint);margin-top:2px; }
.cvc-meta{ display:flex;flex-direction:column;gap:4px;margin-top:8px;font-size:12.5px; }
.cvc-meta a, .cvc-meta span{ color:var(--ink-soft);text-decoration:none; }
.cvc-meta a:hover{ text-decoration:underline; }

/* ---- FOR-03 (painel "Visualizar" do Fornecedor) redesenhada — v2.48.2,
   pedido do usuário ("da pra fazer algo parecido com a tela FOR-03?"),
   escolheu as 3 opções oferecidas: contatos em cards horizontais,
   marcas/portfólio como cards, e reorganizar a tela toda. Mesmo espírito
   arquitetural da COT-01 (ver .cot01-detail-* acima): trilha à esquerda
   com os dados de identificação, área principal com seções de cards que
   rolam na horizontal. Substitui, só para o módulo "fornecedores", o
   .detail-hero/.detail-grid/.contatos-detail-* genéricos acima (que
   continuam intocados e em uso pelos outros cadastros — Produtos,
   Clientes, etc. — via openGenericDetail()). Ver fornecedorDetailBodyHtml()/
   openFornecedorDetail() em assets/frontend.js. */
.for03-detail-layout{ display:flex; gap:16px; height:100%; min-height:0; }
.for03-rail{
  width:220px; flex:none; background:var(--surface-2); border:1px solid var(--border); border-radius:12px;
  padding:18px; overflow-y:auto;
}
/* Logo do fornecedor (v2.48.3, pedido do usuário vendo a tela em produção:
   "quero que o logo da fabrica fique maior, que seja quase da mesma largura
   da coluna e a altura proporcional a isso") — ocupa quase toda a largura da
   trilha, altura livre (object-fit:contain, nunca estica/corta), com um teto
   de altura pra um logo muito "alto" não dominar a trilha inteira. */
.for03-rail-logo-box{
  width:100%; background:var(--surface); border:1px solid var(--border); border-radius:10px;
  padding:8px; display:flex; align-items:center; justify-content:center; margin-bottom:12px; max-height:150px; overflow:hidden;
}
.for03-rail-logo-box img{ width:100%; height:auto; max-height:134px; object-fit:contain; display:block; }
/* Sem logo cadastrado: iniciais pequenas (initials()), igual ao resto do
   app — não tem o que ampliar sem imagem nenhuma. */
.for03-rail-avatar{
  width:52px; height:52px; border-radius:12px; background:var(--primary-strong); color:#fff;
  display:flex; align-items:center; justify-content:center; font-weight:800; font-size:18px; margin-bottom:12px;
}
.for03-rail-nome{ font-weight:800; font-size:15px; line-height:1.3; margin-bottom:14px; word-break:break-word; }
.for03-rail-kv{ padding-top:12px; border-top:1px solid var(--border); margin-top:12px; }
.for03-rail-kv:first-of-type{ padding-top:0; border-top:none; margin-top:0; }
.for03-rail-kv .k{ font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-faint);font-weight:700;display:block; }
.for03-rail-kv .v{ font-size:13.5px;color:var(--ink);margin-top:3px;display:block; }
.for03-rail-kv .v.empty{ color:var(--ink-faint);font-style:italic; }

.for03-main{ flex:1; min-width:0; display:flex; flex-direction:column; gap:20px; overflow-y:auto; }
.for03-section-title{ font-size:10.5px; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:var(--primary-strong); margin:0 0 10px; }
.for03-scroll{ display:flex; gap:12px; overflow-x:auto; padding-bottom:8px; }
.for03-empty-inline{ font-size:12px; color:var(--ink-faint); font-style:italic; }

.for03-contato-card{ flex:none; width:220px; border:1px solid var(--border); border-radius:12px; padding:12px 13px; background:var(--surface); }
.for03-contato-card.is-principal{ border-color:var(--warn); background:var(--warn-soft); }
.for03-contato-head{ display:flex; align-items:center; justify-content:space-between; gap:6px; margin-bottom:4px; }
.for03-contato-nome{ font-weight:800; font-size:13px; }
.for03-contato-badge{ display:inline-flex; align-items:center; gap:3px; font-size:9.5px; font-weight:700; color:var(--warn); background:var(--surface); padding:1px 6px; border-radius:999px; flex:none; }
.for03-contato-badge svg{ width:10px; height:10px; }
.for03-contato-depto{ font-size:10.5px; color:var(--ink-faint); margin-bottom:6px; }
/* Ícone antes do telefone/WhatsApp/Teams/e-mail, sem o rótulo de texto
   ("Tel:" etc.) — v2.48.3, pedido do usuário: "quero que tenha um ícone
   antes do telefone, whatsapp, teams e email... não precisa colocar o nome
   tel. exemplo, basta colocar os ícones". .for03-contato-line serve tanto
   pro <a> (tel/whatsapp/e-mail, clicáveis) quanto pro <span> (Teams, sem
   link) — mesmo layout pros dois. */
.for03-contato-meta{ display:flex; flex-direction:column; gap:5px; margin-top:6px; }
.for03-contato-line{ display:flex; align-items:center; gap:6px; font-size:11px; color:var(--ink-soft); text-decoration:none; }
.for03-contato-line svg{ width:13px; height:13px; flex:none; color:var(--ink-faint); }
a.for03-contato-line:hover{ color:var(--primary); text-decoration:underline; }
a.for03-contato-line:hover svg{ color:var(--primary); }

.for03-chip-card{ flex:none; width:128px; border:1px solid var(--border); border-radius:12px; padding:12px 10px; background:var(--surface); text-align:center; }
.for03-chip-icon{
  width:30px; height:30px; border-radius:9px; background:var(--primary-soft); color:var(--primary-strong);
  display:flex; align-items:center; justify-content:center; margin:0 auto 8px;
}
.for03-chip-icon svg{ width:16px; height:16px; }
/* Logo real da marca/item de portfólio (v2.48.3, pedido do usuário — ver
   comentário em fornecedorMarcaChipHtml()/fornecedorPortfolioChipHtml() em
   assets/frontend.js) no lugar do ícone genérico, quando cadastrado. */
.for03-chip-icon.for03-chip-icon-logo{ background:var(--surface); border:1px solid var(--border); padding:3px; }
.for03-chip-icon-logo img{ width:100%; height:100%; object-fit:contain; border-radius:5px; }
.for03-chip-nome{ font-weight:700; font-size:11.5px; line-height:1.3; word-break:break-word; }

@media (max-width:860px){
  .for03-detail-layout{ flex-direction:column; height:auto; }
  .for03-rail{ width:auto; }
}

/* ---- pares marca/código (Referências Cruzadas) ---- */
.cf-pair-wrap{ display:flex;flex-direction:column;gap:7px;margin-bottom:8px; }
.cf-pair-row{ display:flex;align-items:center;gap:7px; }
.cf-pair-row .cf-pair-marca{ flex:1;min-width:0; }
.cf-pair-row .cf-pair-codigo{ flex:1;min-width:0; }
.cf-pair-remove{
  flex:none;width:26px;height:26px;border-radius:7px;border:1px solid var(--border);
  background:var(--surface-2);color:var(--ink-faint);font-size:16px;line-height:1;cursor:pointer;
}
.cf-pair-remove:hover{ background:var(--danger-soft);color:var(--danger);border-color:var(--danger-soft); }

/* ---- tela "Referências Cruzadas": cartões com número livre de marcas ---- */
.ref-cards{ display:flex;flex-direction:column;gap:10px; }
.ref-card{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);
  padding:14px 16px;
}
.ref-card-head{ display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:8px; }
.ref-card-title-group{ display:flex;align-items:center;gap:8px;min-width:0; }
.ref-card-title{ font-weight:700;color:var(--ink); }
.ref-card-actions{ display:flex;gap:6px;flex:none; }
/* Registro inativo (na lixeira) — continua na mesma listagem, só esmaecido,
   em vez de sumir (mockup "Visualizar/Editar/Lixeira" aprovado). Usado tanto
   em linhas de tabela (tr.row-inactive) quanto nos cartões de Referências
   Cruzadas (.ref-card.row-inactive). */
tr.row-inactive td{ background:var(--surface-2);color:var(--ink-faint); }
tr.row-inactive td .name,tr.row-inactive td .cell-identity .name{ color:var(--ink-faint); }
.ref-card.row-inactive{ background:var(--surface-2); }
.ref-card.row-inactive .ref-card-title{ color:var(--ink-faint); }
.ref-card-pills{ display:flex;flex-wrap:wrap;gap:8px; }
.ref-pill{
  display:inline-flex;align-items:center;gap:6px;background:var(--surface-2);border:1px solid var(--border);
  border-radius:999px;padding:5px 12px;font-size:12.5px;color:var(--ink-soft);
}
.ref-pill strong{ color:var(--primary-strong);font-weight:700; }
.ref-pill .mono{ color:var(--ink); }

.image-field{ display:flex;align-items:center;gap:14px; }
.image-preview{
  width:64px;height:64px;border-radius:12px;object-fit:cover;border:1px solid var(--border);
  background:var(--surface-2);display:flex;align-items:center;justify-content:center;color:var(--ink-faint);flex:none;
}
.image-actions{ display:flex;gap:8px;flex-wrap:wrap; }
.image-actions input[type="file"]{ display:none; }

.detail-grid{ display:grid;grid-template-columns:1fr 1fr;gap:16px; }
@media (max-width:520px){ .detail-grid{ grid-template-columns:1fr; } }
.detail-item{ display:flex;flex-direction:column;gap:3px; }
.detail-item.col-2{ grid-column:1/-1; }
.detail-item .k{ font-size:10.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-faint);font-weight:700; }
.detail-item .v{ font-size:14px;color:var(--ink); }
.detail-item .v.empty{ color:var(--ink-faint);font-style:italic; }
.detail-hero{ display:flex;align-items:center;gap:16px;margin-bottom:20px; }
.detail-hero .avatar{ width:64px;height:64px;border-radius:14px;font-size:20px; }
.detail-hero h3{ margin:0;font-size:17px; }
.detail-hero .sub{ color:var(--ink-faint);font-size:12.5px;margin-top:2px; }

/* ---------- Preços de Fábrica (v2.22.0) ---------- */
/* Tabela de itens dentro do detalhe de uma fábrica (ver
   openPrecoFabricaDetail(), assets/frontend.js). Usa uma altura máxima
   própria (bem menor que a de .table-wrap, pensada pra tela inteira) em
   vez de reaproveitar aquela classe: dentro do painel de detalhe já existe
   uma rolagem própria (.panel-body), então uma tabela tão alta quanto a
   da tela cheia deixaria duas barras de rolagem uma dentro da outra. */
.preco-itens-table-wrap{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);
  overflow:auto;max-height:320px;
}
.preco-itens-table-wrap thead th{
  position:sticky;top:0;z-index:1;background:var(--surface-2);
  text-align:left;font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;
  color:var(--ink-faint);padding:10px 14px;border-bottom:1px solid var(--border);font-weight:700;
}
.preco-itens-table-wrap td{ padding:9px 14px;border-bottom:1px solid var(--border);font-size:13px; }
.preco-itens-table-wrap tr:last-child td{ border-bottom:none; }

/* ---------- detalhe da Requisição (REQ-03) em formato de tabela, v2.29.29 ----------
   Mesma técnica/raciocínio de .preco-itens-table-wrap acima (tabela dentro de
   um painel que já tem rolagem própria — .panel-body — então max-height bem
   menor que .table-wrap da tela cheia, pra nunca empilhar duas barras de
   rolagem). Reaproveitada nas quatro tabelas desta tela: "Dados da
   requisição", "Produtos", "Cotações recebidas" e "Log de alterações". */
.detail-table-wrap{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);
  overflow:auto;max-height:360px;box-shadow:var(--shadow-sm);
}
.detail-table-wrap table{ width:100%;border-collapse:collapse; }
/* "Observação"/"O que fez" podem ter texto longo — ao contrário do resto do
   sistema (tbody td é white-space:nowrap por padrão, ver mais acima), essas
   colunas precisam quebrar linha em vez de alargar a tabela sem limite. */
.detail-table-wrap table.wrap-cells td{ white-space:normal; }
.produto-nome{ font-weight:700;font-size:13px;color:var(--ink); }
.produto-sub{ font-size:11px;color:var(--ink-faint);margin-top:2px; }
/* v2.49.5 (pedido do usuário, mockup "req03-cotacoes-recebidas-tabela-
   mockup.html" aprovado em 4 rodadas) — tabela "Cotações recebidas"
   (cotacoesTableHtml(), compartilhada entre REQ-03 e CMP-02 → aba
   "Lista"). A zebra que existia antes (".row-grupo-par", alternando linhas
   DENTRO de um mesmo grupo de produto) saiu: com a vencedora já destacada
   (".linha-vencedora" abaixo) e as linhas já ordenadas (vencedora(s)
   primeiro, depois mais barata pra mais cara), mais uma cor de fundo só
   deixava a tabela mais cheia — o usuário achou a 1ª versão deste mockup
   "ainda poluída".
   .produto-marca/.produto-qtd: 2ª/3ª linha da célula do Produto (depois do
   nome, antes da observação) — marca aceita e quantidade solicitada pelo
   requisitante, sempre mostradas (mesmo padrão de "—" quando vazias já
   usado em produtosTableHtml()). NÃO é a mesma coisa que a coluna "Marca
   Disp."/"Qtd. Disp." da tabela (o que cada FÁBRICA ofereceu de verdade).
   .produto-obs: 4ª linha, só quando o requisitante escreveu uma observação
   ao criar a requisição (it.observacao) — mesmo dado já mostrado em
   produtosTableHtml(), repetido aqui a pedido do usuário. O portfólio
   (".produto-sub", usada só em produtosTableHtml()) NÃO aparece mais
   nesta célula — pedido do usuário: "na segunda linha não precisa colocar
   o portfolio". */
.produto-marca{ font-size:11px;color:var(--ink-soft);margin-top:4px; }
.produto-qtd{ font-size:11px;color:var(--ink-soft);margin-top:3px; }
.produto-obs{ font-size:11px;color:var(--ink-faint);font-style:italic;margin-top:3px;white-space:normal;max-width:220px;line-height:1.4; }
/* Linha vazia (sem conteúdo nem borda) entre um produto e o próximo —
   pedido do usuário, depois de ver a 1ª versão do mockup com uma borda
   mais grossa no lugar ("ainda esta poluido, poderia ter um espaço entre
   uma linha de produto e a outra linha"): um respiro em branco pesa menos
   do que mais uma linha competindo por atenção numa tabela já cheia de
   bordas. */
.detail-table-wrap tr.group-gap td{ padding:0;border:none;height:12px; }
/* Linha inteira da cotação vencedora, com um fundo verde suave — fácil de
   achar de relance ao rolar a tabela, não só o badge pequeno da coluna
   "Situação" (como era antes). Selo "mais barata", que antes ficava colado
   no Prazo, agora vive junto do Preço Final. */
.detail-table-wrap tr.linha-vencedora td{ background:var(--success-soft); }
.mais-barata-chip{ display:inline-block;margin-left:6px;font-size:10.5px;font-weight:700;color:var(--primary-strong); }
/* .fabrica-cell (coluna "Fábrica" da VEN-05, v2.48.4) removida na v2.51.0 —
   a coluna voltou a sair da tabela (pedido do usuário), ver
   itensCotadosDecisaoHtml() em frontend.js. */

/* ---------- Acessos (v2.21.0) — agenda de login/senha/endereço ---------- */
/* Campo de senha do formulário: mesmo espírito visual do .currency-input
   (input sem borda própria dentro de uma "caixa" com botão ao lado). */
.password-input{ display:flex;align-items:center;gap:6px; }
.password-input input{ flex:1; }
.password-input .btn-icon{ flex:none;padding:6px; }
.password-input .btn-icon svg{ width:15px;height:15px; }
/* Indicador mascarado na listagem (coluna "Senha") — pontos maiores e mais
   espaçados que um texto normal, só para parecer claramente "oculto" em vez
   de um valor de verdade truncado. */
.senha-dots{ font-family:'IBM Plex Mono',ui-monospace,monospace;letter-spacing:2px;color:var(--ink-faint); }
/* Tela de detalhe: usuário/senha + botão(ões) de copiar/mostrar na mesma linha. */
.acesso-cred-row{ display:flex;align-items:center;gap:6px; }
.acesso-cred-row .btn-icon{ padding:5px;flex:none; }
.acesso-cred-row .btn-icon svg{ width:13px;height:13px; }
.senha-reveal{ font-family:'IBM Plex Mono',ui-monospace,monospace;letter-spacing:1.5px;text-transform:none; }
/* Aviso neutro (não é erro nem alerta) quando o acesso não exige login. */
.acesso-sem-login{
  margin:0 0 20px;padding:11px 14px;border-radius:10px;background:var(--surface-2);color:var(--ink-soft);
  font-size:12.5px;display:flex;align-items:center;gap:9px;flex:none;border:1px dashed var(--border);
}
.acesso-sem-login svg{ flex:none;width:16px;height:16px;color:var(--ink-faint); }
.acesso-acessar-wrap{ margin-bottom:20px; }
.acesso-acessar-wrap:empty{ margin-bottom:0; }
.acesso-acessar-btn{ display:inline-flex; }

/* ---------- prioridade da requisição ---------- */
.priority-group{ display:flex;gap:8px;flex-wrap:wrap; }
.priority-chip{
  display:flex;align-items:center;gap:7px;padding:8px 13px;border-radius:999px;
  border:1px solid var(--border);background:var(--surface-2);font-size:12.5px;font-weight:700;
  color:var(--ink-soft);cursor:pointer;transition:background .12s ease,border-color .12s ease,color .12s ease;
}
.priority-chip input{ width:14px;height:14px;accent-color:currentColor; }
.priority-chip.is-active.tone-accent{ background:var(--accent-soft);border-color:var(--accent);color:var(--accent); }
.priority-chip.is-active.tone-primary{ background:var(--primary-soft);border-color:var(--primary);color:var(--primary-strong); }
.priority-chip.is-active.tone-danger{ background:var(--danger-soft);border-color:var(--danger);color:var(--danger); }

/* ---------- itens da requisição ---------- */
.item-card{ border:1px solid var(--border);border-radius:12px;background:var(--surface-2);padding:14px;margin-bottom:10px; }
.item-card-head{ display:flex;align-items:center;justify-content:space-between;margin-bottom:10px; }
.item-num{ font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-faint); }
.item-grid-top{ display:grid;grid-template-columns:1.1fr 1.6fr 70px 90px;gap:10px; }
.item-grid-bottom{ display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:10px; }
/* 8ª coluna (40px, v2.26.5) — botão de remover produto, que deixou de ficar
   numa linha própria acima do cartão (.item-card-head) e passou a ser mais
   um campo na mesma linha dos demais (ver itemRowHtml() em
   assets/frontend.js), alinhado pela base (.item-field[style*="align-self"]
   inline no próprio elemento) com os campos que têm rótulo. */
/* v2.29.18 (pedido do usuário): 9ª coluna "Cod Interno" entre Marcas e
   Observação — Portfólio (1fr->.8fr) e Produto (1.4fr->1.3fr) ficaram um
   pouco mais estreitos pra abrir esse espaço sem alargar a linha inteira.
   Marcas (1.3fr->1.2fr) também cedeu um pouco, já que virou um campo
   fechado (.marcas-select, ver mais abaixo) que não precisa mais da mesma
   largura que tinha como caixa de chips.
   v2.29.19 (pedido do usuário): Cod Interno passou de fração (1.1fr, ficava
   largo demais sobrando espaço vazio — ver print) pra largura FIXA, só o
   suficiente pra um código de até uns 5 dígitos (mesmo raciocínio de
   Qtd/Unid., que já são colunas de largura fixa por terem conteúdo curto) —
   o espaço que sobrou foi redistribuído pra Produto (1.15fr->1.3fr) e
   Observação (.95fr->1.1fr), que se beneficiam mais de espaço extra.
   v2.29.20 (pedido do usuário): os 72px da v2.29.19 eram estreitos demais
   pro PRÓPRIO RÓTULO "Cod Interno" acima do campo (não pro conteúdo digitado
   — o rótulo é sempre maior que um código curto) — "COD INTERNO" quebrava em
   duas linhas. 92px é o suficiente pro rótulo (10px, caixa alta, negrito)
   caber numa linha só, do jeito que o usuário pediu ("deixe o tamanho do
   campo... com o tamanho do titulo"). */
.item-grid-single{ display:grid;grid-template-columns:54px .8fr 1.25fr 58px 68px 1.2fr 92px 1.05fr 40px;gap:10px;align-items:start; }
/* Correção (v2.26.6): faltava um tamanho explícito pro SVG do ícone dentro
   desse botão (.btn-icon, reaproveitado de outras telas) — sem isso, o
   navegador usa o tamanho padrão de um <svg> sem width/height (bem maior
   que o botão), o ícone fica cortado/invisível e o botão em si cresce,
   desalinhando a coluna da linha dos outros campos. Mesma ideia das outras
   regras "<contexto> .btn-icon svg{...}" já usadas no resto do app (ver
   td.actions, .panel-foot-left, etc. — este .btn-icon nunca tem um tamanho
   de ícone genérico, cada tela define o seu). */
.item-grid-single .item-field .btn-icon{ display:inline-flex;align-items:center;justify-content:center; }
.item-grid-single .item-field .btn-icon svg{ width:14px;height:14px;flex:none; }
/* Campo "Item" (v2.26.4) — numeração automática (01, 02...) de cada produto
   da requisição, sempre em primeiro lugar na linha, antes de Portfólio. Só
   de leitura (preenchido pelo índice da linha, não guardado em
   reqItemsState) — ver itemRowHtml() e pad2() em assets/frontend.js. */
.item-field input[disabled]{ background:var(--surface-2);color:var(--ink-faint);text-align:center;font-weight:700; }
/* min-width:0 é o que impede uma coluna do grid de crescer pra caber um
   conteúdo que não quebra linha (ver .marcas-select-text acima) — por
   padrão um item de grid tem min-width:auto (= largura do conteúdo), não 0. */
.item-grid-single .item-field{ min-width:0; }
@media (max-width:560px){
  .item-grid-top{ grid-template-columns:1fr 1fr; }
  .item-grid-bottom{ grid-template-columns:1fr; }
  .item-grid-single{ grid-template-columns:1fr 1fr; }
  .item-field.wide{ grid-column:1/-1; }
  /* No celular (grid de 2 colunas), o campo do botão de remover ocupa a
     linha inteira sozinho, alinhado à direita, em vez de dividir uma
     coluna estreita com outro campo. */
  .item-grid-single .item-field:last-child{ grid-column:1/-1;display:flex;justify-content:flex-end; }
}
/* white-space:nowrap (v2.29.20) — um rótulo de campo nunca deveria quebrar
   linha (ficava "COD" numa linha e "INTERNO" na linha de baixo quando a
   coluna era mais estreita que o texto, como aconteceu com "Cod Interno"
   na v2.29.19 — ver a largura da coluna logo abaixo, agora dimensionada
   pra caber exatamente esse rótulo sem quebrar). */
.item-field label{ font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--ink-faint);font-weight:700;margin-bottom:4px;display:block;white-space:nowrap; }
.item-field input,.item-field select{
  width:100%;padding:8px 9px;border-radius:7px;border:1px solid var(--border);
  background:var(--surface);font-size:12.8px;color:var(--ink);outline:none;
}
.item-field input:focus,.item-field select:focus{ border-color:var(--primary); }

/* v2.47.1 (pedido do usuário, mockup aprovado: "não precisa inserir o
   título dos campos, vamos aproveitar os títulos da linha de cima" + "não
   precisa ter essa separação entre um item e outro") — em telas largas, os
   8 rótulos de campo (Item/Portfólio/.../Observação) deixaram de se repetir
   dentro de CADA produto e passam a aparecer uma vez só, nesta linha
   (.items-header-row, inserida por openRequisicaoForm() logo acima de
   #itemsContainer), e cada ".item-card" de produto perdeu a moldura
   (borda/fundo cinza/cantos arredondados/respiro) que tinha antes — os
   produtos ficam soltos, um logo abaixo do outro, como linhas de uma
   tabela. O seletor é escopado a "#itemsContainer .item-card" (não
   ".item-card" sozinho) de propósito: essa classe é reaproveitada em várias
   OUTRAS telas do app (cartões de Aviso, bloco de fornecedor em Nova
   Cotação, etc.), que devem continuar com a moldura normal — só a lista de
   produtos da Requisição muda aqui. Mesmo grid-template-columns de
   .item-grid-single, pra alinhar com os campos abaixo. */
.items-header-row{
  display:grid;grid-template-columns:54px .8fr 1.25fr 58px 68px 1.2fr 92px 1.05fr 40px;gap:10px;
  padding:0 14px;margin-bottom:6px;
}
.items-header-row span{ font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--ink-faint);font-weight:700;white-space:nowrap;min-width:0;overflow:hidden;text-overflow:ellipsis; }
#itemsContainer .item-card{ border:none;background:transparent;border-radius:0;padding:2px 14px;margin-bottom:0; }
@media (min-width:561px){
  /* Acima de 560px o cabeçalho único (.items-header-row) já mostra os
     rótulos — o rótulo DENTRO de cada campo só reaparece abaixo desse
     tamanho (ver media query seguinte), quando a lista de produtos quebra
     pra um grid de 2 colunas e não fica mais alinhada com um cabeçalho
     único.
     CORREÇÃO (v2.47.2, bug real reportado pelo usuário: campo "Marcas" não
     listava nenhuma marca pra escolher): o seletor ERA
     "#itemsContainer .item-field label" — um seletor de DESCENDENTE, sem
     limite de profundidade. Cada opção do dropdown de Marcas
     (wireMarcasSelect()/renderList() em frontend.js) é um
     "<label class="marcas-opt">" — e esse label TAMBÉM é descendente de
     .item-field (está varios níveis abaixo: .item-field > .marcas-select-wrap
     > .marcas-dropdown > .marcas-dropdown-list > label.marcas-opt), então a
     regra escondia JUNTO cada opção da lista de marcas (display:none),
     deixando o dropdown vazio sempre que havia alguma marca pra mostrar —
     por isso digitar "FAG" (marca já cadastrada) não listava nada: a única
     opção que bateria com a busca estava escondida. Trocado por
     "> label" (combinador de FILHO DIRETO): atinge só o
     "<label>Marcas</label>" que fica logo dentro de .item-field (o rótulo
     da coluna), sem alcançar o label da opção lá dentro do dropdown. */
  #itemsContainer .item-field > label{ display:none; }
}
@media (max-width:560px){
  .items-header-row{ display:none; }
  /* No celular, sem o cabeçalho único acima, cada produto volta a precisar
     de alguma separação visual — uma linha fina embaixo (em vez da moldura
     inteira de antes) já é suficiente, já que cada campo mostra o próprio
     rótulo de novo. */
  #itemsContainer .item-card{ padding:12px 0;border-bottom:1px solid var(--border); }
  #itemsContainer .item-card:last-child{ border-bottom:none; }
}

/* ---------- chips de marcas ---------- */
/* v2.26.7 (pedido do usuário): o campo Marcas (.chip-box) ficava visivelmente
   mais alto que os outros campos da mesma linha (.item-field input/select,
   logo acima) — a causa era um padding DOBRADO: o próprio .chip-box já tinha
   6px de padding vertical, e o <input> de dentro (.chip-input) somava mais
   3px de padding vertical só dele. Correção: .chip-box passou a usar o
   MESMO padding (8px 9px) dos outros campos da linha, e .chip-input perdeu
   o padding vertical próprio (0, só 2px nas laterais) — com isso a conta
   fica idêntica à dos outros campos (padding + borda + linha de texto do
   mesmo tamanho de fonte), então a altura bate certinho sem precisar de um
   min-height "no olho" (o 36px antigo foi removido). Quando há marcas
   (chips) suficientes pra quebrar linha, a caixa ainda cresce normalmente
   — só a altura de UMA linha (o estado mais comum) é que agora é igual. */
.chip-box{
  display:flex;flex-wrap:wrap;gap:5px;align-items:center;padding:8px 9px;
  border:1px solid var(--border);border-radius:7px;background:var(--surface);
}
.chip-box:focus-within{ border-color:var(--primary); }
.marca-chip{
  display:inline-flex;align-items:center;gap:5px;padding:3px 6px 3px 9px;border-radius:999px;
  background:var(--primary-soft);color:var(--primary-strong);font-size:11.5px;font-weight:700;white-space:nowrap;
}
.marca-chip button{
  border:none;background:transparent;color:inherit;cursor:pointer;font-size:11px;line-height:1;
  padding:2px;display:flex;align-items:center;justify-content:center;opacity:.7;
}
.marca-chip button:hover{ opacity:1; }

/* Colunas "Marcas"/"Portfólio" da listagem de Fornecedores (FOR-01, v2.33.0
   tentou chips; v2.33.1, pedido do usuário, trocou pra "Opção A — texto
   curto + contador", mesmo mockup `for01-coluna-marcas-mockup.html`):
   mostra as 2 primeiras marcas/itens de portfólio por extenso, com um "+N"
   mais apagado no final cobrindo o resto da lista (tooltip nativo com os
   nomes restantes) — substitui o texto corrido cortado com "..."
   (.cell-truncate), que escondia a contagem e cortava nomes no meio. Ver
   listCurtoHtml() em assets/frontend.js. */
.marcas-curto{ color:var(--ink); }
.marcas-curto .contador{ color:var(--ink-faint);font-weight:600; }

.chip-input{
  flex:1;min-width:60px;border:none;outline:none;background:transparent;font-size:12.8px;
  color:var(--ink);padding:0 2px;
}

/* ---------- Autocomplete de Produto (catálogo) — v2.23.0 ----------
   Usado no campo "Produto" dos itens de Requisição e da Cotação avulsa (ver
   attachProdutoSuggestDropdown() em assets/frontend.js): dropdown posicionado
   sob o campo de texto, mesmo texto livre continua funcionando pra quem não
   encontrar o produto no catálogo. */
.produto-suggest-wrap{ position:relative; }
.produto-suggest-list{
  display:none;position:absolute;left:0;right:0;top:100%;margin-top:4px;z-index:30;
  background:var(--surface);border:1px solid var(--border);border-radius:8px;
  box-shadow:0 8px 24px rgba(0,0,0,.14);max-height:220px;overflow-y:auto;
}
.produto-suggest-list.open{ display:block; }
.produto-suggest-opt{ padding:7px 10px;font-size:12.5px;color:var(--ink);cursor:pointer; }
.produto-suggest-opt:hover{ background:var(--primary-soft); }
.produto-suggest-opt .muted{ color:var(--ink-faint);font-weight:400; }
.produto-linked-badge{
  position:absolute;right:8px;top:50%;transform:translateY(-50%);font-size:12px;
  pointer-events:none;
}
.field .produto-suggest-wrap input[type="text"]{ padding-right:26px; }
.item-field .produto-suggest-wrap input[type="text"]{ padding-right:24px; }
/* Trecho digitado destacado dentro de uma sugestão — usado pelo campo
   "Cod Interno" (ver attachCodigoInternoSuggestDropdown() em frontend.js),
   que busca por código OU descrição no mesmo catálogo do campo "Produto". */
.produto-suggest-opt mark{ background:var(--primary-soft);color:var(--primary-strong);border-radius:3px;padding:0 1px;font-weight:700; }
/* Lista de sugestões do "Cod Interno" (v2.29.21, pedido do usuário, mockup
   aprovado) — campo fechado continua estreito (só cabe um código curto),
   mas a LISTA que abre embaixo dele não pode acompanhar essa largura (a
   base ".produto-suggest-list" acima usa left:0;right:0, preso ao wrapper
   estreito) — uma descrição mais longa quebrava em várias linhas. Esta
   classe (só no wrapper do Cod Interno — ver itemRowHtml() em frontend.js;
   o campo "Produto" continua com o comportamento de sempre) tira a largura
   presa ao campo e deixa a lista crescer sozinha até caber a sugestão mais
   comprida INTEIRA, nunca cortando com "..." (sem overflow/ellipsis, só
   nowrap). Fica centralizada embaixo do campo (left:50% + translateX(-50%))
   pra crescer pros dois lados conforme o texto precisa — por cima da coluna
   Observação à direita e por cima da coluna Marcas à esquerda, exatamente
   como pedido ("a largura pode também expandir para o lado do campo
   marcas") — com um teto (max-width) só pra nunca estourar a tela numa
   janela estreita. */
.codigo-interno-suggest-wrap .produto-suggest-list{
  left:50%;right:auto;transform:translateX(-50%);
  width:max-content;max-width:min(620px, calc(100vw - 60px));
}
.codigo-interno-suggest-wrap .produto-suggest-opt{ white-space:nowrap; }
.produto-suggest-empty{ padding:10px 9px;font-size:12px;color:var(--ink-faint);text-align:center; }

/* ---------- Marcas: campo fechado com busca (v2.29.18, pedido do usuário) ----------
   Substituiu a caixa de chips (.chip-box acima, que cresce em altura
   conforme marcas vão sendo adicionadas e destoa da altura dos outros
   campos da linha). Agora o campo FECHADO tem a mesma altura/borda/fonte de
   um <input>/<select> normal e nunca cresce — ao clicar, abre um dropdown
   com busca (igual um autocompletar: digitar já filtra a lista) e uma
   linha "+ Adicionar" quando o texto não bate com nenhuma marca já
   cadastrada (state.vocabulario.marcas). Mockup aprovado pelo usuário antes
   desta implementação ("Mockup — campo Marcas"). */
.marcas-select-wrap{ position:relative;min-width:0; }
.marcas-select{
  width:100%;min-width:0;padding:8px 9px;border-radius:7px;border:1px solid var(--border);
  background:var(--surface);font-size:12.8px;color:var(--ink);cursor:pointer;user-select:none;
  display:flex;align-items:center;justify-content:space-between;gap:6px;
}
.marcas-select.placeholder .marcas-select-text{ color:var(--ink-faint); }
.marcas-select:hover{ border-color:#c4cbbd; }
.marcas-select.open{ border-color:var(--primary); }
/* min-width:0 no próprio item flex com o texto é o que realmente permite o
   ellipsis funcionar quando a lista de marcas selecionadas não cabe —
   sem isso o item cresce pra caber o texto inteiro (não quebra linha) e
   empurra a coluna do grid inteira, que é o efeito que o usuário reportou
   como bug na primeira versão do mockup ("a largura do campo marcas
   aumenta de acordo com a quantidade de marcas inseridas"). */
/* v2.29.21 (pedido do usuário): as marcas já escolhidas, mostradas no campo
   fechado (ex: "SKF, FAG +1"), não podem aparecer em negrito — era
   font-weight:600. */
.marcas-select-text{ min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:400; }
.marcas-select-chevron{ flex:none;color:var(--ink-faint);transition:transform .15s ease; }
.marcas-select.open .marcas-select-chevron{ transform:rotate(180deg); }
.marcas-dropdown{
  display:none;position:absolute;left:0;right:0;top:calc(100% + 4px);z-index:30;
  background:var(--surface);border:1px solid var(--border);border-radius:10px;
  box-shadow:0 10px 28px rgba(20,30,20,.16);overflow:hidden;
}
.marcas-dropdown.open{ display:block; }
/* v2.47.3 (pedido do usuário, mockup aprovado): quando não há espaço
   suficiente abaixo do campo (perto do fim da página), o dropdown abre pra
   CIMA em vez de pra baixo — mesma caixa, só ancorada pelo "bottom" do
   campo em vez do "top" (quem decide quando aplicar esta classe é
   posicionarDropdown() em assets/frontend.js, chamada ao abrir). */
.marcas-dropdown.drop-up{ top:auto;bottom:calc(100% + 4px); }
/* Busca sempre no TOPO do dropdown, com foco automático ao abrir — digitar
   já filtra a lista abaixo, sem precisar clicar em outro campo separado
   (pedido do usuário: "é possivel fazer do tipo auto completar, quando
   começar a digitar ir aparecendo as sugestões?"). */
.marcas-dropdown-search{
  display:flex;align-items:center;gap:7px;padding:8px 10px;border-bottom:1px solid var(--border);
}
.marcas-dropdown-search svg{ flex:none;color:var(--ink-faint); }
.marcas-dropdown-search input{
  flex:1;min-width:0;border:none;outline:none;background:transparent;font-size:12.8px;
  color:var(--ink);font-family:inherit;
}
.marcas-dropdown-search input::placeholder{ color:var(--ink-faint); }
.marcas-dropdown-list{ max-height:192px;overflow-y:auto;padding:6px; }
.marcas-opt{
  display:flex;align-items:center;gap:9px;padding:7px 8px;border-radius:7px;cursor:pointer;font-size:12.5px;
}
.marcas-opt:hover{ background:var(--primary-soft); }
/* v2.29.19: tentativa de corrigir o checkbox desalinhado só resetando
   padding/borda/fundo vazados de ".item-field input" — não resolveu de vez
   (usuário reportou que continuava desalinhado). Causa de verdade: um
   checkbox NATIVO (appearance padrão do navegador) é um widget desenhado
   pelo sistema operacional, não uma caixa comum — `border`/`background`/
   `border-radius` do CSS simplesmente não têm efeito nele (por isso a v2.29.19
   não mudou nada visualmente), e cada navegador posiciona esse widget de um
   jeito ligeiramente diferente em relação à linha de texto ao lado, mesmo
   com align-items:center no flex pai. v2.29.20: `appearance:none` tira o
   desenho nativo e transforma o checkbox numa caixa comum, 100% controlada
   por este CSS — a partir daí o align-items:center do .marcas-opt (flex)
   garante o alinhamento de verdade, sem depender de como cada navegador
   desenha o widget nativo. O "✓" marcado é desenhado à mão com ::after
   (borda em L rotacionada 45°, truque clássico de checkmark em CSS puro). */
.marcas-opt input[type="checkbox"]{
  -webkit-appearance:none;appearance:none;-moz-appearance:none;
  width:14px;height:14px;flex:none;padding:0;margin:0;
  border:1.5px solid var(--border);border-radius:4px;background:var(--surface);
  display:inline-block;position:relative;cursor:pointer;
}
.marcas-opt input[type="checkbox"]:checked{ background:var(--primary);border-color:var(--primary); }
.marcas-opt input[type="checkbox"]:checked::after{
  content:"";position:absolute;left:4px;top:1px;width:3px;height:7px;
  border:solid var(--primary-ink);border-width:0 1.6px 1.6px 0;transform:rotate(45deg);
}
/* Nome da marca sem negrito (pedido do usuário) — era font-weight:600. */
.marcas-opt span{ font-weight:400; }
.marcas-opt span mark{ background:var(--primary-soft);color:var(--primary-strong);border-radius:3px;padding:0 1px; }
/* Linha "+ Adicionar 'X'" — só aparece quando o texto digitado não bate com
   nenhuma marca já cadastrada; sempre a primeira linha da lista filtrada. */
.marcas-opt-nova{
  display:flex;align-items:center;gap:8px;padding:7px 8px;border-radius:7px;cursor:pointer;
  font-size:12.5px;font-weight:700;color:var(--primary-strong);
}
.marcas-opt-nova:hover{ background:var(--primary-soft); }
.marcas-opt-nova svg{ flex:none; }
.marcas-dropdown-empty{ padding:14px 10px;text-align:center;font-size:12px;color:var(--ink-faint); }

/* ---------- Cotações: nova cotação a partir de requisição (comparação de preços por fábrica) ----------
   v2.17.0: as cotações já recebidas (antes cartões soltos, `.cotacao-existing-row`)
   e a linha de preencher uma cotação nova (antes uma grade própria,
   `.cotacao-row-grid`) passaram a ser exibidas como uma única tabela — mesmas
   12 colunas nos dois casos (Fábrica, Ref. Fábrica, Marca, Qtd, Vlt. Unit.,
   IPI, PIS/COF, Frete, Preço Final, Prazo, Comparativo, Ver Cotação/ação),
   pedido do usuário depois de ver o mockup aprovado. Altura de linha, divisória
   entre colunas e badge/botão compactos seguem o mesmo padrão de 18px já usado
   em todas as tabelas do sistema desde a v2.8.1/v2.8.2 (ver `tbody .avatar`,
   `tbody .badge`, `td.actions .btn-icon` acima). Como 12 colunas não cabem numa
   tela estreita, o grid tem uma largura mínima e o wrapper
   `.cotacao-table-scroll` rola horizontalmente em vez de espremer os campos —
   mesmo princípio já usado nas tabelas do sistema (largura em vez de quebrar).
   Larguras diferentes por coluna: mais espaço pra texto livre (Fábrica), menos
   pra valores curtos (Qtd, IPI, Frete).
   v2.20.0: acrescentada a 13ª coluna "Status" (à esquerda de tudo, ver
   COT_STATUS_FABRICA_ORDER em frontend.js) — status da resposta de cada
   fábrica cotada, que trava/destrava as colunas de resposta da linha
   (`.is-locked`, ver `.cotacao-table-row.is-locked` abaixo).
   v2.37.6 (pedido do usuário): a coluna "Comparativo" (1fr, penúltima faixa
   antes da ação) saiu — essa comparação passa a viver numa tela própria (ver
   cotTableHeadHtml() em frontend.js). min-width recalculada na mesma proporção
   fr usada desde a v2.37.1 (1480px → 1344px).
   v2.37.9 (pedido do usuário): a última faixa (ação — "Ver Cotação" até a
   v2.37.8, hoje só o ícone de remover linha nas cotações NOVAS) encolheu de
   110px pra 40px — tinha sido dimensionada pro botão "Ver Cotação" (texto
   largo), que já não existe mais aqui; 40px é só o suficiente pro ícone de
   16px (ver .btn-icon.danger abaixo). min-width caiu junto, -70px (1344px →
   1274px). */
.cotacao-none-yet{ margin:0 0 10px;font-size:12px;color:var(--ink-faint);font-style:italic; }
.cotacao-table-scroll{ overflow-x:auto; }
/* v2.37.10 (pedido do usuário, mockup "cot-status-icones-mockup.html"
   aprovado): 1ª faixa (Status) de 90px pra 42px — o <select> com o nome do
   status escrito por extenso virou um ícone (ver .status-ic-wrap/
   cotStatusIconHtml() em frontend.js), que só precisa de ~22px + um
   respiro pequeno. Diferente das outras colunas de texto livre da tabela
   (não encolhidas nesta rodada — ver nota mais abaixo, antes de
   ".cot-cell"), nenhum dado é cortado aqui: o nome completo do status
   continua existindo no title (tooltip) e nas opções do próprio <select>,
   só parou de ficar escrito na célula. min-width caiu junto (-48px). */
/* v2.37.11 (pedido do usuário, mockup "cot-forn-bug-qtd-mockup.html"
   aprovado): a faixa única "Qtd" (0.4fr) virou duas — "Qtd Solic."
   (0.4fr, igual era antes) + "Qtd Disp." (0.4fr nova) — ver
   cotTableHeadHtml() em frontend.js. min-width recalculada na mesma
   proporção fr usada desde a v2.37.1 (1226px → 1284px). A última faixa
   (ação, 40px) não muda nesta visão (Por Produto) — continua existindo
   normalmente, só deixou de existir na grade .has-marcas abaixo (Por
   Fornecedor). */
/* v2.40.0 (pedido do usuário, mockup "anexo-cotacao-mockup.html" aprovado):
   +1 faixa (36px, "Anexo" — botão de clipe, ver cotAnexoCellHtml() em
   frontend.js), inserida antes da faixa de ação (40px) — min-width subiu
   junto (1284px → 1320px). Mesma faixa adicionada na grade .has-marcas
   abaixo, só que no final (lá não existe faixa de ação). */
.cotacao-table-head,.cotacao-table-row{
  display:grid;grid-template-columns:42px 1.6fr 1fr 0.85fr 0.4fr 0.4fr 0.65fr 0.65fr 0.75fr 0.95fr 0.75fr 0.8fr 36px 40px;
  gap:8px;min-width:1320px;
}
/* v2.35.1 — visão "Por Fornecedor" ganhou uma 14ª coluna, "Marcas" (as
   marcas pedidas pelo cliente), então essas linhas precisam de uma grade
   própria com uma coluna a mais — ver o comentário em cotTableHeadHtml()
   (assets/frontend.js) pra quando a classe "has-marcas" é aplicada.
   "Produto" encolheu um pouco (1.6fr → 1.3fr) pra abrir espaço sem alargar
   demais a tabela inteira.
   v2.35.2: ordem das colunas trocada — "Marcas" passou de antes pra depois
   de "Produto" (pedido do usuário), então a 2ª coluna da grade agora é a
   largura de "Produto" (1.3fr) e a 3ª é a de "Marcas" (0.9fr) — só a ORDEM
   das larguras mudou, os valores em si continuam os mesmos.
   v2.37.1 (pedido do usuário, depois de testar o rateio de frete ao vivo):
   "IPI"/"PIS/COF" alargadas (0.45fr/0.6fr → 0.65fr/0.75fr) pra caber o
   valor completo (ex: "15.25") sem cortar, "Vlt. Unit."/"Preço Final"
   encolhidas (0.85fr/0.95fr → 0.65fr/0.75fr) pra abrir espaço sem alargar
   a tabela toda, e "Frete" alargada (0.55fr → 0.95fr) pra caber o checkbox
   de rateio (v2.37.0) + o valor junto sem cortar — min-width subiu junto
   (+30px/+40px) pra não espremer demais em telas estreitas.
   v2.37.6 (pedido do usuário): mesma remoção da coluna "Comparativo" (1fr)
   que a grade base, acima — min-width recalculada na mesma proporção
   (1600px → 1460px).
   v2.37.9: mesma redução da última faixa (110px → 40px) que a grade base,
   acima — min-width recalculada junto (1460px → 1390px).
   v2.37.10: mesma redução da 1ª faixa (Status: 90px → 42px) que a grade
   base, acima — min-width recalculada junto (1390px → 1342px).
   v2.37.11 (pedido do usuário, mockup "cot-forn-bug-qtd-mockup.html"
   aprovado): duas mudanças juntas, só nesta grade (visão "Por
   Fornecedor"): (1) mesmo split de "Qtd" em "Qtd Solic."+"Qtd Disp." (+1
   faixa, 0.4fr) que a grade base, acima; (2) a última faixa (ação, 40px)
   foi REMOVIDA de vez — nesta visão ela já não tinha mais nenhum conteúdo
   em nenhum estado de linha (nem o ícone de remover linha das novas, nem
   o botão "Ver Cotação" das existentes, que já tinham saído daqui em
   rodadas anteriores — ver cotEditableRowHtml()/cotExistingRowHtml()/
   cotExistingEditavelRowHtml() em frontend.js), então a faixa em si virou
   peso morto. min-width recalculada com as duas mudanças juntas
   (1342px → 1354px). */
/* v2.40.0: mesma faixa "Anexo" (36px) acrescentada acima, aqui no final
   (visão "Por Fornecedor" não tem faixa de ação) — min-width recalculada
   junto (1354px → 1390px). */
.cotacao-table-head.has-marcas,.cotacao-table-row.has-marcas{
  grid-template-columns:42px 1.3fr 0.9fr 1fr 0.85fr 0.4fr 0.4fr 0.65fr 0.65fr 0.75fr 0.95fr 0.75fr 0.8fr 36px;
  min-width:1390px;
}
.cotacao-table-head{ padding:6px 2px;margin-bottom:2px;border-bottom:1px solid var(--border); }
.cotacao-table-head span{ font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--ink-faint);font-weight:700; }
.cotacao-table-row{
  align-items:center;padding:1px 2px;border-bottom:1px solid var(--border);
}
.cotacao-table-row:last-child{ border-bottom:none; }
/* v2.37.6: .is-vencedora (selo "Vencedora" desta tabela) foi removida — o
   JS parou de aplicar essa classe aqui (ver cotExistingRowHtml() em
   frontend.js); a comparação agora vive só na tela de Requisição, que usa a
   classe separada .cotacao-compare-item-row.is-vencedora (mais abaixo), não
   tocada por esta mudança.
   Linha travada (status é "Comprado" — ver cotExistingRowHtml()/
   cotExistingRowDispatchHtml() em frontend.js): colunas de resposta mostram
   o que tiver salvo, com "—" só quando o campo em si está vazio. O select de
   status em si NÃO fica apagado — é ele que segue ativo pra o usuário poder
   avançar o status. */
.cotacao-table-row.is-locked .cot-cell:not(:first-child){ color:var(--ink-faint); }
/* Divisória vertical fina entre colunas (pedido do usuário), numa cor discreta
   que não compete com a linha horizontal entre registros.
   v2.37.10 (pedido do usuário: "veja se consegue diminuir a largura de
   alguma coluna para sem perda ou corte de dados"): junto com a coluna
   Status (acima), revisei as outras colunas pra ver se alguma tinha
   gordura pra cortar. Decidi NÃO encolher nenhuma outra, porque esta regra
   corta com reticências (overflow:hidden + text-overflow:ellipsis) o que
   não couber — ou seja, qualquer coluna que hoje já usa sua largura cheia
   passaria a cortar dado de verdade, exatamente o que foi pedido pra
   evitar: Ref. Fábrica/Marca/Prazo são texto livre digitado pela fábrica
   ou pelo usuário, sem tamanho máximo, e nem têm um title de reserva pra
   consultar o valor cortado na linha travada (Comprado); Qtd já é a faixa
   mais estreita da grade (0.4fr); e Vlt. Unit./IPI/PIS COF/Frete/Preço
   Final foram alargadas de propósito na v2.37.1, depois de um corte real
   relatado pelo usuário ("15.25" aparecendo cortado) — encolher de novo
   reabriria o mesmo problema. A coluna Status pôde encolher porque é
   diferente: um <select> de 5 opções fixas, não texto livre — o nome
   completo nunca desaparece, só passou a morar no title/nas options em vez
   de ficar escrito na célula (ver cotStatusIconHtml() em frontend.js). */
.cot-cell{
  font-size:12.5px;line-height:16px;color:var(--ink);white-space:nowrap;overflow:hidden;
  text-overflow:ellipsis;border-right:1px solid var(--border);padding-right:8px;
}
.cot-cell:last-child{ border-right:none;padding-right:0; }
.cot-cell-strong{ font-weight:700;color:var(--ink); }
/* v2.37.11 (pedido do usuário, mockup aprovado): estilo da célula "Qtd
   Solic." nas linhas ainda abertas pra edição (novas ou existentes com
   status diferente de "Comprado") — mesmo tom apagado que
   ".is-locked .cot-cell:not(:first-child)" já usa pra travado, aplicado
   aqui direto porque a linha em si não está travada (as outras células
   continuam no tom normal); sinaliza visualmente "só leitura" sem
   precisar de um ícone de cadeado por célula. */
.cot-cell-readonly{ color:var(--ink-faint); }
.cot-cell-end{ display:flex;justify-content:flex-end;overflow:visible; }
/* Badge (Mais barata/Vencedora) e botão "Ver Cotação" no tamanho compacto já
   usado dentro de qualquer tabela do sistema — mesmos números de
   `tbody .badge`/`td.actions .btn-icon` acima. */
.cot-cell .badge{ padding:1px 7px;font-size:10px; }
/* v2.37.10 (pedido do usuário, mockup "cot-status-icones-mockup.html"
   aprovado): Status da Fábrica deixou de ser um <select> com o nome escrito
   por extenso (precisava de 90px pra caber "SEM RESPOSTA" sem cortar) e
   virou um ícone colorido (reaproveita as cores `.badge-st-*` já
   existentes, ver COT_STATUS_FABRICA_TONE/COT_STATUS_FABRICA_ICON em
   frontend.js) com o nome completo só no title (tooltip). O <select> de
   verdade continua ali, do mesmo tamanho do ícone, só que invisível por
   cima dele (.status-ic-select) — clicar continua abrindo as 5 opções
   escritas por extenso, então fica de fora das regras genéricas de
   `select`/`input` da linha editável logo abaixo
   (`:not(.status-ic-select)`), que dariam a ele a aparência de campo de
   formulário (borda, fundo) em vez de ficar transparente. */
.status-ic-wrap{ position:relative; width:22px; height:22px; flex:none; }
.status-ic-btn{
  width:22px; height:22px; border-radius:7px; display:flex; align-items:center; justify-content:center;
  pointer-events:none;
}
.status-ic-btn svg{ width:13px; height:13px; }
.status-ic-select{
  position:absolute; inset:0; width:100%; height:100%; opacity:0; border:none; margin:0; padding:0;
  cursor:pointer; -webkit-appearance:none; appearance:none;
}
.cotacao-table-row .btn.btn-ghost.btn-sm{
  height:18px;padding:0 10px;font-size:10.5px;border-radius:9px;
  display:inline-flex;align-items:center;
}
.cotacao-table-row .btn-icon.danger{
  width:16px;height:16px;padding:1px;border-radius:5px;box-sizing:border-box;
  display:inline-flex;align-items:center;justify-content:center;
}
/* Anexo de comprovante na Cotação (v2.40.0, pedido do usuário, mockup
   "anexo-cotacao-mockup.html" aprovado): botão de clipe por linha — cinza
   (.badge-st-gray) sem comprovante, verde (.badge-st-green) com uma
   bolinha quando já tem um anexado. Mesmo tamanho/posicionamento do
   .status-ic-btn acima, mas sem o <select> transparente por cima (este é
   um <button> de verdade, ver abrirCotAnexoModal() em frontend.js). */
.cot-cell-anexo{ display:flex; align-items:center; justify-content:center; }
.anexo-btn{
  position:relative; width:22px; height:22px; border-radius:7px; border:none; cursor:pointer;
  display:flex; align-items:center; justify-content:center; padding:0;
}
.anexo-btn svg{ width:13px; height:13px; }
.anexo-dot{
  position:absolute; top:1px; right:1px; width:6px; height:6px; border-radius:50%;
  background:var(--success); border:1.5px solid var(--surface);
}
.cotacao-table-row .btn-icon.danger svg{ width:12px;height:12px;flex:none; }
/* Linha editável (preencher uma cotação nova): campos digitados à mão (ou
   calculados) encolhidos pra caber perto da altura de linha da tabela — um
   pouco mais alto que as outras colunas (pedido do usuário, v2.20.1), pra
   não ficar desproporcional ao lado dos campos maiores das outras colunas.

   v2.49.0 (pedido do usuário, mockup "cot02-altura-campos-local-fabrica-
   mockup.html" aprovado: "preciso que os campos onde eu vou digitar re.
   fábrica, marca, qtd solic., qtd disp., vlt. unit., ipi, pis/cof, e etc,
   seja da mesma altura do campo nome da fábrica, atulmente esses campos
   estão com pouca altura, com isso gera um pouco de desconforto da hora de
   digitar, precisa ser da mesma altura do campo nome da fábrica"): de
   22px pra 34px — mesma altura de ".forn-group-head input[type="text"]"
   (padding 8px + fonte 13px), em vez de inventar um valor novo. A linha da
   tabela cresce um pouco (cresce sozinha, já que a altura destes campos é
   quem define a altura da linha), sem precisar mexer em mais nada. */
.cotacao-table-row.is-editable .cot-cell select:not(.status-ic-select),
.cotacao-table-row.is-editable .cot-cell > input{
  width:100%;height:34px;padding:0 6px;border-radius:5px;border:1px solid var(--border);
  background:var(--surface);font-size:11.5px;color:var(--ink);outline:none;box-sizing:border-box;
}
.cotacao-table-row.is-editable .cot-cell select:not(.status-ic-select):focus,
.cotacao-table-row.is-editable .cot-cell > input:focus{ border-color:var(--primary); }
/* v2.49.0 — ".currency-input" tem border:1px próprio (regra global,
   ".currency-input" no topo deste arquivo) e todo elemento aqui dentro é
   box-sizing:border-box (".cf-app-fullscreen *", também no topo) — então
   "height:34px" nele mede border INCLUSA, sobrando só 32px de área de
   conteúdo pro <input> de dentro (height:100%, abaixo) preencher. 36px
   (34 + os mesmos 2px de border) faz o conteúdo interno chegar nos 34px
   cheios, batendo com os outros campos. ".percent-input" não tem border
   nenhuma, então não precisa dessa compensação — fica em 34px mesmo. */
.cotacao-table-row.is-editable .currency-input{
  height:36px;background:var(--surface);border-radius:5px;
}
.cotacao-table-row.is-editable .percent-input{
  height:34px;background:var(--surface);border-radius:5px;
}
/* v2.37.1: .percent-input (IPI / PIS-COF) nunca teve display:flex, diferente
   do .currency-input (que tem a regra global em .currency-input, linha ~738).
   Sem flex, o <input> interno assume a largura padrão do navegador (~155px),
   maior que o próprio container, e o excesso é cortado silenciosamente pelo
   overflow:hidden do .cot-cell pai — por isso "7.8" aparecia como "7.".
   flex:1 + min-width:0 faz o input respeitar a largura real da coluna. */
.cotacao-table-row.is-editable .percent-input{ display:flex; align-items:center; }
/* v2.49.0 — o height:34px de ".currency-input"/".percent-input" acima só
   redimensionava a CAIXA (container flex com align-items:center); o
   <input> de dentro, sem altura própria, continuava com a altura natural
   do navegador (~14-18px), só centralizado — ou seja, a área de fato
   clicável/digitável não crescia, só a moldura em volta. "height:100%"
   aqui faz o campo em si (não só a caixa) ocupar os 34px inteiros, mesmo
   comportamento dos campos sem wrapper (".cot-cell > input" acima). */
.cotacao-table-row.is-editable .currency-input input,
.cotacao-table-row.is-editable .percent-input input{ font-size:11.5px;padding:0 4px;height:100%;box-sizing:border-box; }
.cotacao-table-row.is-editable .percent-input input{ flex:1; min-width:0; }
.cotacao-table-row.is-editable .currency-input span,
.cotacao-table-row.is-editable .percent-input span{ font-size:11px; }
/* Preço Final é calculado, não digitado — visual levemente diferente (fundo
   cinza, texto em negrito) deixa claro que não é pra editar ali. */
.cotacao-table-row.is-editable .currency-input.is-readonly{ background:var(--surface-2); }
.cotacao-table-row.is-editable .currency-input.is-readonly input{ font-weight:700;color:var(--ink);cursor:default; }
.cotacao-add-row-btn{ margin-top:8px; }
@media (max-width:640px){
  .cotacao-table-head{ display:none; }
  .cotacao-table-row{ grid-template-columns:1fr 1fr;min-width:0; }
  /* v2.35.1: sem isto, a regra ".has-marcas" (mais específica, 2 classes)
     ganharia da regra genérica acima mesmo aqui dentro — ver o comentário
     perto de ".cotacao-table-head.has-marcas" (fora da media query). */
  .cotacao-table-row.has-marcas{ grid-template-columns:1fr 1fr;min-width:0; }
  .cot-cell{ border-right:none;white-space:normal; }
  .cotacao-table-scroll{ overflow-x:visible; }
}

/* ---------- COT-02: alternância "Por Produto" / "Por Fornecedor" (v2.35.0) ----------
   Pedido do usuário, mockup aprovado "cot02-dois-layouts-mockup.html" —
   mesmas dimensões do mockup. */
.mode-toggle-wrap{ margin:4px 0 18px; }
.mode-toggle{
  display:inline-flex; background:var(--surface-2); border:1px solid var(--border);
  border-radius:10px; padding:4px; gap:4px;
}
.mode-btn{
  border:none; background:transparent; padding:9px 16px; border-radius:7px;
  font-family:inherit; font-weight:600; font-size:13px; color:var(--ink-soft); cursor:pointer;
}
.mode-btn.active{ background:var(--primary); color:var(--primary-ink); }
.mode-hint{ margin:10px 2px 0; font-size:12.5px; color:var(--ink-faint); }

/* ---------- COT-02: barra única de status (v2.37.5, fundida na v2.45.6) ----------
   Pedido do usuário, mockup aprovado "cot02-barra-unificada-ordenacao-
   mockup.html" — só aparece no topo da visão "Por Fornecedor" (ver
   cotStatusSummaryHtml() em frontend.js), logo abaixo do alternador Por
   Produto/Por Fornecedor. Antes da v2.45.6 eram DUAS faixas separadas: esta
   (contagem, com pontinho colorido) e ".cotcard-legend" (ícone, dentro de
   "Cotações recebidas", v2.45.5) — viraram uma só, reaproveitando o MESMO
   ícone colorido de cada card (".cotcard-status-ic"/"badge-st-*", ver
   cotRecebidaCardHtml()) no lugar do pontinho. Por continuar FORA do
   contêiner com overflow-x:auto (".cotcard-received-wrap", mais abaixo),
   nunca rola junto quando os cards de fábrica rolam na horizontal — não
   precisa de position:sticky nem nada parecido. */
.cotcard-statusbar{
  display:flex; align-items:center; gap:10px; flex-wrap:wrap;
  margin:0 0 16px; padding:10px 14px; border:1px solid var(--border);
  border-radius:10px; background:var(--surface-2);
}
.cotcard-statusbar-chip{
  display:inline-flex; align-items:center; gap:6px; padding:4px 10px 4px 6px;
  border-radius:999px; font-size:12.5px; font-weight:600; white-space:nowrap;
}
.cotcard-statusbar-chip .cotcard-status-ic{ width:17px; height:17px; }
.cotcard-statusbar-chip.is-zero{ opacity:.5; }
.cotcard-statusbar-total{ margin-left:auto; font-size:12px; color:var(--ink-faint); white-space:nowrap; }
@media (max-width:720px){
  .cotcard-statusbar-total{ margin-left:0; width:100%; }
}

/* Bloco de fornecedor (visão Por Fornecedor) — mesma moldura de ".item-card"
   (visão Por Produto), com uma faixa de cabeçalho destacada (igual ao
   mockup) pro campo "Fábrica", já que ali ele vale pra TODAS as linhas do
   bloco, não só uma. */
.forn-group{ border:1px solid var(--border); border-radius:12px; margin-bottom:10px; overflow:hidden; }
.forn-group-head{
  padding:12px 14px; background:var(--primary-soft); border-bottom:1px solid var(--border);
  display:flex; align-items:center; gap:12px; flex-wrap:wrap;
}
.forn-group-head .fl{ font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.03em; color:var(--primary-strong); white-space:nowrap; }
.forn-group-head .produto-suggest-wrap{ min-width:260px; }
.forn-group-head input[type="text"]{
  border:1px solid var(--primary); border-radius:7px; padding:8px 10px; font-size:13px;
  font-weight:600; width:100%; font-family:inherit; background:var(--surface); color:var(--ink);
  box-sizing:border-box;
}
.forn-group-head .btn{ margin-left:auto; }
.forn-group .cotacao-table-scroll{ padding:10px 14px 14px; }

/* v2.37.6 (pedido do usuário, mockup "cot02-fabrica-travada-sem-
   comparativo-mockup.html" aprovado): bloco cujo nome de fábrica já tem
   cotação salva (ver cotFornecedorGroupHtml() em frontend.js) — o cabeçalho
   fica mais baixo (sem o <input>, só o nome + cadeado) e o botão "Remover
   fornecedor" continua do mesmo jeito, só sem o "margin-left:auto" sobrando
   de um <input> que não existe mais nesse estado (padding reduzido já
   resolve o alinhamento). */
.forn-group-head.is-locked{ padding:8px 14px; }
.forn-group-head .fabrica-locked{
  display:inline-flex; align-items:center; gap:6px; font-size:13px; font-weight:700; color:var(--ink);
}
.forn-group-head .fabrica-locked svg{ width:13px; height:13px; flex:none; color:var(--primary-strong); }

/* v2.37.9 (pedido do usuário, mockup "cot02-coluna-estreita-logo-fabrica-
   mockup.html" aprovado): logo da fábrica antes do nome, nos dois estados do
   cabeçalho do bloco (ver cotFabricaLogoHtml()/cotFornecedorGroupHtml() em
   frontend.js). No estado editável, .fabrica-field agrupa a logo e o campo de
   texto (.produto-suggest-wrap já tinha min-width:260px — segue valendo, só
   ficou aninhado um nível mais dentro). .fabrica-logo é a versão compacta do
   padrão já usado em avatarHtml() (34px em Fornecedores/Produtos, 14px em
   tabela) — aqui 22px, do tamanho certo pro cabeçalho reduzido do bloco. */
.forn-group-head .fabrica-field{ display:flex; align-items:center; gap:8px; flex:1; min-width:0; }
.forn-group-head .fabrica-locked{ gap:7px; }
.fabrica-logo{
  width:22px; height:22px; border-radius:6px; flex:none; object-fit:cover;
  background:var(--surface); color:var(--primary-strong); border:1px solid var(--border);
  display:flex; align-items:center; justify-content:center; font-weight:800; font-size:9px;
}

/* v2.49.0 (pedido do usuário, mockup "cot02-altura-campos-local-fabrica-
   mockup.html" aprovado): chip de Cidade/UF (fábrica reconhecida) ou botão
   "Cadastrar fábrica" (sem cadastro ainda), ao lado do campo "Nome da
   fábrica" — ver cotFabricaLocalNotaHtml() em frontend.js. flex:none pra
   nunca ser espremido pelo campo de texto.

   v2.49.3 (pedido do usuário, mockup "cot02-ajustes-nome-fabrica-preco-
   card-mockup.html" aprovado, com print em anexo mostrando o campo
   esticado até o botão "Remover fornecedor"): "é para diminuir o tamanho
   do campo do nome fabrica que esta em anexo, onde eu vou digitar uma nova
   fabrica" — ".produto-suggest-wrap" aqui deixa de crescer até o fim da
   faixa (era "flex:1", decisão da v2.49.0 citada acima) e ganha uma
   largura fixa (260px, o mesmo valor do "min-width" de sempre — ver regra
   ".forn-group-head .produto-suggest-wrap" mais acima no arquivo) — volta
   a ser só do tamanho de um nome de fábrica normal, em vez de esticar até
   onde sobrar espaço na faixa. */
.forn-group-head .fabrica-field .produto-suggest-wrap{ flex:none;width:260px;min-width:0; }
.fabrica-local-nota{ flex:none; }
.fabrica-local-chip{
  display:inline-flex; align-items:center; font-size:11px; font-weight:700; white-space:nowrap;
  background:var(--surface); border:1px solid var(--border); border-radius:999px; padding:4px 11px; color:var(--ink-soft);
}
.fabrica-local-cadastrar{
  border:none; background:none; padding:0; font-size:11.5px; font-weight:700; color:var(--primary-strong);
  text-decoration:underline; cursor:pointer; white-space:nowrap; font-family:inherit;
}
.fabrica-local-cadastrar:hover{ color:var(--primary); }

/* v2.43.0 — autocompletar com logo do campo "Nome da fábrica" ao cadastrar
   fábrica nova em Preços de Fábrica/Carteira e Pendências (pedido do
   usuário, mockup aprovado "prf01-logo-autocomplete-mockup.html"; ver
   attachFabricaNovaSuggestDropdown()/fabricaNovaMatchNoteHtml() em
   frontend.js). .fabrica-nova-suggest-opt só acrescenta o layout em flex
   (com o .fabrica-logo de 22px ao lado do nome) por cima da classe base
   .produto-suggest-opt, que já traz padding/cor/cursor. */
.fabrica-nova-suggest-opt{ display:flex; align-items:center; gap:8px; }
.fabrica-nova-match{
  display:flex; align-items:center; gap:8px; margin-top:6px; padding:7px 10px;
  border-radius:9px; font-size:11.5px; line-height:1.5;
}
.fabrica-nova-match.found{ background:var(--success-soft); color:var(--success); }
.fabrica-nova-match.found b{ color:var(--ink); font-weight:700; }
.fabrica-nova-match.notfound{ background:var(--surface-2); color:var(--ink-soft); border:1px solid var(--border); }

/* ---------- COT-02: rateio de frete entre produtos da mesma fábrica (v2.37.0) ----------
   Pedido do usuário, mockup aprovado "cot-frete-rateio-mockup.html" — checkbox
   de rateio na célula de Frete de cada linha (visão Por Fornecedor) e, quando
   algum produto da fábrica está marcado, a calculadora abaixo da tabela do
   bloco (ver cotFreteCalcHtml() em frontend.js). */
/* v2.37.1: overflow:visible quebrava a otimização de "tamanho mínimo automático
   = 0" do CSS Grid (ver spec de Grid). Como .cotacao-table-head e
   .cotacao-table-row são grids independentes que só compartilham as mesmas
   proporções de coluna, o conteúdo desta célula (checkbox + valor) forçava a
   trilha do Frete a crescer só nas linhas, nunca no cabeçalho — por isso as
   colunas desalinhavam a partir do Frete para a direita. overflow:hidden
   restaura o comportamento padrão de todas as outras .cot-cell. */
.cot-cell-frete{ display:flex; align-items:center; gap:4px; overflow:hidden; min-width:0; }
.cot-cell-frete .currency-input{ flex:1; min-width:0; }
.frete-rateio-toggle{ display:flex; align-items:center; flex:none; cursor:pointer; }
.frete-rateio-toggle input[type="checkbox"]{ width:14px; height:14px; margin:0; cursor:pointer; accent-color:var(--accent); }
/* Linha marcada: leve destaque laranja, igual ao tom do badge "frete
   rateado" (cot-cell-strong fica preservado por especificidade). */
.cotacao-table-row.is-rateio{ background:var(--accent-soft); }
.cotacao-table-row.is-rateio .cot-cell{ background:transparent; }

.frete-calc{
  margin-top:0; border-top:2px dashed var(--border); background:var(--surface-2);
  padding:12px 14px 14px;
}
.frete-calc-head{ display:flex; align-items:center; gap:8px; margin-bottom:10px; }
.frete-calc-head svg{ width:15px; height:15px; color:var(--accent); flex:none; }
.frete-calc-head .t{ font-weight:700; font-size:12.5px; color:var(--ink); }
.frete-calc-grid{ display:grid; grid-template-columns:repeat(4,minmax(120px,1fr)); gap:10px; align-items:end; }
.fc-field label{
  display:block; font-size:10px; font-weight:700; color:var(--ink-soft); text-transform:uppercase;
  letter-spacing:.03em; margin-bottom:4px;
}
.fc-field .currency-input{ height:32px; background:var(--surface); border-radius:7px; border:1px solid var(--border); }
.fc-field .currency-input input{ font-size:13px; }
.fc-field.readout .val{
  border:1px solid var(--border); border-radius:7px; padding:7px 10px; font-size:13px;
  font-family:'IBM Plex Mono',ui-monospace,monospace; background:var(--primary-soft); color:var(--primary-strong);
  font-weight:700; box-sizing:border-box;
}
.fc-field.readout.total .val{ background:var(--accent-soft); color:var(--accent); }
.fc-note{ font-size:11px; color:var(--ink-faint); margin:10px 2px 0; line-height:1.5; }
@media (max-width:640px){
  .frete-calc-grid{ grid-template-columns:1fr 1fr; }
}

/* Lista de produtos ad-hoc da cotação avulsa (sem requisição) — mesmas
   dimensões de campo já usadas no resto do formulário. */
.avulsa-itens-manager{ margin-bottom:18px; }
.field-label{ font-size:11.5px; font-weight:700; color:var(--ink-soft); display:block; margin-bottom:8px; }
.avulsa-item-row{
  display:grid; grid-template-columns:1fr 100px 90px 32px; gap:8px; align-items:center; margin-bottom:8px;
}
.avulsa-item-row input[type="text"],
.avulsa-item-row input[type="number"],
.avulsa-item-row select{
  width:100%; height:32px; padding:0 10px; border-radius:7px; border:1px solid var(--border);
  background:var(--surface); font-size:12.5px; color:var(--ink); box-sizing:border-box;
}
@media (max-width:640px){
  .avulsa-item-row{ grid-template-columns:1fr 1fr; }
  .avulsa-item-row .produto-suggest-wrap{ grid-column:1 / -1; }
}

/* ---------- Requisição: comparação de cotações recebidas + escolha da vencedora ---------- */
.cotacao-compare-card{ border:1px solid var(--border);border-radius:12px;background:var(--surface-2);padding:14px;margin-bottom:10px; }
.cotacao-compare-item-row{
  display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 12px;
  border-radius:8px;border:1px solid var(--border);background:var(--surface);margin-bottom:6px;
}
.cotacao-compare-item-row:last-child{ margin-bottom:0; }
.cotacao-compare-item-row.is-vencedora{ border-color:var(--success);background:var(--success-soft); }
.cotacao-compare-info{ display:flex;flex-direction:column;gap:2px; }
.cotacao-compare-info .fornecedor{ font-weight:700;font-size:13px;color:var(--ink); }
.cotacao-compare-info .detalhes{ font-size:11.5px;color:var(--ink-faint); }
.cotacao-compare-actions{ display:flex;align-items:center;gap:8px;flex:none; }
.cotacao-progress{
  display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 14px;
  border-radius:10px;background:var(--surface-2);border:1px solid var(--border);margin-top:16px;flex-wrap:wrap;
}
.cotacao-progress-label{ font-size:12.5px;color:var(--ink-soft);font-weight:600; }

/* v2.38.0 (pedido do usuário, mockups "cot-comparativo-matriz-mockup.html"
   aprovados em várias rodadas): botão genérico "link" — texto colorido, sem
   fundo nem borda — usado no "‹ Voltar ao comparativo" da nova tela
   "Calcular Preços de Venda da Requisição" (REQ-05). Modificador de .btn,
   igual a .btn-ghost/.btn-soft/.btn-danger acima, só que nunca existiu até
   agora porque nenhuma tela anterior precisou de um botão sem moldura. */
.btn-link{ background:transparent;color:var(--ink-soft);padding:9px 2px; }
.btn-link:hover{ color:var(--primary);text-decoration:underline;filter:none; }
.btn-link.btn-sm{ padding:6px 2px; }

/* ---------- Requisição: alternância Lista/Comparativo + matriz de cotações (v2.38.0) ----------
   Pedido do usuário, mockup "cot-comparativo-matriz-mockup.html" aprovado em
   várias rodadas (v4/v5) — ver cotacoesMatrixHtml()/cotComparativoVisao em
   frontend.js. Classes prefixadas "cotmx-" pra não colidir com nada do COT-01/
   COT-02 (.cel/.matrix/.tabs/.tab-btn/.badge já existem com outro significado
   nesses módulos). Reaproveita as variáveis de cor já existentes no :root
   (--success/--success-soft/--warn/--primary/--border/--surface/--surface-2/
   --ink/--ink-soft/--ink-faint), já com suporte a dark mode. */
.cotmx-tabs{ display:flex;gap:6px;margin-bottom:14px; }
.cotmx-tab-btn{
  font-size:12px;font-weight:700;padding:7px 14px;border-radius:8px;border:1px solid var(--border);
  background:var(--surface);color:var(--ink-soft);cursor:pointer;font-family:inherit;
}
.cotmx-tab-btn:hover{ background:var(--surface-2);color:var(--ink); }
.cotmx-tab-btn.active{ background:var(--primary);color:var(--primary-ink);border-color:var(--primary); }
.cotmx-tab-btn.active:hover{ background:var(--primary);color:var(--primary-ink); }

.cotmx-grid{ display:grid;gap:10px;margin-bottom:4px; }

.cotmx-produto-card{ background:transparent;padding:10px 2px;display:flex;flex-direction:column;justify-content:center;min-width:0; }
.cotmx-pnome{ font-weight:700;font-size:12.5px;color:var(--ink);line-height:1.3; }
.cotmx-pmarca{ font-size:10.5px;color:var(--ink-soft);margin-top:3px; }
.cotmx-pmarca b{ color:var(--ink);font-weight:600; }
.cotmx-pqtd{ font-size:10.5px;color:var(--ink-faint);margin-top:2px; }
/* v2.47.18: .cotmx-split ("Dividido: X de Y PC") removida por ficar sem
   nenhum uso — ver comentário em cotacoesMatrixHtml(), frontend.js. */

.cotmx-cel{
  background:var(--surface);border:1px solid var(--border);border-radius:10px;padding:10px 12px;
  cursor:pointer;transition:border-color .12s ease,background .12s ease;display:flex;flex-direction:column;
  gap:3px;min-width:0;
}
.cotmx-cel:hover:not(.vazia):not(.filler){ border-color:var(--primary); }
/* .cotmx-forn continua usado nas células "vazia" (sem este item/aguardando
   resposta) e no modo de edição do card do Comparativo — ver
   cotacoesMatrixHtml() em frontend.js. */
.cotmx-forn{ font-size:11.5px;font-weight:700;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis; }
/* v2.49.0 (pedido do usuário, mockup "cmp02-cards-comparativo-mockup.html"
   aprovado): Preço e Qtd. Disp./Prazo passam a viver na mesma linha
   (".cotmx-linha-preco", só usada pelos cards do Comparativo —
   cotacoesMatrixHtml() — card mais baixo em uma linha a menos), com o
   preço maior e numa cor própria (verde-escuro, --primary-strong — mesmo
   tom de destaque já usado em títulos/ícones fortes do app) pra continuar
   se destacando mesmo dividindo a linha. */
.cotmx-linha-preco{ display:flex;align-items:baseline;gap:7px;margin-top:3px;flex-wrap:wrap; }
.cotmx-preco{ font-size:16px;font-weight:800;color:var(--primary-strong);line-height:1; }
.cotmx-meta{ font-size:10.5px;color:var(--ink-faint); }
.cotmx-flag{ font-size:10px;font-weight:700;color:var(--success);margin-top:1px; }
/* v2.47.17 (pedido do usuário, mockup "cmp02-card-logo-campos-mockup.html"
   aprovado): o card do Comparativo (cotacoesMatrixHtml()) passou a
   reaproveitar DIRETO .cotcard-head-view/.cotcard-logo-mini/.cotcard-forn/
   .cotcard-line2 (já existentes, usadas pelo card de "Nova Cotação"/COT-02
   — ver mais abaixo) em vez de .cotmx-nomeprod/.cotmx-marca (removidas
   daqui por ficarem sem nenhum uso) e do campo "Qtd:" editável
   (.cotmx-qtd-split, removida por ficar sem nenhum uso — a divisão
   continua automática, só não aparece mais repetida no card). */

.cotmx-cel.barata{ border-color:var(--success);border-left-width:3px; }
/* v2.47.13 (pedido do usuário, mockup "cmp02-comparativo-melhorias-mockup.html"
   aprovado): card mais barato ainda NÃO escolhido, só no Comparativo
   (cotacoesMatrixHtml()) — classe NOVA "sugestao" (laranja, var(--accent)),
   nunca uma alteração de ".cotmx-cel.barata"/".cotmx-flag" em si (que
   continuam verdes, intocadas, ainda usadas sem mudança nenhuma pelos
   cartões de "Nova Cotação"/COT-02 — mesma classe reaproveitada lá). Antes
   dessa mudança, "mais barata" (sugestão) e "selecionada" (escolha de
   verdade) usavam a mesma cor verde — só um fundo preenchido ou não
   diferenciava os dois, fácil de confundir num relance. */
/* v2.49.0 (pedido do usuário: "Hoje a cor da borda do card mais barato
   vermelha, pode trocar a cor para verde, e o nome mais barata para cor
   verde também"): "sugestao" deixa de usar var(--accent) (laranja,
   percebida como vermelha) e passa a usar var(--success) (verde) — igual
   à cor de ".cotmx-cel.barata"/".cotmx-flag" acima. A distinção visual
   entre "sugestão" e "selecionada" (nota do v2.47.13 acima) passa a
   depender só do fundo preenchido (.selecionada tem --success-soft; esta
   classe não), não mais de cores diferentes. */
.cotmx-cel.sugestao{ border-color:var(--success);border-left-width:3px; }
.cotmx-flag-sugestao{ color:var(--success); }
.cotmx-cel.selecionada{ background:var(--success-soft);border-color:var(--success); }
.cotmx-cel.selecionada .cotmx-forn{ color:var(--success); }
/* v2.47.17: mesma regra acima, só que pro nome dentro de .cotcard-forn
   (card com logo do Comparativo) — classe NOVA, não mexe em
   ".cotmx-cel.selecionada .cotmx-forn" (continua valendo pras células
   "vazia"/modo edição, que ainda usam .cotmx-forn puro). */
.cotmx-cel.selecionada .cotcard-forn{ color:var(--success); }
.cotmx-cel.dim{ opacity:.45; }
.cotmx-cel.vazia{
  color:var(--ink-faint);cursor:default;background:var(--surface-2);border-style:dashed;
  align-items:flex-start;justify-content:center;
}
.cotmx-cel.vazia .cotmx-forn{ color:var(--ink-soft);font-weight:600; }
.cotmx-cel.filler{ background:transparent;border-style:dashed;border-color:var(--border);cursor:default;opacity:.3; }
.cotmx-estado{ font-size:11px;font-style:italic;color:var(--ink-faint); }

/* v2.47.20 (pedido do usuário, mockup "cmp02-contraste-card-mockup.html"
   aprovado — na aprovação, pediu pra trocar a borda proposta de cinza-escuro
   pra um tom verde-escuro): aumenta o contraste da borda e do texto dos
   cards do Comparativo (cotacoesMatrixHtml()) quando NÃO estão selecionados
   nem são a "sugestão" (mais barata) — ficavam claros demais pra ler de
   relance. Escopo limitado ao Comparativo via [data-matrix-toggle]
   (atributo exclusivo desses cards — as células "vazia" não têm e os cards
   de "Nova Cotação"/COT-02 usam [data-cot-card] em vez disso), pra não
   alterar .cotmx-cel/.cotcard-line2/.cotmx-meta nas outras telas que
   reaproveitam essas mesmas classes. :not(.selecionada):not(.sugestao) na
   borda garante que ela nunca sobreponha o verde de "selecionada"
   (var(--success)) nem o laranja de "sugestao" (var(--accent)),
   independente da ordem das regras no arquivo. */
.cotmx-cel[data-matrix-toggle]:not(.selecionada):not(.sugestao){ border-color:var(--primary); }
.cotmx-cel[data-matrix-toggle] .cotcard-line2{ color:var(--ink); }
.cotmx-cel[data-matrix-toggle] .cotmx-meta{ color:var(--ink-soft); }

@media (max-width:960px){
  .cotmx-grid{ grid-template-columns:1fr!important; }
  .cotmx-produto-card{ padding-top:16px; }
}

/* ---------- "Cotações recebidas": cards por produto na visão "Por
   Fornecedor" de Nova Cotação (COT-02, v2.45.0) ----------
   Pedido do usuário, mockups "cot02-bloco-recolhivel-mockup.html" até
   "cot02-card-detalhado-mockup.html" aprovados em 5 rodadas — ver
   cotRecebidasMatrixHtml()/cotRecebidaCardHtml() em frontend.js. Reaproveita
   DIRETO (sem alterar nenhuma regra acima) .cotmx-grid/.cotmx-produto-card/
   .cotmx-cel/.cotmx-cel.barata/.cotmx-cel.filler/.cotmx-flag — as mesmas
   classes que o Comparativo (cotacoesMatrixHtml()) já usa em produção.
   Tudo que é NOVO aqui fica prefixado "cotcard-" e é somado como classe
   ADICIONAL no mesmo elemento ".cotmx-cel" (ex: class="cotmx-cel
   cotcard-wrap barata"), nunca como alteração da regra ".cotmx-cel" em si —
   assim a tela de Comparativo não corre nenhum risco. */
.cotcard-received-wrap{ margin:0 0 26px;padding-bottom:22px;border-bottom:2px dashed var(--border);overflow-x:auto; }
.cotcard-received-head{ display:flex;align-items:center;gap:8px;margin:0 0 10px; }
.cotcard-received-head h4{ font-size:13px;margin:0;font-weight:800;color:var(--ink); }
.cotcard-received-head svg{ width:15px;height:15px;color:var(--primary-strong); }
/* v2.45.5: a legenda de ícones que vivia aqui, logo abaixo do título,
   saiu na v2.45.6 — fundida na barra de status única, agora acima do
   alternador Por Produto/Por Fornecedor (ver ".cotcard-statusbar" mais
   acima e cotStatusSummaryHtml() em frontend.js). */

.cotcard-wrap{ position:relative;cursor:default; }
.cotcard-corner{ position:absolute;top:7px;right:7px;display:flex;align-items:center;gap:3px; }
.cotcard-status-ic{ width:19px;height:19px;border-radius:6px;display:flex;align-items:center;justify-content:center;flex:none; }
.cotcard-status-ic svg{ width:11px;height:11px; }
.cotcard-icon-btn{
  width:19px;height:19px;border-radius:6px;border:1px solid var(--border);background:var(--surface-2);
  color:var(--ink-soft);display:flex;align-items:center;justify-content:center;cursor:pointer;flex:none;padding:0;
}
.cotcard-icon-btn svg{ width:11px;height:11px; }
.cotcard-icon-btn:hover{ background:var(--surface);color:var(--ink); }
.cotcard-icon-btn.danger:hover{ background:var(--danger-soft);color:var(--danger);border-color:var(--danger); }
.cotcard-icon-btn.ok{ background:var(--success);color:#fff;border-color:var(--success); }
.cotcard-icon-btn.ok:hover{ background:var(--primary-strong); }

/* v2.45.4 (pedido do usuário): ".cotcard-head" (com "padding-right:72px",
   reservando espaço pro canto de ícones) agora é usada só pelo modo de
   EDIÇÃO do card (Salvar/Cancelar em ".cotcard-corner", absoluto) — esse
   modo não entrou no pedido de reorganizar a primeira linha, então
   continua como estava. O modo de VISUALIZAÇÃO passou a usar
   ".cotcard-head-view" (logo a um lado, ícone de status inline do outro
   extremo, nenhum espaço reservado — não tem mais nada flutuando por
   cima). */
.cotcard-head{ display:flex;align-items:flex-start;gap:6px;padding-right:72px; }
.cotcard-head-view{ display:flex;align-items:center;gap:6px; }
.cotcard-head-view .cotcard-status-ic{ margin-left:auto; }
.cotcard-logo-mini{ flex:none; }
.cotcard-logo-mini .fabrica-logo{ width:19px;height:19px;border-radius:5px;font-size:8px; }
/* v2.47.19 (pedido do usuário, mockup "cmp02-flag-selecao-mockup.html"
   aprovado): quadradinho de seleção no canto do card do Comparativo
   (cotacoesMatrixHtml()) — fica verde com um ✓ quando o card está
   ".selecionada", vazio quando não. Puro visual: o clique nele sobe pro
   mesmo listener de sempre do card (sem "data-stop-toggle"), nenhuma regra
   nova de clique. Só usada aqui — não mexe em ".cotcard-head-view"/
   ".cotcard-logo-mini" em si, que continuam exatamente como estavam pros
   outros cards (COT-02, modo de edição do Comparativo). */
.cotmx-flagsel{
  flex:none;width:17px;height:17px;border-radius:5px;border:1.5px solid var(--border);
  display:flex;align-items:center;justify-content:center;background:var(--surface);
  transition:background .12s ease,border-color .12s ease;
}
.cotmx-flagsel svg{ width:11px;height:11px;opacity:0;transition:opacity .1s ease; }
.cotmx-cel.selecionada .cotmx-flagsel{ background:var(--success);border-color:var(--success);color:#fff; }
.cotmx-cel.selecionada .cotmx-flagsel svg{ opacity:1; }
.cotmx-cel:not(.selecionada):hover .cotmx-flagsel{ border-color:var(--primary); }
/* v2.45.2 (pedido do usuário, ao vivo, com print): nenhum texto do card pode
   cortar com "..." — nem o nome da fábrica, nem nenhum outro campo. Antes,
   só o nome (.cotcard-forn) tinha white-space:nowrap+ellipsis; trocado por
   min-width:0 (deixa o item flex encolher dentro de .cotcard-head, em vez
   de empurrar o card) + overflow-wrap:anywhere (quebra a linha, inclusive
   no meio de uma palavra sem espaço, se precisar — nunca corta visualmente
   o texto). Os demais campos (.cotcard-line2/.cotcard-line3) nunca tiveram
   nowrap/ellipsis, mas ganharam o mesmo overflow-wrap de proteção, por
   segurança, pro mesmo pedido valer pra "qualquer outra descrição".

   v2.45.3 (pedido do usuário, revisando o acima): só pro NOME DA FÁBRICA,
   voltou a cortar com "..." — mas agora com o card mais largo (ver
   cotRecebidasMatrixHtml() em frontend.js, "minmax(220px,1fr)", antes
   "190px") e um orçamento de 12 caracteres (max-width:12ch) reservado só
   pra ele: um nome de até 12 caracteres cabe inteiro, sem quebrar linha;
   passou disso, corta com "...". .cotcard-line2/.cotcard-line3 (Ref./
   Marca/Valor, Qtd./Prazo) NÃO entraram nesse pedido — continuam com
   overflow-wrap:anywhere (nunca cortam, quebram linha se precisar), como
   decidido na v2.45.2. O atributo title="" (ver cotRecebidaCardHtml()) deixa
   o nome completo visível ao passar o mouse quando cortado.

   v2.45.4 (pedido do usuário, print mostrando nomes cortando cedo demais):
   "com 12 caracteres ainda coube poucas letras no nome da fabrica" — o
   motivo era a unidade "ch" do CSS, que mede pela largura do glifo "0", bem
   mais estreito que a média de letras maiúsculas num nome de fábrica em
   caixa alta; na prática cabiam ~9 letras visíveis com "max-width:12ch".
   Trocado por um valor fixo em PIXELS (max-width:124px), calibrado medindo
   com Playwright a largura real de várias combinações de 15 letras
   maiúsculas (nomes de fábrica de exemplo) — cobre qualquer nome de até 15
   caracteres com folga; orçamento subiu de 12 pra 15, como pedido. */
.cotcard-forn{ font-size:11.5px;font-weight:700;color:var(--ink);min-width:0;max-width:124px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis; }
.cotcard-line2{ font-size:11px;color:var(--ink-soft);display:flex;align-items:baseline;gap:4px;flex-wrap:wrap;overflow-wrap:anywhere; }
.cotcard-line2 .sep{ color:var(--ink-faint); }
/* v2.49.1 — ".cotcard-valor" (Valor Final, que vivia dentro de
   ".cotcard-line2" junto com Ref./Marca) foi removida: o valor saiu dessa
   linha e passa a usar ".cotcard-preco" (mais abaixo), numa linha própria
   com Qtd./Prazo — ver cotRecebidaCardHtml() em frontend.js. Nenhuma outra
   regra usava ".cotcard-valor". */
/* v2.49.3 (pedido do usuário, mockup "cot02-ajustes-nome-fabrica-preco-
   card-mockup.html" aprovado): "os campos dentro do card com o nome do
   produto, marca, qtd disponível e prazo, pode aumentar um ponto e deixar
   mais escuro, atualmente esta muito claro" — Qtd./Prazo (só do card de
   "Nova Cotação"/COT-02, ninguém mais usa ".cotcard-line3") sobe de
   10,5px/var(--ink-faint) pra 11,5px/var(--ink-soft) (1 "camada" mais
   escura na mesma paleta já usada no resto do app). Ref./Marca
   (".cotcard-line2") é tratado separadamente logo abaixo, por ser
   compartilhada com o card do Comparativo — não dá pra mudar a regra
   base sem arriscar mudar o Comparativo junto. */
.cotcard-line3{ font-size:11.5px;color:var(--ink-soft);overflow-wrap:anywhere; }
/* v2.49.1 (pedido do usuário, mockup "cot02-card-acoes-fixas-preco-
   mockup.html" aprovado): "deixe o preço abaixo do produto, e a qtd
   disponivel e prazo na frente do preço, o preço com uma font maior"):
   nova linha, só do card de "Nova Cotação" (cotRecebidaCardHtml(), COT-02)
   — Qtd./Prazo (".cotcard-line3") e Preço (".cotcard-preco", tamanho/cor
   iguais ao ".cotmx-preco" do Comparativo) na mesma linha.

   v2.49.3 (pedido do usuário, mesmo mockup acima, 2ª rodada): "dentro do
   card, deixe o preço do lado esquerdo, e na frete [frente] do preço, na
   mesma linha vai ficar a qtd disp. e o prazo" — a ordem HTML já inverteu
   (Preço primeiro, ver cotRecebidaCardHtml() em frontend.js) e o
   "justify-content:space-between" (que empurrava o preço pra ponta
   direita) saiu daqui — os dois ficam colados à esquerda, lado a lado,
   mesmo princípio do Comparativo (".cotmx-linha-preco"), que nunca usou
   space-between. */
.cotcard-linha-preco{ display:flex;align-items:baseline;gap:8px;margin-top:4px;flex-wrap:wrap; }
.cotcard-linha-preco .cotcard-line3{ margin-top:0; }
.cotcard-preco{ font-size:16px;font-weight:800;color:var(--primary-strong);line-height:1;white-space:nowrap; }
/* v2.49.3 — mesmo pedido de Ref./Marca mais forte citado acima, aplicado só
   ao card de "Nova Cotação" (escopado por "[data-cot-card]", atributo
   exclusivo dele — ver comentário sobre "[data-matrix-toggle]" mais acima
   no arquivo, perto de ".cotmx-grid"): 11px/var(--ink-soft) sobe pra
   12px/var(--ink)/600. O card do Comparativo, que reaproveita
   ".cotcard-line2" sem este atributo, não é afetado — já tinha sua própria
   cor (var(--ink), ver "[data-matrix-toggle] .cotcard-line2" mais acima) e
   mantém o tamanho de sempre. */
.cotmx-cel[data-cot-card] .cotcard-line2{ font-size:12px;color:var(--ink);font-weight:600; }

/* v2.45.4 (pedido do usuário, mockup "cot02-card-15chars-acoes-rodape-
   mockup.html" aprovado, Opção B): editar/excluir saem da primeira linha do
   card (que passou a ter só logo+nome+status, ver ".cotcard-head-view"
   acima) e viram este rodapé — escondido por padrão (max-height:0;
   opacity:0) e revelado só ao passar o mouse ou focar em cima do card
   (":hover"/":focus-within" em ".cotcard-wrap", pra funcionar também
   navegando por teclado). Opção A do mockup (rodapé sempre visível) NÃO foi
   escolhida — fica documentada aqui só pra contexto, caso o usuário prefira
   trocar depois: bastaria remover max-height/opacity:0 e a regra
   ":hover"/":focus-within" abaixo. */
.cotcard-foot{
  display:flex;align-items:center;justify-content:flex-end;gap:5px;
  max-height:0;opacity:0;overflow:hidden;margin-top:0;
  transition:max-height .14s ease,opacity .14s ease,margin-top .14s ease;
}
/* v2.49.2 (correção de bug, reportado pelo usuário com print real: "quando
   eu passo o mouse no card o botão editar fica cortado"): ganhou
   ":not(.cotcard-foot-fixo)" nos dois seletores. Causa real — estas 2
   regras (3 seletores simples: ".cotcard-wrap"+":hover"+".cotcard-foot")
   tinham MAIS especificidade CSS que ".cotcard-foot.cotcard-foot-fixo"
   (2 seletores simples, logo abaixo), então ao passar o mouse elas
   voltavam a vencer e reimpunham "max-height:30px" — pequeno demais pros
   2 botões empilhados do card de COT-02 (19px+gap 4px+19px = 42px),
   cortando o Editar; o "overflow:hidden" (herdado de ".cotcard-foot" logo
   acima, nunca sobrescrito) cortava o que não coubesse nesse limite. No
   card do Comparativo (CMP-02, só 1 botão de 19px) o mesmo problema
   existia, só que invisível — cabia folgado dentro dos 30px, por isso
   não tinha sido notado antes. Com ":not(.cotcard-foot-fixo)", esta regra
   de hover simplesmente para de valer pra qualquer rodapé fixo — nos dois
   cards, passar o mouse deixa de mudar absolutamente nada no rodapé
   (que já é sempre visível, sem precisar de hover pra nada). */
.cotcard-wrap:hover .cotcard-foot:not(.cotcard-foot-fixo),
.cotcard-wrap:focus-within .cotcard-foot:not(.cotcard-foot-fixo){
  max-height:30px;opacity:1;margin-top:7px;padding-top:6px;border-top:1px dashed var(--border);
}

/* v2.49.0 (pedido do usuário, mockup "cmp02-cards-comparativo-mockup.html"
   aprovado: "o botão de editar... precisa que ele fique fixo do card, que
   não precise passar o mouse para ver ele, pode colocar ele no centro
   vertical do card no lado direito"): nasceu só pros cards do Comparativo
   (cotacoesMatrixHtml(), classe adicional ".cotcard-foot-fixo" somada em
   ".cotcard-foot") — tira o botão Editar do fluxo normal (que ficava
   escondido/revelado por hover, herdado de ".cotcard-foot" acima) e fixa
   ele com position:absolute, sempre visível, sem precisar de nenhuma
   regra de :hover/:focus-within.

   v2.49.1 (pedido do usuário, mockup "cot02-card-acoes-fixas-preco-
   mockup.html" aprovado): os cards de "Nova Cotação"/COT-02
   (cotRecebidaCardHtml()) passam a usar esta MESMA classe também — por
   isso "flex-direction:column" entrou na regra (o Comparativo, que só
   tem 1 botão aqui, não nota diferença nenhuma entre linha/coluna; COT-02,
   com Editar E Remover, passa a empilhar os dois verticalmente neste
   canto fixo, em vez de lado a lado). */
.cotcard-foot.cotcard-foot-fixo{
  position:absolute;top:50%;right:7px;transform:translateY(-50%);
  flex-direction:column;max-height:none;opacity:1;margin-top:0;padding-top:0;border-top:none;
}
.cotcard-wrap:has(.cotcard-foot-fixo){ padding-right:34px; }

/* v2.49.1 tinha somado ".cotcard-forn-sm" (max-width:30px) na visualização
   normal do card de "Nova Cotação" (pedido do usuário: "o campo nome da
   fabrica pode ser bem menor do que o atual"). v2.49.3 (pedido do usuário,
   mockup "cot02-ajustes-nome-fabrica-preco-card-mockup.html" aprovado):
   "não é para diminuir o tamanho do campo nome da fabrica que esta dentro
   do card, pode voltar ao tamanho de como estava antes" — a classe foi
   removida de cotRecebidaCardHtml() (volta a usar só ".cotcard-forn" puro,
   124px) e esta regra, sem nenhum uso, foi removida também. Quem ficou
   menor, no lugar, foi o campo de TEXTO onde se digita uma fábrica nova no
   cabeçalho do bloco "Por Fornecedor" — ver
   ".forn-group-head .fabrica-field .produto-suggest-wrap" mais abaixo. */

/* v2.45.3 (pedido do usuário, mockup "cot02-coluna-produto-fixa-mockup.html"
   aprovado): com a barra de rolagem horizontal das "Cotações recebidas" já
   em produção (v2.45.1), só os cards de fábrica devem rolar — a coluna de
   produto (.cotmx-produto-card, a mesma classe-base que o Comparativo já usa
   em produção, intocada) fica fixa. Classe ADICIONAL, somada na mesma célula
   (ver cotRecebidasMatrixHtml() em frontend.js: class="cotmx-produto-card
   cotcard-produto-fixo"), nunca uma alteração de ".cotmx-produto-card" em
   si — a tela de Comparativo não corre nenhum risco. position:sticky;left:0
   trava a coluna na borda esquerda de ".cotcard-received-wrap" (o contêiner
   que rola); background:var(--surface) fica explícito (a classe-base é
   transparente, contando com o fundo branco do painel por trás — aqui
   precisa ser opaco de verdade, pra tampar os cards de fábrica que passam
   por baixo enquanto a grade rola); borda+sombra sutil à direita marcam a
   divisão entre a coluna fixa e a área que rola. */
.cotmx-produto-card.cotcard-produto-fixo{
  position:sticky;left:0;z-index:4;background:var(--surface);
  padding:10px 14px 10px 2px;border-right:1px solid var(--border);
  box-shadow:6px 0 10px -6px rgba(20,30,24,.18);
}

.cotcard-wrap.is-editing{ border-color:var(--primary);box-shadow:0 0 0 2px var(--primary-soft); }
.cotcard-edit-grid{ display:grid;grid-template-columns:1fr 1fr;gap:6px 8px;margin-top:2px; }
.cotcard-edit-field label{ display:block;font-size:9px;font-weight:700;color:var(--ink-faint);text-transform:uppercase;letter-spacing:.03em;margin-bottom:2px; }
.cotcard-mini-input{ width:100%;height:24px;border:1px solid var(--border);border-radius:6px;padding:0 6px;font-size:11px;background:var(--surface);font-family:inherit;color:var(--ink); }
.cotcard-currency{ display:flex;align-items:center;border:1px solid var(--border);border-radius:6px;background:var(--surface);height:24px;overflow:hidden; }
.cotcard-currency span{ padding:0 0 0 6px;color:var(--ink-faint);font-size:10px; }
.cotcard-currency input{ border:none;background:transparent;flex:1;min-width:0;font-size:11px;padding:0 4px;width:100%;font-family:inherit;color:var(--ink); }
@media (max-width:960px){
  .cotcard-head{ padding-right:46px; }
}

/* ---------- Comparativo: tela "Calcular Preços de Venda da Requisição" (CMP-03, v2.38.0 — antes REQ-05) ----------
   Pedido do usuário, mesmo mockup acima — ver abrirCalcularPrecosRequisicao()/
   renderCalcPrecosReqBody() em frontend.js. Classes prefixadas "cotvr-".
   v2.46.0 (pedidos do usuário, mockups aprovados "cmp03-colunas-categoria-
   uf-mockup.html"/"cmp03-colunas-margens-mockup.html"/"cmp03-coluna-status-
   mockup.html"): reordenada e com 6 colunas a mais — Categoria, UF da
   Fábrica, 3 colunas de margem (Oper./Lucro/Revenda) e Status — ver o
   comentário em calcPrecosReqRowHtml() em frontend.js pra ordem completa.
   v2.47.22 (pedido do usuário, mockup "cmp03-frete-coluna-propria-mockup.
   html" aprovado, "ficou perfeito, pode retirar essa ultima coluna chamada
   status... altera a localização da coluna UF para ficar depois da coluna
   FABRICA"): coluna Status removida por completo; UF movida pra depois de
   Fábrica (era a 2ª coluna, logo depois de Categoria); nova coluna Frete
   entre Revenda e Preço de Venda — ver o comentário em calcPrecosReqRowHtml()
   em frontend.js pra ordem completa e pro motivo da coluna Frete (margem
   deixou de incidir sobre o valor do frete).
   v2.47.26 (pedidos do usuário, mockups "cmp03-colunas-preco-ipi-piscof-
   mockup.html" — rodadas 2.47.23 a 2.47.26 — aprovados, exceto o botão de
   mostrar/esconder colunas da última rodada, recusado: "não gostei, não
   precisa esconder essas colunas"): 13 → 17 colunas. 3 novas antes de
   "Custo Final" (ver abaixo): Custo, IPI, PIS/COF — mesmos valores já
   digitados na cotação (Valor Unitário/IPI/PIS·COFINS, COT-02), só nunca
   tinham aparecido aqui. "Preço Final" renomeada pra "Custo Final" ("Custo
   → +IPI → +PIS/COF", já sem o frete, igual antes). "Preço de Venda"
   renomeada pra "Vlr Unit Venda" + nova coluna "Vlr Total Venda" (Vlr Unit
   Venda × Qtd) logo depois. Frete deixou de ficar em negrito. Divisórias
   claras entre colunas (ver "> *" abaixo). Com 17 colunas não cabe mais
   tudo nem no tamanho máximo do painel mantendo "Produto" legível — min-
   width + rolagem horizontal (mesmo padrão de .cotacao-table-head/
   .cotacao-table-row, "Nova Cotação") — ver o comentário em
   calcPrecosReqRowHtml()/renderCalcPrecosReqBody() em frontend.js pra
   ordem completa. */
/* v2.49.0 (pedido do usuário, mockup "cmp03-grid-calculo-mockup.html"
   aprovado): Custo/IPI/PIS·COF (76px/56px/64px, v2.47.26 acima) saíram da
   grade — continuam em "Detalhar Cálculo", sem mudança. Prazo (64px, nova)
   entrou logo depois de Frete. 17 colunas → 15; min-width reduzido na
   mesma proporção. */
.cotvr-head-row{
  display:grid;grid-template-columns:92px 150px 90px 40px 1fr 46px 92px 68px 68px 68px 68px 64px 96px 96px 26px;gap:10px;
  min-width:1374px;
  font-size:10.5px;font-weight:700;color:var(--ink-faint);text-transform:uppercase;letter-spacing:.02em;
  padding:0 4px 8px;
}
.cotvr-row{
  display:grid;grid-template-columns:92px 150px 90px 40px 1fr 46px 92px 68px 68px 68px 68px 64px 96px 96px 26px;gap:10px;align-items:center;
  min-width:1374px;
  padding:12px 4px;border-bottom:1px solid var(--border);
}
.cotvr-row:last-child{ border-bottom:none; }
/* v2.47.26 — divisórias claras entre colunas, pedido do usuário ("Coloque
   uma linha para dividir as colunas, uma cor mais clara"). */
.cotvr-head-row > *, .cotvr-row > *{ border-right:1px solid var(--border);padding-right:10px; }
.cotvr-head-row > *:last-child, .cotvr-row > *:last-child{ border-right:none;padding-right:0; }
/* v2.46.0 — antes a linha "Enviado" inteira ficava com opacity:.55 e a
   coluna de Preço de Venda virava só o badge "Enviado" (escondia o valor).
   Pedido do usuário: "não precisa remover o valor da venda, o cálculo e a
   tabela deve permanecer exibindo" — agora só uma leve suavizada no
   conteúdo (não na linha inteira, que inclui o badge de Status, esse sim
   sempre com força total) diferencia visualmente do que ainda está
   pendente de envio. v2.47.22: coluna Status removida (ver acima), mas o
   mesmo tratamento de opacidade no conteúdo continua fazendo sentido pras
   colunas que restaram — ".cotvr-frete" somada à lista. */
.cotvr-row.enviado .cotvr-cat, .cotvr-row.enviado .cotvr-uf, .cotvr-row.enviado .cotvr-forn,
.cotvr-row.enviado .cotvr-nome, .cotvr-row.enviado .cotvr-sub, .cotvr-row.enviado .cotvr-qtd,
.cotvr-row.enviado .cotvr-preco, .cotvr-row.enviado .margem-cell, .cotvr-row.enviado .cotvr-frete,
.cotvr-row.enviado .cotvr-prazo, .cotvr-row.enviado .cotvr-venda,
.cotvr-row.enviado .cotvr-venda-total{
  opacity:.85;
}
.cotvr-cat{ font-size:12px;color:var(--ink-soft); }
.cotvr-uf{ font-size:12px;color:var(--ink-soft);font-weight:700; }
.cotvr-uf.is-empty{ color:var(--ink-faint);font-weight:400; }
.cotvr-nome{ font-weight:700;font-size:12.5px;color:var(--ink); }
.cotvr-sub{ font-size:10.5px;color:var(--ink-faint);margin-top:2px; }
.cotvr-forn{ font-size:12px;color:var(--ink-soft); }
.cotvr-qtd{ font-size:12px;color:var(--ink-soft); }
.cotvr-preco{ font-size:12.5px;font-weight:700;color:var(--ink); }
/* v2.47.22 — "sem frete" pequeno embaixo do valor, só nesta tela, pra não
   confundir com o "Preço Final" de Cotações/Comparativo (que sempre inclui
   o frete) — ver o comentário em calcPrecosReqRowHtml() em frontend.js. */
.cotvr-preco-sub{ display:block;font-size:9px;font-weight:400;color:var(--ink-faint);text-transform:none;margin-top:1px; }
/* v2.47.26 — Frete deixou de ficar em negrito, pedido do usuário ("O valor
   do frete não precisa ser em negrito."), pra não competir visualmente com
   Custo Final e Vlr Unit Venda. */
.cotvr-frete{ font-size:12.5px;font-weight:400;color:var(--ink-soft); }
/* v2.49.0 — Prazo (c.prazoEntrega), coluna nova logo depois de Frete. */
.cotvr-prazo{ font-size:12px;color:var(--ink-soft); }
.cotvr-select{
  font-size:11.5px;padding:6px 8px;border-radius:7px;border:1px solid var(--border);width:100%;
  background:var(--surface);color:var(--ink);font-family:inherit;
}
.cotvr-select:focus{ border-color:var(--primary); }
.cotvr-venda{ font-size:13px;font-weight:800;color:var(--success); }
/* v2.47.26 — coluna nova: Vlr Total Venda (Vlr Unit Venda × Qtd).
   v2.49.0 — as colunas Custo/IPI/PIS·COF (também desta rodada) saíram
   daqui: ver nota em .cotvr-head-row acima. */
.cotvr-venda-total{ font-size:13px;font-weight:800;color:var(--success); }
/* v2.46.0 — as 3 colunas de margem entre Preço Final e Preço de Venda:
   percentual em cima (negrito), valor em R$ embaixo (apagado) — "—" quando
   ainda não calculado (ver margemCellHtml() em frontend.js). */
.margem-cell{ font-size:11.5px;line-height:1.3; }
.margem-cell .pct{ display:block;font-weight:700;color:var(--ink); }
.margem-cell .val{ display:block;color:var(--ink-faint);font-size:10.5px; }
.margem-cell.is-empty .pct{ color:var(--ink-faint);font-weight:400; }
.cotvr-foot{
  display:flex;align-items:center;justify-content:space-between;margin-top:16px;border-top:1px solid var(--border);
  padding-top:16px;gap:14px;flex-wrap:wrap;
}
.cotvr-nota{ font-size:11.5px;color:var(--ink-soft);margin-top:14px;max-width:760px;line-height:1.6; }
@media (max-width:860px){
  .cotvr-head-row{ display:none; }
  .cotvr-row{ grid-template-columns:1fr 1fr;row-gap:8px; }
}
/* v2.39.0 — percentuais de uma Tabela de Venda "Cálculo Manual", digitados
   linha a linha dentro desta mesma tela (ver calcManualPctRowHtml() em
   frontend.js — bug corrigido nesta rodada: essa tela não tinha nenhum
   suporte a tabelas manuais, sempre calculava com 0% de margem
   silenciosamente).
   v2.46.0 (pedido do usuário, mockup aprovado "cmp03-calculo-manual-
   compacto-mockup.html"): layout compactado numa linha só — rótulo ao lado
   do campo (não mais em cima, com .field/.percent-input genéricos e caixas
   grandes) e o resultado em R$ (Preço de Venda ao vivo) no lugar do antigo
   "Total: +X%". Classes próprias (.mfield), não mais .field, pra não herdar
   o tamanho dos formulários genéricos. */
.cotvr-manual-row{
  background:var(--surface-2);border-radius:var(--radius-md);padding:9px 12px;
  margin:0 0 12px;display:flex;flex-wrap:wrap;gap:14px;align-items:center;
}
.cotvr-manual-row .mfield{ display:flex;align-items:center;gap:6px; }
.cotvr-manual-row .mfield label{ font-size:11px;font-weight:700;color:var(--ink-soft);white-space:nowrap; }
.cotvr-manual-row .mfield .percent-input{
  display:flex;align-items:center;width:72px;border:1px solid var(--border);
  border-radius:6px;background:var(--surface);padding:0 6px;height:26px;
}
.cotvr-manual-row .mfield .percent-input input{
  border:none;background:transparent;width:100%;font-size:12.5px;padding:0;outline:none;color:var(--ink);
}
.cotvr-manual-row .mfield .percent-input span{ font-size:11px;color:var(--ink-faint); }
.cotvr-manual-row .mdivider{ width:1px;align-self:stretch;background:var(--border);margin:0 2px; }
.cotvr-manual-row .mresult{
  margin-left:auto;display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--ink-soft);white-space:nowrap;
}
.cotvr-manual-row .mresult strong{ font-size:14.5px;color:var(--ink);font-weight:700; }
@media (max-width:860px){
  .cotvr-manual-row{ flex-direction:column;align-items:stretch; }
  .cotvr-manual-row .mresult{ margin-left:0; }
  .cotvr-manual-row .mdivider{ display:none; }
}

/* ================= "Detalhar Cálculo" / "Atualizar" (CMP-03 → CMP-04) =================
   v2.47.30 — dois botões novos no rodapé da CMP-03 (ver .cotvr-foot acima e
   renderCalcPrecosReqBody()/wireCalcPrecosReqBody() em frontend.js), pedido
   do usuário: "do lado do botão enviar para cotação eu estava pensando em
   criar um botão chamado Detalhar Calculo... Estou pensando em outro botão
   chamado atualizar, toda vez que clicar nele, o sistema vai atualizar
   todos os calculos."

   "Detalhar Cálculo" abre a CMP-04 (troca de lugar com a CMP-03 dentro do
   mesmo #detailPanel, igual ao "‹ Voltar ao comparativo" já faz hoje) com o
   passo a passo de TODOS os itens marcados (mesmas caixinhas de seleção já
   existentes) — do Custo (Valor Unitário, COT-02) até o Vlr Total Venda.
   Mockup "cmp03-detalhar-atualizar-mockup.html" (3 rodadas, todas
   aprovadas):
   - cada item é uma linha "fechada" (acordeão) — só Produto + Custo Final +
     Vlr Unit Venda + Vlr Total Venda + uma seta, igual aos grupos do menu
     lateral (.nav-group-header/.nav-group-chevron) e à linha de
     "Comentários" (.cf-comentarios-entry) que já existem no sistema; clica
     pra abrir e ver o passo a passo completo, clica de novo pra fechar —
     "Expandir todos"/"Recolher todos" no topo;
   - a tela usa .panel-wide (760px), não .panel-xwide (1480px, só a CMP-03
     — tabela de 17 colunas — continua usando essa largura) — ela não
     precisa da largura toda, é só uma lista de linhas resumidas (pedido:
     "podemos diminuir a largura dessa tela");
   - o nome do Produto fica logo do lado dos 3 valores (não mais espalhado
     nas 2 pontas da linha) — pedido: "a descrição precisa ficar mais
     proxima dos valores". */
.calcdet-toolbar{ display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px;font-size:12px;color:var(--ink-soft); }
.calcdet-toolbar .hint{ color:var(--ink-faint); }
.calcdet-item{
  background:var(--surface);border:1px solid var(--border);border-radius:10px;
  margin-bottom:8px;overflow:hidden;
}
.calcdet-item:last-child{ margin-bottom:0; }
.calcdet-head{ display:flex;align-items:center;gap:16px;padding:10px 14px;cursor:pointer;user-select:none; }
.calcdet-head:hover{ background:var(--surface-2); }
.calcdet-chevron{ display:flex;flex:none;color:var(--ink-faint);transition:transform .15s ease; }
.calcdet-chevron svg{ width:12px;height:12px; }
.calcdet-item.open .calcdet-chevron{ transform:rotate(90deg); }
.calcdet-titles{ min-width:0;max-width:190px;flex:0 1 190px; }
.calcdet-nome{ font-weight:700;font-size:13px;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
.calcdet-sub{ font-size:11px;color:var(--ink-faint);margin-top:1px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
.calcdet-summary{ display:flex;gap:16px;flex:none; }
.calcdet-mini{ text-align:right;min-width:78px; }
.calcdet-mini .lbl{ display:block;font-size:9.5px;text-transform:uppercase;letter-spacing:.03em;color:var(--ink-faint);margin-bottom:1px; }
.calcdet-mini .val{ font-size:12.5px;font-weight:700;color:var(--ink);font-variant-numeric:tabular-nums; }
.calcdet-mini.final .val{ color:var(--success);font-size:13px;font-weight:800; }
.calcdet-body{ display:none;border-top:1px solid var(--border);padding:6px 14px 10px 42px; }
.calcdet-item.open .calcdet-body{ display:block; }
.calcdet-steps{ display:flex;flex-direction:column; }
.calcdet-step{
  display:grid;grid-template-columns:1fr 78px 118px;gap:10px;align-items:center;
  padding:5px 2px;border-bottom:1px dashed var(--border);font-size:12px;
}
.calcdet-step:last-child{ border-bottom:none; }
.calcdet-step .lbl{ color:var(--ink-soft); }
.calcdet-step .pct{ color:var(--ink-faint);font-size:11px;text-align:right; }
.calcdet-step .val{ text-align:right;font-variant-numeric:tabular-nums;color:var(--ink); }
.calcdet-step.eq{ background:var(--surface-2);border-radius:7px;margin:2px 0; }
.calcdet-step.eq .lbl{ font-weight:700;color:var(--ink); }
.calcdet-step.eq .val{ font-weight:700;color:var(--ink); }
.calcdet-step.final{ background:var(--success-soft);border-radius:7px;margin-top:4px; }
.calcdet-step.final .lbl, .calcdet-step.final .val{ font-weight:800;color:var(--success); }
.calcdet-step.final .val{ font-size:13px; }
.calcdet-empty{ color:var(--ink-faint);font-size:12.5px;padding:10px 2px; }
.calcdet-back{ display:inline-flex;align-items:center;gap:6px;margin-bottom:16px; }
@media (max-width:620px){
  .calcdet-summary{ display:none; }
}

/* Destaque temporário numa linha da CMP-03 cujo valor mudou depois de
   clicar em "Atualizar" (cotvrAtualizarTodos() em frontend.js). */
@keyframes cfRowFlash{ 0%{ background:var(--warn-soft); } 100%{ background:transparent; } }
.cotvr-row.flash{ animation:cfRowFlash 1.6s ease;border-radius:8px; }

/* ---------- relatórios ---------- */
.cf-stat-grid{ display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:14px;margin-bottom:26px; }
.cf-stat-tile{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);
  padding:18px 20px;box-shadow:var(--shadow-sm);
}
.cf-stat-value{ font-family:'Manrope',Inter,system-ui,sans-serif;font-weight:800;font-size:24px;color:var(--primary-strong); }
.cf-stat-label{ font-size:12px;color:var(--ink-soft);margin-top:4px; }
.cf-bars-grid{ display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:20px; }
.cf-bars-block{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);
  padding:18px 20px;box-shadow:var(--shadow-sm);
}
.cf-bars-block h3{ margin:0 0 14px;font-size:14px; }
.cf-bar-row{ display:flex;align-items:center;gap:10px;margin-bottom:9px;font-size:12.5px; }
.cf-bar-label{ width:38%;color:var(--ink-soft);white-space:nowrap;overflow:hidden;text-overflow:ellipsis; }
.cf-bar-track{ flex:1;height:8px;border-radius:999px;background:var(--surface-2);overflow:hidden; }
.cf-bar-fill{ height:100%;border-radius:999px;background:var(--primary); }
.cf-bar-value{ width:26px;text-align:right;font-weight:700;color:var(--ink); }

/* ---------- Página Inicial (HOME-01) ---------- */
.cf-home{ display:flex;flex-direction:column;gap:16px; }
.cf-home-hero{
  display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;
  background:linear-gradient(135deg,var(--primary-soft),var(--surface-2));
  border:1px solid var(--border);border-radius:var(--radius-md);padding:20px 26px;
}
.cf-home-brand{ font-family:'Manrope',Inter,system-ui,sans-serif;font-weight:800;font-size:24px;color:var(--primary-strong);letter-spacing:.01em; }
.cf-home-tagline{ font-size:12.5px;color:var(--ink-soft);margin-top:2px; }
.cf-home-logo-img{ max-width:140px;max-height:56px;object-fit:contain;border-radius:8px;background:var(--surface);padding:6px;box-shadow:var(--shadow-sm); }
.cf-home-logo-placeholder{
  width:132px;height:52px;border:1.5px dashed var(--ink-faint);border-radius:10px;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;
  background:rgba(255,255,255,.35);text-align:center;padding:4px;
}
.cf-home-logo-placeholder span{ font-size:9.5px;font-weight:700;color:var(--ink-soft);letter-spacing:.03em; }
.cf-home-logo-placeholder small{ font-size:8.5px;color:var(--ink-faint); }

.cf-home-greeting{ display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap; }
.cf-home-greeting-left{ display:flex;align-items:center;gap:12px; }
.cf-home-greeting-name{ font-size:16.5px;font-weight:700;color:var(--ink); }
.cf-home-greeting-sub{ font-size:12px;color:var(--ink-faint);margin-top:1px; }

.cf-home-kpis{ display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px; }
.cf-home-kpi{ background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:14px 16px;box-shadow:var(--shadow-sm); }
.cf-home-kpi-head{ display:flex;align-items:center;justify-content:space-between;margin-bottom:8px;font-size:10.5px;font-weight:700;color:var(--ink-faint);text-transform:uppercase;letter-spacing:.03em; }
.cf-home-kpi-icon svg{ width:14px;height:14px;display:block; }
.cf-home-kpi-value{ font-family:'Manrope',Inter,system-ui,sans-serif;font-weight:800;font-size:22px;color:var(--ink); }
.cf-home-kpi-sub{ font-size:10.5px;color:var(--ink-faint);margin-top:2px; }

.cf-home-cols{ display:flex;gap:16px;align-items:flex-start;flex-wrap:wrap; }
.cf-home-panel{ flex:1;min-width:280px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:16px 18px;box-shadow:var(--shadow-sm); }
.cf-home-panel-head{ display:flex;align-items:center;justify-content:space-between;font-size:13.5px;font-weight:700;margin-bottom:10px;color:var(--ink); }
.cf-home-panel-badge{ background:var(--danger-soft);color:var(--danger);font-size:11px;font-weight:700;border-radius:9px;padding:1px 8px; }
.cf-home-panel-link{ background:none;border:none;padding:0;font-size:11.5px;font-weight:600;color:var(--primary);cursor:pointer; }
.cf-home-panel-link:hover{ text-decoration:underline; }

.cf-home-atencao-item{ display:flex;align-items:flex-start;gap:10px;padding:8px 0;border-bottom:1px solid var(--surface-2); }
.cf-home-atencao-item:last-child{ border-bottom:none; }
.cf-home-atencao-icon{ width:28px;height:28px;border-radius:8px;display:flex;align-items:center;justify-content:center;flex-shrink:0; }
.cf-home-atencao-icon svg{ width:14px;height:14px; }
.cf-home-atencao-text{ flex:1;min-width:0; }
.cf-home-atencao-title{ font-size:12.5px;font-weight:600;color:var(--ink); }
.cf-home-atencao-sub{ font-size:11px;color:var(--ink-faint);margin-top:1px; }
.cf-home-atencao-link{ background:none;border:none;padding:0;font-size:11.5px;font-weight:600;color:var(--primary);cursor:pointer;flex-shrink:0; }
.cf-home-atencao-link:hover{ text-decoration:underline; }

.cf-home-recentes-head{
  display:grid;grid-template-columns:1fr 1.3fr 1fr .7fr;gap:6px;
  font-size:10.5px;font-weight:700;color:var(--ink-faint);text-transform:uppercase;letter-spacing:.02em;
  padding-bottom:6px;border-bottom:1px solid var(--surface-2);
}
.cf-home-recente-row{
  display:grid;grid-template-columns:1fr 1.3fr 1fr .7fr;gap:6px;align-items:center;
  font-size:12px;padding:7px 0;border-bottom:1px solid var(--surface-2);cursor:pointer;
}
.cf-home-recente-row:last-child{ border-bottom:none; }
.cf-home-recente-row:hover{ background:var(--surface-2); }
.cf-home-recente-cliente{ overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }

.cf-home-item-cotado{ display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 0;border-bottom:1px solid var(--surface-2);cursor:pointer; }
.cf-home-item-cotado:last-child{ border-bottom:none; }
.cf-home-item-cotado:hover{ background:var(--surface-2); }
.cf-home-item-cotado-nome{ font-size:12.5px;font-weight:600;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
.cf-home-item-cotado-preco{ font-size:13px;font-weight:700;color:var(--primary-strong);flex-shrink:0; }

.cf-home-empty{ display:flex;align-items:center;gap:8px;color:var(--ink-faint);font-size:12.5px;padding:10px 0; }
.cf-home-empty svg{ width:16px;height:16px;flex-shrink:0; }

.cf-home-chart{ background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:16px 18px;box-shadow:var(--shadow-sm); }

/* ---------- Busca Avançada (v2.49.7, pedido do usuário: "na tela home-01
   eu gostaria de colocar um sistema de busca avançado... aprovado, gere os
   arquivos pra eu subir pro wordpress") — mockup aprovado em
   home01-busca-avancada-mockup.html. Barra reaproveitada no Início
   (buscaGlobalBarraHtml(), dentro de .cf-home acima) e na tela de
   resultados cheia BUSCA-01 (buscaResultadosShellHtml()) — ver frontend.js.
   Classes com prefixo "busca-" (nenhuma colidia com o resto do app na
   época). */
.busca-wrap{ position:relative;margin-bottom:18px; }
.busca-row{ display:flex;gap:10px; }
.busca-box{
  flex:1;display:flex;align-items:center;gap:10px;background:var(--surface-2);border:1px solid var(--border);
  border-radius:10px;padding:0 14px;transition:border-color .15s,box-shadow .15s;
}
.busca-box:focus-within{ border-color:var(--primary);background:var(--surface);box-shadow:0 0 0 3px var(--primary-soft); }
.busca-box svg{ width:17px;height:17px;flex:none;color:var(--ink-faint); }
.busca-box input{ flex:1;min-width:0;border:none;background:transparent;font-size:13.5px;color:var(--ink);padding:11px 0;outline:none;font-family:inherit; }
.busca-box input::placeholder{ color:var(--ink-faint); }
.busca-filter-btn{
  display:flex;align-items:center;gap:7px;background:var(--surface);border:1px solid var(--border);border-radius:10px;
  padding:0 15px;font-size:12.5px;font-weight:700;color:var(--ink);white-space:nowrap;cursor:pointer;
}
.busca-filter-btn:hover{ background:var(--surface-2); }
.busca-filter-btn svg{ width:15px;height:15px;color:var(--ink-soft); }
.busca-filter-btn.active{ border-color:var(--primary);color:var(--primary-strong);background:var(--primary-soft); }
.busca-filter-count{
  background:var(--primary);color:var(--primary-ink);font-size:10px;font-weight:800;border-radius:999px;
  min-width:16px;height:16px;display:flex;align-items:center;justify-content:center;padding:0 4px;
}

/* dropdown de resultados instantâneos / popover de filtros — flutuam sobre o
   conteúdo (position:absolute, ancorados em .busca-wrap), nunca empurram o
   resto da tela pra baixo. */
.busca-dropdown, .busca-fp{
  position:absolute;top:calc(100% + 8px);left:0;right:0;z-index:40;
  background:var(--surface);border:1px solid var(--border);border-radius:12px;box-shadow:var(--shadow-lg);
}
.busca-dropdown{ max-height:70vh;overflow:hidden auto; }
.busca-fp{ max-width:640px;padding:18px 20px; }

.busca-dr-group{ border-bottom:1px solid var(--border); }
.busca-dr-group:last-of-type{ border-bottom:none; }
.busca-dr-group-head{
  display:flex;align-items:center;gap:8px;padding:9px 16px;background:var(--surface-2);
  font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-faint);
}
.busca-chip-icon{ width:18px;height:18px;border-radius:6px;display:flex;align-items:center;justify-content:center;flex:none; }
.busca-chip-icon svg{ width:11px;height:11px; }
.busca-dr-count{ margin-left:auto;background:var(--surface);border:1px solid var(--border);border-radius:999px;padding:1px 7px;font-weight:800;color:var(--ink-soft); }
.busca-dr-row{ display:flex;align-items:center;gap:12px;padding:9px 16px;font-size:12.8px;cursor:pointer; }
.busca-dr-row:hover{ background:var(--surface-2); }
.busca-dr-ico{ width:30px;height:30px;border-radius:8px;display:flex;align-items:center;justify-content:center;flex:none; }
.busca-dr-ico svg{ width:15px;height:15px; }
.busca-dr-main{ flex:1;min-width:0; }
.busca-dr-title{ font-weight:700;color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
.busca-dr-sub{ font-size:11px;color:var(--ink-faint);margin-top:1px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
.busca-dr-marca{ font-size:11px;font-weight:700;color:var(--ink-soft); }
.busca-dr-empty{ display:flex;align-items:center;gap:8px;color:var(--ink-faint);font-size:12.5px;padding:16px; }
.busca-dr-empty svg{ width:16px;height:16px;flex:none; }
.busca-dr-footer{ display:flex;align-items:center;justify-content:center;gap:6px;padding:11px;background:var(--surface-2);font-size:12px;font-weight:700;color:var(--primary-strong);cursor:pointer; }
.busca-dr-footer:hover{ background:var(--border); }
.busca-dr-title mark, .busca-res-table mark{ background:#ffe9b3;color:#1a231e;padding:0 1px;border-radius:2px; }

/* ícones por tipo de registro — reaproveita tokens de cor já existentes, sem
   precisar de nenhum novo (role-admin/accent/role-gestor/st-purple/success/
   primary já cobrem light + dark mode). */
.busca-ico-req{ background:var(--primary-soft);color:var(--primary-strong); }
.busca-ico-cot{ background:var(--role-admin-soft);color:var(--role-admin); }
.busca-ico-for{ background:var(--accent-soft);color:var(--accent); }
.busca-ico-pro{ background:var(--role-gestor-soft);color:var(--role-gestor); }
.busca-ico-ref{ background:var(--st-purple-soft);color:var(--st-purple); }
.busca-ico-cli{ background:var(--success-soft);color:var(--success); }

/* popover de filtros */
.busca-fp-head{ display:flex;align-items:center;justify-content:space-between;margin-bottom:14px; }
.busca-fp-head span{ font-size:13px;font-weight:800; }
.busca-fp-close{ background:none;border:none;color:var(--ink-faint);cursor:pointer;display:flex;padding:2px; }
.busca-fp-close svg{ width:14px;height:14px; }
.busca-fp-close:hover{ color:var(--ink); }
.busca-fp-section{ margin-bottom:14px; }
.busca-fp-label{ font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--ink-faint);margin-bottom:7px; }
.busca-fp-chips{ display:flex;flex-wrap:wrap;gap:7px; }
.busca-fp-chip{
  display:flex;align-items:center;gap:5px;padding:6px 12px;border-radius:999px;border:1px solid var(--border);
  background:var(--surface-2);font-size:12px;font-weight:700;color:var(--ink-soft);cursor:pointer;
}
.busca-fp-chip:hover{ background:var(--border); }
.busca-fp-chip.on{ background:var(--primary);color:var(--primary-ink);border-color:var(--primary); }
.busca-fp-chip svg{ width:11px;height:11px; }
.busca-fp-grid2{ display:grid;grid-template-columns:1fr 1fr;gap:12px; }
.busca-fp-field label{ display:block;font-size:11px;font-weight:700;color:var(--ink-faint);margin-bottom:5px;text-transform:uppercase;letter-spacing:.03em; }
.busca-fp-field input, .busca-fp-field select{
  width:100%;border:1px solid var(--border);border-radius:7px;padding:8px 10px;font-size:12.5px;color:var(--ink);
  background:var(--surface);font-family:inherit;
}
.busca-fp-foot{ display:flex;justify-content:flex-end;gap:8px;margin-top:16px;padding-top:14px;border-top:1px solid var(--border); }

/* tela de resultados cheia (BUSCA-01) */
.busca-res{ max-width:1200px; }
.busca-res-head{ display:flex;align-items:baseline;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:4px; }
.busca-res-head h3{ font-size:16px;margin:0;font-weight:800;color:var(--ink); }
.busca-res-count{ font-size:12px;color:var(--ink-faint); }
.busca-res-tabs{ display:flex;gap:7px;flex-wrap:wrap;margin:16px 0; }
.busca-res-tab{ padding:6px 13px;border-radius:999px;font-size:12px;font-weight:700;border:1px solid var(--border);background:var(--surface);color:var(--ink-soft);cursor:pointer; }
.busca-res-tab:hover{ background:var(--surface-2); }
.busca-res-tab.on{ background:var(--primary);color:var(--primary-ink);border-color:var(--primary); }
.busca-res-section{ background:var(--surface);border:1px solid var(--border);border-radius:12px;margin-bottom:14px;overflow:hidden; }
.busca-res-section-head{ display:flex;align-items:center;gap:8px;padding:11px 16px;border-bottom:1px solid var(--border);background:var(--surface-2); }
.busca-res-ico{ width:26px;height:26px;border-radius:7px;display:flex;align-items:center;justify-content:center;flex:none; }
.busca-res-ico svg{ width:14px;height:14px; }
.busca-res-section-head b{ font-size:13px; }
.busca-res-section-count{ margin-left:auto;font-size:11px;color:var(--ink-faint); }
.busca-res-table{ width:100%;border-collapse:collapse;font-size:12.5px; }
.busca-res-table th{ text-align:left;font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--ink-faint);font-weight:700;padding:7px 16px;border-bottom:1px solid var(--border); }
.busca-res-table td{ padding:8px 16px;border-bottom:1px solid var(--border);vertical-align:middle; }
.busca-res-table tr:last-child td{ border-bottom:none; }
.busca-res-table tbody tr{ cursor:pointer; }
.busca-res-table tbody tr:hover{ background:var(--surface-2); }
.busca-res-ver{ font-size:11.5px;font-weight:700;color:var(--primary-strong);white-space:nowrap; }
.busca-res-section-foot{ padding:9px 16px;font-size:11.5px;font-weight:700;color:var(--primary-strong);background:var(--surface-2);cursor:pointer; }
.busca-res-section-foot:hover{ background:var(--border); }

@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .busca-dr-title mark,
  :root:not([data-theme="light"]) .busca-res-table mark{ background:#5c4a1a;color:#f3e6bd; }
}

@media (max-width:820px){
  .busca-row{ flex-wrap:wrap; }
  .busca-filter-btn span{ display:none; }
  .busca-fp{ max-width:none; }
  .busca-fp-grid2{ grid-template-columns:1fr; }
  .busca-res-section{ overflow-x:auto; }
}

@media (max-width:820px){
  .cf-home-cols{ flex-direction:column; }
  .cf-home-hero{ padding:16px 18px; }
  .cf-home-recentes-head,.cf-home-recente-row{ grid-template-columns:1fr 1fr .6fr; }
  .cf-home-recente-row .cf-home-recente-cliente,.cf-home-recentes-head span:nth-child(2){ display:none; }
}

/* ---------- toasts ---------- */
.toast-stack{ position:fixed;bottom:20px;right:20px;display:flex;flex-direction:column;gap:8px;z-index:80; }
@media (max-width:820px){ .toast-stack{ bottom:80px;right:14px;left:14px; } }
.toast{
  display:flex;align-items:center;gap:9px;background:var(--surface);border:1px solid var(--border);
  border-left:4px solid var(--primary);box-shadow:var(--shadow-md);border-radius:10px;
  padding:11px 14px;font-size:12.8px;color:var(--ink);max-width:340px; animation:toast-in .18s ease;
}
.toast.danger{ border-left-color:var(--danger); }
.toast.success{ border-left-color:var(--success); }
@keyframes toast-in{ from{opacity:0;transform:translateY(6px);} to{opacity:1;transform:translateY(0);} }

/* ---------- popup de notificação (v2.36.0) ----------
   Variante mais completa do .toast genérico acima (ícone + título +
   descrição + botões Ver/Dispensar + X), usada só pelo sistema de
   notificação (ver showNotifToast() em frontend.js) — o .toast simples
   (mensagem de uma linha, some sozinho em ~3.6s) continua existindo do
   jeito que sempre foi, pra feedback rápido de salvar/excluir/erro. Vive no
   mesmo #toastStack (canto inferior direito), empilhando com ele quando os
   dois aparecerem juntos. NÃO tem nenhuma animação/timer de saída — pedido
   do usuário: só fecha por clique da própria pessoa (ver os 3
   addEventListener de "Ver"/"Dispensar"/X em showNotifToast()). */
.toast.toast-notif{ align-items:flex-start;max-width:360px;padding:12px 13px;gap:10px;border-left-color:var(--primary); }
.toast-notif .toast-icon{
  flex:none;width:34px;height:34px;border-radius:9px;display:flex;align-items:center;justify-content:center;
  background:var(--primary-soft);color:var(--primary-strong);
}
.toast-notif .toast-icon svg{ width:18px;height:18px;flex:none; }
.toast-notif .toast-icon.tone-warn{ background:var(--warn-soft);color:var(--warn); }
.toast-notif .toast-icon.tone-danger{ background:var(--danger-soft);color:var(--danger); }
.toast-notif .toast-body{ flex:1;min-width:0; }
.toast-notif .toast-title{ margin:0 0 2px;font-size:13px;font-weight:700;color:var(--ink); }
.toast-notif .toast-desc{ margin:0;font-size:12px;color:var(--ink-soft);line-height:1.4; }
.toast-notif .toast-actions{ display:flex;gap:14px;margin-top:8px; }
.toast-notif .toast-link,.toast-notif .toast-dismiss{
  border:none;background:none;padding:0;font-size:11.5px;font-weight:700;cursor:pointer;font-family:inherit;
}
.toast-notif .toast-link{ color:var(--primary-strong); }
.toast-notif .toast-dismiss{ color:var(--ink-faint); }
.toast-notif .toast-link:hover,.toast-notif .toast-dismiss:hover{ text-decoration:underline; }
.toast-notif .toast-close{
  flex:none;border:none;background:none;color:var(--ink-faint);cursor:pointer;padding:2px;
  margin:-2px -2px 0 0;border-radius:6px;display:flex;
}
.toast-notif .toast-close:hover{ background:var(--surface-2);color:var(--ink); }
.toast-notif .toast-close svg{ width:14px;height:14px;flex:none; }

/* Botões de mudo/notificação nativa no rodapé da barra lateral (ver
   appShellHtml()/wireNotifControls() em frontend.js). */
.notif-controls{ display:flex;gap:6px;margin-top:8px; }
.notif-controls .btn-icon{ flex:1;display:flex;align-items:center;justify-content:center; }
.notif-controls .btn-icon svg{ width:15px;height:15px;flex:none; }
.notif-controls .btn-icon.is-active{ background:var(--primary-soft);color:var(--primary-strong);border-color:var(--primary-soft); }
.notif-controls .btn-icon.is-blocked{ color:var(--ink-faint);cursor:not-allowed; }

/* ---------- Calcular Preço de Venda / Itens Cotados / Avisos ---------- */
/* Caixa de destaque com o resultado calculado (Preço de Venda), no painel da
   tela "Calcular Preço de Venda" e no detalhe de "Itens Cotados". */
.result-highlight{
  background:var(--accent-soft);border:1px solid var(--accent);border-radius:var(--radius-md);
  padding:16px 18px;text-align:center;
}
.result-highlight .k{ font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;color:var(--primary-strong);font-weight:700;margin-bottom:6px; }
.result-highlight .v{ font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:28px;font-weight:700;color:var(--accent); }
.result-highlight .f{ font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:11.5px;color:var(--ink-soft);margin-top:6px; }
/* Lista de percentuais somados (componentes da Tabela de Venda escolhida). */
.comp-breakdown{ border:1px solid var(--border);border-radius:10px;background:var(--surface-2);overflow:hidden; }
.comp-row{ display:flex;align-items:center;justify-content:space-between;padding:9px 14px;font-size:12.5px;color:var(--ink-soft);border-bottom:1px solid var(--border); }
.comp-row:last-child{ border-bottom:none; }
.comp-row.total{ background:var(--surface);font-weight:700;color:var(--ink); }
/* Botões empilhados verticalmente (as três decisões de "Itens Cotados"). */
.stack-buttons{ display:flex;flex-direction:column;gap:10px; }
.stack-buttons .btn{ justify-content:center; }
/* Cartões de "Avisos" (Comprador) — reaproveita .item-card, só que sem o
   fundo cinza (fica igual a um cartão comum, mais destacado que uma linha de
   tabela, já que cada aviso pede uma ação). */
.aviso-card{ background:var(--surface);box-shadow:var(--shadow-sm); }
.aviso-card.is-resolvido{ opacity:.55; }
.aviso-card-head{ display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:10px; }
.aviso-headline{ font-size:14px;font-weight:700;color:var(--ink); }
.aviso-quando{ font-size:11.5px;color:var(--ink-faint);margin-top:2px; }
.aviso-grid{ display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px 16px;margin:12px 0; }
.aviso-actions{ display:flex;justify-content:flex-end;margin-top:4px; }

/* ---------- Comentários da Requisição (REQ-04) ---------- */
/* Ponto de entrada dentro do detalhe da Requisição (openRequisicaoDetail()):
   linha clicável "Comentários · N comentários · M novos" com um chevron à
   direita, no mesmo espírito de .cotacao-progress logo acima. */
.cf-comentarios-entry{
  display:flex;align-items:center;justify-content:space-between;gap:10px;
  margin-top:22px;padding:13px 14px;border-radius:10px;border:1px solid var(--border);
  background:var(--surface-2);cursor:pointer;transition:background .12s ease;
}
.cf-comentarios-entry:hover{ background:var(--primary-soft); }
.cf-comentarios-entry-left{ display:flex;align-items:center;gap:10px;font-size:13px;font-weight:600;color:var(--ink); }
.cf-comentarios-entry-left svg{ width:17px;height:17px;flex:none;color:var(--ink-soft); }
.cf-comentarios-entry-chevron{ display:flex;flex:none;color:var(--ink-faint); }
.cf-comentarios-entry-chevron svg{ width:15px;height:15px; }

/* Botão "Voltar à requisição" no topo da tela de comentários — reaproveita o
   ícone de chevron (que aponta pra direita) espelhado, em vez de desenhar um
   segundo path só pra isso. */
.cf-comentarios-back{
  display:inline-flex;align-items:center;gap:6px;background:none;border:none;padding:0;
  margin-bottom:16px;color:var(--ink-soft);font-size:12.5px;font-weight:700;cursor:pointer;
}
.cf-comentarios-back:hover{ color:var(--ink); }
.cf-comentarios-back svg{ width:14px;height:14px;transform:rotate(180deg); }

.cf-comment-list{ display:flex;flex-direction:column;gap:16px; }
.cf-comment-item{ display:flex;flex-direction:column;gap:6px; }
.cf-comment-head{ display:flex;align-items:center;gap:9px; }
/* Avatar com iniciais colorido pelo PAPEL do autor NO MOMENTO em que postou
   (snapshot gravado em _cf_autor_papel — ver includes/rest-comentarios.php),
   não pelo papel atual dele. Três cores bem distintas: Requisitante reaproveita
   --primary (verde, cor principal do app), Comprador reaproveita --accent
   (laranja, já usado nos botões primários), Administrador usa --role-admin
   (azul, criada só pra isso — ver comentário em :root). */
.cf-comment-avatar{
  width:30px;height:30px;border-radius:50%;flex:none;display:flex;align-items:center;justify-content:center;
  font-weight:800;font-size:11px;color:#fff;
}
.cf-comment-avatar.role-requisitante{ background:var(--primary); }
.cf-comment-avatar.role-comprador{ background:var(--accent); }
.cf-comment-avatar.role-administrador{ background:var(--role-admin); }
.cf-comment-avatar.role-gestor{ background:var(--role-gestor); }
.cf-comment-name{ font-weight:700;font-size:13px;color:var(--ink); }
.cf-comment-role-badge{
  font-size:9.5px;font-weight:800;letter-spacing:.04em;padding:2px 8px;border-radius:999px;
}
.cf-comment-role-badge.role-requisitante{ background:var(--primary-soft);color:var(--primary-strong); }
.cf-comment-role-badge.role-comprador{ background:var(--accent-soft);color:var(--accent); }
.cf-comment-role-badge.role-administrador{ background:var(--role-admin-soft);color:var(--role-admin); }
.cf-comment-role-badge.role-gestor{ background:var(--role-gestor-soft);color:var(--role-gestor); }
.cf-comment-time{ margin-left:auto;font-size:11px;color:var(--ink-faint);white-space:nowrap; }
/* white-space:pre-wrap preserva as quebras de linha do texto original — sem
   isso, todo o comentário viraria uma única linha (\n vira espaço em branco
   normal no HTML), mesmo o servidor guardando as quebras corretamente. */
.cf-comment-text{
  font-size:13.3px;color:var(--ink);line-height:1.55;white-space:pre-wrap;
  padding-left:39px;word-break:break-word;
}

/* Divisória "M NOVOS COMENTÁRIOS", posicionada imediatamente antes do
   primeiro comentário novo para o usuário atual (ver
   primeiroComentarioNovoIndex() em frontend.js). */
.cf-comments-divider{
  display:flex;align-items:center;gap:10px;margin:4px 0;
  color:var(--danger);font-size:10.5px;font-weight:800;letter-spacing:.06em;
}
.cf-comments-divider::before,.cf-comments-divider::after{
  content:'';flex:1;height:0;border-top:1px dashed var(--danger);opacity:.45;
}

.cf-comment-compose{ margin-top:22px;padding-top:16px;border-top:1px solid var(--border); }
.cf-comment-textarea{
  width:100%;min-height:76px;resize:vertical;padding:10px 12px;border-radius:8px;
  border:1px solid var(--border);background:var(--surface-2);color:var(--ink);
  font-size:13.3px;font-family:inherit;outline:none;
}
.cf-comment-textarea:focus{ border-color:var(--primary);background:var(--surface); }
.cf-comment-send-row{ display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:10px; }
.cf-comment-caption{ font-size:10.5px;color:var(--ink-faint); }

::selection{ background:var(--accent-soft); }
:focus-visible{ outline:2px solid var(--accent);outline-offset:2px; }
@media (prefers-reduced-motion: reduce){ *{ animation:none!important;transition:none!important; } }

/* ==================== v2.28.0: Exportar Relatórios, Histórico de
   Alterações, Licença no App, Marcas Duplicadas, Relatórios Visuais ==================== */

/* ---------- Exportar Relatórios (CSV/PDF) ---------- */
.cf-relatorios-head{ display:flex;justify-content:flex-end;margin-bottom:16px; }
.cf-export-dropdown{ position:relative; }
.cf-export-menu{
  position:absolute;top:calc(100% + 6px);right:0;min-width:170px;z-index:20;
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);
  box-shadow:var(--shadow-md);padding:6px;display:none;flex-direction:column;gap:2px;
}
.cf-export-dropdown.open .cf-export-menu{ display:flex; }
.cf-export-menu button{
  display:block;width:100%;text-align:left;padding:8px 10px;border-radius:6px;border:none;
  background:transparent;color:var(--ink);font-size:12.5px;font-weight:600;cursor:pointer;
}
.cf-export-menu button:hover{ background:var(--surface-2); }

/* Folha de impressão (v2.28.0, "Exportar PDF" = window.print() nativo, sem
   nenhuma biblioteca — ver exportRelatoriosPdf() em assets/frontend.js):
   esconde tudo que não é o conteúdo dos Relatórios, e tira interações
   (dropdown de exportação, hover de gráfico) que não fazem sentido no papel. */
@media print{
  .sidebar, .topbar, .toolbar, .backdrop, .toast-stack, .panel{ display:none!important; }
  .cf-app-fullscreen, .content, .view-area{ height:auto!important;overflow:visible!important; }
  .cf-relatorios-head{ display:none!important; }
  body{ background:#fff!important; }
}

/* ---------- Histórico de Alterações (detalhe de Cotação) ---------- */
.cf-historico-block{ margin-top:22px;padding-top:18px;border-top:1px solid var(--border); }
.cf-historico-block h3{ margin:0 0 14px;font-size:14px; }
.cf-historico-timeline{ display:flex;flex-direction:column;gap:0; }
.cf-historico-item{ display:flex;gap:12px;position:relative;padding-bottom:16px; }
.cf-historico-item:last-child{ padding-bottom:0; }
.cf-historico-item::before{
  content:'';position:absolute;left:4px;top:14px;bottom:-2px;width:1px;background:var(--border);
}
.cf-historico-item:last-child::before{ display:none; }
.cf-historico-dot{
  width:9px;height:9px;border-radius:50%;background:var(--primary);flex:none;margin-top:4px;
  box-shadow:0 0 0 3px var(--primary-soft);z-index:1;
}
.cf-historico-content{ flex:1;min-width:0; }
.cf-historico-desc{ font-size:12.8px;color:var(--ink);line-height:1.5; }
.cf-historico-de{ color:var(--ink-faint);text-decoration:line-through; }
.cf-historico-para{ color:var(--primary-strong);font-weight:700; }
.cf-historico-meta{ font-size:11px;color:var(--ink-faint);margin-top:2px; }
/* "Motivo" (v2.50.0, Margem Marcas, pedido do usuário: "no histórico,
   acrescente um campo para colocar o motivo da alteração") — linha extra
   opcional dentro de uma entrada do histórico, só aparece quando preenchida
   (ver mmHistoricoTimelineHtml() em assets/frontend.js); genérica o
   suficiente pra qualquer outro histórico que no futuro queira a mesma
   informação. */
.cf-historico-motivo{ font-size:12px;color:var(--ink-soft);font-style:italic;margin-top:2px; }
.cf-historico-vazio{ font-size:12px;color:var(--ink-faint);margin:0; }

/* ---------- Licença no App ---------- */
.cf-licenca-card{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);
  padding:22px 24px;box-shadow:var(--shadow-sm);max-width:560px;
}
.cf-licenca-head{ margin-bottom:14px; }
.cf-licenca-msg{
  display:flex;align-items:flex-start;gap:8px;padding:10px 12px;border-radius:8px;
  font-size:12.5px;line-height:1.5;margin-bottom:16px;
}
.cf-licenca-msg svg{ width:16px;height:16px;flex:none;margin-top:1px; }
.cf-licenca-msg.tone-warn{ background:var(--warn-soft);color:var(--warn); }
.cf-licenca-msg.tone-danger{ background:var(--danger-soft);color:var(--danger); }
.cf-licenca-sub{ font-size:11px;color:var(--ink-faint);margin:14px 0 0; }

/* ---------- Marcas Duplicadas ---------- */
.cf-dup-list{ display:flex;flex-direction:column;gap:10px; }
.cf-dup-row{
  display:flex;align-items:center;gap:12px;padding:12px 14px;border:1px solid var(--border);
  border-radius:10px;background:var(--surface-2);flex-wrap:wrap;
}
.cf-dup-names{ display:flex;align-items:center;gap:8px;flex:1;min-width:220px;flex-wrap:wrap; }
.cf-dup-name{ font-weight:700;color:var(--ink);font-size:13px; }
.cf-dup-vs{ font-size:11px;color:var(--ink-faint);font-style:italic; }
/* Reaproveita .checkbox-field (v2.27.1) também para radio — mesmo visual de
   campo de escolha já usado em Tabela de Venda "Cálculo Manual". */
.checkbox-field input[type="radio"]{ width:16px;height:16px;flex:none;margin-top:1px;accent-color:var(--primary);cursor:pointer; }

/* ---------- Relatórios Visuais (gráficos SVG) ---------- */
.cf-relatorios-visuais{ margin-top:26px; }
.cf-relatorios-visuais > h2{ font-size:16px;margin:0 0 14px; }
.cf-svgchart-grid{ display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:20px; }
.cf-svgchart-block{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);
  padding:18px 20px;box-shadow:var(--shadow-sm);overflow-x:auto;
}
.cf-svgchart-block h3{ margin:0 0 14px;font-size:14px; }
/* max-width (nunca width:100%) é de propósito (v2.28.1, corrige um bug
   visual): o <svg> agora tem width/height explícitos no próprio desenho
   (ver svgBarChartHtml(), assets/frontend.js) — max-width só encolhe em
   telas estreitas, sem esticar o desenho pra preencher um cartão largo
   (o que, com poucas barras, deixava o gráfico gigantesco). */
.cf-svgchart{ display:block;max-width:100%;height:auto; }
.cf-svgchart-bar{ fill:var(--primary); }
.cf-svgchart-label{ fill:var(--ink-soft);font-size:10.5px;font-family:'Inter',system-ui,sans-serif; }
.cf-svgchart-value{ fill:var(--ink);font-size:11px;font-weight:700;font-family:'Inter',system-ui,sans-serif; }

/* ---------- Carteira e Pendências (v2.29.0, mockup aprovado) ----------
   Classes novas (não existia nada parecido no app antes): lista de
   fábricas, filtro avançado gerado a partir das colunas da planilha, e o
   modal de envio/substituição — nomes e valores portados quase sem
   alteração do mockup-carteira-pendencias.html aprovado, já que usam as
   mesmas variáveis de cor/raio/sombra do app de verdade. */
.carteira-row-nome{ font-weight:700;color:var(--ink); }
.carteira-row-sub{ font-size:11px;color:var(--ink-faint);margin-top:1px; }

.role-banner{
  display:flex;align-items:center;gap:8px;background:var(--warn-soft);color:var(--warn);border-radius:8px;
  padding:8px 12px;font-size:11.5px;font-weight:600;margin-bottom:12px;
}
.role-banner svg{ width:15px;height:15px;flex:none; }

.hide-badge{
  display:block;font-size:8px;font-weight:800;color:var(--accent);letter-spacing:.02em;margin-top:3px;
}

.note-callout{
  display:flex;gap:9px;align-items:flex-start;background:var(--surface-2);border:1px solid var(--border);
  border-radius:10px;padding:11px 13px;margin-top:14px;font-size:12px;color:var(--ink-soft);line-height:1.55;
}
.note-callout svg{ width:15px;height:15px;flex:none;margin-top:1px;color:var(--ink-faint); }
.note-callout b{ color:var(--ink); }
.note-callout.tone-warn{ background:var(--warn-soft);border-color:var(--warn); }
.note-callout.tone-warn svg{ color:var(--warn); }

/* Filtro avançado, gerado dinamicamente a partir das colunas da planilha
   desta fábrica (ver renderCarteiraFiltroHtml(), assets/frontend.js) —
   nunca o mesmo conjunto de campos de uma fábrica para outra. */
.adv-filter{
  background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-md);
  padding:14px 16px;margin:14px 0 16px;
}
.adv-filter-head{ display:flex;align-items:center;gap:8px;margin-bottom:10px; }
.adv-filter-head svg{ width:15px;height:15px;color:var(--primary-strong);flex:none; }
.adv-filter-head span{ font-size:11px;font-weight:800;letter-spacing:.04em;color:var(--primary-strong); }
.adv-filter-grid{ display:grid;grid-template-columns:repeat(auto-fill,minmax(170px,1fr));gap:10px; }
.adv-filter-field{ display:flex;flex-direction:column;gap:4px; }
.adv-filter-field label{ font-size:9.5px;font-weight:700;color:var(--ink-faint);letter-spacing:.03em; }
.adv-filter-field input, .adv-filter-field select{
  padding:7px 9px;border-radius:7px;border:1px solid var(--border);background:var(--surface);
  color:var(--ink);font-size:12px;outline:none;width:100%;
}
.adv-filter-field input:focus, .adv-filter-field select:focus{ border-color:var(--primary); }
.adv-filter-daterange{ display:flex;gap:5px; }
.adv-filter-foot{ display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:12px;padding-top:10px;border-top:1px dashed var(--border); }
.adv-filter-count{ font-size:11.5px;color:var(--ink-soft); }
.adv-filter-count b{ color:var(--ink); }
.link-btn{ background:none;border:none;color:var(--primary-strong);font-size:11.5px;font-weight:700;cursor:pointer;padding:0; }

/* Modal de envio/substituição de planilha (dois passos — ver
   openCarteiraUploadModal()/renderCarteiraUploadModal()). */
.upload-dropzone{
  border:1.5px dashed var(--border);border-radius:12px;padding:22px;text-align:center;background:var(--surface-2);
  display:flex;flex-direction:column;align-items:center;gap:8px;cursor:pointer;
}
.upload-dropzone svg{ width:28px;height:28px;color:var(--ink-faint); }
.upload-dropzone .ud-title{ font-weight:700;font-size:13px;color:var(--ink); }
.upload-dropzone .ud-sub{ font-size:11px;color:var(--ink-faint); }
.upload-file-picked{
  display:flex;align-items:center;gap:10px;background:var(--success-soft);border-radius:10px;padding:10px 12px;margin-top:4px;
}
.upload-file-picked svg{ width:18px;height:18px;color:var(--success);flex:none; }
.upload-file-picked .ufp-name{ font-weight:700;font-size:12.5px;color:var(--ink); }
.upload-file-picked .ufp-meta{ font-size:10.5px;color:var(--ink-faint); }
/* Modal de anexo de comprovante na Cotação (v2.40.0, pedido do usuário,
   mockup "anexo-cotacao-mockup.html" aprovado) — reaproveita o
   #detailPanel (ver comentário em abrirCotAnexoModal(), frontend.js) com
   este conteúdo próprio. Dropzone/preview de arquivo escolhido reaproveitam
   .upload-dropzone/.upload-file-picked acima; só a área de "colar"
   (Ctrl+V) e o estado "já tem um anexado" são novos. */
.cot-anexo-paste-area{
  border:1.5px dashed var(--border);border-radius:12px;padding:18px;text-align:center;
  background:var(--surface-2);color:var(--ink-faint);font-size:12px;margin-bottom:10px;
}
.cot-anexo-paste-area b{ color:var(--ink); }
.cot-anexo-current{
  display:flex;align-items:center;gap:10px;background:var(--success-soft);border-radius:10px;padding:12px 14px;
}
.cot-anexo-current svg{ width:20px;height:20px;color:var(--success);flex:none; }
.cot-anexo-current a{ font-weight:700;font-size:13px;color:var(--primary-strong);text-decoration:none; }
.cot-anexo-current a:hover{ text-decoration:underline; }
/* Lightbox de visualização do print (v2.40.0) — nunca fica exposto numa
   linha/tela sozinho, só abre ao clicar no link "Ver print" (ver
   abrirCotAnexoLightbox(), frontend.js). z-index acima de .panel/.backdrop
   (51/50) pra sempre aparecer por cima, mesmo com um modal aberto. */
.cf-lightbox-backdrop{
  position:fixed;inset:0;background:rgba(10,14,11,.78);z-index:70;
  display:flex;align-items:center;justify-content:center;padding:30px;cursor:zoom-out;
}
.cf-lightbox-img{ max-width:92vw;max-height:88vh;border-radius:8px;box-shadow:var(--shadow-lg);cursor:default; }
.cf-lightbox-close{
  position:absolute;top:18px;right:22px;width:34px;height:34px;border-radius:50%;border:none;
  background:rgba(255,255,255,.14);color:#fff;display:flex;align-items:center;justify-content:center;cursor:pointer;
}
.cf-lightbox-close svg{ width:16px;height:16px; }
.cf-lightbox-pdf-card{
  background:var(--surface);border-radius:12px;padding:28px;display:flex;flex-direction:column;align-items:center;
  gap:12px;cursor:default;
}
.cf-lightbox-pdf-card svg{ width:40px;height:40px;color:var(--primary-strong); }

/* Recortador de logo (v2.44.0) — pedido do usuário: "ha uma maneira de eu
   subir uma imagem de qualquer tamanho e ter a opção do sistema fazer esse
   recorte quadrado?" (escopo confirmado só pro campo "Logo do Fornecedor",
   ver abrirRecortadorLogo() em frontend.js). Mesmo padrão de overlay de tela
   cheia do lightbox de anexo acima (.cf-lightbox-backdrop), com conteúdo
   próprio; z-index acima dele (80) porque o recorte abre em cima do
   #formPanel, que já é mais alto que o #detailPanel onde o lightbox de
   anexo normalmente aparece. */
.cf-croptool-backdrop{
  position:fixed;inset:0;background:rgba(10,14,11,.5);z-index:80;
  display:flex;align-items:center;justify-content:center;padding:20px;
}
.cf-croptool-card{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);
  box-shadow:var(--shadow-lg);padding:20px 22px;max-width:360px;width:100%;
}
.cf-croptool-card h3{ font-size:14px;margin:0 0 3px;font-weight:800;color:var(--ink); }
.cf-croptool-card p{ font-size:12px;color:var(--ink-soft);margin:0 0 16px;line-height:1.5; }
.cf-croptool-stage{
  width:280px;height:280px;max-width:100%;margin:0 auto;border-radius:14px;overflow:hidden;position:relative;
  background:repeating-conic-gradient(var(--surface-2) 0% 25%, var(--surface) 0% 50%) 50% / 16px 16px;
  border:1px solid var(--border);cursor:grab;touch-action:none;user-select:none;
}
.cf-croptool-stage.dragging{ cursor:grabbing; }
.cf-croptool-stage img{ position:absolute;left:0;top:0;transform-origin:0 0;pointer-events:none;display:block; }
.cf-croptool-zoom{ display:flex;align-items:center;gap:10px;margin-top:14px; }
.cf-croptool-zoom svg{ width:15px;height:15px;color:var(--ink-faint);flex:none; }
.cf-croptool-zoom input[type="range"]{ flex:1;accent-color:var(--primary); }
.cf-croptool-actions{ display:flex;gap:8px;margin-top:16px;justify-content:flex-end; }
.cf-croptool-hint{ font-size:11px;color:var(--ink-faint);text-align:center;margin-top:10px;line-height:1.5; }

/* Modal de motivo (v2.47.38, pedido do usuário): pedido antes de confirmar
   "Não Comprar"/"Aguardar"/"Solicitar Revisão" na barra de decisão de "Itens
   Cotados desta Requisição"/"Req Cotadas" (ver abrirMotivoModal() em
   frontend.js) — "Comprar" continua imediato, sem motivo. Mesmo padrão de
   overlay de tela cheia criado/removido dinamicamente via JS que
   .cf-croptool-backdrop acima já usa (nunca fica parado no HTML do app
   shell). z-index acima de TODOS os outros overlays deste arquivo (50/51/
   70/80) porque este modal pode abrir por cima de um #detailPanel já aberto
   (51) no meio de uma decisão (ex: painel "Decidir" de "Aguardando").
   Mesmas variáveis/convenções visuais de .cf-croptool-card. */
.cf-motivo-backdrop{
  position:fixed;inset:0;background:rgba(10,14,11,.5);z-index:90;
  display:flex;align-items:center;justify-content:center;padding:20px;
}
.cf-motivo-card{
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);
  box-shadow:var(--shadow-lg);padding:20px 22px;max-width:440px;width:100%;
}
.cf-motivo-card h3{ font-size:14px;margin:0 0 3px;font-weight:800;color:var(--ink); }
.cf-motivo-card p{ font-size:12px;color:var(--ink-soft);margin:0 0 14px;line-height:1.5; }
.cf-motivo-card textarea{
  width:100%;min-height:90px;border:1px solid var(--border);border-radius:var(--radius-sm);
  padding:10px 12px;font:inherit;font-size:13px;color:var(--ink);resize:vertical;background:var(--surface);
}
.cf-motivo-card textarea:focus{ outline:none;border-color:var(--primary);box-shadow:0 0 0 3px var(--primary-soft); }
.cf-motivo-actions{ display:flex;gap:8px;margin-top:14px;justify-content:flex-end; }

/* v2.51.0 — modal "Confirmar Compra" (abrirConfirmarCompraModal(), VEN-05),
   mesmo overlay/card de .cf-motivo-backdrop/.cf-motivo-card acima, só mais
   largo (.cf-compra-card, mesma técnica de .cf-gerarmsg-card mais abaixo:
   sobrescreve só o max-width) pra caber uma linha por item marcado, cada
   uma com nome+marca, campo de quantidade e valor total daquele item. */
.cf-compra-card{ max-width:620px; }
.cfc-item{ display:flex;align-items:center;gap:12px;padding:12px 0;border-bottom:1px solid var(--border); }
.cfc-item:last-child{ border-bottom:none; }
.cfc-info{ flex:1;min-width:0; }
.cfc-info .nome{ font-weight:700;font-size:13px;color:var(--ink); }
.cfc-info .sub{ font-size:11px;color:var(--ink-faint);margin-top:2px; }
.cfc-qtd{ flex:none;display:flex;flex-direction:column;align-items:flex-end;gap:4px; }
.cfc-qtd label{ font-size:9.5px;font-weight:800;text-transform:uppercase;letter-spacing:.03em;color:var(--ink-faint); }
.cfc-qtd-row{ display:flex;align-items:center;gap:6px; }
.cfc-qtd-row input{
  width:64px;height:32px;border:1px solid var(--border);border-radius:7px;padding:0 8px;
  font-size:13px;font-weight:700;color:var(--ink);text-align:center;font-family:inherit;
}
.cfc-qtd-row input:focus{ outline:none;border-color:var(--primary);box-shadow:0 0 0 3px var(--primary-soft); }
.cfc-qtd-row .un{ font-size:11px;color:var(--ink-faint); }
.cfc-valor{ flex:none;text-align:right;min-width:88px; }
.cfc-valor .l{ font-size:9.5px;color:var(--ink-faint);text-transform:uppercase;letter-spacing:.03em; }
.cfc-valor .v{ font-weight:800;font-size:13px;color:var(--primary-strong); }
.cfc-total{ display:flex;justify-content:space-between;align-items:center;margin-top:12px;padding-top:12px;border-top:1px solid var(--border); }
.cfc-total .l{ font-size:12.5px;font-weight:700;color:var(--ink-soft); }
.cfc-total .v{ font-size:17px;font-weight:800;color:var(--primary-strong); }

/* v2.49.0 — cadastro rápido de fábrica (abrirCadastroFabricaModal(), COT-02),
   mesmo card/overlay de .cf-motivo-card acima, só com campos de texto/select
   em vez da textarea única. */
.cf-cadfab-field{ margin-bottom:12px; }
.cf-cadfab-field label{ display:block;font-size:11px;font-weight:700;color:var(--ink-soft);text-transform:uppercase;letter-spacing:.03em;margin-bottom:4px; }
.cf-cadfab-field input,.cf-cadfab-field select{
  width:100%;height:36px;border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 10px;
  font-size:13px;font-family:inherit;background:var(--surface);color:var(--ink);box-sizing:border-box;
}
.cf-cadfab-field input:focus,.cf-cadfab-field select:focus{ outline:none;border-color:var(--primary);box-shadow:0 0 0 3px var(--primary-soft); }
.cf-cadfab-row{ display:grid;grid-template-columns:1fr 90px;gap:10px; }

.col-tag-list{ display:flex;flex-direction:column;gap:7px;margin-top:10px; }
.col-tag-row{ display:flex;align-items:center;justify-content:space-between;gap:10px;padding:7px 10px;background:var(--surface-2);border-radius:8px; }
.col-tag-row .ctr-name{ font-size:12.5px;font-weight:600;color:var(--ink); }
.col-tag-row label{ display:flex;align-items:center;gap:6px;font-size:11px;color:var(--ink-soft);cursor:pointer;font-weight:600; }
.col-tag-row input[type="checkbox"]{ width:14px;height:14px;accent-color:var(--accent); }

/* ==================== v2.30.0: Tarefas (individuais e em grupo) ====================
   Mockup aprovado "Tarefas — individuais e em grupo" (análise dos
   gerenciadores de tarefas mais usados do mercado — Todoist, Linear, Trello,
   Asana, ClickUp — ver includes/rest-tarefas.php para o desenho de dados/
   permissões). Tela 100% custom (como "Carteira e Pendências"): a barra de
   ferramentas/toolbar padrão (.toolbar) fica escondida (ver renderCurrentView()
   em frontend.js) e esta tela desenha a própria (.tar-toolbar), reaproveitando
   .search-box/select.filter-select já existentes acima. */
.tar-tabs{ display:flex;gap:6px;margin-bottom:12px;flex-wrap:wrap; }
.tar-tab{ padding:8px 15px;border-radius:999px;font-size:12.5px;font-weight:700;color:var(--ink-soft);border:1px solid var(--border);background:var(--surface);cursor:pointer; }
.tar-tab.active{ background:var(--primary-soft);color:var(--primary-strong);border-color:transparent; }

.tar-toolbar{
  display:flex;gap:10px;align-items:center;flex-wrap:wrap;
  background:var(--surface);border:1px solid var(--border);border-bottom:none;
  border-radius:14px 14px 0 0;padding:13px 16px;
}
.tar-view-toggle{ display:flex;border:1px solid var(--border);border-radius:var(--radius-sm);overflow:hidden;margin-left:auto; }
.tar-view-btn{ padding:7px 13px;font-size:12px;font-weight:700;background:var(--surface);color:var(--ink-soft);cursor:pointer;border:none;display:flex;align-items:center;gap:5px; }
.tar-view-btn svg{ width:13px;height:13px; }
.tar-view-btn.active{ background:var(--primary-soft);color:var(--primary-strong); }
.tar-body{ background:var(--surface);border:1px solid var(--border);border-top:none;border-radius:0 0 14px 14px;box-shadow:var(--shadow-sm); }

.tar-quickadd{ display:flex;align-items:center;gap:10px;padding:13px 16px;border-bottom:1px solid var(--border); }
.tar-quickadd svg.plus{ width:16px;height:16px;color:var(--ink-faint);flex:none; }
.tar-quickadd input{ flex:1;border:none;outline:none;background:transparent;font-size:13.3px;color:var(--ink); }
.tar-quickadd input::placeholder{ color:var(--ink-faint); }
.tar-quickadd button[type="submit"]{ flex:none; }
/* Seletor de responsável da tarefa rápida (v2.37.13) — só aparece pra quem
   gerencia Tarefas (CFG.canManageTarefas); reaproveita o visual do
   select.filter-select já usado em toda a tela, só com largura menor pra
   caber ao lado do campo de título dentro da mesma linha. */
.tar-quickadd select.tar-quickadd-resp{ flex:none;width:auto;max-width:150px;padding:7px 26px 7px 10px;font-size:12.5px; }

.tar-smart-heading{ display:flex;align-items:center;gap:8px;padding:14px 16px 6px;font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.07em;color:var(--ink-faint); }
.tar-smart-heading.late{ color:var(--danger); }
.tar-smart-heading .count{ background:var(--surface-2);border-radius:999px;padding:1px 7px;font-size:10px;font-weight:700; }

/* v2.40.0 (pedido do usuário, mockup "tarefas-redesign-mockup.html"
   aprovado) — redesenho da linha da listagem: barra de cor lateral por
   prioridade (border-left, trocado pela cor certa em ".tar-row.prio-*"
   abaixo — mesma paleta de TAR_PRIORIDADE_TONE em frontend.js, só com o
   prefixo "prio-" no lugar de "badge-"), prévia da descrição
   (.tar-row-desc), bolinha de status (.tar-status-cell, reaproveitando
   .cot-status-dot já existente da Cotação) e indicador de comentários
   (reaproveita .tar-subprogress, já usado por subtarefas/anexos). */
.tar-row{ display:flex;align-items:center;gap:12px;padding:10px 16px 10px 13px;border-bottom:1px solid var(--border);border-left:3px solid transparent; }
.tar-row:last-child{ border-bottom:none; }
.tar-row:hover{ background:var(--surface-2); }
.tar-row.prio-muted{ border-left-color:var(--ink-faint); }
.tar-row.prio-primary{ border-left-color:var(--primary); }
.tar-row.prio-warn{ border-left-color:var(--warn); }
.tar-row.prio-danger{ border-left-color:var(--danger); }
.tar-row.done{ border-left-color:var(--success); }
.tar-checkbox{ width:17px;height:17px;border-radius:6px;border:1.5px solid var(--border);flex:none;accent-color:var(--success);cursor:pointer; }
.tar-row.done .tar-row-title{ color:var(--ink-faint);text-decoration:line-through; }
.tar-row-main{ flex:1;min-width:0;display:flex;flex-direction:column;gap:4px;cursor:pointer; }
.tar-row-title{ font-size:13.3px;font-weight:600;color:var(--ink); }
.tar-row-desc{ font-size:11.5px;color:var(--ink-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:520px; }
.tar-row-meta{ display:flex;gap:6px;flex-wrap:wrap;align-items:center; }
.tar-status-cell{ display:inline-flex;align-items:center;gap:5px;font-size:10.5px;font-weight:700;color:var(--ink-soft); }
.tar-link-chip{ display:inline-flex;align-items:center;font-size:10.5px;font-weight:700;padding:2px 8px;border-radius:999px;background:var(--surface-2);color:var(--ink-soft);border:1px dashed var(--border); }
.tar-group-chip{ display:inline-flex;align-items:center;gap:4px;font-size:10.5px;font-weight:700;padding:2px 8px 2px 6px;border-radius:999px; }
.tar-row-right{ display:flex;align-items:center;gap:12px;flex:none; }
.tar-due{ font-size:11.5px;color:var(--ink-soft);white-space:nowrap; }
.tar-due.late{ color:var(--danger);font-weight:700; }
.tar-due.today{ color:var(--warn);font-weight:700; }
.tar-due.done{ color:var(--success); }
.tar-subprogress{ font-size:11px;color:var(--ink-faint);background:var(--surface-2);border-radius:999px;padding:2px 7px;white-space:nowrap;display:inline-flex;align-items:center;gap:3px; }
.tar-subprogress svg{ width:10px;height:10px;flex:none; }
@media (max-width:760px){ .tar-row-desc{ max-width:260px; } }

.avatar-stack{ display:flex; }
.avatar-stack .avatar{ width:26px;height:26px;border-radius:50%;font-size:10px;border:2px solid var(--surface);margin-left:-9px; }
.avatar-stack .avatar:first-child{ margin-left:0; }
.avatar-stack .avatar-more{ background:var(--surface-2);color:var(--ink-faint);font-size:9.5px; }

/* ---- quadro kanban ---- */
.tar-board{ display:grid;grid-template-columns:repeat(3,1fr);gap:16px;padding:16px; }
.tar-col{ background:var(--surface-2);border-radius:14px;padding:12px;display:flex;flex-direction:column;gap:10px;min-height:140px; }
.tar-col-head{ display:flex;align-items:center;justify-content:space-between;padding:0 4px 2px; }
.tar-col-title{ font-size:11.5px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;color:var(--ink-soft);display:flex;align-items:center;gap:7px; }
.tar-col-count{ background:var(--surface);border-radius:999px;padding:1px 7px;font-size:10.5px;font-weight:700;color:var(--ink-faint); }
.tar-card{ background:var(--surface);border:1px solid var(--border);border-radius:10px;padding:11px 12px;box-shadow:var(--shadow-sm);display:flex;flex-direction:column;gap:9px;cursor:pointer; }
.tar-card-title{ font-size:13px;font-weight:600;color:var(--ink); }
.tar-card-foot{ display:flex;align-items:center;justify-content:space-between;gap:8px; }
@media (max-width:980px){ .tar-board{ grid-template-columns:1fr; } }

/* ---- grupos de tarefas ---- */
.tar-groups-grid{ display:grid;grid-template-columns:repeat(3,1fr);gap:16px; }
.tar-group-card{ background:var(--surface);border:1px solid var(--border);border-radius:14px;padding:16px;box-shadow:var(--shadow-sm);display:flex;flex-direction:column;gap:11px;cursor:pointer; }
.tar-group-dot{ width:10px;height:10px;border-radius:50%;flex:none; }
.tar-group-head{ display:flex;align-items:center;gap:9px; }
/* Botão "Editar grupo" (lápis) no cabeçalho do cartão — mesmo padrão de
   "<contexto> .btn-icon svg{...}" já usado no resto do app (ver o comentário
   em assets/frontend.css, seção de Itens de Portfólio): sem isto o ícone sai
   sem largura/altura (padrão do navegador pra um <svg> sem width/height). */
.tar-group-head .btn-icon{ margin-left:auto;flex:none; }
.tar-group-head .btn-icon svg{ width:14px;height:14px;flex:none; }
.tar-group-name{ font-weight:700;font-size:14px;flex:1; }
.tar-progress-bar{ height:6px;border-radius:999px;background:var(--surface-2);overflow:hidden; }
.tar-progress-fill{ height:100%;background:var(--success); }
.tar-group-stats{ display:flex;justify-content:space-between;font-size:11.5px;color:var(--ink-faint); }
.tar-new-group-card{ border:1.5px dashed var(--border);border-radius:14px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;color:var(--ink-faint);font-weight:700;font-size:12.5px;min-height:142px;background:none;cursor:pointer; }
.tar-new-group-card svg{ width:22px;height:22px; }
@media (max-width:980px){ .tar-groups-grid{ grid-template-columns:1fr 1fr; } }
@media (max-width:620px){ .tar-groups-grid{ grid-template-columns:1fr; } }

/* ---- checklist de subtarefas (painel de detalhe) ---- */
.tar-checklist{ display:flex;flex-direction:column;gap:9px; }
.tar-checklist-item{ display:flex;align-items:center;gap:9px;font-size:13px; }
.tar-checklist-item.done span{ color:var(--ink-faint);text-decoration:line-through; }
.tar-checklist-item button{ margin-left:auto;background:none;border:none;color:var(--ink-faint);cursor:pointer;padding:2px; }
.tar-checklist-item button:hover{ color:var(--danger); }
.tar-checklist-item button svg{ width:13px;height:13px;flex:none; }
.tar-checklist-add{ display:flex;align-items:center;gap:9px;margin-top:4px; }
.tar-checklist-add input{ flex:1;border:none;border-bottom:1px dashed var(--border);outline:none;background:transparent;font-size:12.5px;color:var(--ink);padding:4px 0; }

/* ---- anexos de tarefa (v2.30.1) ---- */
.tar-anexos{ display:flex;flex-direction:column;gap:7px; }
.tar-anexo-item{ display:flex;align-items:center;gap:9px;font-size:13px;background:var(--surface-2);border-radius:10px;padding:8px 10px; }
.tar-anexo-info{ display:flex;align-items:center;gap:8px;flex:1;min-width:0;color:var(--ink);text-decoration:none; }
.tar-anexo-info:hover .tar-anexo-nome{ text-decoration:underline; }
.tar-anexo-info svg{ width:15px;height:15px;flex:none;color:var(--ink-faint); }
.tar-anexo-nome{ overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600; }
.tar-anexo-meta{ font-size:11px;color:var(--ink-faint);white-space:nowrap;flex:none; }
.tar-anexo-item button{ margin-left:auto;background:none;border:none;color:var(--ink-faint);cursor:pointer;padding:2px;flex:none; }
.tar-anexo-item button:hover{ color:var(--danger); }
.tar-anexo-item button svg{ width:13px;height:13px;flex:none; }
.tar-anexo-item button:disabled{ opacity:.5;cursor:default; }
.tar-anexo-add{ display:inline-flex;align-items:center;gap:7px;margin-top:9px;font-size:12.5px;color:var(--primary);cursor:pointer;font-weight:600; }
.tar-anexo-add svg{ width:14px;height:14px;flex:none; }
.tar-anexo-add.loading{ opacity:.6;pointer-events:none; }

/* ================= Administrador → Configurações (v2.31.0) =================
   Permissões ("Por Papel"/"Por Usuário") e Ordem dos Menus — mockup aprovado
   "Novo menu 'Administrador' → Configurações". Mesmos tokens de sempre
   (--surface/--border/--ink/--primary etc., ver :root no topo deste
   arquivo); nenhuma cor nova foi introduzida. */
.settings-shell{ display:grid;grid-template-columns:220px 1fr;gap:20px;align-items:start; }
@media (max-width:760px){ .settings-shell{ grid-template-columns:1fr; } }
.settings-nav{ display:flex;flex-direction:column;gap:4px;background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:8px; }
.settings-nav-item{
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  padding:10px 12px;border-radius:8px;background:none;border:none;text-align:left;
  font-size:13.3px;font-weight:600;color:var(--ink-soft);cursor:pointer;
}
.settings-nav-item:hover{ background:var(--surface-2);color:var(--ink); }
.settings-nav-item.active{ background:var(--primary-soft);color:var(--primary-strong); }
.settings-nav-item.soon{ cursor:default;color:var(--ink-faint); }
.settings-nav-item.soon:hover{ background:none;color:var(--ink-faint); }
.tag-soon{ font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;color:var(--ink-faint);background:var(--surface-2);border:1px dashed var(--border);border-radius:999px;padding:2px 7px; }
.settings-content{ background:var(--surface);border:1px solid var(--border);border-radius:12px;padding:18px;min-width:0; }

.cf-config-subtabs{ display:flex;gap:6px;margin-bottom:16px;border-bottom:1px solid var(--border);padding-bottom:10px; }
.cf-config-subtab{ background:none;border:none;padding:8px 14px;border-radius:999px;font-size:12.5px;font-weight:700;color:var(--ink-soft);cursor:pointer; }
.cf-config-subtab:hover{ background:var(--surface-2);color:var(--ink); }
.cf-config-subtab.active{ background:var(--primary);color:var(--primary-ink); }

/* ---- tabela "Por Papel" ---- */
.perm-table{ width:100%;border-collapse:collapse;font-size:13px; }
.perm-table thead th{ text-align:left;font-size:11px;text-transform:uppercase;letter-spacing:.03em;color:var(--ink-faint);padding:8px 10px;border-bottom:1px solid var(--border);position:sticky;top:0;background:var(--surface); }
.perm-table tbody td{ padding:10px;border-bottom:1px solid var(--border);vertical-align:middle; }
.perm-group-row td{ background:var(--surface-2);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;color:var(--ink-soft);padding:7px 10px; }
.perm-mod-nome{ font-weight:700;color:var(--ink); }
.perm-mod-desc{ font-size:11.5px;color:var(--ink-faint);margin-top:2px; }
.perm-cell{ text-align:center; }
.perm-checkbox input{ width:17px;height:17px;cursor:pointer;accent-color:var(--primary); }
.perm-cell-locked{ text-align:center;color:var(--ink-faint);display:table-cell; }
.perm-cell-locked svg{ width:13px;height:13px;flex:none;vertical-align:-2px;margin-right:3px; }
.perm-table-legend{ display:flex;align-items:flex-start;gap:7px;margin-top:14px;font-size:11.5px;color:var(--ink-faint); }
.perm-table-legend svg{ width:13px;height:13px;flex:none;margin-top:1px; }

/* ---- "Por Usuário" (exceções) ---- */
.exception-list{ display:flex;flex-direction:column;gap:8px;margin-bottom:14px; }
.exception-row{ display:flex;align-items:center;gap:14px;flex-wrap:wrap;background:var(--surface-2);border-radius:10px;padding:10px 12px; }
.exc-user{ display:flex;flex-direction:column;gap:2px;min-width:130px; }
.exc-user-papel{ font-size:10.5px;font-weight:700;text-transform:uppercase;color:var(--ink-faint); }
.exc-chips{ display:flex;gap:6px;flex-wrap:wrap;flex:1; }
.exc-chip{ display:inline-flex;align-items:center;gap:5px;background:var(--primary-soft);color:var(--primary-strong);font-size:11.5px;font-weight:600;border-radius:999px;padding:4px 6px 4px 10px; }
.exc-remove{ background:none;border:none;color:var(--primary-strong);cursor:pointer;padding:2px;display:inline-flex; }
.exc-remove svg{ width:10px;height:10px;flex:none; }
.exc-remove:hover{ color:var(--danger); }
.add-exception{
  display:inline-flex;align-items:center;gap:7px;background:none;border:1.5px dashed var(--border);
  border-radius:10px;padding:10px 14px;color:var(--ink-faint);font-weight:700;font-size:12.5px;cursor:pointer;
}
.add-exception:hover{ border-color:var(--primary);color:var(--primary); }
.add-exception svg{ width:14px;height:14px;flex:none; }
.user-search-box{ display:flex;flex-direction:column;gap:12px;background:var(--surface-2);border-radius:10px;padding:14px;max-width:420px; }
.exc-busca-resultados{ display:flex;flex-direction:column;gap:2px;margin-top:4px; }
.exc-busca-resultado{ padding:7px 9px;border-radius:7px;font-size:12.5px;cursor:pointer;display:flex;justify-content:space-between;gap:8px; }
.exc-busca-resultado:hover{ background:var(--surface); }
.exc-busca-vazia{ font-size:11.5px;color:var(--ink-faint);padding:4px 2px; }
.exc-usuario-escolhido{ font-size:12px;color:var(--success);margin-top:4px; }

/* ---- "Ordem dos Menus" — sem arrastar-e-soltar de propósito, mesma
   decisão já tomada pro board de Tarefas; reordenar é sempre um clique num
   botão com seta, nunca um drag. ---- */
.reorder-block{ margin-bottom:22px; }
.reorder-block h3{ font-size:12.5px;font-weight:700;color:var(--ink-soft);margin:0 0 10px; }
.reorder-item{ display:flex;align-items:center;gap:10px;background:var(--surface-2);border-radius:9px;padding:9px 12px;margin-bottom:6px; }
.reorder-label{ font-size:13px;font-weight:600;color:var(--ink);flex:1; }
.reorder-actions{ display:flex;gap:4px;flex:none; }
.reorder-actions .btn-icon svg{ width:13px;height:13px;flex:none; }
.pin-tag{ font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;color:var(--ink-faint);background:var(--surface);border:1px dashed var(--border);border-radius:999px;padding:3px 8px;flex:none; }
.reorder-group-item{ border:1px solid var(--border);border-radius:10px;margin-bottom:6px;overflow:hidden; }
.reorder-group-head{ display:flex;align-items:center;gap:10px;padding:10px 12px;cursor:pointer;background:var(--surface-2); }
.reorder-group-head svg:first-child{ width:16px;height:16px;flex:none;color:var(--ink-soft); }
.reorder-group-item.open .reorder-group-head{ background:var(--primary-soft); }
.reorder-group-body{ padding:8px 12px 10px 30px;background:var(--surface); }
.reorder-group-body .reorder-item{ background:var(--surface-2); }
#ordemRestaurarBtn svg{ width:14px;height:14px;flex:none; }

/* ==================== Margem Marcas (MAR-02, v2.47.35, mockup aprovado
   "aprovado...pode gerar os arquivos para eu subir") ====================
   Tela de layout 2 colunas (card de cadastro + tabela à esquerda,
   calculadora de conversão à direita) — ver renderMargemMarcas() e
   companhia em assets/frontend.js. Classes .mm-* transplantadas do mockup
   aprovado sem alteração de estrutura, só a correção pedida nesta rodada
   (altura do campo "Valor com Margem", ver .mm-calc-input-row .currency-input
   logo abaixo). */
.mm-layout{ display:grid;grid-template-columns:1fr 340px;gap:18px;align-items:start; }
@media (max-width:980px){ .mm-layout{ grid-template-columns:1fr; } }

.mm-form-card{ background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);padding:18px 20px;margin-bottom:18px;box-shadow:var(--shadow-sm); }
.mm-form-card h3{ margin:0 0 12px;font-size:14px; }
.mm-form-row{ display:flex;gap:12px;flex-wrap:wrap;align-items:end; }
.mm-form-row .field{ flex:1 1 220px;min-width:180px; }
.mm-form-row .field.small{ flex:0 0 130px;min-width:110px; }

/* ---- lista de marcas (v2.50.0, pedido do usuário, mockup
   "margem-marcas-layout-historico-mockup.html" aprovado: "ficou muito bom,
   mas alinhe as margens para ficar alinhadas uma debaixo da outra, como
   tivesse em uma coluna alinhada") — substitui a tabela de 3 colunas
   (VER/MARCA/MARGEM) de até a v2.49.x por "cartões de linha" só, com o logo
   bem maior ("logo maior, logo a frente a margem", pedido original) e a
   margem num bloco de LARGURA FIXA logo em seguida do nome — é essa largura
   fixa que faz a margem começar sempre no MESMO x em toda linha (a "coluna
   alinhada" pedida), em vez de empurrada pra posições diferentes conforme o
   tamanho do nome da marca, que era o problema da 1ª rodada do mockup. ---- */
.mm-list{ border:1px solid var(--border);border-radius:10px;overflow:hidden;background:var(--surface); }
.mm-list-row{
  display:flex;align-items:center;gap:16px;padding:11px 14px;border-bottom:1px solid var(--border);
  cursor:pointer;
}
.mm-list-row:last-child{ border-bottom:none; }
.mm-list-row:hover,.mm-list-row:focus-visible{ background:var(--surface-2); }
.mm-list-row:focus-visible{ outline:2px solid var(--primary);outline-offset:-2px; }
.mm-list-logo .avatar{ width:48px;height:48px;border-radius:12px;font-size:15px;flex:none; }
/* .mm-list-nome com largura FIXA (flex:0 0 Npx, sem crescer nem encolher) é
   o que alinha a margem — ver comentário do bloco acima. */
.mm-list-nome{
  font-weight:800;font-size:14px;color:var(--ink);
  flex:0 0 200px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.mm-list-margem{
  flex:none;width:92px;text-align:center;background:var(--success-soft);color:var(--success);
  font-weight:800;font-size:14.5px;border-radius:999px;padding:5px 0;
}
.mm-list-chevron{ margin-left:auto;flex:none;color:var(--ink-faint);display:flex; }
.mm-list-chevron svg{ width:15px;height:15px; }
@media (max-width:620px){
  .mm-list-nome{ flex:1 1 auto; }
  .mm-list-margem{ width:auto;padding:5px 12px; }
}

/* ---- calculadora ---- */
.mm-calc-card{ background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-md);box-shadow:var(--shadow-sm);overflow:hidden; }
.mm-calc-head{ background:var(--ink,#16233c);color:#fff;font-weight:800;font-size:12.5px;letter-spacing:.03em;text-transform:uppercase;padding:14px 18px; }
.mm-calc-body{ padding:16px 18px; }
.mm-calc-input-row{ margin-bottom:14px; }
.mm-calc-input-row label{ display:block;font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.02em;color:var(--ink-soft);margin-bottom:6px; }
/* v2.47.35 (pedido do usuário logo após aprovar o mockup): o campo "Valor
   com Margem" usava só o .currency-input genérico (sem padding próprio,
   pensado pra ficar DENTRO de um .field — ver a regra de .field input mais
   acima no arquivo), então nascia mais baixo que o campo "Margem (%)" do
   card "Nova Margem de Marca" ao lado (esse sim dentro de um .field). Aqui
   ele é usado solto (sem .field em volta, só dentro de .mm-calc-input-row),
   por isso ganha o mesmo padding/font-size/altura de .field input direto,
   igualando as duas alturas lado a lado. */
.mm-calc-input-row .currency-input{
  padding:9px 11px;font-size:13.3px;color:var(--ink);outline:none;width:100%;box-sizing:border-box;
}
.mm-calc-row{
  display:flex;align-items:center;justify-content:space-between;gap:8px;
  padding:10px 0;border-top:1px solid var(--border);font-size:12.5px;
}
.mm-calc-row:first-of-type{ border-top:none; }
.mm-calc-row .mm-calc-label{ color:var(--ink-soft);font-weight:600; }
.mm-calc-row .mm-calc-value-wrap{ display:flex;align-items:center;gap:4px; }
.mm-calc-row .mm-calc-value{ font-weight:800;color:var(--ink); }
.mm-calc-row.result .mm-calc-value{ color:var(--primary-strong); }
.mm-calc-row .btn-icon{ width:24px;height:24px; }
.mm-calc-row .btn-icon svg{ width:12px;height:12px; }

/* ---- seletor de marca (reaproveita o visual de .marcas-select/.marcas-
   dropdown já usado no campo "Marcas" de um item de Requisição — aqui é
   seleção ÚNICA, com logo, em vez de múltipla escolha por checkbox;
   classes próprias — mm-marca-picker/mm-marca-dropdown/mm-marca-opt — pra
   não colidir em JS/CSS com o widget de múltipla escolha). ---- */
.mm-marca-picker-wrap{ position:relative;min-width:0; }
.mm-marca-picker{
  width:100%;min-width:0;padding:7px 9px;border-radius:7px;border:1px solid var(--border);
  background:var(--surface);font-size:12.8px;color:var(--ink);cursor:pointer;user-select:none;
  display:flex;align-items:center;gap:8px;justify-content:space-between;
}
.mm-marca-picker.placeholder .mm-marca-picker-text{ color:var(--ink-faint); }
.mm-marca-picker:hover{ border-color:#c4cbbd; }
.mm-marca-picker.open{ border-color:var(--primary); }
.mm-marca-picker-left{ display:flex;align-items:center;gap:8px;min-width:0; }
.mm-marca-picker-left .avatar{ width:22px;height:22px;border-radius:6px;font-size:10px;flex:none; }
.mm-marca-picker-text{ min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
.mm-marca-picker-chevron{ flex:none;color:var(--ink-faint);transition:transform .15s ease; }
/* v2.47.36 (bug reportado pelo usuário com print, logo após a v2.47.35):
   icon('chevron')/icon('plus') (assets/frontend.js) devolvem um <svg
   viewBox="0 0 24 24"> SEM width/height próprios — ao contrário do ícone
   "+ Cadastrar marca" do MOCKUP (que tinha sua própria função icon() local,
   com width/height="14" fixos sempre embutidos no <svg>), o icon() de
   verdade depende inteiramente do CSS do contêiner pra definir o tamanho
   (mesmo padrão de .nav-group-chevron svg/.calcdet-chevron svg já usados no
   resto do arquivo). Essas duas regras ficaram faltando na v2.47.35: sem
   elas, o SVG caía no tamanho intrínseco padrão do navegador (bem maior que
   o texto ao lado), exatamente o "+" gigante que o usuário mostrou no
   print, cobrindo a opção "Cadastrar marca" inteira no dropdown.
   .mm-marca-dropdown-search (logo abaixo) nunca teve esse problema porque
   seu ícone de busca é um <svg> escrito à mão com width/height="14" fixos,
   não vem de icon(). */
.mm-marca-picker-chevron svg{ width:13px;height:13px; }
.mm-marca-picker.open .mm-marca-picker-chevron{ transform:rotate(180deg); }
.mm-marca-dropdown{
  display:none;position:absolute;left:0;right:0;top:calc(100% + 4px);z-index:30;
  background:var(--surface);border:1px solid var(--border);border-radius:10px;
  box-shadow:0 10px 28px rgba(20,30,20,.16);overflow:hidden;min-width:240px;
}
.mm-marca-dropdown.open{ display:block; }
.mm-marca-dropdown-search{ display:flex;align-items:center;gap:7px;padding:8px 10px;border-bottom:1px solid var(--border); }
.mm-marca-dropdown-search svg{ flex:none;color:var(--ink-faint); }
.mm-marca-dropdown-search input{ flex:1;min-width:0;border:none;outline:none;background:transparent;font-size:12.8px;color:var(--ink);font-family:inherit; }
.mm-marca-dropdown-list{ max-height:220px;overflow-y:auto;padding:6px; }
.mm-marca-opt{ display:flex;align-items:center;gap:9px;padding:7px 8px;border-radius:7px;cursor:pointer;font-size:12.5px; }
.mm-marca-opt:hover{ background:var(--primary-soft); }
.mm-marca-opt .avatar{ width:24px;height:24px;border-radius:6px;font-size:10px;flex:none; }
.mm-marca-opt-nova{ display:flex;align-items:center;gap:8px;padding:7px 8px;border-radius:7px;cursor:pointer;font-size:12.5px;font-weight:700;color:var(--primary-strong); }
.mm-marca-opt-nova:hover{ background:var(--primary-soft); }
/* Mesma correção de .mm-marca-picker-chevron svg acima — icon('plus') sem
   essa regra renderizava gigante (o bug do print do usuário). */
.mm-marca-opt-nova svg{ width:14px;height:14px;flex:none; }
.mm-marca-dropdown-empty{ padding:14px 10px;text-align:center;font-size:12px;color:var(--ink-faint); }

/* ================= "Gerar Mensagem para Fábrica(s)" (v2.47.40) =================
   Telas "Cotar" (COT-05, renderCotar()) e "Nova Cotação" (COT-02,
   cotModeToggleHtml()) — ver abrirGerarMensagemModal() em frontend.js pro
   contexto completo da decisão. Prefixo "gm-" novo, só desta tela; reaproveita
   .cf-motivo-backdrop/.cf-motivo-card/.cf-motivo-actions já existentes
   (mesmo padrão de modal central) com duas classes adicionais só pra esta
   tela: .cf-gerarmsg-backdrop (rolagem vertical — este modal é bem mais alto
   que o de motivo, que nunca precisou rolar) e .cf-gerarmsg-card (mais
   largo). */
.cf-gerarmsg-backdrop{ overflow-y:auto;align-items:flex-start; }
.cf-gerarmsg-card{ max-width:600px;margin:20px auto; }

/* Botão "Gerar Mensagem" ao lado do alternador Por Produto/Por Fornecedor
   (COT-02) — .mode-toggle-wrap/.mode-toggle já existiam (ver acima); esta
   linha nova só organiza os dois lado a lado, com o botão empurrado pra
   direita quando a 2ª tela deixa espaço, e quebrando pra baixo dele no
   celular (mesmo breakpoint de .mode-toggle-wrap, sem media query própria
   — flex-wrap já resolve). */
.mode-toggle-row{ display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap; }
.mode-toggle-row .mode-toggle{ flex:none; }

/* Ícone novo da coluna "Gerar Mensagem" na tela "Cotar" (COT-05) — mesmo
   tamanho de .cotar-actions .btn-icon svg (13px), pra ficar visualmente
   igual aos ícones de Cotar mais/Concluir cotação ao lado. */
.cotar-gerarmsg-btn svg{ width:13px;height:13px;flex:none; }

/* Checklist de itens / log de disparo — mesma caixa rolável nos dois casos. */
.gm-selected-list{ max-height:150px;overflow-y:auto;border:1px solid var(--border);border-radius:8px;padding:8px 10px;background:var(--surface-2);margin:10px 0 14px; }
.gm-selected-row{ display:flex;justify-content:space-between;gap:10px;font-size:12px;color:var(--ink);padding:4px 0; }
.gm-selected-row .ref{ font-weight:700; }
.gm-item-check-label{ display:flex;align-items:center;gap:8px;cursor:pointer; }
.gm-item-check-label input[type="checkbox"]{ width:16px;height:16px;accent-color:var(--primary);cursor:pointer;flex:none; }

.gm-field-label{ font-size:11.5px;font-weight:700;color:var(--ink-soft);display:block;margin-bottom:6px;margin-top:14px; }
.gm-msg-textarea{
  width:100%;min-height:110px;border:1px solid var(--border);border-radius:8px;
  padding:10px 12px;font:inherit;font-size:13px;color:var(--ink);resize:vertical;
  background:var(--surface);box-sizing:border-box;margin-top:6px;
}
.gm-msg-textarea:focus{ outline:none;border-color:var(--primary);box-shadow:0 0 0 3px var(--primary-soft); }
.gm-help{ font-size:11.5px;color:var(--ink-faint);margin-top:8px;line-height:1.5; }

/* Busca rápida + lista de fábricas selecionáveis (pedido do usuário: "além
   da opção de flegar, precisa ter um campo para busca rápida"). */
.gm-fab-search{
  width:100%;height:34px;padding:0 10px;border-radius:7px 7px 0 0;
  border:1px solid var(--border);border-bottom:none;background:var(--surface);
  font-size:12.5px;color:var(--ink);box-sizing:border-box;font-family:inherit;
}
.gm-fab-search:focus{ outline:none;border-color:var(--primary); }
.gm-fab-list{ display:flex;flex-direction:column;gap:6px;max-height:220px;overflow-y:auto;border:1px solid var(--border);border-radius:0 0 8px 8px;padding:8px;background:var(--surface-2); }
.gm-fab-empty{ font-size:11.5px;color:var(--ink-faint);font-style:italic;padding:10px;text-align:center; }
.gm-fab-row{ display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:7px;background:var(--surface);border:1px solid var(--border); }
.gm-fab-row.disabled{ opacity:.55; }
.gm-fab-row input[type="checkbox"]{ width:16px;height:16px;accent-color:var(--primary);cursor:pointer;flex:none; }
.gm-fab-row .gm-fab-nome{ font-weight:700;font-size:12.8px;color:var(--ink);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap; }
.gm-fab-none{ font-size:11px;color:var(--ink-faint);font-style:italic;flex:none; }

/* Chip de canal (WhatsApp/Teams) — "available" é quem tem o canal
   cadastrado no Contato Principal (clicável pra escolher quando a fábrica
   tem os dois); "selected" é o canal que vai ser usado no disparo;
   "unavailable" fica esmaecido e não clica (fábrica sem aquele canal). */
.gm-fab-channels{ display:flex;gap:5px;flex:none; }
.gm-chan-chip{
  display:inline-flex;align-items:center;gap:4px;font-size:10.5px;font-weight:700;
  padding:3px 8px;border-radius:999px;border:1px solid var(--border);color:var(--ink-faint);
  cursor:pointer;background:var(--surface);white-space:nowrap;
}
.gm-chan-chip svg{ width:11px;height:11px;flex:none; }
.gm-chan-chip.available{ color:var(--ink-soft); }
.gm-chan-chip.selected{ background:var(--primary-soft);color:var(--primary-strong);border-color:transparent; }
.gm-chan-chip.unavailable{ cursor:default;opacity:.45; }

/* Escolha "uma de cada vez" × "todas de uma vez" (v2.47.40, pedido do
   usuário na rodada final de aprovação). v2.47.41 (pedido do usuário, "deixe
   só o titulo (...) pode remover a descricao (...) a inteção é deixa a tela
   menos alta"): .gm-mode-sub (a explicação de cada modo) saiu — só o título
   fica, então .gm-mode-title não precisa mais de margem embaixo. */
.gm-dispatch-mode{ display:flex;gap:8px;margin-top:6px;flex-wrap:wrap; }
.gm-mode-btn{ flex:1;min-width:180px;padding:10px 12px;border-radius:8px;border:1px solid var(--border);background:var(--surface);cursor:pointer;text-align:left;font-family:inherit; }
.gm-mode-btn .gm-mode-title{ display:block;font-size:12.5px;font-weight:700;color:var(--ink); }
.gm-mode-btn.selected{ border-color:var(--primary);background:var(--primary-soft); }
.gm-mode-btn.selected .gm-mode-title{ color:var(--primary-strong); }
