/* Tokens da marca Alcance Solar (spec §13.1) — azul domina, laranja pontua.
   Redesign v4 (SaaS clean): paleta sóbria, cinzas frios, laranja como acento.
   Decisão do PO (28/08): azul e laranja passam a ser os do SVG oficial
   (logo-cor.svg: #00528B / #E88025), substituindo os da instrução. O cinza da
   marca (#8E9093) NÃO vira token de texto: mede 3,20 sobre branco, abaixo de
   AA — ele vive no logotipo; --cinza segue sendo o slate escurecido da 11.9. */
:root {
  --azul: #00528B;
  --azul-escuro: #123A5E;
  --navy: #0C2036;
  --laranja: #E88025;
  --accent: #E88025;
  --cinza: #5F6D80;        /* texto secundário (slate) */
  /* Fase 11.9 (decisão do PO, 08/08): era #98A2B3 e dava 2,58 sobre o card —
     abaixo do mínimo AA (4,5). Escurecido até passar nos TRÊS fundos onde
     aparece: card 5,49 · superfície recuada 5,15 · painel 4,75 (o painel é o
     pior caso, onde fica o breadcrumb).
     ⚠️ Consequência assumida: ficou quase idêntico ao --cinza. Entre "passar
     em AA" e "ser mais claro que o texto secundário" não há espaço — a
     hierarquia entre os dois passa a ser dada por tamanho e peso, que já
     diferenciam (rótulo 0.68rem/700 vs texto 0.9rem/400). */
  --faint: #5C6A80;
  --fundo: #EAEFF6;        /* cinza-azulado mais frio: o branco dos cards salta */
  --texto: #0E1A2B;
  --erro: #BE3222;
  --ok: #16794C;
  --alerta: #A66A0C;
  --line: #E6EBF1;         /* bordas sutis */
  --line-in: #D9E1EA;      /* borda de campos */
  --line2: #F4F6F9;
  --r-card: 14px;
  --r-ctl: 10px;
  /* sombras mais presentes (cards com mais carater, sem virar caixa dura) */
  --sh: 0 1px 2px rgba(16,24,40,.05), 0 2px 6px rgba(16,24,40,.05);

  /* --- Fase 8: tokens SEMÂNTICOS (guia v4). Os componentes passam a usar
     estes; o TEMA ESCURO (Fase 11) troca só este bloco, sem mexer em
     componente. Por ora apontam para os valores do tema claro já existentes. */
  --superficie: #FFFFFF;       /* fundo de card/painel */
  --superficie-2: #F5F8FC;     /* superfície recuada (coluna de kanban, chips) */
  --borda: var(--line);        /* borda sutil */
  --texto-2: var(--cinza);     /* texto secundário */
  --acento: var(--laranja);    /* ação/progresso */

  /* ===== Fase 11 — fundação do tema escuro =====
     REGRA: daqui em diante componente NÃO declara cor literal; usa token.
     O bloco html[data-tema="escuro"] redefine só estes valores. */

  /* Camadas, do fundo para a frente. `--moldura` existe porque `--navy` é
     usado como COR DE TEXTO em 20+ lugares (h1, .tile-val, .vt…): escurecer
     `--navy` no tema escuro apagaria os textos. Separar é obrigatório. */
  --moldura: var(--navy);      /* rail lateral + faixa que emoldura o painel */
  --superficie-3: #EDF1F5;     /* recuo mais fundo: trilhos, barras, chips */

  /* Texto */
  --texto-3: var(--faint);     /* rótulos, metadados, texto de apoio */
  /* texto sobre superfície ESCURA ou azul saturado (rail, rodapé do escopo,
     botões cheios, bolha do chat). Branco nos DOIS temas: essas superfícies
     não clareiam no escuro. Não confundir com 'inverso do texto'. */
  --texto-inv: #FFFFFF;
  /* azul de SUPERFÍCIE (fundo de botão/bolha). Separado do --azul de LINK:
     no escuro o link precisa clarear para ser legível, mas o fundo de botão
     precisa continuar escuro o bastante para o texto branco funcionar. */
  --azul-sup: var(--azul);
  --azul-sup-hover: var(--azul-escuro);
  --texto-sobre-moldura: #9FB0C4;   /* rodapé e nav sobre a moldura navy */

  /* Bordas por finalidade */

  /* Estados: par fundo + texto. Absorvem ~93 literais semânticas espalhadas. */
  --ok-bg: #E7F4EA;      --ok-fg: var(--ok);       --ok-borda: #A6D5BB;
  /* Fase 14 (reforco 1 do PO): --alerta-fg era var(--alerta) = 4,06 sobre o
     proprio --alerta-bg — abaixo de AA, e era o par das badges de desvio.
     Escurecido ate 4,93/5,43 (alerta-bg/superficie); mesmo matiz, um passo
     mais fundo. Efeito colateral desejado: as ~17 pills pre-existentes que
     usavam este par sobem para AA juntas. --alerta (base) fica intocado
     para icones e graficos. */
  --alerta-bg: #FDF3DD;  --alerta-fg: #945E0A;     --alerta-borda: #EDD3A0;
  --erro-bg: #FDECEA;    --erro-fg: var(--erro);   --erro-borda: #F0C0BA;
  --info-bg: #EAF2FA;    --info-fg: var(--azul);   --info-borda: #CFE2F2;

  /* Red flags — superfície PRÓPRIA. No escuro elas precisavam de força de
     verdade (pedido do PO): os tokens de alerta gerais são quase neutros lá, e
     os chips de ícone eram cor crua clara, que virava pastel. Aqui no claro os
     valores apontam para o que já existia: tema aprovado, aparência intocada. */
  --flag-r-bg: var(--erro-bg);      --flag-r-borda: var(--erro-borda);
  --flag-r-ac: var(--erro-borda);   --flag-r-chip: #F4D2CC;
  --flag-r-ic: var(--erro);
  --flag-o-bg: var(--alerta-bg);    --flag-o-borda: var(--alerta-borda);
  --flag-o-ac: var(--alerta-borda); --flag-o-chip: #F6E2B6;
  --flag-o-ic: var(--alerta);
  --flag-ac-w: 1px;                 /* barra lateral de acento: só o escuro engrossa */

  /* Quadro Kanban: 2 camadas próprias — o fundo do board é mais fundo que a
     coluna, e a coluna é mais funda que o card. Unificar com --superficie-2
     achataria a hierarquia visual do quadro. */
  --board-bg: #DDE5F0;
  --board-col: #F2F6FB;
  --board-borda: #D3DCE9;
  --hover-suave: #F2F7FC;   /* realce de linha/botão ao passar o mouse */

  /* Sombras e véus */
  --sh-forte: 0 24px 60px rgba(8,20,36,.35);
  --veu: rgba(16,24,38,.82);        /* lightbox */
  --veu-modal: rgba(6,15,28,.74);   /* quick-view */

  /* Séries dos gráficos (Chart.js lê via getComputedStyle — Fase 11.5).
     Escolhidas contra superfície CLARA; o tema escuro define as suas. */
  --serie-1: #00528B;  --serie-2: #C96A08;  --serie-3: #2E8B6A;
  --serie-4: #8E44AD;  --serie-5: #B4700A;
  --grafico-grade: #EFF3F7;

  /* Tokens que EXISTIAM em uso mas NUNCA foram declarados — bug silencioso:
     `color: var(--muted)` era inválido e o elemento herdava a cor do pai.
     Declarados com o valor EFETIVO de hoje (medido no navegador), não com o
     que o nome sugere: consertar o nome mudaria o visual sem decisão do PO.
     ⚠️ `--muted` no botão A/NA não-selecionado deveria ser apagado (--faint);
     hoje sai com a cor de texto normal. Fica como proposta do passe estético. */
  /* Distancia entre a borda da JANELA e a face direita do conteudo. O valor
     util e medido por `tratativa.js` (o `main` fica centrado quando bate no
     teto de largura, e a folga depende da tela); aqui fica o padrao para
     quando o JS nao roda — o padding do proprio `main`. */
  --folga-conteudo: 22px;
  /* Faixa do zebrado. SOBREPOSICAO com alfa, e nao um tom fixo: assim ela se
     ajusta sozinha a qualquer superficie por baixo e nao disputa com os tons
     de realce da linha, que sao proximos. Medido: 1,08 no claro. */
  --zebra: rgba(12, 32, 54, .04);
  --marca-dagua: #14476F;      /* §12 forense: legível-mas-discreta */
  --muted: var(--texto);       /* .toggle button — efetivo hoje, não --faint */
  --ink: var(--navy);          /* .qv-bl-nome, .qv-esc li */
  --verde: #1E7D4E;            /* .aceite-ok (já tinha este fallback inline) */

  /* Escala de espaçamento (o guia aponta o respiro como o #1 do "moderno") */
  --sp-2: 8px;
  --sp-3: 12px;
  --sp-4: 16px;
  --sp-5: 24px;
  --sp-6: 32px;
  --r-lg: 16px;                /* raio maior, cards/superfícies de destaque */
}

/* ===== Fase 11 — TEMA ESCURO =====================================
   Redefine SÓ tokens; nenhum componente sabe que o tema existe. Segue o
   precedente de `html.side-collapsed`, que já redefine --side-w.

   A relação de camadas se INVERTE com um cuidado: no claro a moldura navy é
   a camada mais escura e o painel é claro; no escuro a moldura tem de ficar
   MAIS ESCURA que o painel, senão o contorno some e a tela vira um bloco só.
   Ordem no escuro: moldura (mais fundo) → painel → card → recuo.
   ================================================================= */
html[data-tema="escuro"] {
  --zebra: rgba(255, 255, 255, .055);
  /* camadas */
  --moldura: #050B14;          /* mais escuro que o painel: mantém o contorno */
  --fundo: #0E1B2B;            /* painel */
  --superficie: #16273A;       /* card — elevado sobre o painel */
  --superficie-2: #1D2C40;
  --superficie-3: #24384F;

  /* texto: nunca branco puro sobre escuro (cansa); cinza-azulado claro */
  --texto: #E4ECF5;
  --texto-2: #A9BACD;
  --cinza: #A9BACD;            /* usado direto em 30+ lugares (tile-rot, psub…) */
  --faint: #93A6BC;   /* clareado: o th fica sobre --superficie-2, não sobre o card */
  --texto-3: #7C8FA6;
  --texto-inv: #FFFFFF;
  --azul-sup: #2A6DA8;
  --azul-sup-hover: #1F5386;
  --texto-sobre-moldura: #A9BACD;
  --navy: #DCE7F3;             /* era cor de texto forte no claro → clareia */
  --azul-escuro: #C3D6EA;
  --ink: var(--navy);
  --muted: var(--texto);
  --marca-dagua: #8FA8C4;   /* clareia: sobre escuro o navy sumiria */

  /* bordas: separam por luz, não por sombra */
  --line: #27394F;
  --line-in: #33485F;
  --line2: #1E2E42;
  --borda: var(--line);

  /* marca: o azul do claro (#00528B) não passa em AA sobre escuro (1,86 no
     card) — clareia. Medido em 28/08 contra o azul novo: continua valendo. */
  --azul: #6FA8DC;
  --laranja: #F59A47;
  --accent: var(--laranja);
  --acento: var(--laranja);

  /* estados: fundo tintado escuro + texto claro do mesmo matiz */
  --ok: #6FD3A3;      --ok-bg: #102A20;      --ok-fg: #7EDCB0;  --ok-borda: #1E4A38;
  --alerta: #E8B563;  --alerta-bg: #2E2416;  --alerta-fg: #EFC078; --alerta-borda: #55411F;
  --erro: #F08573;    --erro-bg: #2E1917;    --erro-fg: #F79C8B; --erro-borda: #5A2C26;
  --info-bg: #14273A; --info-fg: #8FC3EA;    --info-borda: #2B4763;
  /* Red flags no escuro: vermelho e laranja com CHROMA de verdade, barra
     lateral de 4px e chip de ícone vívido com glifo escuro. */
  --flag-r-bg: #5A1A14;  --flag-r-borda: #A63B2B; --flag-r-ac: #FF6A4D;
  --flag-r-chip: #F0654B; --flag-r-ic: #2A0D09;
  --flag-o-bg: #5A3E0E;  --flag-o-borda: #A87A1E; --flag-o-ac: #FFB04A;
  --flag-o-chip: #F0A93C; --flag-o-ic: #2A1D05;
  --flag-ac-w: 4px;
  --verde: var(--ok);

  /* quadro Kanban */
  --board-bg: #0A1524;
  --board-col: #13202F;
  --board-borda: #22344A;
  --hover-suave: #1B2C3F;

  /* sombras: no escuro a profundidade vem de luz e borda, não de sombra preta */
  --sh: 0 1px 2px rgba(0,0,0,.35), 0 2px 6px rgba(0,0,0,.25);
  --sh-forte: 0 24px 60px rgba(0,0,0,.6);
  --veu: rgba(3,8,15,.88);
  --veu-modal: rgba(3,8,15,.82);

  /* séries dos gráficos: paleta PRÓPRIA (as do claro escurecem demais aqui) */
  --serie-1: #6FA8DC;  --serie-2: #F0A45C;  --serie-3: #6FD3A3;
  --serie-4: #C89BE0;  --serie-5: #E8C061;
  --grafico-grade: #27394F;
}

/* Sem escolha manual, segue o sistema operacional (decisão do PO). O
   `:not([data-tema])` garante que a escolha explícita SEMPRE vence. */
@media (prefers-color-scheme: dark) {
  html:not([data-tema="claro"]):not([data-tema="escuro"]) {
  --zebra: rgba(255, 255, 255, .055);
    --moldura: #050B14;
    --fundo: #0E1B2B;
    --superficie: #16273A;
    --superficie-2: #1D2C40;
    --superficie-3: #24384F;
    --texto: #E4ECF5;
    --texto-2: #A9BACD;
    --cinza: #A9BACD;            /* usado direto em 30+ lugares (tile-rot, psub…) */
    --faint: #93A6BC;   /* clareado: o th fica sobre --superficie-2, não sobre o card */
    --texto-3: #7C8FA6;
    --texto-inv: #FFFFFF;
    --azul-sup: #2A6DA8;
    --azul-sup-hover: #1F5386;
    --texto-sobre-moldura: #A9BACD;
    --navy: #DCE7F3;
    --azul-escuro: #C3D6EA;
    --ink: var(--navy);
    --muted: var(--texto);
    --marca-dagua: #8FA8C4;
    --line: #27394F;
    --line-in: #33485F;
    --line2: #1E2E42;
    --borda: var(--line);
    --azul: #6FA8DC;
    --laranja: #F59A47;
    --accent: var(--laranja);
    --acento: var(--laranja);
    --ok: #6FD3A3;      --ok-bg: #102A20;      --ok-fg: #7EDCB0;  --ok-borda: #1E4A38;
    --alerta: #E8B563;  --alerta-bg: #2E2416;  --alerta-fg: #EFC078; --alerta-borda: #55411F;
    --erro: #F08573;    --erro-bg: #2E1917;    --erro-fg: #F79C8B; --erro-borda: #5A2C26;
    --info-bg: #14273A; --info-fg: #8FC3EA;    --info-borda: #2B4763;
    /* Red flags no escuro: vermelho e laranja com CHROMA de verdade, barra
       lateral de 4px e chip de ícone vívido com glifo escuro. */
    --flag-r-bg: #5A1A14;  --flag-r-borda: #A63B2B; --flag-r-ac: #FF6A4D;
    --flag-r-chip: #F0654B; --flag-r-ic: #2A0D09;
    --flag-o-bg: #5A3E0E;  --flag-o-borda: #A87A1E; --flag-o-ac: #FFB04A;
    --flag-o-chip: #F0A93C; --flag-o-ic: #2A1D05;
    --flag-ac-w: 4px;
    --verde: var(--ok);
    --board-bg: #0A1524;
    --board-col: #13202F;
    --board-borda: #22344A;
    --hover-suave: #1B2C3F;
    --sh: 0 1px 2px rgba(0,0,0,.35), 0 2px 6px rgba(0,0,0,.25);
    --sh-forte: 0 24px 60px rgba(0,0,0,.6);
    --veu: rgba(3,8,15,.88);
    --veu-modal: rgba(3,8,15,.82);
    --serie-1: #6FA8DC;  --serie-2: #F0A45C;  --serie-3: #6FD3A3;
    --serie-4: #C89BE0;  --serie-5: #E8C061;
    --grafico-grade: #27394F;
  }
}

/* Impressão SEMPRE clara: papel não tem tema escuro, e a marca d'água
   forense (§12) precisa continuar legível na folha. */
@media print {
  html, html[data-tema="escuro"] {
    --moldura: #0C2036; --fundo: #EAEFF6; --superficie: #FFFFFF;
    --superficie-2: #F5F8FC; --superficie-3: #EDF1F5;
    --texto: #0E1A2B; --texto-2: #5F6D80; --texto-3: #98A2B3;
    --texto-inv: #FFFFFF; --navy: #0C2036; --azul: #00528B;
    --azul-escuro: #123A5E; --line: #E6EBF1; --line-in: #D9E1EA;
    --line2: #F4F6F9; --borda: #E6EBF1;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: var(--fundo);
  color: var(--texto);
  line-height: 1.55;
  font-size: 15.5px;
  -webkit-font-smoothing: antialiased;
}

/* Container central consistente (~1100px) em todas as telas.
   O antigo `header.topo` (barra superior azul, pre-redesign v4) foi removido na
   faxina da Fase 15: o shell hoje e .side + .topbar. */
main.conteudo { max-width: 1100px; margin: 2rem auto; padding: 0 1.2rem; }
footer.rodape { padding-left: max(1.2rem, calc((100% - 1100px) / 2)); padding-right: max(1.2rem, calc((100% - 1100px) / 2)); }

h1 { color: var(--navy); font-size: 1.85rem; font-weight: 800; letter-spacing: -0.03em; line-height: 1.15; }
h2 { color: var(--navy); font-size: 1.12rem; font-weight: 700; letter-spacing: -0.01em; }
a { color: var(--azul); }

.cartao {
  background: var(--superficie);
  border: 1px solid var(--borda);
  border-radius: var(--r-lg);
  padding: var(--sp-5);
  margin-bottom: 1rem;
  box-shadow: var(--sh);
}

form p { margin: 0.8rem 0; }
form label { display: block; font-weight: 600; margin-bottom: 0.3rem; font-size: 0.85rem; color: var(--cinza); }
input[type="text"], input[type="password"], input[type="email"],
input[type="search"], input[type="number"], input[type="date"], select, textarea {
  width: 100%;
  max-width: 420px;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--line-in);
  border-radius: var(--r-ctl);
  font-size: 0.95rem;
  font-family: inherit;
  color: var(--texto);
  background: var(--superficie);
  transition: border-color .15s, box-shadow .15s;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--azul);
  box-shadow: 0 0 0 3px rgba(29, 91, 149, 0.15);
}

.botao, button[type="submit"], input[type="submit"] {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  background: var(--azul-sup);
  color: var(--texto-inv);
  /* transparente (e não 0) para o botão cheio ter a MESMA caixa do
     secundário, que tem borda de 1px — senão saem 2px mais baixos. */
  border: 1px solid transparent;
  border-radius: var(--r-ctl);
  padding: 0.62rem 1.25rem;
  font-size: 0.92rem;
  font-weight: 600;
  font-family: inherit;
  /* <button> herda a entrelinha do agente do usuário e <a> herda a do corpo:
     sem fixar, o MESMO botão sai com alturas diferentes conforme a tag. */
  line-height: 1.25;
  cursor: pointer;
  text-decoration: none;
  box-shadow: 0 1px 2px rgba(16,24,40,.12);
  transition: background .15s, transform .12s, box-shadow .15s;
}
.botao:active, button[type="submit"]:active { transform: translateY(1px); }
.botao:hover, button[type="submit"]:hover:not(:disabled) { background: var(--azul-sup-hover); }
button[type="submit"]:disabled { background: #C3CDD9; cursor: not-allowed; opacity: 0.85; }
/* Os modificadores precisam de `.botao.` porque a regra base acima casa por
   `button[type="submit"]` (0,1,1) — mais específico que uma classe sozinha
   (0,1,0). Sem isso o MESMO par de classes sai azul num submit e branco num
   type="button", que foi o que o PO viu entre o painel e os registros. */
/* Acento laranja para a AÇÃO principal da tela (usar com parcimônia) */
.botao-acento, .botao.botao-acento { background: var(--accent); }
.botao-acento:hover, .botao.botao-acento:hover { background: #DA6E10; }
.botao-secundario, .botao.botao-secundario { background: var(--superficie); color: var(--azul-escuro);
  border: 1px solid var(--line); box-shadow: var(--sh); }
.botao-secundario:hover, .botao.botao-secundario:hover { background: #FBFCFE; border-color: var(--borda); }
/* PERIGO: acao que retira ou desfaz. Vermelho TINGIDO, nao chapado — o botao
   abre uma confirmacao, nao executa. Vermelho cheio aqui gritaria mais que o
   "Confirmar o cancelamento" que vem depois, e o alarme tem de crescer, nao
   diminuir. Mesmos tokens do `.btn-recusar`, que e o confirmar do fornecedor.
   ⚠️ Precisa do `.botao.` pela mesma razao dos modificadores acima, e vem
   DEPOIS do secundario porque e ele quem este substitui na pratica. */
/* ⚠️ Borda em `--erro-fg`, nao em `--erro-borda`: o fundo tingido mede 1,09
   contra o cartao no tema escuro (medido) — ou seja, a forma do botao some e so
   o texto denuncia que ha algo ali. Quem desenha a borda de um botao contornado
   e a borda. */
.botao-perigo, .botao.botao-perigo { background: var(--erro-bg); color: var(--erro-fg);
  border: 1px solid var(--erro-fg); box-shadow: var(--sh); }
.botao-perigo:hover, .botao.botao-perigo:hover { background: var(--erro-bg); border-color: var(--erro-fg); }

/* Checkbox alinhado na mesma linha do rótulo (item 3 do PO) */
p.campo-checkbox { display: flex; align-items: center; gap: 0.55rem; }
p.campo-checkbox label { margin: 0; font-weight: 600; }
p.campo-checkbox input[type="checkbox"] { width: 1.1rem; height: 1.1rem; accent-color: var(--azul); }

.erros, .errorlist { color: var(--erro); margin: 0.3rem 0; padding-left: 1.1rem; }
.aviso { color: var(--alerta); }
.ok { color: var(--ok); }

details.termo {
  border: 1px solid var(--borda);
  border-radius: 6px;
  padding: 0.6rem 0.9rem;
  margin: 0.6rem 0;
  background: var(--superficie);
}
details.termo summary { cursor: pointer; font-weight: 600; color: var(--azul); }
details.termo .texto { font-size: 0.9rem; max-height: 16rem; overflow-y: auto; margin-top: 0.6rem; }

table.lista {
  width: 100%; border-collapse: collapse; background: var(--superficie);
  border-radius: 10px; overflow: hidden;
  box-shadow: 0 1px 3px rgba(31, 42, 55, 0.08), 0 4px 12px rgba(31, 42, 55, 0.06);
}
table.lista th, table.lista td { padding: 0.65rem 0.9rem; border-bottom: 1px solid var(--borda); text-align: left; }
table.lista th { background: var(--azul-sup); color: var(--texto-inv); font-size: 0.85rem; }
table.lista tbody tr:hover { background: var(--hover-suave); }

/* Chips de status: rascunho=âmbar · enviada=verde · não iniciada=cinza */
.badge { display: inline-block; padding: 0.14rem 0.6rem; border-radius: 999px; font-size: 0.78rem; font-weight: 600; }
.badge.nao-iniciada { background: #eef0f2; color: var(--cinza); }
.badge.rascunho { background: var(--alerta-bg); color: var(--alerta); }
.badge.enviada { background: var(--ok-bg); color: var(--ok); }
.badge.reaberta { background: var(--alerta-bg); color: var(--alerta); }

footer.rodape { text-align: center; color: var(--cinza); font-size: 0.8rem; margin: 2.5rem 0 1.5rem; }
footer.rodape p { margin: 0.25rem 0; }
footer.rodape .acesso-info { color: var(--azul-escuro); }

/* ===== Fase 3 — Tela de preenchimento =====
   O layout em 2 colunas (.forn-grid + aside com .bloco-nav/.sec-item/.tot-aside
   e main.preench) foi substituido pela LISTA CONTINUA (.escopo) na Fase 3.10 e
   saiu na faxina da Fase 15. O que a lista continua usa vive em .b-resumo /
   .s-resumo / .area / .secao-lista, mais abaixo. */
.aside-prazo { font-size: 0.78rem; color: var(--cinza); margin-top: 2px; }
.banner { border-radius: 8px; padding: 10px 14px; margin-bottom: 14px; font-size: 0.9rem; }
.banner-prazo { background: var(--erro-bg); border: 1px solid var(--erro); color: var(--erro); }

.progress-wrap { display: flex; align-items: center; gap: 16px; background: var(--superficie); border: 1px solid var(--line); border-radius: var(--r-card); padding: 12px 16px; margin-bottom: 14px; box-shadow: var(--sh); }
.progress-info { font-size: 0.85rem; color: var(--cinza); white-space: nowrap; }
.progress-info b { font-size: 16px; color: var(--azul-escuro); margin: 0 4px; }
.trilho { flex: 1; height: 10px; background: var(--borda); border-radius: 6px; overflow: hidden; }
.barra { height: 10px; background: var(--laranja); transition: width 0.4s; }
.salvo { color: var(--ok); font-size: 12px; white-space: nowrap; }

.busca-wrap { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
.busca-wrap input[type="search"] { flex: 1; max-width: 480px; padding: 0.6rem 0.8rem; border: 1px solid var(--line-in); border-radius: var(--r-ctl); font-size: 0.9rem; }
.busca-info { font-size: 0.8rem; color: var(--cinza); }
mark { background: #FFE2B8; }

h2.bloco { color: var(--azul-escuro); font-size: 1.05rem; margin: 6px 0 10px; }

table.itens { width: 100%; border-collapse: separate; border-spacing: 0; background: var(--superficie); border: 1px solid var(--line); border-radius: var(--r-card); overflow: hidden; box-shadow: var(--sh); }
table.itens th { background: var(--superficie-2); color: var(--faint); text-transform: uppercase; font-size: 0.68rem; letter-spacing: 0.05em; font-weight: 700; padding: 9px 12px; text-align: left; border-bottom: 1px solid var(--line); }
table.itens td { padding: 12px; border-bottom: 1px solid var(--line2); vertical-align: top; font-size: 0.9rem; }
tr.item-row td { border-bottom: none; }
tr.obs-row td { background: var(--superficie-2); padding-top: 0; }
/* ZEBRADO — linha sim, linha nao (PO, 14/08): com descricao e requisito longos,
   o olho perde a linha ao atravessar da esquerda para a direita.

   Cada item e um `<tbody>` proprio, entao a alternancia e por `nth-of-type`
   entre tbodies e nao por `nth-child` de `<tr>` — contar linhas pegaria a
   `obs-row` do parecer e inverteria a faixa dali para baixo.

   ⚠️ Fica ANTES das regras de realce, que tem mais especificidade e continuam
   vencendo — senao o zebrado apagaria o sinal de "aqui tem o que analisar".

   ⚠️ A faixa e SOBREPOSICAO com alfa (--zebra), nao um tom fixo. Com tom fixo
   ela media 1,07 nos dois temas e o PO achou "suave demais" no escuro; subir o
   tom esbarrava nos tons de realce, que ficam logo acima. Com alfa da para
   calibrar cada tema por si: 1,08 no claro e 1,18 no escuro. */
table.itens tbody.grupo-item:nth-of-type(even) tr.item-row > td { background: var(--zebra); }
.cod { color: var(--azul); font-weight: 700; white-space: nowrap; }
/* Descricao x requisito: colunas VIZINHAS de largura igual, como eram na
   planilha de origem (PO, validacao da 15).

   `table-layout: fixed` porque a alternativa MEDIU MAL: com as duas colunas em
   50% os 100% estouram (as outras somam 520px em valor fixo) e o navegador
   espremia TODAS na mesma proporcao — o campo de valor unitario caiu de 130px
   para 63px, largura em que nao cabe um preco. Nada na suite via isso.

   No layout fixo os px declarados no `<th>` sao honrados ao pe da letra e o
   que sobra e dividido em partes iguais entre as colunas sem largura — que sao
   exatamente estas duas. Igualdade exata, sem cravar pixel. */
table.itens { table-layout: fixed; }
/* Mesmo corpo de texto da descricao — sao colunas PARES, e reduzir uma delas
   diria que vale menos, que e o contrario da leitura em paralelo. (O 0.8rem que
   a antiga `.req` tinha nem valeria aqui: `table.itens td` e mais especifico e
   ganharia em silencio.) A cor mais suave basta para diferenciar: medido em
   5,27 no claro e 7,65 no escuro, AA nos dois. */
td.req { color: var(--texto-2); }
/* Texto longo sem espaco (codigo de norma, URL) nao pode alargar a coluna nem
   vazar: no layout fixo a largura nao cede, entao a quebra e obrigatoria. */
table.itens td.spec, td.req { overflow-wrap: break-word; }
/* ⚠️ SEM `white-space: nowrap`. Ele convivia com a tabela de largura
   automatica, que alargava a coluna para caber. Desde que a tabela virou
   `table-layout: fixed`, a largura NAO cede: unidade longa ("ÁREA (hectares)")
   transbordava 59px por baixo da celula vizinha e a unidade sumia da tela.
   Regressao introduzida junto com as colunas descricao/requisito. */
.qtd { font-variant-numeric: tabular-nums; overflow-wrap: break-word; }
img.fig { height: 86px; border: 1px solid var(--borda); border-radius: 6px; margin-top: 6px; cursor: zoom-in; display: block; }
.leg { font-size: 0.72rem; color: var(--cinza); margin-top: 2px; }

input.vu { width: 100%; padding: 0.5rem 0.7rem 0.5rem 2.1rem; border: 1px solid var(--line-in); border-radius: var(--r-ctl); text-align: right; font-variant-numeric: tabular-nums; font-size: 0.9rem; transition: border-color .15s, box-shadow .15s; }
/* Simbologia de moeda no campo (apontamento do PO). E um ELEMENTO, nao um
   pseudo: pseudo nao tem caixa mensuravel e o alinhamento com o numero so dava
   para acertar no chute — foi o que o PO viu, "aparece o R$ mas esta
   desalinhado".

   O truque do alinhamento: a caixa do rotulo REPETE a do input (mesmo topo,
   mesmo padding vertical, mesma borda transparente, mesma metrica de fonte).
   Com as duas caixas identicas, as duas linhas de texto caem no mesmo lugar
   sem nenhum ajuste manual. */
td.vu-cel { position: relative; }
.vu-moeda { position: absolute; left: 12px; top: 12px;
  padding: 0.5rem 0 0.5rem 0.7rem; border: 1px solid transparent;
  font-size: 0.9rem; line-height: normal; color: var(--texto-2);
  pointer-events: none; }
input.vu:focus { outline: none; border-color: var(--azul); box-shadow: 0 0 0 3px rgba(29,91,149,.15); }
input.vu.expr { border-color: var(--azul); background: var(--hover-suave); text-align: left; }
.vu-hint { font-size: 0.68rem; color: var(--faint); margin-top: 4px; }
/* O total e TEXTO puro numa linha cujos vizinhos sao CONTROLES: o texto do
   input comeca 9px abaixo do topo da celula (padding 0.5rem + 1px de borda), e
   o do toggle na mesma altura (3px do trilho + 0.4rem do botao). Sem compensar,
   o total flutuava 9px acima dos dois — apontamento do PO. O calc amarra a
   compensacao as MESMAS medidas do input; mexer nele move os dois juntos. */
.vt { text-align: right; font-variant-numeric: tabular-nums; font-weight: 700; white-space: nowrap; color: var(--navy); }
/* ⚠️ Seletor com `table.itens` de proposito: `table.itens td { padding: 12px }`
   e MAIS especifico (0,1,2) que `.vt` (0,1,0), entao um `padding-top` solto na
   classe seria ignorado em silencio. Mesma armadilha do `font-size` da coluna
   de requisito, e eu cai nela duas vezes. */
table.itens td.vt { padding-top: calc(12px + 0.5rem + 1px); }

/* ⚠️⚠️ ESTADO DE GRAVACAO — entrega 1, etapa 2, e SEM COLUNA PROPRIA.

   Regra 20 do CLAUDE.md (PO, 26/08): ESTADO RARO NAO PAGA COLUNA PERMANENTE.
   A primeira versao desta etapa deu a ele uma coluna de 134px; medido, ela
   levava descricao e requisito de 388px para 321px — abaixo dos 324px pelos
   quais tres arranjos de chat ja tinham sido recusados.

   A marca mora na celula de `Qtd · Un`, que tem 104px usaveis contra os 92px
   que `✓ 24/08 14:32` mede, e 66px de folga vertical. Custo de altura medido
   antes/depois na tela real: ZERO. */
.marca-estado { margin-top: 4px; font-size: 0.82rem; line-height: 1.3; }
table.itens .estado-salvo { color: var(--ok); white-space: nowrap; }

/* A linha que nao gravou ganha barra de acento de 6px na PRIMEIRA celula.
   Fundo colorido esta nos "becos sem saida" do CLAUDE.md: o melhor tingimento
   desta paleta da contraste 1,27 (escuro) e 1,14 (claro), invisivel. */
table.itens tbody.grupo-item[data-nao-salvo="1"] tr.item-row > td.cod {
  box-shadow: inset 6px 0 0 var(--erro);
}
/* "salvando" esmaece a marca: e transitorio e nao deve competir com a falha,
   que e a unica que exige acao. */
table.itens tbody.grupo-item[data-estado="salvando"] .marca-estado {
  color: var(--texto-3);
}

/* ⚠️⚠️ A FAIXA DA FALHA — largura inteira, embaixo da linha do item.
   "Uma mensagem de 134px de largura vira 254px de altura; a mesma mensagem em
   1434px vira uma linha de texto." Ela so existe quando ha falha, entao custa
   ZERO no caso comum. */
table.itens tr.linha-da-falha > td {
  background: var(--erro-bg);
  border-bottom: 1px solid var(--erro-borda);
  color: var(--erro-fg);
  padding: 8px 12px;
}
/* TRES CANAIS: cor (as duas regras acima), icone e texto (no HTML). */
table.itens .falha-aviso { font-weight: 700; white-space: nowrap; }
table.itens .falha-texto { color: var(--erro-fg); }
table.itens .falha-retry {
  margin-left: 10px;
  padding: 3px 10px;
  border: 1px solid var(--erro-borda);
  border-radius: var(--r-ctl);
  background: transparent;
  color: var(--erro-fg);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}
table.itens .falha-retry:hover { background: var(--erro-borda); }

/* ⚠️⚠️ O RECADO DA TRAVA DO ENVIO — entrega 1, etapa 3.

   Ele fica NO RODAPE, ao lado do botao, porque e ali que a pessoa clica: recado
   que explica por que o envio nao anda tem de estar onde o envio esta.

   ⚠️ E ele NAO usa a cor de erro cheia. A faixa da linha ja e vermelha; repetir
   o mesmo peso aqui poria dois alarmes de mesma intensidade competindo, e o que
   exige acao e a LINHA. Aqui e aviso e caminho, nao alarme. */
.recado-do-envio:empty { display: none; }
.recado-do-envio {
  flex: 1 1 100%;
  order: 2;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--erro-fg);
  background: var(--erro-bg);
  border: 1px solid var(--erro-borda);
  border-radius: var(--r-ctl);
  padding: 6px 10px;
}
/* ⚠️ Os nomes das linhas pendentes sao LINKS de verdade — sublinhados e
   focalizaveis. Condicao 1 do PO: "diz QUAIS linhas estao pendentes e LEVA ate
   elas"; algo que leva e um link, e link que nao parece link ninguem clica. */
.recado-do-envio .ir-para-pendente {
  color: inherit;
  font-weight: 700;
  text-decoration: underline;
}

/* ⚠️ O envio TRAVADO nao some e nao vira cinza morto: ele continua clicavel e o
   clique LEVA ate a primeira pendente. Recusa sem caminho e o pior desfecho
   desta tela. O atributo aria-disabled diz a quem usa leitor de tela o que a
   cor diz a quem enxerga. */
.rodape-total a.enviar.travado {
  opacity: 0.55;
  cursor: help;
}

.toggle { display: inline-flex; gap: 0; background: var(--borda); border-radius: 10px; padding: 3px; }
/* Borda de 2px SEMPRE, transparente quando nao selecionado: a selecionada
   ganha cor sem mudar o tamanho do botao. Antes o nao-selecionado tinha
   `border: 0` e o selecionado 1px, entao os dois nao tinham a mesma altura.
   O padding compensa os 2px para o controle nao crescer na coluna de 118px. */
.toggle button { flex: 1; padding: calc(0.4rem - 2px) calc(0.75rem - 2px); border: 2px solid transparent; background: transparent; border-radius: 8px; cursor: pointer; font-weight: 700; font-size: 0.82rem; color: var(--muted); transition: .12s; }
/* A/NA com FUNDO de cor (pedido do PO): antes era fundo neutro com texto
   colorido e a leitura de relance nao acontecia. Usa o PAR de tokens em vez de
   branco sobre cor forte -- no tema escuro --ok e --erro sao CLAROS, e branco
   sobre eles reprova em contraste (erro que eu ja cometi duas vezes hoje). */
/* ⚠️ Borda na cor FORTE (--ok-fg/--erro-fg), nao na `--*-borda` suave. No tema
   claro o preenchimento do chip dava 1,05 contra o trilho — o chip praticamente
   nao existia, e foi o que o PO viu ("continua muito suave"). O texto ja
   passava; o que faltava era o COMPONENTE se distinguir, criterio de 3:1.
   Com a cor forte: 4,27 e 4,77 no claro, 7,15 e 5,65 no escuro.
   Escurecer o trilho foi medido e nao resolve (1,05 -> 1,30 no melhor caso).
   E o mesmo padrao de `.recusa-veredito`, que ja esta na tela do saneamento. */
.toggle button.a.on { background: var(--ok-bg); color: var(--ok-fg); box-shadow: var(--sh); border-color: var(--ok-fg); }
.toggle button.na.on { background: var(--erro-bg); color: var(--erro-fg); box-shadow: var(--sh); border-color: var(--erro-fg); }
.toggle button:not(.on):hover { color: var(--navy); }
/* ⚠️ SEM `opacity` no desabilitado. Ela valia 0.55, e opacidade MISTURA o texto
   com o fundo: a aderencia — o dado que mais importa da linha — saia em 2,39 no
   tema claro e 3,38 no escuro, medido compondo a mistura (a cor nominal dava
   5,01 e 7,95 e enganava). Nas telas de leitura, que sao a vista integral e o
   saneamento, TODO botao esta desabilitado; apagar o dado ali nao sinaliza
   "nao editavel", so esconde a resposta. O nao-editavel ja se le pelo cursor e
   pela ausencia de hover. Apontamento do PO na validacao da 15. */
.toggle button:disabled { cursor: default; }
/* ⚠️ Sem baixar a cor do NAO selecionado. Tentei `--texto-2` para dar
   hierarquia e deu 4,40 no claro — reprova AA por pouco, que e como um defeito
   destes volta. A hierarquia ja existe e e mais forte que cor: o selecionado
   ganha FUNDO, borda e sombra; o outro fica sem chip nenhum. */

/* Campos DESABILITADOS (proposta em leitura: pós-envio, item fora do pleito,
   vista do admin). Sem isto o navegador aplica o estilo nativo — fundo claro
   e texto cinza — que ignora os tokens e fica ilegível no tema escuro
   (valor unitário quase invisível; PO 08/08). Também remove a aparência
   nativa, que no Windows pinta o campo de cinza. */
input:disabled, textarea:disabled, select:disabled,
.vu:disabled, .obs-box textarea:disabled {
  -webkit-appearance: none; appearance: none;
  background: var(--superficie-2);
  color: var(--texto);
  border-color: var(--borda);
  opacity: 1;                      /* opacity nativa some com o texto */
  -webkit-text-fill-color: var(--texto);   /* Safari/Chrome ignoram color em :disabled */
  cursor: default;
}
input:disabled::placeholder, textarea:disabled::placeholder { color: var(--texto-3); }

/* Bar de ações da linha (observação / perguntar) — conjunto padronizado */
.acoes-linha { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 8px 0 2px; }
.acoes-linha .obs-box, .acoes-linha .esc-box { flex-basis: 100%; }
.acao-linha { display: inline-flex; align-items: center; gap: 6px; border: 1px solid; border-radius: 20px; padding: 6px 15px; font-size: 0.82rem; font-weight: 600; cursor: pointer; background: var(--superficie); transition: background .15s, box-shadow .15s; }
.acao-linha .acao-ico { font-size: 0.95rem; line-height: 1; }
.acao-linha:hover { box-shadow: 0 1px 3px rgba(20,71,111,0.15); }
.acao-obs { color: var(--azul); border-color: var(--info-borda); background: var(--hover-suave); }
.acao-obs:hover { background: #E9F1F9; }
.acao-esc { color: var(--alerta-fg); border-color: var(--alerta-borda); background: var(--alerta-bg); }
.acao-esc:hover { background: var(--alerta-bg); }
.obs-box { border: 1px solid var(--line); border-radius: var(--r-ctl); padding: 11px 12px; margin: 6px 0 10px; background: var(--superficie); box-shadow: var(--sh); }
.obs-box.just { border-color: var(--alerta-borda); background: var(--alerta-bg); }
.obs-box .cab { font-size: 0.78rem; font-weight: 700; color: var(--navy); display: flex; justify-content: space-between; align-items: center; }
/* max-width:none: a regra genérica de inputs (420px) capava o width:100% —
   com o escopo em largura cheia a caixa ficava perdida à esquerda (PO, 07/08) */
.obs-box textarea { width: 100%; max-width: none; margin-top: 8px; padding: 0.55rem 0.7rem; border: 1px solid var(--line-in); border-radius: var(--r-ctl); font: inherit; font-size: 0.88rem; resize: vertical; transition: border-color .15s, box-shadow .15s; }
.obs-box textarea:focus { outline: none; border-color: var(--azul); box-shadow: 0 0 0 3px rgba(29,91,149,.15); }
.obs-box textarea.preenchido { border-color: var(--ok-borda); }
.estado { font-size: 0.72rem; font-weight: 600; }
.estado.vazio { color: var(--cinza); }
.estado.sujo { color: var(--alerta-fg); }
.estado.salvo { color: var(--ok); }
.obs-rodape { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 4px; }
.obs-rodape .chars { margin-right: auto; }  /* empurra "✓ salvo" + Salvar para a direita */
.chars { font-size: 0.72rem; color: var(--cinza); }
.mini-salvar { background: var(--azul-sup); color: var(--texto-inv); border: 0; border-radius: 6px; padding: 0.3rem 0.9rem; font-size: 0.8rem; font-weight: 600; cursor: pointer; }
.mini-salvar:hover { background: var(--azul-sup-hover); }
.just-msg { color: var(--erro); font-size: 0.76rem; margin-top: 4px; font-weight: 600; }

.preco-lote { background: var(--superficie); border: 1px solid var(--borda); border-radius: 10px; padding: 14px 16px; margin-top: 14px; max-width: 380px; }
.preco-lote label { font-weight: 600; font-size: 0.85rem; color: var(--azul-escuro); display: block; margin-bottom: 6px; }

.rodape-total { position: fixed; bottom: 0; left: 0; right: 0; background: var(--azul-sup-hover); color: var(--texto-inv); z-index: 50; display: flex; align-items: center; gap: 34px; padding: 10px 26px; }
.rodape-total .t { font-size: 12px; opacity: 0.75; }
.rodape-total .v { font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums; }
.rodape-total .enviar { margin-left: auto; background: var(--laranja); color: var(--texto-inv); border: 0; border-radius: 8px; padding: 0.6rem 1.6rem; font-weight: 700; font-size: 0.95rem; opacity: 0.45; text-decoration: none; pointer-events: none; }
.rodape-total .enviar.ativo { opacity: 1; pointer-events: auto; }
/* Escopo tem barra fixa de ação própria — esconde o rodapé do app (evita colisão) */
main.conteudo.escopo-page ~ footer.rodape { display: none; }
/* âncora da marca d'água: sem isto o `absolute` sobe até a viewport e volta
   a cobrir a barra lateral (PO 08/08). */
main.conteudo.escopo-page, main.conteudo.confidencial { position: relative; overflow: clip; }

/* Fase 15: veu pelo TOKEN (o literal cravado deixava o lightbox sem escurecer
   no tema escuro — achado da faxina). */
.lightbox { position: fixed; inset: 0; background: var(--veu); display: none; align-items: center; justify-content: center; z-index: 100; cursor: zoom-out; }
.lightbox.on { display: flex; }
.lightbox img { max-width: 88vw; max-height: 80vh; border-radius: 8px; background: var(--superficie); }

/* O @media (max-width:600px) que existia aqui so continha regras do
   `header.topo` — saiu junto com ele na faxina da Fase 15. */

@media (max-width: 900px) {
  table.itens thead { display: none; }
  table.itens tr { display: block; }
  table.itens tr.item-row { border-top: 8px solid var(--fundo); }
  table.itens td { display: block; border-bottom: none; padding: 6px 14px; }
  /* O thead some aqui (a tabela vira cartao), entao o requisito perderia o
     rotulo que agora e a coluna dele — volta pelo ::before, mesmo idioma de
     qtd e total. A descricao segue sem rotulo: e o texto de abertura da linha.
     E o reempilhamento das duas colunas: neste corte td ja e display:block. */
  table.itens td.req::before { content: "Requisito técnico mínimo: "; font-weight: 600; color: var(--cinza); }
  table.itens td.qtd::before { content: "Qtd · Un: "; font-weight: 600; color: var(--cinza); }
  table.itens td .vu { width: 100%; text-align: left; }
  /* Aqui a celula vira bloco e o "R$" posicionado nao teria a que se ancorar —
     vira rotulo, no mesmo idioma de qtd e total. */
  table.itens td.vu-cel { position: static; }
  table.itens td.vu-cel::before { content: "Valor unit. (R$): "; position: static;
    font-weight: 600; color: var(--cinza); font-size: inherit; }
  table.itens td .vu { padding-left: 0.7rem; }
  /* O total volta ao padding do bloco: nao ha input ao lado com que alinhar. */
  table.itens td.vt { padding-top: 6px; }
  table.itens td.vt::before { content: "Total: "; font-weight: 600; color: var(--cinza); }
  /* ⚠️ A marca de estado mora DENTRO da celula de qtd, que ja tem rotulo
     proprio aqui ("Qtd · Un: "). Ela nao precisa de rotulo separado — e uma
     segunda linha da mesma celula, e no cartao ela fica logo abaixo da
     quantidade, que e onde a pessoa acabou de olhar. */
  .rodape-total { flex-wrap: wrap; gap: 6px 18px; padding: 10px 14px; align-items: center; }
  .rodape-total > div { flex: 1 1 40%; min-width: 0; }
  .rodape-total .t { font-size: 11px; }
  .rodape-total .v { font-size: 15px; }
  /* Enviar ganha a linha inteira embaixo (nao disputa espaco) */
  .rodape-total .enviar { order: 3; margin-left: 0; width: 100%; text-align: center; box-sizing: border-box; }
  .rodape-total .enviar { padding: 0.7rem; }
  .progress-wrap { flex-direction: column; align-items: stretch; gap: 8px; padding: 11px 14px; }
  .progress-info { white-space: normal; }
  .trilho { width: 100%; }
  /* Avisos com botão: no mobile o texto usa a largura, o botão vai pra baixo à DIREITA */
  .aviso-card { flex-wrap: wrap; align-items: flex-start; }
  .aviso-card .aviso-txt { flex: 1 1 60%; }
  .aviso-card .botao { order: 3; flex: 0 0 auto; margin-top: 12px; margin-left: auto; }
  .escopo { padding-bottom: 160px; }
}

/* ===== Fase 3.10 — Escopo em lista contínua (decisão do PO, estilo Excel) ===== */
/* PO 08/08: a marca d'água cobria a tela toda (barra lateral inclusive) e
   ficava feia. Ancorada aqui, cobre só o escopo — que é o texto protegido
   pela medida §12. O overflow:hidden recorta a diagonal na borda. */
.escopo { position: relative; overflow-x: clip; }
/* PO (07/08): o teto de 1100px desperdiçava a tela — o bloco de preenchimento
   acompanha a largura do painel (main.largo). Sem teto o mobile não muda:
   o main já limita antes. */
.escopo { margin: 0 auto; padding: 0 0 130px; }
@media (min-width: 901px) { .escopo { padding: 0 16px 130px; } }
.escopo-cab h1 { margin-bottom: 0.1rem; }
.escopo-cab h1 small { color: var(--cinza); font-weight: 400; font-size: 0.85rem; }

details.area { border: 1px solid var(--line); border-radius: var(--r-card); margin-bottom: 10px; background: var(--superficie); overflow: hidden; box-shadow: var(--sh); }
details.area > summary { list-style: none; cursor: pointer; padding: 12px 14px; position: relative; }
details.area > summary::-webkit-details-marker { display: none; }
details.area > summary::after { content: "▾"; position: absolute; right: 14px; top: 12px; color: var(--cinza); transition: transform 0.2s; }
details.area[open] > summary::after { transform: rotate(180deg); }
details.area[open] > summary { background: var(--hover-suave); border-bottom: 1px solid var(--line); }
.b-resumo { display: block; padding-right: 22px; }
.b-resumo .b-tit { display: block; font-weight: 700; font-size: 0.92rem; color: var(--azul-escuro); }
.b-resumo .b-info { display: block; font-size: 0.76rem; color: var(--cinza); margin: 2px 0 5px; }
.b-resumo .b-info b { color: var(--azul-escuro); }
.b-resumo .mini, .s-resumo .mini { display: block; height: 3px; background: var(--superficie-3); border-radius: 2px; }
.b-resumo .mini span, .s-resumo .mini span { display: block; height: 3px; background: var(--laranja); border-radius: 2px; }

.area-conteudo { padding: 8px 10px; }
details.secao-lista { border: 1px solid var(--line); border-radius: var(--r-ctl); margin-bottom: 8px; background: var(--superficie); }
details.secao-lista > summary { list-style: none; cursor: pointer; padding: 9px 12px; position: relative; }
details.secao-lista > summary::-webkit-details-marker { display: none; }
details.secao-lista > summary::after { content: "▾"; position: absolute; right: 12px; top: 9px; color: var(--cinza); font-size: 0.8rem; transition: transform 0.2s; }
details.secao-lista[open] > summary::after { transform: rotate(180deg); }
details.secao-lista[open] > summary { background: var(--superficie-2); border-bottom: 1px solid var(--borda); }
.s-resumo { display: block; padding-right: 20px; }
.s-resumo .l1 { display: flex; align-items: center; gap: 7px; font-size: 0.86rem; }
.s-resumo .dot { width: 9px; height: 9px; border-radius: 50%; background: #D4DBE2; flex: none; }
.s-resumo .dot.part { background: var(--laranja); }
.s-resumo .dot.full { background: var(--ok); }
.s-resumo .s-tit { font-weight: 600; color: var(--texto); }
.s-resumo .l2 { display: flex; justify-content: space-between; font-size: 0.76rem; color: var(--cinza); margin: 3px 0 4px 16px; }
.s-resumo .soma { color: var(--azul-escuro); font-weight: 700; font-variant-numeric: tabular-nums; }
.s-resumo .mini { margin-left: 16px; }

/* Tabelas largas rolam dentro do próprio cartão no mobile (revisão final) */
.rolagem-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.rolagem-x table { min-width: 560px; }

/* Ações do envio: lado a lado com quebra — nunca sobrepostos */
.acoes-envio { display: flex; gap: 0.8rem; flex-wrap: wrap; align-items: center; }

/* Barrinha de operadores junto ao campo de valor (teclado numérico mobile) */
.op-barra { display: flex; gap: 6px; margin-top: 6px; }
.op-barra button { flex: 1; min-width: 40px; padding: 0.5rem 0; border: 1px solid var(--borda); background: var(--hover-suave); color: var(--azul-escuro); border-radius: 6px; font-size: 1.05rem; font-weight: 700; cursor: pointer; touch-action: manipulation; }
.op-barra button:active { background: var(--azul-sup); color: var(--texto-inv); }
@media (min-width: 901px) { .op-barra { display: none; } } /* desktop tem teclado físico */

.itens-container { padding: 6px 10px 10px; }
.itens-container .carregando { color: var(--cinza); font-size: 0.85rem; padding: 8px; }
.itens-container table.itens { border: none; }
.itens-container .preco-lote { margin: 10px 4px 4px; }

/* Apresentação da RFP + termo de habilitação (Fase 3a, spec §6.2.1) */
.apresentacao { max-width: 860px; margin: 0 auto; }
.apresentacao h2 { color: var(--azul-escuro); font-size: 1.05rem; margin-top: 0; }
.texto-preservado { white-space: pre-line; }
.termo li { margin: 0.55em 0; }
.aceite-linha { display: flex; gap: 0.6rem; align-items: flex-start; margin: 0.8rem 0; font-weight: 600; }
.aceite-linha input { margin-top: 3px; }
.aceite-ok { color: var(--verde, var(--ok-fg)); font-weight: 700; }
button#btn-termo:disabled { opacity: 0.45; cursor: not-allowed; }

/* Aviso de plausibilidade (§8.1a camada 1) — consultivo, nunca bloqueia */
.aviso-fraca { margin-top: 6px; padding: 6px 10px; background: var(--alerta-bg); border-left: 3px solid var(--laranja, #E88025); color: var(--alerta-fg); font-size: 0.82rem; border-radius: 4px; }

/* Esclarecimentos (§6.3.1) */
.esc-box { margin-top: 8px; padding: 10px 12px; background: var(--alerta-bg); border: 1px solid var(--alerta-borda); border-left: 3px solid var(--laranja); border-radius: 6px; }
.esc-box .cab { font-size: 0.82rem; font-weight: 600; color: var(--alerta-fg); margin-bottom: 4px; }
.esc-box textarea { width: 100%; max-width: none; box-sizing: border-box; padding: 0.45rem 0.6rem; border: 1px solid var(--borda); border-radius: 6px; font: inherit; font-size: 0.85rem; resize: vertical; }
.esc-ok { margin-top: 8px; padding: 8px 10px; background: var(--ok-bg); border-left: 3px solid var(--ok-fg); color: var(--ok-fg); font-size: 0.85rem; border-radius: 4px; }
.esc-pub { border-bottom: 1px solid var(--borda); padding: 8px 0; }
.esc-pub .perg { color: var(--azul-escuro); }

/* Link de volta à apresentação/termo/esclarecimentos a partir do escopo */
.esc-ajuda { color: var(--cinza); font-size: 0.82rem; margin: 2px 0 8px; }
.esc-geral .esc-box { margin-top: 8px; max-width: none; width: 100%; box-sizing: border-box; }  /* PO 07/08: caixa pequena */
.esc-geral textarea { width: 100%; box-sizing: border-box; }

/* Formulários de autenticação (login, reset…) — cartão centrado estilo
   ClientOS: respiro generoso, inputs altos e arredondados, botão sólido. */
.auth-wrap { max-width: 400px; margin: 6vh auto 0; }
.auth-wrap h1 { text-align: center; font-size: 1.5rem; letter-spacing: -.02em; margin: 0 0 var(--sp-5); }
.auth-wrap .cartao { padding: var(--sp-6) var(--sp-5); }
.auth-wrap form p { margin: 0 0 var(--sp-4); }
.auth-wrap label { font-size: .8rem; font-weight: 600; color: var(--texto-2); margin-bottom: 6px; }
.auth-wrap input[type="text"], .auth-wrap input[type="email"], .auth-wrap input[type="password"] {
  width: 100%; max-width: none; box-sizing: border-box; padding: 0.8rem 0.95rem;
  border-radius: 12px; font-size: 0.98rem; }
/* botão primário ocupa a largura, alto contraste */
.auth-wrap button[type="submit"], .auth-wrap .botao { width: 100%; justify-content: center;
  padding: 0.85rem; font-size: 0.98rem; margin-top: var(--sp-2); }
.auth-wrap > p, .auth-wrap .cartao > p:last-child { text-align: center; }
.auth-wrap a { color: var(--azul); }
.mini-cancelar { background: var(--erro-bg); border: 1px solid var(--erro-borda); color: var(--erro); border-radius: 6px; padding: 0.3rem 0.9rem; font-size: 0.8rem; font-weight: 600; cursor: pointer; margin-left: 6px; }
.mini-cancelar:hover { background: var(--erro-bg); }
.esc-eco { margin: 6px 0; padding: 6px 10px; background: var(--superficie); border-radius: 4px; font-style: italic; }
.esc-ok small { display: block; margin-top: 4px; color: var(--cinza); font-style: normal; }

/* A TRATATIVA do item: o texto do fornecedor e a conversa sobre ele, LADO A
   LADO (PO, 14/08). O chat vinha ACIMA da justificativa e ali nao se lia — o
   questionamento e SOBRE aquele desvio, entao nasce colado ao texto que o
   motivou.

   `auto-fit` e nao duas colunas fixas: sem chat, o texto do fornecedor ocupa a
   linha inteira em vez de deixar metade vazia. O minmax faz o que o PO pediu —
   "a depender do espaco horizontal" ficam lado a lado, e no estreito a conversa
   desce, que e a mesma ordem de leitura, em coluna.

   `min-width: 0` nas colunas: sem ele, texto longo sem espaco estoura a faixa
   do grid em vez de quebrar dentro dela. */
/* A TRATATIVA do item — bloco COLAPSÁVEL em largura cheia, na linha de baixo.
   Fechada por padrão; o `summary` é o selo.

   ⚠️ Ela ja foi a oitava COLUNA do item, e durou algumas horas. O PO: "ficou
   muito estreita e muito alta por conta dos varios blocos... muito espaco
   sobrando sob a descricao e os requisitos". Os tres defeitos vinham do mesmo
   lugar: um chat de 380px nao e um chat, a altura dele esticava a linha
   inteira, e as colunas de texto caiam de 555 para 324px para lhe dar espaco.

   Em largura cheia as threads cabem LADO A LADO em vez de empilhadas — e a
   linha do item volta a ser baixa, porque a conversa so aparece se for aberta. */
.tratativa > summary { list-style: none; cursor: pointer; }
.tratativa > summary::-webkit-details-marker { display: none; }
.conv-selo { display: inline-flex; align-items: center; gap: 8px; padding: 4px 12px; border-radius: 999px; background: var(--superficie); border: 1px solid var(--borda); color: var(--texto-2); font-size: .76rem; font-weight: 700; }
.conv-selo::before { content: "▸"; color: var(--cinza); }
.tratativa[open] > .conv-selo::before { content: "▾"; }
.conv-selo:hover { border-color: var(--azul); color: var(--azul); }
.conv-n { background: var(--info-bg); color: var(--azul); border-radius: 999px; padding: 0 8px; font-variant-numeric: tabular-nums; }
.conv-vazio { color: var(--cinza); font-weight: 600; }
/* ===== O PAINEL DA TRATATIVA =====
   Cartao FLUTUANTE do lado direito, sobre a pagina, com o fundo esmaecido — e
   nao uma faixa colada de ponta a ponta (PO, 14/08: "esse lance de aparecer um
   bloco todo numa faixa colada"). A altura e a do CONTEUDO, com teto; so os
   blocos de chat que existirem aparecem.

   O painel sai da tabela SEM sair do DOM: `position: fixed` reposiciona, e o
   elemento continua dentro do `tbody`. E isso que mantem o preenchimento
   funcionando — os campos postam com `hx-include="closest tbody"` e o
   csrf_token vive no tbody. */
.tratativa[open] > .tratativa-painel {
  position: fixed; top: 50%; transform: translateY(-50%); z-index: 70;
  /* A face direita do painel fica DENTRO da face direita do CONTEUDO (PO).
     `--folga-conteudo` e a distancia entre a borda da janela e a face do
     `main`, medida por `tratativa.js` e reposta a cada resize.

     ⚠️ TRES voltas ate entender o problema, e as duas primeiras erraram o ALVO,
     nao o numero. Eu ancorava na JANELA, e a janela nao e a referencia: numa
     tela larga o `main` bate no teto de `--larg-trabalho` (2150px) e fica
     CENTRADO, sobrando moldura dos dois lados — entao um painel preso ao
     viewport passava POR FORA da face do conteudo, que foi o que o PO viu.
     Na minha tela de medicao o `main` enchia a largura e a folga era zero, e o
     defeito nao reproduzia. Fixo ou proporcional, nada ancorado na janela
     resolveria.

     O token tem PADRAO no `:root` (o padding do `main`), para o caso de o JS
     nao rodar: pior que o certo, melhor que passando por fora. */
  right: calc(var(--folga-conteudo) + 40px);
  width: min(660px, calc(100vw - 48px)); box-sizing: border-box;
  max-height: min(78vh, 760px); overflow-y: auto;
  background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--r-card);
  box-shadow: 0 20px 52px rgba(0,0,0,.40);
  padding: 0 18px 20px;
}
@media (max-width: 900px) {
  .tratativa[open] > .tratativa-painel { right: 12px; left: 12px; width: auto; transform: none; top: 8vh; }
}
/* Veu: e um ::before do proprio <details>, entao clicar nele tem o <details>
   como alvo — e assim `tratativa.js` distingue do clique dentro do painel. */
.tratativa[open]::before { content: ""; position: fixed; inset: 0; z-index: 69; background: var(--veu-modal); }
.painel-topo { position: sticky; top: 0; z-index: 1; display: flex; align-items: baseline; gap: 10px;
  background: var(--superficie); border-bottom: 1px solid var(--line); margin: 0 -18px 14px; padding: 14px 18px 12px; }
.painel-topo b { color: var(--navy); font-size: .95rem; white-space: nowrap; }
.painel-desc { color: var(--texto-2); font-size: .82rem; flex: 1; min-width: 0; }
.painel-fechar { flex: none; border: 1px solid var(--borda); background: var(--superficie-2); color: var(--texto-2);
  width: 30px; height: 30px; border-radius: 8px; font-size: 1.1rem; line-height: 1; cursor: pointer; align-self: center; }
.painel-fechar:hover { border-color: var(--azul); color: var(--azul); }
.tratativa-threads { display: flex; flex-direction: column; gap: var(--sp-3); }
.tratativa-threads > * { min-width: 0; }

/* O SELO vive na celula da ADERENCIA, embaixo do A/NA (PO): e ali que se decide
   o item, entao e dali que se abre a conversa. A celula tem ~94px uteis — daí o
   rotulo curto e o numero num chip. */
.tratativa { margin-top: 8px; }
.conv-selo { display: inline-flex; align-items: center; gap: 6px; padding: 3px 9px; border-radius: 999px;
  background: var(--superficie); border: 1px solid var(--borda); color: var(--texto-2);
  font-size: .7rem; font-weight: 700; white-space: nowrap; }
.conv-selo:hover { border-color: var(--azul); color: var(--azul); }
.conv-n { background: var(--info-bg); color: var(--azul); border-radius: 999px; padding: 0 6px; font-variant-numeric: tabular-nums; }
.conv-selo-pendente { border-color: var(--erro-fg); color: var(--erro-fg); }
.conv-falta { background: var(--erro-bg); color: var(--erro-fg); border-radius: 999px; padding: 0 7px; }

/* A LINHA do subitem tem de SALTAR AOS OLHOS quando ha algo a analisar (PO).
   ⚠️ Medido: FUNDO nao resolve. O melhor tom disponivel da 1,27 contra a
   superficie da tabela no escuro e 1,14 no claro — e o `--info-bg` que eu usara
   antes dava 1,00 no escuro, ou seja, invisivel. Fundo tingido nesta paleta e
   sempre sutil.

   Quem tem forca e a BARRA DE ACENTO: `--azul` mede 6,0 no escuro e 7,04 no
   claro, `--erro-fg` 7,28 e 5,72 — bem acima do piso de 3,0 de componente. Por
   isso a barra ficou larga (6px) e o SELO ganhou a cor do estado.

   ⚠️ O fundo NEUTRO de realce saiu de vez quando o zebrado entrou: os dois
   disputavam a mesma faixa estreita de tons e um anulava o outro. Ficou so no
   `falta-justificativa`, que usa `--erro-bg` — ali a diferenca e de MATIZ
   (avermelhado), nao de claridade, entao se le por cima do zebrado. */
tbody.tem-tratativa tr.item-row > td:first-child { box-shadow: inset 6px 0 0 var(--azul); }
tbody.tem-tratativa .conv-selo { background: var(--info-bg); border-color: var(--azul); color: var(--azul); }

tbody.ponto-questionado tr.item-row > td:first-child { box-shadow: inset 6px 0 0 var(--alerta-fg); }
tbody.ponto-questionado .conv-selo { background: var(--alerta-bg); border-color: var(--alerta-fg); color: var(--alerta-fg); }

/* Falta a justificativa obrigatoria: o estado que mais precisa saltar, porque
   trava o envio do fornecedor. */
tbody.falta-justificativa tr.item-row > td { background: var(--erro-bg); }
tbody.falta-justificativa tr.item-row > td:first-child { box-shadow: inset 6px 0 0 var(--erro-fg); }
.tratativa-threads .item-chat { margin-top: 0; }
/* Titulo de cada thread: sem ele, duas threads coladas viram uma so aos olhos. */
.chat-tit { font-size: .72rem; font-weight: 700; color: var(--texto-2); text-transform: uppercase; letter-spacing: .03em; margin: 0 0 2px; padding-bottom: 8px; border-bottom: 1px solid var(--line); }
.chat-tit small { text-transform: none; letter-spacing: 0; color: var(--cinza); font-weight: 600; }
.chat-vazio { font-size: .8rem; color: var(--cinza); font-style: italic; }
/* O lancamento vira BALAO: mesma forma do balao do Q&A, com o canto de baixo
   cortado do lado de quem falou. Reusa `lancamento_bloco.html` inteiro — o
   historico de versoes e o botao Editar continuam funcionando. */
.item-chat .lanc-bloco { padding: 8px 12px; border-radius: 14px; font-size: .86rem; line-height: 1.45; margin: 0; position: relative; box-shadow: 0 1px 2px rgba(0,0,0,.14); }
.chat-outro .lanc-bloco { background: var(--superficie); border: 1px solid var(--borda); color: var(--texto); border-bottom-left-radius: 4px; }
.chat-eu .lanc-bloco { background: var(--azul-sup); color: var(--texto-inv); border-bottom-right-radius: 4px; }
.chat-eu .lanc-bloco .obs-texto, .chat-eu .lanc-bloco .lanc-quando { color: var(--texto-inv); }
/* ⚠️ Dentro do chat, o BALAO ja e a caixa. `.obs-texto` traz caixa propria —
   fundo, borda e raio — e o resultado era caixa DENTRO de balao, que foi o
   "sem graca" que o PO apontou na observacao. Aqui ela vira texto puro. */
.item-chat .lanc-bloco .obs-texto { margin: 0; padding: 0; background: none; border: 0; border-radius: 0; font-size: inherit; line-height: inherit; color: inherit; }
/* O carimbo vira METADADO de conversa: pequeno, discreto e do lado de quem
   falou — nao uma legenda de formulario atravessada embaixo. */
.item-chat .lanc-meta { margin-top: 5px; gap: 8px; font-size: .7rem; opacity: .85; }
.chat-eu .lanc-meta { justify-content: flex-end; }
.chat-eu .lanc-bloco .lanc-quando { color: var(--texto-inv); }
.item-chat .lanc-quando { font-size: .7rem; }
.item-chat .lanc-novo { align-self: stretch; }

/* Esclarecimentos persistentes na linha do item — formato de chat (§6.3.1) */
/* ⚠️ TRES CAMADAS, e nao duas. A tela do chat usava `--info-bg`, que no ESCURO
   e praticamente a mesma cor da superficie do painel — medido 1,00, ou seja,
   nao havia camada nenhuma e a coisa saia chapada (PO: "meio sem graca").

   Agora: painel (--superficie) > TELA do chat rebaixada (--fundo) > balao
   erguido de volta. Medido — tela vs painel 1,14 no escuro e 1,16 no claro;
   balao do outro vs tela 1,23 e 1,16; balao proprio vs tela 3,18 e 6,09.
   O balao ganha sombra para o "erguido" se ler tambem no escuro, onde
   diferenca de claridade sozinha rende pouco. */
.item-chat { margin: 4px 0 10px; padding: 12px; background: var(--fundo); border: 1px solid var(--line); border-radius: 12px; display: flex; flex-direction: column; gap: 10px; box-shadow: inset 0 1px 3px rgba(0,0,0,.10); }
.chat-msg { max-width: 88%; display: flex; flex-direction: column; }
/* O lado sai do AUTOR, relativo a quem olha — nao do TIPO da mensagem (decisao
   do PO, 13/08). As classes de antes eram `.chat-pergunta`/`.chat-resposta`:
   toda pergunta a esquerda, toda resposta a direita. Isso acertava por acaso na
   tela do fornecedor (a Alcance pergunta, ele responde = ele a direita) e
   errava na da Alcance, onde o texto DELA aparecia a esquerda enquanto o campo
   de escrever ficava a direita — a tela se contradizia. */
.chat-eu { align-self: flex-end; align-items: flex-end; }       /* quem olha */
.chat-outro { align-self: flex-start; align-items: flex-start; } /* o outro lado */
.chat-autor { font-size: 0.72rem; font-weight: 700; margin: 0 4px 3px; }
.chat-outro .chat-autor { color: var(--azul); }
/* `--laranja` e SINAL (ponto, barra, borda), nao cor de texto: media 2,47 sobre
   o fundo do chat no tema claro, bem abaixo de AA. Estava aqui desde a Fase 3a
   e passou por todas as varreduras de contraste — elas mediram telas sem
   conversa aberta, e onde nao ha bolha nao ha o que medir. `--alerta-fg` e o
   token de PRIMEIRO PLANO da mesma familia (escurecido na 14.8 justamente para
   passar em AA): 4,81 no claro, 9,04 no escuro. */
.chat-eu .chat-autor { color: var(--alerta-fg); }
/* O rabicho e o que faz o balao parecer BALAO e nao caixa. Feito com o canto
   de baixo reto do lado de quem fala (`border-*-radius: 4px`) mais um triangulo
   em `::after` — dois elementos ja existentes, sem imagem nem SVG. */
.chat-bolha { padding: 8px 12px; border-radius: 14px; font-size: 0.86rem; line-height: 1.45; position: relative; box-shadow: 0 1px 2px rgba(0,0,0,.14); }
.chat-msg .chat-bolha::after, .item-chat .lanc-bloco::after { content: ""; position: absolute; bottom: 0; width: 0; height: 0; border: 7px solid transparent; }
.chat-outro .chat-bolha::after, .chat-outro .lanc-bloco::after { left: -6px; border-right-color: var(--superficie); border-bottom-color: var(--superficie); border-left: 0; border-bottom-width: 0; }
.chat-eu .chat-bolha::after, .chat-eu .lanc-bloco::after { right: -6px; border-left-color: var(--azul-sup); border-bottom-color: var(--azul-sup); border-right: 0; border-bottom-width: 0; }
.chat-outro .chat-bolha { background: var(--superficie); border: 1px solid var(--borda); color: var(--texto); border-bottom-left-radius: 4px; }
.chat-eu .chat-bolha { background: var(--azul-sup); color: var(--texto-inv); border-bottom-right-radius: 4px; }
.chat-hora { font-size: 0.68rem; color: var(--cinza); margin: 2px 4px 0; }
.chat-aguardando { align-self: flex-end; font-size: 0.78rem; color: var(--cinza); font-style: italic; }
/* Fase 15: o fornecedor responde ao questionamento da Alcance no proprio item */
.chat-responder { align-self: stretch; display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }
.chat-responder label { font-size: .8rem; color: var(--texto-2); }
.chat-responder small { color: var(--cinza); }
.chat-responder textarea { width: 100%; }
.chat-responder .mini-salvar { align-self: flex-start; }
/* Fase 15 (formato de preenchimento): a Alcance questiona no proprio item. Do
   lado DELA — a pergunta que se vai fazer nasce onde as anteriores ficaram. */
.chat-questionar { align-self: flex-end; display: flex; flex-direction: column; gap: 6px; margin-top: 4px; width: min(100%, 560px); }
.chat-questionar label { font-size: .8rem; color: var(--texto-2); text-align: right; }
.chat-questionar small { color: var(--cinza); }
.chat-questionar textarea { width: 100%; max-width: none; box-sizing: border-box; }
.chat-questionar .mini-salvar { align-self: flex-end; }
.item-chat .acao-esc { align-self: flex-start; margin-top: 2px; }
.item-chat .esc-box { align-self: stretch; }

/* Navegação entre esclarecimentos (feedback do PO) */
.nav-esc { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin: 8px 0; }
.nav-esc-btn { border: 1px solid var(--borda); border-radius: 16px; padding: 4px 14px; font-size: 0.82rem; font-weight: 600; cursor: pointer; background: var(--superficie); }
.nav-esc-btn.aberta { color: var(--alerta-fg); border-color: var(--alerta-borda); background: var(--alerta-bg); }
.nav-esc-btn.respondida { color: var(--ok-fg); border-color: var(--ok-borda); background: var(--ok-bg); }
.nav-esc-btn:hover { filter: brightness(0.96); }
.nav-esc-dica { color: var(--cinza); font-size: 0.78rem; }
.realce-nav { animation: realce-nav 2.5s ease; }
@keyframes realce-nav { 0%, 40% { background: #FFF2C2; } 100% { background: transparent; } }

/* Formulário de solicitação de reabertura (§6.3.2) */
.reab-item { display: block; padding: 5px 4px; border-bottom: 1px solid var(--borda); font-size: 0.86rem; cursor: pointer; }
.reab-item:hover { background: var(--hover-suave); }
.reab-item input { margin-right: 8px; }

/* Topo do escopo — cartão de cabeçalho (feedback do PO, Fase 3b) */
.cab-card { background: var(--superficie); border: 1px solid var(--line); border-radius: var(--r-card); padding: 16px 18px; box-shadow: var(--sh); margin-bottom: 14px; }
.escopo-cab-topo { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.escopo-cab-topo h1 { margin: 0; flex: 1 1 auto; min-width: 0; }
.escopo-cab-topo .status-pill { flex: none; margin-top: 6px; }
/* Cabecalho COMPACTO (PO, 14/08): a pill cola no titulo, e o grupo de estado vai
   para a DIREITA — "somente leitura" e, na ponta, o botao da decisao. O `h1`
   perdeu o `flex: 1` para nao empurrar a pill; quem separa e o `margin-left`
   automatico do grupo. */
.escopo-cab-topo h1 { flex: 0 1 auto; }
.cab-estado { margin-left: auto; display: flex; align-items: center; gap: 10px; flex: none; }
.cab-leitura { display: inline-flex; align-items: center; gap: 6px; padding: 4px 12px; border-radius: 999px;
  background: var(--alerta-bg); color: var(--alerta-fg); border: 1px solid var(--alerta-borda);
  font-size: .76rem; font-weight: 700; white-space: nowrap; }
/* O selo e o que chama: so o botao, sem a faixa explicativa, precisava de um
   sinal de que ha algo esperando (decisao do PO). */
.cab-decidir { display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; }
/* ⚠️ AMBAR, nao vermelho (PO, 18/08). Vermelho de erro para dizer "ha um
   desconto esperando voce" faz a cor contradizer o texto: nao ha erro nenhum, ha
   uma decisao com prazo. E o mesmo defeito que o PO ja apontou duas vezes aqui —
   o ambar de atencao dizendo "esta tudo certo" e o verde com "✓" dizendo
   "Proposta desclassificada". Trocado JUNTO com o chip do card: duas cores para
   o mesmo fato seria pior que a cor errada. */
.cab-decidir-selo { display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%; background: var(--alerta-bg); color: var(--alerta-fg);
  font-weight: 700; font-size: .72rem; }
@media (max-width: 900px) {
  .escopo-cab-topo { flex-wrap: wrap; }
  .cab-estado { margin-left: 0; width: 100%; }
}
/* Progresso e busca dividem a LINHA: nenhum dos dois precisa da largura toda, e
   eram duas faixas empilhadas antes do escopo comecar. */
.busca-linha { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; margin-bottom: 12px; }
.busca-linha .busca-wrap { margin-bottom: 0; flex: 1 1 320px; }
.busca-linha .progress-wrap { margin-bottom: 0; flex: 1 1 380px; }
@media (max-width: 900px) { .busca-linha { flex-direction: column; align-items: stretch; } }
.status-pill { display: inline-flex; align-items: center; gap: 6px; padding: 4px 12px; border-radius: 999px; font-size: 0.78rem; font-weight: 700; }
.status-pill .dot { width: 8px; height: 8px; border-radius: 50%; }
.status-pill.enviada { background: var(--ok-bg); color: var(--ok); } .status-pill.enviada .dot { background: var(--ok); }
/* ⚠️ Fundo por TOKEN, nao cravado. #FDF1DE era literal, entao nao acompanhava o
   tema: no escuro dava uma pastilha clara com texto claro em cima — medido em
   1,51. Com o par tokenizado: 4,93 no claro e 9,04 no escuro. */
.status-pill.reaberta { background: var(--alerta-bg); color: var(--alerta-fg); } .status-pill.reaberta .dot { background: var(--laranja); }
.status-pill.rascunho { background: var(--alerta-bg); color: var(--alerta); } .status-pill.rascunho .dot { background: var(--alerta); }
.status-pill.desclassificada { background: var(--erro-bg); color: var(--erro); } .status-pill.desclassificada .dot { background: var(--erro); }
.escopo-acoes { display: flex; gap: 8px; flex-wrap: wrap; align-items: flex-start; margin-top: 12px; }
.btn-topo { display: inline-flex; align-items: center; gap: 7px; border: 1px solid var(--line); border-radius: var(--r-ctl); padding: 8px 14px; font-size: 0.84rem; font-weight: 600; color: var(--azul-escuro); background: var(--superficie); box-shadow: var(--sh); text-decoration: none; cursor: pointer; list-style: none; }
.btn-topo::-webkit-details-marker { display: none; }
.btn-topo:hover { background: var(--superficie-2); border-color: var(--borda); }
.esc-geral { margin-top: 0; }
/* aberta, a dúvida geral desce para a própria linha e usa a largura toda
   (o details fecha em shrink-to-fit — sem isso a caixa encolhia ao botão) */
.escopo-acoes .esc-geral[open] { flex: 1 1 100%; }
.esc-geral .esc-box { margin-top: 8px; max-width: none; width: 100%; box-sizing: border-box; }  /* PO 07/08: caixa pequena */

/* Avisos como cartão com ícone (reaberta / pendente / leitura / prazo) */
.aviso-card { display: flex; gap: 14px; align-items: center; border-radius: 12px; padding: 14px 16px; margin-bottom: 14px; }
.aviso-ic { flex: none; width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 1.2rem; }
.aviso-txt { flex: 1; }
.aviso-txt strong { display: block; font-size: 0.98rem; margin-bottom: 2px; }
.aviso-meta { font-size: 0.86rem; color: var(--texto-2); }
.aviso-meta b { color: inherit; font-weight: 700; }
.aviso-card .botao { flex: none; }
.aviso-pendente { background: var(--info-bg); border: 1px solid var(--info-borda); }
.aviso-pendente .aviso-ic { background: var(--info-bg); } .aviso-pendente .aviso-txt strong { color: var(--azul-escuro); }
.aviso-reaberta { background: var(--alerta-bg); border: 1px solid var(--alerta-borda); }
.aviso-reaberta .aviso-ic { background: #F7E3C6; } .aviso-reaberta .aviso-txt strong { color: var(--alerta-fg); }
/* Variante de APROVACAO: mensagem positiva pedia cor positiva. Usar o ambar
   de 'atencao' para dizer 'esta tudo certo' fazia a cor contradizer o texto
   (apontamento do PO). */
.aviso-ok { background: var(--ok-bg); border: 1px solid var(--ok-borda); }
.aviso-ok .aviso-ic { background: var(--ok-bg); color: var(--ok-fg); }
.aviso-ok .aviso-txt strong { color: var(--ok-fg); }
.aviso-leitura { background: var(--alerta-bg); border: 1px solid var(--alerta-borda); }
.aviso-leitura .aviso-ic { background: #F7E9CC; } .aviso-leitura .aviso-txt strong { color: var(--alerta-fg); }
/* Desfecho NEGATIVO (desclassificada). Mesma pele vermelha do prazo, nome
   proprio: o proximo leitor nao deve procurar prazo aqui. Nasceu porque a
   desclassificacao vinha com selo verde de "tudo certo" e a cor contradizia o
   texto — mesmo defeito que o PO ja apontara ao contrario. */
.aviso-encerrado { background: var(--erro-bg); border: 1px solid var(--erro-borda); }
.aviso-encerrado .aviso-ic { background: #F7D5D0; } .aviso-encerrado .aviso-txt strong { color: var(--erro); }
.aviso-prazo { background: var(--erro-bg); border: 1px solid var(--erro-borda); }
.aviso-prazo .aviso-ic { background: #F7D5D0; } .aviso-prazo .aviso-txt strong { color: var(--erro); }
.reab-tipo { display: flex; gap: 0.6rem; align-items: flex-start; padding: 8px 4px; font-weight: 400; cursor: pointer; }
.reab-tipo input { margin-top: 4px; }
.obs-reabertura { color: var(--cinza); font-size: 0.85rem; margin-top: 8px; }

/* Balão in-platform (tooltip) + botão desabilitado (feedback do PO, Fase 3b) */
.botao-desabilitado { background: #E3E8EE; color: var(--cinza); cursor: not-allowed; }
.tooltip-wrap { position: relative; display: inline-block; outline: none; }
.tooltip-balao { position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); margin-bottom: 9px; background: var(--azul-sup-hover); color: var(--texto-inv); font-size: 0.8rem; line-height: 1.35; padding: 9px 12px; border-radius: 8px; width: max-content; max-width: 250px; opacity: 0; visibility: hidden; transition: opacity .15s; z-index: 20; box-shadow: 0 3px 10px rgba(20,71,111,.25); text-align: left; }
.tooltip-balao::after { content: ""; position: absolute; top: 100%; left: 50%; transform: translateX(-50%); border: 6px solid transparent; border-top-color: var(--azul-escuro); }
.tooltip-wrap:hover .tooltip-balao, .tooltip-wrap:focus .tooltip-balao, .tooltip-wrap:focus-within .tooltip-balao { opacity: 1; visibility: visible; }

/* Painel do admin (Fase 4) — lista de projetos */
.painel-filtros { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: flex-end; background: var(--superficie-2); border: 1px solid var(--borda); border-radius: 10px; padding: 12px 14px; margin-bottom: 14px; }
.painel-filtros label { margin-bottom: 0; display: flex; flex-direction: column; gap: 3px; font-size: 0.72rem; color: var(--cinza); text-transform: uppercase; letter-spacing: .02em; }
.painel-filtros input, .painel-filtros select { margin: 0; padding: 5px 8px; font-size: 0.85rem; }
.painel-filtros input[type="number"] { width: 78px; }
.painel-filtros input[type="search"] { width: 150px; }
.painel-filtros .botao { align-self: flex-end; }
/* A .painel-tabela (o painel antes de virar quadro, Fase 9) e os .badge-st/
   .dash-topo que a acompanhavam sairam na faxina da Fase 15. */
.painel-vazio-filtro { color: var(--cinza); padding: 14px 4px; }

/* Painel — cabeçalho de página (breadcrumb + título + ações) */
.phead { display: flex; align-items: flex-end; justify-content: space-between; flex-wrap: wrap; gap: 14px; margin-bottom: 22px; }
.phead .bc { display: flex; align-items: center; gap: 6px; font-size: 0.78rem; color: var(--faint); font-weight: 600; margin-bottom: 8px; }
.phead .bc a { color: var(--cinza); text-decoration: none; } .phead .bc a:hover { color: var(--azul); }
.phead .bc span { color: var(--texto-2); }
.phead h1 { margin: 0; }
.phead .psub { margin: 5px 0 0; color: var(--cinza); font-size: 0.9rem; }
.phead .pbtns { display: flex; gap: 10px; flex-wrap: wrap; }

/* Painel — drill-down do projeto */
.tiles { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin: 4px 0 20px; }
/* Fase 15.7: o quadro do processo ficou com 3 KPIs (menor total e aderencia
   media foram para a visao irma). Sem isto, o 4o slot vazio deixava um buraco
   na fileira. */
.tiles-3 { grid-template-columns: repeat(3, 1fr); }
/* KPI compacto (feedback do PO: tile alto com vazio dentro): ícone à ESQUERDA,
   rótulo + número à direita — o mesmo conteúdo em ~1/3 da altura. */
.tile { min-width: 0; background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--r-lg);
  padding: var(--sp-4) 18px; box-shadow: var(--sh);
  display: grid; grid-template-columns: auto 1fr; column-gap: 14px; align-items: center; }
.tile-val { overflow-wrap: anywhere; grid-column: 2; }
.tile-rot { grid-column: 2; }
/* tiles sem ícone (resumo do cliente): texto ocupa a largura toda */
.tile > .tile-rot:first-child, .tile > .tile-rot:first-child + .tile-val { grid-column: 1 / -1; }
.tile-chip { width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center;
  margin-bottom: 0; grid-row: 1 / span 2; }
.tile-chip svg { width: 19px; height: 19px; stroke: currentColor; stroke-width: 1.9; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.tile-chip.b { background: var(--info-bg); color: var(--azul); }
.tile-chip.g { background: var(--ok-bg); color: var(--ok); }
.tile-chip.o { background: #FCF0E1; color: var(--accent); }
.tile-chip.r { background: var(--erro-bg); color: var(--erro); }
.tile-rot { font-size: 0.75rem; color: var(--cinza); font-weight: 600; }
.tile-val { font-size: 1.6rem; font-weight: 800; letter-spacing: -0.02em; color: var(--navy); margin-top: 2px; font-variant-numeric: tabular-nums; }
.tile.flag .tile-val { color: var(--erro); }
/* PO 08/08: o comparativo ficava espremido (988px, com rolagem horizontal)
   enquanto as red flags levavam 623px. As flags são cartões de texto e leem
   bem estreitas: ganham faixa contida e o comparativo fica com o resto.
   minmax(0,1fr) na 1ª coluna: sem o 0, o conteúdo largo da tabela impede o
   grid de encolher a coluna. Em ≤900px o grid vira 1 coluna (mobile intacto). */
.grid2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 360px); gap: 16px; align-items: start; }
.grid2 > * { min-width: 0; }  /* impede que tabelas largas estourem a largura */
.grid2-eq { grid-template-columns: 1fr 1fr; align-items: stretch; }  /* par de gráficos: blocos do MESMO tamanho, mesmo quando um tem nota */
.painel-bloco { background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--r-lg); padding: var(--sp-5) var(--sp-5); margin-bottom: var(--sp-4); box-shadow: var(--sh); }
.painel-bloco h2 { margin: 0 0 var(--sp-4); font-size: 1.02rem; letter-spacing: -.01em; }
.tab-scroll { overflow-x: auto; }
table.comp { width: 100%; border-collapse: collapse; font-size: 0.9rem; }
/* rótulo da dimensão (Bloco) pequeno e discreto; EMPRESAS com peso — são as
   protagonistas da comparação */
table.comp th { color: var(--faint); text-align: right; padding: 10px 12px; white-space: nowrap; border-bottom: 2px solid var(--line-in); font-size: 0.7rem; text-transform: uppercase; letter-spacing: .05em; font-weight: 700; background: var(--superficie-2); }
table.comp th:first-child { text-align: left; border-radius: 10px 0 0 0; }
table.comp th:last-child { border-radius: 0 10px 0 0; }
table.comp th:not(:first-child) { color: var(--navy); font-size: .86rem; text-transform: none; letter-spacing: 0; }
/* selos do cabecalho: menor total / vencedora / desclassificada */
table.comp th .th-pill { display: inline-block; margin-left: 7px; padding: 2px 9px; border-radius: 999px; font-size: .64rem; letter-spacing: .03em; vertical-align: 1px; }
.th-pill.menor { background: var(--ok-bg); color: var(--ok-fg); }
.th-pill.win { background: var(--alerta-bg); color: var(--alerta-fg); }
.th-pill.out { background: var(--erro-bg); color: var(--erro-fg); }
.th-pill.envios { background: var(--info-bg); color: var(--info-fg); }
table.comp td { padding: 12px; text-align: right; border-bottom: 1px solid var(--line2); white-space: nowrap; font-variant-numeric: tabular-nums; }
/* zebra sutil + divisor fino entre as colunas de valores */
table.comp tbody tr:nth-child(even) td { background: var(--superficie-2); }
table.comp td:not(:first-child), table.comp th:not(:first-child) { border-left: 1px solid var(--borda); }
table.comp td.cel-bloco, table.comp td.cel-item { text-align: left; font-weight: 600; color: var(--navy); }
table.comp td.cel-item small { color: var(--cinza); font-weight: 400; }
table.comp tbody tr:hover td { background: var(--superficie-2); }
/* menor da linha: check + verde, SEM pintar a celula (o colunao verde
   empilhado parecia planilha — queixa do PO) */
table.comp td.min { color: var(--ok); font-weight: 700; }
table.comp td.min::before { content: "✓"; margin-right: 7px; font-weight: 800; opacity: .85; }
/* no TOTAL o vencedor recebe o preenchimento — um destaque so, com forca */
/* total como FAIXA de fechamento (zebra não alcança: regra depois vence) */
table.comp tr.total td { background: var(--superficie-2); border-top: 2px solid var(--line-in); border-bottom: 0; font-weight: 800; color: var(--navy); font-size: 1.02rem; padding: 14px 12px; }
table.comp tr.total td.min { background: var(--ok-bg); }
table.comp tr.rswp td { background: transparent; color: var(--texto-2); font-size: .8rem; padding: 7px 12px; border-bottom: 0; }
table.comp tr.rswp td:first-child { text-transform: uppercase; letter-spacing: .04em; font-size: .68rem; font-weight: 700; color: var(--faint); }
/* Fase 14: o "NA" da celula e marcador de desvio — sobe junto para AA */
.cel-na { color: var(--alerta-fg); font-weight: 700; }
.flags { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 9px; }
.flags li { display: flex; gap: 11px; align-items: flex-start; padding: 11px 12px; border-radius: 12px; font-size: 0.85rem; line-height: 1.4; border: 1px solid; border-left-width: var(--flag-ac-w); }
.flags li.r { background: var(--flag-r-bg); border-color: var(--flag-r-borda); border-left-color: var(--flag-r-ac); }
.flags li.o { background: var(--flag-o-bg); border-color: var(--flag-o-borda); border-left-color: var(--flag-o-ac); }
.flags .fic { width: 28px; height: 28px; border-radius: 8px; display: grid; place-items: center; flex: none; }
.flags .fic svg { width: 15px; height: 15px; stroke: currentColor; stroke-width: 2; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.flags li.r .fic { background: var(--flag-r-chip); color: var(--flag-r-ic); }
.flags li.o .fic { background: var(--flag-o-chip); color: var(--flag-o-ic); }
.flags b { color: var(--navy); }
.drill-bloco { border: 1px solid var(--borda); border-radius: 8px; margin-bottom: 8px; }
.drill-bloco > summary { cursor: pointer; padding: 8px 12px; font-weight: 600; color: var(--azul); }
.drill-bloco > summary small { color: var(--cinza); font-weight: 400; }
.drill-bloco .tab-scroll { padding: 0 12px 12px; }
.desvios { display: flex; flex-wrap: wrap; gap: 12px; }
.desvio-card { flex: 1 1 260px; border: 1px solid var(--borda); border-radius: 8px; padding: 10px 12px; }
.desvio-empresa { font-weight: 700; color: var(--azul-escuro); margin-bottom: 6px; }
.desvio-n { background: var(--alerta-bg); color: var(--alerta-fg); font-size: 0.72rem; font-weight: 700; border-radius: 999px; padding: 1px 8px; margin-left: 6px; }
.desvio-card ul { margin: 0; padding-left: 18px; font-size: 0.82rem; color: var(--texto-2); }
/* Fase 14: resumo de desvios por bloco no topo da analise. Chips por item com
   o PAR de tokens das flags (severidade vem do dado; nada de emoji na UI). */
.desvios-topo > summary small { color: var(--texto-2); }
.desvios-topo .check-explica { padding: 0 12px; }
.desvios-topo .desvios, .desvios-topo .painel-vazio-filtro { padding: 0 12px 12px; }
.desvio-linha { margin: 4px 0; font-size: .84rem; color: var(--texto-2); line-height: 1.9; }
.desvio-item { display: inline-block; margin: 0 4px 0 2px; padding: 1px 8px; border-radius: 999px; font-size: .72rem; font-weight: 700; text-decoration: none; border: 1px solid; }
/* Texto do chip usa o PAR fg/bg do estado (AA nos 2 temas). A 1a escolha usava
   --flag-*-chip, que e FUNDO de icone das flags — como texto dava 1,2:1. */
.desvio-item.r { background: var(--erro-bg); color: var(--erro-fg); border-color: var(--erro-borda); }
.desvio-item.o { background: var(--alerta-bg); color: var(--alerta-fg); border-color: var(--alerta-borda); }
.desvio-analise { font-size: .78rem; margin-left: 6px; white-space: nowrap; }
.chart-box { position: relative; height: 280px; }
.chart-nota { color: var(--cinza); font-size: 0.8rem; margin-top: 8px; }
@media (max-width: 900px) {
  .grid2, .grid2-eq { grid-template-columns: 1fr; }
  .tiles, .tiles-3 { grid-template-columns: repeat(2, 1fr); }
  .phead { margin-bottom: 16px; }
}
/* Celular: tiles compactos (não podem tomar a tela toda) */
@media (max-width: 600px) {
  .tiles { gap: 10px; }
  .tile { padding: 10px 12px; column-gap: 10px; }
  .tile-chip { width: 30px; height: 30px; border-radius: 9px; }
  .tile-chip svg { width: 16px; height: 16px; }
  .tile-rot { font-size: 0.68rem; }
  .tile-val { font-size: 1.15rem; }
  .painel-bloco { padding: 14px; }
  .phead h1 { font-size: 1.25rem; }
}

/* Kanban de "Minhas RFPs" (fornecedor) */
/* Mesmo token do shell com barra lateral: um teto so para tela de trabalho,
   com ou sem a lateral. Era 1600px cravado -- mais um dos quatro valores que
   deixavam as telas desalinhadas. */
main.conteudo.largo { max-width: var(--larg-trabalho); }
/* Mesma correcao: #EEF0F2 era cravado e media 1,74 no escuro. */
.status-pill.nao-iniciada { background: var(--superficie-2); color: var(--cinza); } .status-pill.nao-iniciada .dot { background: var(--cinza); }
/* A que o PO apontou: fundo #FBF0CE cravado, texto --alerta-fg. No claro dava
   4,78, no limite; no ESCURO, 1,48 — pastilha clara com texto claro. As tres
   pills de cor crua vinham da Fase 13, com a nota de que ficavam para depois. */
/* ⚠️⚠️ 24/08 — A CONTEMPLADA SAI DO AMBAR E VAI PARA O VERDE. Decisao do PO.
   Ela usava --alerta-*, o MESMO ambar de `em_negociacao` e de `rascunho`: a
   proposta VENCEDORA aparecia na cor de "atencao", e tres status diferentes
   ficavam indistinguiveis de longe numa coluna de 9 cards.
   ⚠️ Mexe SO nesta regra, e por TOKEN (--ok-*, que ja existe medido nos dois
   temas). Nenhum token foi alterado, entao o modulo de BM — que compartilha
   este arquivo — nao e afetado. */
.status-pill.contemplada { background: var(--ok-bg); color: var(--ok-fg); } .status-pill.contemplada .dot { background: var(--ok); }
/* Fase 13 — estagios entre o envio e a adjudicacao. A classe vem do proprio
   valor do status, entao o nome tem underscore. Cor por token (as pills
   antigas ainda tem cor crua; nao mexo nelas nesta fase). */
.status-pill.tecnica_aprovada { background: var(--info-bg); color: var(--info-fg); }
.status-pill.tecnica_aprovada .dot { background: var(--azul); }
/* laranja sobre ambar deu 2,53 no claro (medido): o texto vai de --navy e o
   sinal laranja fica no ponto. */
.status-pill.em_negociacao { background: var(--alerta-bg); color: var(--navy); }
.status-pill.em_negociacao .dot { background: var(--acento); }

/* Opção 2: o quadro é uma SUPERFÍCIE própria (fundo do board, estilo Trello) */
.kanban { display: flex; gap: 14px; align-items: flex-start; overflow-x: auto; background: var(--board-bg); border: 1px solid var(--board-borda); border-radius: var(--r-lg); padding: var(--sp-4); }
/* Board: página travada na altura da tela; a SUPERFÍCIE preenche o espaço (colunas
   naturais em cima), então o board chega até o rodapé sem scroll vertical. */
@media (min-width: 901px) {
  .app:has(main.conteudo.board) { height: 100vh; overflow: hidden; }
  main.conteudo.board { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  /* PO 08/08: com muitos cards a coluna ESTOURAVA a tela em vez de rolar.
     Causa: `body.has-side main.conteudo` (0,2,2) vence `main.conteudo.board`
     (0,2,1) e impõe `flex: 1 0 auto` — flex-shrink 0 faz o main crescer até o
     conteúdo e furar o 100vh do .app, que corta o excedente no overflow:hidden.
     Aqui a especificidade é maior: o main volta a poder encolher e a rolagem
     acontece DENTRO da coluna (estilo Trello), como o desenho previa. */
  body.has-side main.conteudo.board { flex: 1 1 0%; min-height: 0; }
  .board > h1, .board > .home-hero { flex: none; }
  .board .kanban { flex: 1; min-height: 0; align-items: flex-start; }
  .board .kanban-col { max-height: 100%; }
  .board .kanban-col-corpo { overflow-y: auto; }
  /* A home da 15.6 nao e um quadro: e uma LISTA DE GRUPOS que cresce com o
     conteudo. O board trava a pagina em 100vh contando que algo la dentro
     role; o Kanban tinha isso (a coluna), a lista nao tinha nada -- e por
     isso transbordava por cima do rodape (apontamento do PO).
     A rolagem e do BLOCO, nao da pagina, como ele pediu: quem rola aqui e
     `.grupos-natureza`. Tudo o que vem antes dela (titulo, destaque, tiles,
     filtros) fica fixo no topo. */
  .board > .grupos-natureza { flex: 1; min-height: 0; overflow-y: auto; }
  .board > .tiles, .board > .painel-aguarda { flex: none; }
}
/* coluna de largura FIXA, como o Trello: em ultrawide as colunas NAO
   esticam (cards viravam tapetes — queixa do PO); o fundo do quadro usa a
   tela toda e sobra respiro a direita */
.kanban-col { flex: 0 0 330px; min-width: 330px; background: var(--board-col); border: 1px solid var(--borda); border-radius: 14px; display: flex; flex-direction: column; }
.kanban-col-cab { display: flex; align-items: center; gap: 8px; justify-content: space-between; padding: 12px 14px 9px; }
/* bolinha de status antes do título (referência ClientOS) */
.kanban-col-titulo { font-weight: 700; color: var(--azul-escuro); font-size: 0.85rem; display: flex; align-items: center; gap: 7px; }
.kanban-col-titulo::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--faint); }
.kanban-col:nth-child(1) .kanban-col-titulo::before { background: var(--faint); }
.kanban-col:nth-child(2) .kanban-col-titulo::before { background: var(--alerta); }
.kanban-col:nth-child(3) .kanban-col-titulo::before { background: var(--azul); }
.kanban-col:nth-child(4) .kanban-col-titulo::before { background: var(--laranja); }
.kanban-col:nth-child(5) .kanban-col-titulo::before { background: var(--ok); }
.kanban-col:nth-child(6) .kanban-col-titulo::before { background: var(--erro); }
.kanban-col-conta { background: var(--superficie); color: var(--cinza); font-size: 0.72rem; font-weight: 700; border-radius: 999px; padding: 1px 9px; border: 1px solid var(--line); }
.kanban-col-corpo { padding: 2px 8px 10px; display: flex; flex-direction: column; gap: 10px; min-height: 40px; }
.kanban-vazia { color: var(--texto-2); text-align: center; padding: 10px 0; font-size: 0.86rem; }

.card-rfp { background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--r-lg); padding: var(--sp-4) var(--sp-4) var(--sp-3); box-shadow: var(--sh); transition: transform .15s, box-shadow .15s, border-color .15s; }
.card-rfp:hover { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(20,71,111,.10); border-color: var(--borda); }
.card-rfp-topo { display: flex; flex-direction: column; gap: 8px; }
/* código do projeto no canto (estilo TSK7 do ClientOS): monoespaçado, discreto */
.card-rfp-cod { align-self: flex-start; font-family: ui-monospace, "SF Mono", monospace;
  font-size: .68rem; font-weight: 600; letter-spacing: .04em; color: var(--texto-2);
  background: var(--superficie-2); border: 1px solid var(--borda); border-radius: 999px;
  padding: 2px 9px; }
.card-rfp-titulo { font-weight: 700; color: var(--azul); line-height: 1.3; }
.card-rfp-titulo small { color: var(--cinza); font-weight: 500; display: block; margin-top: 1px; }
.card-rfp-topo .status-pill { align-self: flex-start; }
.card-rfp-projeto { color: var(--azul-escuro); font-size: 0.84rem; font-weight: 500; margin-top: 7px; }
.card-rfp-prazo { color: var(--cinza); font-size: 0.79rem; margin-top: 2px; }
.card-rfp-chip { margin-top: 9px; background: var(--alerta-bg); color: var(--alerta); font-size: 0.77rem; font-weight: 600; border-radius: 9px; padding: 6px 9px; }

.card-rfp-kpis { margin-top: 11px; border-top: 1px solid var(--line2); padding-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.card-rfp-kpis .kpi { display: flex; flex-direction: column; gap: 2px; }
.card-rfp-kpis .kpi-rot { font-size: 0.68rem; color: var(--faint); text-transform: uppercase; letter-spacing: .03em; font-weight: 600; }
.card-rfp-kpis .kpi-val { font-size: 0.85rem; font-weight: 700; color: var(--navy); font-variant-numeric: tabular-nums; }
.card-rfp-kpis .kpi-barra { display: block; height: 6px; border-radius: 999px; background: var(--borda); overflow: hidden; margin-top: 3px; }
.card-rfp-kpis .kpi-barra > span { display: block; height: 100%; background: linear-gradient(90deg, var(--laranja), #ED9E58); }
.card-rfp-kpis .kpi-linha { display: flex; gap: 14px; }
.card-rfp-kpis .kpi-linha .kpi { flex: 1; }

/* Card inteiro clicável (abre a proposta na etapa atual). As acoes em botao
   (.card-rfp-acoes) e o rodape "abrir" (.card-rfp-abrir) migraram para o
   quick-view e sairam na faxina da Fase 15. */
.card-rfp[data-href] { cursor: pointer; }
.card-rfp[data-href]:focus-visible { outline: 2px solid var(--azul); outline-offset: 2px; }

/* Quick-view da proposta — modal sobreposto (estética Trello) */
body.qv-open { overflow: hidden; }
/* Fase 15: o veu e a sombra usam o TOKEN. O literal estava cravado aqui, o
   que deixava o quick-view sem escurecer no tema escuro — o token existia
   justamente para isso e ninguem tinha plugado (achado da faxina). */
.qv-overlay { position: fixed; inset: 0; z-index: 80; display: flex; align-items: flex-start; justify-content: center; padding: 4vh 16px 4vh; background: var(--veu-modal); animation: qv-fade .15s ease; }
.qv-overlay[hidden] { display: none; }
@keyframes qv-fade { from { opacity: 0; } to { opacity: 1; } }
.qv-modal { position: relative; background: var(--superficie); border-radius: 16px; box-shadow: var(--sh-forte); width: 100%; max-width: 680px; max-height: 92vh; overflow-y: auto; padding: 28px 30px; animation: qv-pop .16s ease; }
@keyframes qv-pop { from { transform: translateY(8px) scale(.98); opacity: .5; } to { transform: none; opacity: 1; } }
.qv-close { position: absolute; top: 12px; right: 12px; width: 34px; height: 34px; border: 0; border-radius: 9px; background: var(--superficie-2); color: var(--cinza); display: grid; place-items: center; cursor: pointer; }
.qv-close:hover { background: var(--hover-suave); color: var(--navy); }
.qv-close svg { width: 18px; height: 18px; stroke: currentColor; stroke-width: 2; fill: none; stroke-linecap: round; }
.qv-head { padding-right: 34px; margin-bottom: 6px; }
.qv-head .status-pill { margin-bottom: 10px; }
.qv-title { margin: 0; font-size: 1.15rem; font-weight: 800; color: var(--navy); line-height: 1.3; }
.qv-title small { color: var(--cinza); font-weight: 500; }
.qv-meta { color: var(--cinza); font-size: 0.86rem; margin-top: 4px; }
.qv-body .card-rfp-kpis { margin-top: 14px; }

/* Quick-view completo: stat grid + subtotais + esclarecimentos */
.qv-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 16px; }
.qv-stat { background: var(--superficie-2); border: 1px solid var(--line); border-radius: 11px; padding: 10px 12px; display: flex; flex-direction: column; gap: 3px; }
.qv-lab { font-size: 0.68rem; text-transform: uppercase; letter-spacing: .03em; color: var(--faint); font-weight: 600; }
.qv-val { font-size: 0.95rem; font-weight: 700; color: var(--navy); font-variant-numeric: tabular-nums; }
.qv-val small { color: var(--cinza); font-weight: 500; font-size: 0.78rem; }
.qv-stat .kpi-barra { margin-top: 4px; }
.qv-sec { margin-top: 16px; }
.qv-sec-tit { font-size: 0.75rem; text-transform: uppercase; letter-spacing: .03em; color: var(--faint); font-weight: 700; margin-bottom: 8px; }
.qv-blocos { display: flex; flex-direction: column; }
.qv-bloco-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 7px 2px; border-bottom: 1px solid var(--line2); font-size: 0.87rem; }
.qv-bloco-row:last-child { border-bottom: none; }
.qv-bl-nome { color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qv-bl-val { font-weight: 700; color: var(--navy); font-variant-numeric: tabular-nums; white-space: nowrap; }
.qv-esc { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.qv-esc li { font-size: 0.85rem; color: var(--ink); display: flex; gap: 6px; align-items: baseline; }
.qv-esc b { color: var(--azul-escuro); font-weight: 700; }
.qv-esc-st { margin-left: auto; font-size: 0.68rem; font-weight: 700; text-transform: uppercase; border-radius: 999px; padding: 1px 8px; flex: none; }
.qv-esc-st.aberta { background: var(--alerta-bg); color: var(--alerta); }
.qv-esc-st.respondida { background: var(--ok-bg); color: var(--ok); }
.qv-esc-mais { color: var(--cinza); font-size: 0.8rem; }
.qv-vazio { color: var(--cinza); font-size: 0.9rem; margin-top: 14px; }
.qv-actions { margin-top: 18px; display: flex; flex-wrap: wrap; gap: 10px; }

@media (max-width: 900px) {
  .kanban { flex-direction: column; overflow-x: visible; }
  .kanban-col { flex: 1 1 auto; width: 100%; }
}

/* ===== Redesign v4 — shell de app (sidebar) e shell público ===== */
.app { display: flex; min-height: 100vh; align-items: stretch; }
/* largura única da lateral: a barra fixa do total se apoia nela (não pode
   tapar o "Sair"), então os dois valores precisam sair do mesmo lugar */
:root {
  --side-w: 236px;
  /* Larguras do shell com barra lateral. Sao DUAS, de proposito:
     - `--larg-trabalho`: toda tela de trabalho do admin (painel, quadro geral,
       processo, comparativo, analise, comercial, saneamento, vista integral).
       Valor vem do tamanho natural das colunas do quadro, que e o conteudo
       mais largo do portal.
     - `--larg-leitura`: telas de texto corrido, onde linha longa PIORA a
       leitura (escopo, formularios simples).
     Nao criar uma terceira. Foi a proliferacao de tetos (1720/1980/2150) que
     deixou o Painel largo e a tela do projeto encolhida -- apontamento do PO
     na validacao da Fase 15. */
  --larg-trabalho: 2150px;
  --larg-leitura: 1180px;
}
html.side-collapsed { --side-w: 66px; }
.side { width: var(--side-w); flex: none; background: var(--moldura); color: var(--texto-sobre-moldura); display: flex; flex-direction: column; padding: 16px 12px; position: sticky; top: 0; height: 100vh; overflow-y: auto; }
.side-brand { display: block; padding: 8px 8px 18px; }
.side-brand img { display: block; height: 38px; width: auto; }
.side .navlab { font-size: .64rem; text-transform: uppercase; letter-spacing: .1em; color: #5A7191; padding: 14px 10px 6px; font-weight: 700; }
.side-nav { display: flex; flex-direction: column; gap: 2px; }
.side-nav a { position: relative; display: flex; align-items: center; gap: 11px; padding: 9px 11px; border-radius: 10px; color: var(--texto-sobre-moldura); text-decoration: none; font-weight: 500; font-size: .9rem; transition: .13s; }
.side-nav a:hover { background: rgba(255,255,255,.06); color: var(--texto-inv); }
/* item ativo: preenchimento azul-marca + barra de acento laranja à esquerda */
.side-nav a.on { background: linear-gradient(90deg, rgba(232,128,37,.16), rgba(255,255,255,.06)); color: var(--texto-inv); font-weight: 600; }
.side-nav a.on::before { content: ""; position: absolute; left: -12px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 20px; border-radius: 0 3px 3px 0; background: var(--accent); }
.side-nav a.on .ic { color: var(--accent); }
.side .ic { width: 18px; height: 18px; stroke: currentColor; stroke-width: 1.9; fill: none; stroke-linecap: round; stroke-linejoin: round; flex: none; }
/* Menu de conta (Fase 8): gatilho no rodapé + dropdown que abre para cima */
.side-account { margin-top: auto; position: relative; }
.su-trigger { width: 100%; display: flex; align-items: center; gap: 10px; padding: 9px;
  border: 0; border-radius: 11px; background: rgba(255,255,255,.04); color: inherit;
  cursor: pointer; font: inherit; text-align: left; }
.su-trigger:hover { background: rgba(255,255,255,.08); }
.side-account.on .su-trigger { background: rgba(255,255,255,.12); }
.side-avatar { width: 32px; height: 32px; border-radius: 8px; background: var(--azul-sup); display: grid; place-items: center; color: var(--texto-inv); font-weight: 700; font-size: .8rem; flex: none; }
.su-info { min-width: 0; flex: 1; }
.su-nm { font-size: .82rem; color: var(--texto-inv); font-weight: 600; line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.su-rl { font-size: .69rem; color: var(--texto-sobre-moldura); }
.su-chev { width: 16px; height: 16px; flex: none; stroke: #6C7F96; stroke-width: 2; fill: none;
  stroke-linecap: round; stroke-linejoin: round; transition: transform .15s; }
.su-trigger[aria-expanded="true"] .su-chev { transform: rotate(180deg); }
.su-menu { position: absolute; left: 0; right: 0; bottom: calc(100% + 6px);
  background: #12283F; border: 1px solid rgba(255,255,255,.1); border-radius: 11px;
  padding: 5px; box-shadow: 0 12px 30px rgba(0,0,0,.4); z-index: 20; }
.su-menu a, .su-menu button { width: 100%; display: flex; align-items: center; gap: 9px;
  padding: 8px 10px; border: 0; border-radius: 8px; background: transparent;
  color: #C4D2E2; font: inherit; font-size: .85rem; text-decoration: none; cursor: pointer; text-align: left; }
.su-menu a:hover, .su-menu button:hover { background: rgba(255,255,255,.08); color: var(--texto-inv); }
.su-menu svg { width: 16px; height: 16px; flex: none; stroke: currentColor; stroke-width: 1.9;
  fill: none; stroke-linecap: round; stroke-linejoin: round; }
.su-menu form { margin: 4px 0 0; padding-top: 4px; border-top: 1px solid rgba(255,255,255,.08); }

/* REGRA UNIVERSAL (PO): em qualquer tela logada, o conteúdo fica num painel
   claro CENTRADO; o que sobrar dos lados em telas largas preenche com o navy
   da barra — moldura simétrica, para nenhum perfil ver conteúdo "encostado". */
.main { flex: 1; min-width: 0; display: flex; flex-direction: column; overflow-x: clip; background: var(--moldura); }
.topbar { height: 56px; display: flex; align-items: center; gap: 12px; padding: 0 20px; border-bottom: 1px solid var(--line); background: rgba(255,255,255,.9); position: sticky; top: 0; z-index: 20; }
/* No desktop a topbar fica vazia (marca/nav na sidebar) — esconde a faixa branca */
@media (min-width: 901px) { .topbar { display: none; } }
.side-toggle { display: none; background: var(--superficie); border: 1px solid var(--line); border-radius: 9px; width: 38px; height: 38px; place-items: center; cursor: pointer; color: var(--cinza); }
.side-toggle:hover { color: var(--azul); border-color: var(--borda); }
.side-toggle .ic { width: 20px; height: 20px; stroke: currentColor; stroke-width: 2; fill: none; stroke-linecap: round; }
.tb-logo { display: none; }
.tb-logo img { display: block; }

/* Topo da barra: logo (completo/símbolo) + seta de recolher */
.side-top { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 2px 4px 12px; }
.side-brand { display: flex; align-items: center; }
.side-brand .brand-full { display: block; height: 34px; width: auto; }
.side-brand .brand-mark { display: none; width: 30px; height: 30px; }
.side-collapse { flex: none; width: 28px; height: 28px; display: grid; place-items: center; border: 0; border-radius: 8px; background: rgba(255,255,255,.06); color: var(--texto-sobre-moldura); cursor: pointer; }
.side-collapse:hover { background: rgba(255,255,255,.14); color: var(--texto-inv); }
.side-collapse .chev { width: 18px; height: 18px; stroke: currentColor; stroke-width: 2; fill: none; stroke-linecap: round; stroke-linejoin: round; transition: transform .15s; }

/* Desktop: rail recolhido (só símbolo do logo + ícones) — estilo Trello */
@media (min-width: 901px) {
  html.side-collapsed .side { padding: 16px 10px; }  /* largura vem de --side-w */
  html.side-collapsed .side-top { flex-direction: column; gap: 10px; padding: 2px 0 12px; }
  html.side-collapsed .brand-full { display: none; }
  html.side-collapsed .brand-mark { display: block; }
  html.side-collapsed .side-collapse .chev { transform: rotate(180deg); }
  html.side-collapsed .navlab { display: none; }
  html.side-collapsed .side-nav a { justify-content: center; gap: 0; padding: 9px; }
  html.side-collapsed .side-nav .lbl,
  html.side-collapsed .side-nav .badge { display: none; }
  html.side-collapsed .su-trigger { justify-content: center; padding: 8px 0; }
  html.side-collapsed .su-info, html.side-collapsed .su-chev { display: none; }
  /* recolhido: o menu estoura a largura do rail e o overflow da barra o
     CORTAVA (aparecia "por baixo" do navy — PO, 07/08). position:fixed escapa
     do clip: o containing block passa a ser a viewport. */
  html.side-collapsed .su-menu { position: fixed; left: 10px; right: auto; bottom: 70px; min-width: 190px; }
  /* rail e moldura são o mesmo navy; sem um traço, recolhido "parece que a
     barra continua lá" (PO, 07/08) */
  html.side-collapsed .side { border-right: 1px solid rgba(255,255,255,.09); }
/* PO 08/08: no escuro o rail se confundia com o painel — a separação
   passa a existir sempre, não só com a barra recolhida. */
.side { border-right: 1px solid rgba(255,255,255,.10); }

  /* A barra fixa do total do escopo é `left: 0` e atravessava por cima da
     barra lateral, tapando o bloco do usuário e o "Sair". No desktop ela
     começa depois da lateral; no mobile a lateral é gaveta, então segue 0. */
  body.has-side .rodape-total { left: var(--side-w); }
}

body.has-side main.conteudo { max-width: var(--larg-leitura); margin: 0 auto;
  padding: 26px 30px; width: 100%; background: var(--fundo); flex: 1 0 auto; }
/* ⚠️ UMA largura para TODA tela de trabalho do admin (PO, validação da 15:
   "padronize todas as telas para mesma largura").

   Aqui havia QUATRO tetos, cada um nascido de um pedido diferente e todos
   certos isoladamente: `largo` 1720, `comparativo` 1980 (a tabela cabia sem
   rolar), `board` 2150 (tamanho natural das colunas). O efeito somado era o
   que ele viu: o Painel largo e a tela do projeto encolhida, com margens
   enormes dos lados — e eu vinha corrigindo caso a caso, o que só trocava
   qual par ficava desalinhado.

   Agora é um token só. Mexer nele move todas as telas juntas; acrescentar um
   quinto teto para uma tela específica é reabrir exatamente este defeito. */
body.has-side main.conteudo.largo,
body.has-side main.conteudo.comparativo,
body.has-side main.conteudo.board { max-width: var(--larg-trabalho); padding: 22px 22px; }
/* Recolher a barra tem de DAR espaço (PO, 07/08): o painel claro absorve a
   largura liberada (236−66px) em vez de só engordar a moldura navy. Vale para
   a tela de LEITURA; as de trabalho já usam o teto único, que não muda. */
html.side-collapsed body.has-side main.conteudo { max-width: 1350px; }
html.side-collapsed body.has-side main.conteudo.largo,
html.side-collapsed body.has-side main.conteudo.comparativo,
html.side-collapsed body.has-side main.conteudo.board { max-width: var(--larg-trabalho); }

/* Scrollbars finas e modernas (estilo Trello) */
* { scrollbar-width: thin; scrollbar-color: #C4CED9 transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #C4CED9; border-radius: 999px; border: 2px solid transparent; background-clip: content-box; }
::-webkit-scrollbar-thumb:hover { background: #A9B6C6; }
/* Barra escura dentro da sidebar navy */
.side::-webkit-scrollbar-thumb { background: rgba(255,255,255,.16); }
body.has-side footer.rodape { padding: 14px 30px 20px; margin-top: 0; color: #7E93AB; }
body.has-side footer.rodape .acesso-info { color: #A7B8CB; }
.side-bd { display: none; }

@media (max-width: 900px) {
  .side { position: fixed; left: 0; top: 0; z-index: 60; transform: translateX(-100%); transition: transform .2s; box-shadow: 0 10px 40px rgba(0,0,0,.3); }
  body.side-open .side { transform: translateX(0); }
  .side-bd { display: block; position: fixed; inset: 0; background: rgba(8,20,36,.5); z-index: 50; opacity: 0; visibility: hidden; transition: opacity .2s; }
  body.side-open .side-bd { opacity: 1; visibility: visible; }
  .side-toggle { display: grid; }
  .side-collapse { display: none; }  /* rail é só desktop */
  /* Drawer: 100dvh (nao 100vh) para o rodape com o Sair ficar visivel sem rolar */
  .side { width: 250px; height: 100dvh; padding-bottom: 22px; }
  .tb-logo { display: block; }
  body.has-side main.conteudo { padding: 18px 16px; }
  /* No mobile a topbar vira barra escura (navy), como a sidebar — o logo branco aparece */
  .topbar { background: #0C2036; border-bottom: none; }
  .side-toggle { background: rgba(255,255,255,.12); border-color: transparent; color: var(--texto-inv); }
  .side-toggle:hover { background: rgba(255,255,255,.22); color: var(--texto-inv); }
}

/* Shell público (login, senha, convite, bloqueado) */
.public { min-height: 100vh; display: flex; flex-direction: column; }
.public-top { display: flex; align-items: center; justify-content: center; padding: 34px 20px 4px; }
/* logotipo real da marca: colorido no claro, branco no escuro (auth-dark) */
.pt-marca { height: 46px; width: auto; display: block; }
.pt-marca-branca { display: none; }
body.auth-dark .pt-marca-cor { display: none; }
body.auth-dark .pt-marca-branca { display: block; }
body.is-public main.conteudo { flex: 1; max-width: 620px; margin: 0 auto; padding: 14px 20px 40px; width: 100%; }
body.is-public footer.rodape { margin: 8px 0 20px; }

/* ===== Fase 5 — marca d'água forense (§12) ===== */
.marca-dagua { position: absolute; inset: 0; z-index: 9000; pointer-events: none; overflow: hidden;
  transform: rotate(-42deg); transform-origin: center; opacity: 0.05; }
.marca-dagua .mw-row { white-space: nowrap; line-height: 3.6; }
/* padrão "tijolo": linhas pares começam ~meia frase deslocadas (menos repetitivo) */
.marca-dagua .mw-row:nth-child(even) { margin-left: -17em; }
.marca-dagua .mw-t { color: var(--marca-dagua); font-size: 12.5px; font-weight: 600; padding: 0 44px; letter-spacing: .02em; user-select: none; }
@media print {
  .marca-dagua { opacity: 0.22; position: fixed; }
}

/* ===== Fase 5 — atrito de cópia (§12 medida 4) ===== */
main.conteudo.confidencial, .escopo { -webkit-user-select: none; user-select: none; }
/* campos do fornecedor seguem livres */
main.conteudo.confidencial input, main.conteudo.confidencial textarea,
main.conteudo.confidencial [contenteditable="true"],
.escopo input, .escopo textarea { -webkit-user-select: text; user-select: text; }

.print-aviso { display: none; }
@media print {
  .side, .topbar, footer.rodape { display: none !important; }
  main.conteudo.confidencial > *:not(.marca-dagua):not(.print-aviso) { display: none !important; }
  .print-aviso { display: block !important; text-align: center; padding: 26vh 24px 0; color: var(--texto-2); }
  .print-aviso strong { font-size: 1.25rem; }
  .print-aviso p { margin-top: 12px; color: var(--texto-2); }
  .print-aviso .pa-id { color: var(--texto-2); margin-top: 20px; font-size: .9rem; }
  .marca-dagua { display: flex !important; opacity: 0.22; }
}

/* ===== §12 medida 3 — atividade de leitura do escopo (painel) ===== */
.leituras { display: flex; flex-direction: column; gap: 12px; }
.leitura-card { border: 1px solid var(--borda); border-radius: var(--r-lg); padding: var(--sp-4) var(--sp-4); }
/* destaque, NÃO veredito: chama o olho sem rotular de "suspeito" */
.leitura-card.atipico { border-color: var(--alerta-borda); background: var(--alerta-bg); }
.lc-cab { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.lc-emp { font-weight: 700; color: var(--navy); }
.lc-tag { font-size: .7rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--alerta-fg); background: #FBEBC8; border-radius: 999px; padding: 3px 9px; }
.lc-nums { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 8px; margin-bottom: 12px; }
/* cada métrica é um bloco fechado: sem isso viram uma tira de textos soltos
   quando a grade colapsa numa coluna só (celular) */
.lc-nums > div { display: flex; flex-direction: column; justify-content: center;
  background: var(--superficie-2); border-radius: 10px; padding: 9px 11px; min-height: 58px; }
.leitura-card.atipico .lc-nums > div { background: #FDF7EA; }
.lc-nums b { font-size: 1.15rem; color: var(--navy); line-height: 1.2; }
.lc-nums span { font-size: .74rem; color: var(--cinza); line-height: 1.3; }
.lc-nums small { display: block; color: var(--texto-2); }
.lc-quem { width: 100%; border-collapse: collapse; font-size: .82rem; }
.lc-quem th { text-align: left; font-size: .7rem; text-transform: uppercase;
  letter-spacing: .04em; color: var(--cinza); border-bottom: 1px solid var(--line); padding: 5px 6px; }
.lc-quem td { padding: 6px; border-bottom: 1px solid var(--borda); vertical-align: top; }
.lc-quem small { display: block; color: var(--cinza); }
.lc-ips .ip { display: inline-block; font-family: ui-monospace, monospace; font-size: .76rem;
  background: var(--superficie-2); border-radius: 6px; padding: 2px 7px; margin: 0 4px 4px 0; }
.lc-ips .ip i { color: var(--cinza); font-style: normal; }
@media (max-width: 640px) {
  /* 2 colunas fixas: o auto-fit colapsa para 1 no celular e vira uma tira
     vertical de 6 blocos. A janela de datas é larga e ocupa a linha toda. */
  .lc-nums { grid-template-columns: 1fr 1fr; }
  .lc-nums .lc-janela { grid-column: 1 / -1; }

  .lc-quem, .lc-quem tbody, .lc-quem tr, .lc-quem td { display: block; }
  .lc-quem thead { display: none; }
  .lc-quem tr { padding: 10px 0; border-bottom: 1px solid var(--line); }
  .lc-quem tr:last-child { border-bottom: 0; }
  .lc-quem td { border: 0; padding: 3px 0; }
  /* o cabeçalho some no celular: sem este rótulo o número fica órfão */
  .lc-quem td[data-rot]::before { content: attr(data-rot); display: block;
    font-size: .66rem; text-transform: uppercase; letter-spacing: .05em;
    color: var(--cinza); margin-top: 6px; }
}
.lc-quem .lc-falha { color: var(--erro-fg); font-weight: 600; }

/* ===== Painel — registros (espelho do log, decisão do PO) ===== */
.log-abas { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 14px; }
.log-abas a { display: flex; align-items: center; gap: 7px; padding: 8px 14px;
  border: 1px solid var(--line); border-radius: 999px; background: var(--superficie);
  color: var(--navy); text-decoration: none; font-weight: 600; font-size: .84rem; }
.log-abas a span { font-size: .72rem; color: var(--cinza); background: var(--superficie-2);
  border-radius: 999px; padding: 1px 8px; }
.log-abas a.on { background: var(--navy); color: var(--texto-inv); border-color: var(--navy); }
.log-abas a.on span { background: rgba(255,255,255,.18); color: var(--texto-inv); }
.log-filtros { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px;
  background: var(--superficie); border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 12px 14px; margin-bottom: 14px; }
/* margin-bottom: 0 anula a regra global `form label` (0.3rem): ela empurrava
   a caixa do rotulo para cima e o botao Filtrar ficava ~5px mais baixo. */
.log-filtros label { margin-bottom: 0; display: flex; flex-direction: column; gap: 4px;
  font-size: .7rem; text-transform: uppercase; letter-spacing: .04em; color: var(--cinza); }
.log-filtros input, .log-filtros select { border: 1px solid var(--line-in);
  border-radius: var(--r-ctl); padding: .45rem .6rem; font: inherit; font-size: .85rem; }
/* Filtrar + Limpar como um par: o align-self:center do Limpar o fazia
   flutuar acima do botao (o bloco de filtros e mais alto que ele). */
.log-acoes { display: flex; align-items: center; gap: 14px; }
.log-tab { width: 100%; border-collapse: collapse; font-size: .82rem; }
.log-tab th { text-align: left; padding: 0 10px 10px; color: var(--faint);
  font-size: .7rem; text-transform: uppercase; letter-spacing: .05em; font-weight: 700;
  border-bottom: 1px solid var(--line); white-space: nowrap; }
.log-tab td { text-align: left; vertical-align: top; padding: 9px 10px;
  border-bottom: 1px solid var(--line2); }
.log-ts, .log-ip, .log-ua { font-family: ui-monospace, monospace; font-size: .76rem; white-space: nowrap; }
.log-ua { color: var(--cinza); white-space: normal; }
.log-obj { color: var(--texto-2); }
.log-acao { background: var(--info-bg); color: var(--info-fg); border-radius: 6px;
  padding: 2px 8px; font-size: .74rem; font-weight: 600; white-space: nowrap; }
.log-aberta { color: var(--alerta-fg); font-size: .76rem; }
.log-bloqueio { background: #FDF1F1; }
.log-tab small { display: block; color: var(--cinza); font-size: .72rem; }
.log-pag { display: flex; align-items: center; justify-content: center; gap: 14px;
  margin-top: 12px; font-size: .82rem; color: var(--cinza); }
@media (max-width: 640px) { .log-filtros label { flex: 1 1 100%; } }

/* ===== Fase 6 — quadro do contratante (reusa .kanban/.card-rfp) ===== */
/* o card virou <a>: precisa anular a decoração de link herdada */
/* REGRESSAO da 15.6, apontada pelo PO na validacao: esta regra estava presa a
   `.kanban`. Quando a capa deixou de ser quadro, os cards da home sairam do
   escopo e voltaram ao estilo de LINK CRU — titulo, datas e contratante todos
   sublinhados e azuis. O card e um <a> inteiro; o sublinhado pertence ao texto
   que se le, nao ao bloco que se clica. Vale para qualquer card-link. */
.card-rfp[href] { display: block; text-decoration: none; color: inherit; }
.cli-kpis { display: flex; gap: 16px; margin-top: 10px; flex-wrap: wrap; }
.cli-kpis > div { display: flex; flex-direction: column; min-width: 0; }
.cli-kpis b { font-size: 1.02rem; color: var(--navy); line-height: 1.2; }
.cli-kpis span { font-size: .71rem; color: var(--cinza); }
.cli-vencedora { margin-top: 9px; background: var(--ok-bg); color: var(--ok-fg); font-size: .78rem;
  font-weight: 600; border-radius: 9px; padding: 5px 9px; }
.cli-rfp-nome { margin-top: 9px; font-size: .78rem; color: var(--cinza); }
.cli-rfp-nome small { color: var(--texto-2); }

/* ===== Fase 9 — Kanban do painel (reusa .kanban/.card-rfp) ===== */
/* A regra `.kanban-painel .kanban-col:nth-child(4)` (bolinha neutra na 4a
   coluna) MORREU na 15.6: a capa deixou de ser quadro e ninguem mais emite a
   classe `kanban-painel`. Removida na 15.8. Vale o registro do que ela
   ensinava: aquele override existia porque a 4a posicao herda `--laranja` da
   regra global, e o laranja e a cor de menor contraste da paleta no tema
   claro (2,57 sobre o fundo da coluna). */
/* O layout 100vh do board (media 901+) espreme flex-children sem flex:none —
   a barra de filtros não pode ser esmagada quando a altura aperta. */
.board > .painel-filtros { flex: none; }
/* Fase 15.7 — as duas VISOES IRMAS (home: natureza x quadro geral; certame:
   processo x comparativo). Servem as QUATRO telas.

   ⚠️ Eram abas de texto: cinza, sem fundo, sem borda, e so a ativa ganhava um
   risquinho de 2px embaixo. O PO (17/08): *"estes dois botoes ficam muito
   escondidos, quase nao da pra ver que existem essas duas opcoes de
   visualizacao"*. O defeito nao era contraste do texto — era AFFORDANCE:
   nada ali dizia "isto e clicavel e tem outro lado".

   Virou CONTROLE SEGMENTADO: caixa com borda visivel envolvendo os dois, e o
   lado ativo com fundo cheio. Le como chave de duas posicoes de longe, que e
   o que faltava.

   O fundo cheio usa `--azul-sup` com `--texto-inv`, o par ja usado pelo botao
   primario: e o unico azul da paleta medido nos DOIS temas (7,04 claro /
   5,45 escuro). `--azul` cru serviria no claro e afundaria no escuro, onde ele
   e #6FA8DC. */
/* ⚠️ `align-self` e `flex: none` NAO sao decoracao: o Quadro geral roda dentro
   de `.board`, que e um flex em coluna. Filho de flex e BLOCKIFICADO — o
   `inline-flex` vira `flex` e a caixa estica na largura toda (medido: 1000px),
   que e o oposto de um controle segmentado. Sem isto, a mesma regra da dois
   desenhos diferentes nas duas telas irmas. */
.visoes-irmas { display: inline-flex; align-self: flex-start; flex: none;
                gap: 3px; margin: 0 0 18px; padding: 3px;
                background: var(--superficie); border: 1px solid var(--borda);
                border-radius: 12px; box-shadow: var(--sh); }
.visoes-irmas a { display: block; padding: 7px 15px 8px; text-decoration: none;
                  color: var(--texto-2); font-weight: 700; font-size: .88rem;
                  border-radius: 9px; transition: background .15s, color .15s; }
.visoes-irmas a span { display: block; font-weight: 500; font-size: .73rem; color: var(--texto-3); margin-top: 1px; }
.visoes-irmas a:hover { color: var(--azul-escuro); background: var(--fundo); }
/* Depois do :hover de proposito — passar o mouse no lado ativo nao pode
   apaga-lo, que era o efeito de deixar o hover ganhar por ordem. */
.visoes-irmas a.ativa, .visoes-irmas a.ativa:hover { background: var(--azul-sup); color: var(--texto-inv); }
.visoes-irmas a.ativa span { color: var(--texto-inv); }
@media (max-width: 600px) {
  .visoes-irmas { display: flex; }         /* ocupa a linha; dois lados iguais */
  .visoes-irmas a { flex: 1 1 0; text-align: center; }
  .visoes-irmas a span { display: none; }  /* no celular so o rotulo cabe */
}
/* Fase 15.6 — home agrupada por NATUREZA (substitui o Kanban da capa).
   Grade fluida: os cards do painel tem largura minima confortavel e o numero
   de colunas cai sozinho conforme a tela, sem media query. */
.grupos-natureza { display: flex; flex-direction: column; gap: 26px; }
.grupo-nat-cab { display: flex; align-items: center; gap: 10px; margin-bottom: 11px;
                 padding-bottom: 7px; border-bottom: 1px solid var(--borda); }
.grupo-nat-cab h2 { font-size: .95rem; font-weight: 700; color: var(--azul-escuro); margin: 0; }
.grupo-nat-conta { background: var(--superficie); color: var(--cinza); font-size: .72rem;
                   font-weight: 700; border-radius: 999px; padding: 1px 9px; border: 1px solid var(--line); }
.grupo-nat-corpo { display: grid; grid-template-columns: repeat(auto-fill, minmax(310px, 1fr)); gap: 12px; }
/* Linha de destaque da capa: o numero que o PO procura ao abrir a tela. */
.painel-aguarda { margin: -4px 0 16px; font-size: .86rem; color: var(--texto); }
.painel-aguarda b { color: var(--alerta-fg); font-size: 1.05rem; }
.painel-aguarda span { color: var(--cinza); font-size: .78rem; }
/* Resumo do processo no card: UM chip por etapa, e a etapa que espera pela
   Alcance diz isso dentro do proprio chip. Havia aqui um chip separado de
   "aguardando voce", que com a analise tecnica vazia repetia o numero da etapa
   ao lado — dois alertas para um motivo so (PO, validacao da 15). */
.cardp-etapas { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 8px; }
.cardp-etapa { background: var(--superficie); color: var(--texto); border: 1px solid var(--line);
               border-radius: 999px; padding: 1px 9px; font-size: .7rem; font-weight: 700; }
.cardp-etapa span { color: var(--cinza); font-weight: 600; }
/* ⚠️ Seletor DUPLO de proposito: as duas classes convivem no mesmo chip agora,
   e `.cardp-aguarda` sozinho tem a mesma especificidade de `.cardp-etapa` —
   perderia por vir antes na folha. O mesmo vale para o `span` interno, que
   herdaria o cinza da regra acima e apagaria o destaque. */
.cardp-etapa.cardp-aguarda { background: var(--alerta-bg); color: var(--alerta-fg);
                             border-color: var(--alerta-borda); }
.cardp-etapa.cardp-aguarda span { color: var(--alerta-fg); }
.cardp-datas { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin-top: 10px; }
.cardp-datas span { display: block; font-size: .66rem; color: var(--cinza); text-transform: uppercase; letter-spacing: .04em; }
.cardp-datas b { font-size: .82rem; color: var(--navy); }
.cardp-props { margin-top: 9px; font-size: .78rem; color: var(--cinza); }
.cardp-props b { color: var(--navy); }
/* Reenvio no card da capa: chamada discreta, mas que se enxerga varrendo o
   quadro (pedido do PO — nao pode depender de memoria). */
.cardp-reenvio { margin-top: 7px; display: inline-block; font-size: .72rem; font-weight: 700;
  border-radius: 999px; padding: 2px 10px; background: var(--alerta-bg); color: var(--alerta-fg);
  border: 1px solid var(--alerta-borda); }

/* Fase 9 — vista integral da proposta (admin, somente leitura) */
.pp-trilha { font-size: .82rem; color: var(--cinza); margin-bottom: 8px; }
.pp-trilha a { color: var(--azul); text-decoration: none; }
.pp-trilha a:hover { text-decoration: underline; }
.pp-cab { display: flex; align-items: center; gap: 22px; flex-wrap: wrap; }
.pp-stats { display: flex; gap: 26px; flex-wrap: wrap; }
.pp-stats span { display: block; font-size: .68rem; color: var(--cinza); text-transform: uppercase; letter-spacing: .04em; }
.pp-stats b { font-size: .95rem; color: var(--navy); }
.pp-flag { flex-basis: 100%; background: var(--flag-r-bg); color: var(--erro-fg); border-radius: 9px; padding: 8px 12px; font-size: .85rem; font-weight: 600; }
.linha-tempo { list-style: none; margin: 0; padding: 0; }
.linha-tempo li { display: flex; gap: 14px; padding: 6px 0; border-bottom: 1px solid var(--borda); font-size: .88rem; }
.linha-tempo li:last-child { border-bottom: 0; }
.linha-tempo b { flex: 0 0 130px; color: var(--navy); font-variant-numeric: tabular-nums; }
/* Cabecalho do escopo na vista integral, com o recolher/expandir tudo */
.pp-escopo-cab { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; margin-top: var(--sp-5); }
.pp-escopo-cab h2 { margin: 0; font-size: 1.02rem; color: var(--azul-escuro); }
.pp-bloco { margin-top: var(--sp-5); }
.pp-bloco-cab { font-size: 1.02rem; color: var(--azul-escuro); margin-bottom: 8px; }
.pp-bloco-cab small { color: var(--cinza); font-weight: 400; }
.pp-secao { background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--r-lg); margin-bottom: 10px; overflow: hidden; }
.pp-secao > summary { cursor: pointer; padding: 11px 16px; display: flex; justify-content: space-between; gap: 12px; align-items: baseline; }
.pp-secao > summary b { color: var(--azul-escuro); font-size: .92rem; }
.pp-secao > summary small { color: var(--cinza); white-space: nowrap; }
.pp-secao[open] > summary { border-bottom: 1px solid var(--borda); }
.pp-secao .itens { margin: 0; }
.pp-lista { display: flex; flex-direction: column; }
.pp-lista-linha { display: flex; align-items: center; gap: 14px; padding: 9px 0; border-bottom: 1px solid var(--borda); }
.pp-lista-linha:last-child { border-bottom: 0; }
.pp-lista-linha b { flex: 1; color: var(--navy); font-size: .92rem; }
.pp-lista-flag { background: var(--erro-bg); color: var(--erro-fg); font-size: .72rem; font-weight: 700; border-radius: 999px; padding: 2px 10px; }
/* Fase 14: selo contador — laranja quando nenhum desvio e de item essencial */
.pp-lista-flag.o { background: var(--alerta-bg); color: var(--alerta-fg); }
/* Contagem de envios na lista de propostas: com mais de um envio o selo
   destaca e vira link para a comparação dos dois últimos. */
.pp-lista-envios { font-size: .72rem; font-weight: 700; border-radius: 999px; padding: 2px 10px; background: var(--superficie-2); color: var(--texto-2); white-space: nowrap; }
.pp-lista-envios.destaque { background: var(--info-bg); color: var(--info-fg); border: 1px solid var(--info-borda); text-decoration: none; }
.pp-lista-envios.destaque:hover { text-decoration: underline; }

/* ===== Fase 10 — lançamentos datados (blocos fixos + edição versionada) ===== */
.lanc-bloco { margin-top: 8px; }
.lanc-bloco + .lanc-bloco { margin-top: 10px; }
.lanc-meta { display: flex; align-items: center; gap: 12px; margin-top: 4px; }
.lanc-quando { font-size: .72rem; color: var(--cinza); }
.lanc-editar, .lanc-cancelar { border: 0; background: none; color: var(--azul); font: inherit; font-size: .75rem; font-weight: 600; cursor: pointer; padding: 0; }
.lanc-editar:hover, .lanc-cancelar:hover { text-decoration: underline; }
.lanc-edicao { margin-top: 6px; }
.lanc-novo { margin-top: 10px; }
.lanc-hist { margin-top: 6px; }
.lanc-hist > summary { cursor: pointer; font-size: .74rem; color: var(--cinza); font-weight: 600; }
.lanc-hist-item { margin-top: 6px; opacity: .75; }
/* vista integral: texto do fornecedor como REGISTRO fixo, não campo */
.obs-texto { margin-top: 8px; padding: 0.55rem 0.7rem; background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--r-ctl); font-size: 0.88rem; line-height: 1.5; color: var(--navy); }
.obs-texto-vazia { color: var(--erro-fg); font-style: italic; }
.obs-quando { margin-top: 4px; font-size: 0.72rem; color: var(--cinza); }

/* ===== Fase 7 — aviso de certame encerrado ===== */
.encerrada-aviso { max-width: 620px; margin: 8vh auto 0; text-align: center; padding: 32px 28px; }
.encerrada-aviso .ea-ic { font-size: 2.2rem; line-height: 1; margin-bottom: 10px; }
.encerrada-aviso h1 { font-size: 1.35rem; margin: 0 0 14px; }
.encerrada-aviso p { color: var(--texto-2); font-size: .92rem; line-height: 1.55; margin: 0 0 12px; }
.encerrada-aviso .ea-ok { background: var(--ok-bg); color: var(--ok-fg); border-radius: var(--r-ctl);
  padding: 11px 14px; margin: 18px 0 20px; }

/* ===== Fase 8 — saudação/contador da home (fornecedor e contratante) ===== */
.home-hero { margin-bottom: var(--sp-5); }
.home-hero h1 { margin: 0; font-size: 2rem; letter-spacing: -.03em; }
.home-hero .home-sub { margin: 6px 0 0; color: var(--texto-2); font-size: .98rem; }
.home-hero .home-sub b { color: var(--texto); font-variant-numeric: tabular-nums; }

/* ===== Login/acesso ESCURO (referência ClientOS, no navy da marca) =====
   Só o fluxo de acesso (body.auth-dark): o guia veda o escuro como tema do
   APP, mas o navy já é o escuro da marca (sidebar). O formulário FLUTUA no
   fundo — o "cartão" perde caixa, borda e sombra. */
/* auth-dark é uma superfície SEMPRE escura (gradiente), em qualquer tema.
   Logo os tokens de texto dentro dela têm de ser os do escuro — senão, com o
   usuário no tema CLARO, o título e os rótulos ficam escuros sobre fundo
   escuro (medido: 1,16 de contraste). É o espelho do bug do --texto-inv. */
body.auth-dark {
  --texto: #E4ECF5;
  --texto-2: #A9BACD;
  --texto-3: #93A6BC;
  --faint: #93A6BC;
  --cinza: #A9BACD;
  --navy: #FFFFFF;
  --azul: #6FA8DC;
  --azul-escuro: #C3D6EA;
  --borda: rgba(255,255,255,.14);
  --line: rgba(255,255,255,.14);
  --line-in: rgba(255,255,255,.18);
  --superficie: rgba(255,255,255,.06);
}
/* PO 08/08: nas telas de acesso o rodapé ficava colado no fim da página,
   longe do conteúdo. A causa era o main esticar para preencher os 100vh
   (flex: 1 0 auto) e empurrar o rodapé; aqui ele fica com altura natural. */
body.auth-dark main.conteudo { flex: 0 0 auto; }
body.auth-dark footer.rodape { margin: 1.6rem 0 2.5rem; }

body.auth-dark { background: radial-gradient(90rem 60rem at 50% -20%, #14395C 0%, #0C2036 55%, #081627 100%); }
/* Conjunto logo+formulário CENTRADO na vertical (o bloco ficava pendurado no
   topo em telas altas): margin-top:auto no header + margin-bottom:auto no main
   centram o grupo; o rodapé segue no pé. Logo maior no escuro (pedido do PO). */
body.auth-dark .public-top { margin-top: auto; padding: 20px 20px 10px; }
/* A centralização vertical vem de margens auto (logo tem margin-top:auto).
   O margin-bottom:auto estava NO MAIN, então o rodapé ficava FORA do bloco
   centralizado e caía no fim da página. Passa para o rodapé: o conjunto
   logo+form+rodapé centraliza junto e o rodapé fica logo abaixo do link. */
body.auth-dark main.conteudo.public-main { flex: 0 0 auto; }
body.auth-dark footer.rodape { margin-bottom: auto; }
/* logo horizontal se dimensiona pela LARGURA (72px de altura ainda ficou
   tímido — 2ª queixa do PO): ~30% a mais, com teto no mobile */
body.auth-dark .pt-marca { width: min(360px, 80vw); height: auto; }
body.auth-dark .auth-wrap { margin: 0 auto; }
body.auth-dark .auth-wrap h1 { color: var(--texto-inv); font-size: 1.6rem; }
body.auth-dark .auth-wrap .cartao { background: transparent; border: 0; box-shadow: none; padding: var(--sp-4) 0 0; }
body.auth-dark .auth-wrap p { color: #A7B8CB; }
body.auth-dark .auth-wrap label { color: #8FA3B8; }
body.auth-dark .auth-wrap a { color: #CBD9E9; }
body.auth-dark .auth-wrap a:hover { color: var(--texto-inv); }
body.auth-dark .auth-wrap .erros { color: #FFB4A8; }
body.auth-dark .auth-wrap .ok { color: #9AD9B5; }
body.auth-dark .auth-wrap input[type="text"],
body.auth-dark .auth-wrap input[type="email"],
body.auth-dark .auth-wrap input[type="password"] {
  background: rgba(255,255,255,.06); border-color: rgba(255,255,255,.14); color: var(--texto-inv); }
body.auth-dark .auth-wrap input::placeholder { color: #6C8098; }
body.auth-dark .auth-wrap input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(232,128,37,.22); }
/* autofill do Chrome pinta amarelo — inset shadow força o fundo escuro */
body.auth-dark .auth-wrap input:-webkit-autofill {
  -webkit-box-shadow: 0 0 0 60px #16304B inset; -webkit-text-fill-color: var(--texto-inv); }
body.auth-dark .auth-wrap button[type="submit"], body.auth-dark .auth-wrap .botao {
  background: var(--accent); box-shadow: 0 6px 18px rgba(232,128,37,.3); }
body.auth-dark .auth-wrap button[type="submit"]:hover, body.auth-dark .auth-wrap .botao:hover { background: #D06D16; }
body.auth-dark footer.rodape, body.auth-dark footer.rodape .acesso-info { color: #5E738C; }

/* ===== Fase 12 — comparação entre envios (retrato congelado) ===== */
/* Cor SEMPRE por token: test_tokens_css reprova token usado sem declaração. */
.dif-seletor h2, .dif-cartao h2 { font-size: 1.02rem; color: var(--azul-escuro); margin: 0 0 10px; }
.dif-seletor h2 small, .dif-cartao h2 small { display: block; font-weight: 400; font-size: .76rem; color: var(--cinza); margin-top: 2px; }
.dif-seletor-campos { display: flex; gap: var(--sp-3); flex-wrap: wrap; align-items: flex-end; }
.dif-seletor-campos label { display: flex; flex-direction: column; gap: 4px; font-size: .72rem; color: var(--cinza); text-transform: uppercase; letter-spacing: .04em; }
.dif-seletor-campos select { min-width: 250px; }
.dif-aviso { background: var(--alerta-bg); color: var(--alerta-fg); border: 1px solid var(--alerta-borda); border-radius: var(--r-ctl); padding: 10px 12px; font-size: .86rem; margin: 0; }
.dif-igual { color: var(--cinza); font-size: .88rem; margin: 0; }
.dif-contagem { display: flex; gap: 26px; flex-wrap: wrap; margin-bottom: var(--sp-3); }
.dif-contagem span { display: block; font-size: .68rem; color: var(--cinza); text-transform: uppercase; letter-spacing: .04em; }
.dif-contagem b { font-size: .95rem; color: var(--navy); }
.dif-sub { font-size: .92rem; color: var(--azul-escuro); margin: var(--sp-4) 0 8px; }
.dif-tabela td { vertical-align: top; }
/* De/Para campo por campo: o valor manda na leitura, o rotulo do campo apoia,
   e uma linha separa visualmente um item do proximo. */
.dif-campo { color: var(--cinza); font-size: .78rem; white-space: nowrap; }
.dif-valor { color: var(--navy); font-variant-numeric: tabular-nums; }
.dif-nota { color: var(--cinza); font-size: .7rem; }
.dif-tabela tr.dif-item-inicio > td { border-top: 1px solid var(--borda); }
.dif-tabela .cel-item b { color: var(--navy); }
.dif-tabela .cel-item small { display: block; color: var(--cinza); font-size: .76rem; line-height: 1.4; }
.dif-selo { display: inline-block; background: var(--info-bg); color: var(--info-fg); border: 1px solid var(--info-borda); border-radius: 999px; padding: 1px 9px; font-size: .7rem; font-weight: 700; margin: 1px 3px 1px 0; }
.dif-ausente { color: var(--cinza); font-style: italic; font-size: .8rem; }
.dif-atalho { color: var(--azul); font-size: .76rem; font-weight: 600; text-decoration: none; margin-left: 8px; white-space: nowrap; }
.dif-atalho:hover { text-decoration: underline; }
/* Marcador na própria linha do item (só com comparação ativa) */
.item-mudou > td { background: var(--info-bg); }
.dif-marca { margin-top: 6px; }
.dif-marca-antes { color: var(--cinza); font-size: .7rem; margin-top: 3px; line-height: 1.4; }
/* Rótulo de procedência do dado: "estado atual" x "como enviado" */
.fonte-dado { display: block; font-weight: 400; font-size: .76rem; color: var(--cinza); margin-top: 2px; }

/* ===== Fase 13 — janela de aprovacao tecnica (checklist do gate) ===== */
.check-lista { list-style: none; margin: 0 0 var(--sp-4); padding: 0; display: flex; flex-direction: column; gap: 10px; }
.check-item { display: flex; gap: 12px; align-items: flex-start; padding: 12px 14px; border-radius: var(--r-ctl); border: 1px solid var(--borda); background: var(--superficie); }
.check-item.ok { background: var(--ok-bg); border-color: var(--ok-borda); }
.check-item.pendente { background: var(--alerta-bg); border-color: var(--alerta-borda); }
/* Nao atendida mas NAO bloqueante (proposta que ja seguiu): tom neutro, sem
   ambar de alerta -- senao a tela se contradiz com o aviso de que nada trava. */
.check-item.neutro { background: var(--superficie-2); border-color: var(--borda); }
.check-item.neutro .check-marca { color: var(--texto-2); border-color: var(--borda); }
/* Todas as etiquetas com a largura da MAIOR (PO, 14/08): sao tres — ATENDIDO,
   FALTA ATENDER e SEM REGISTRO —, e com largura livre cada uma empurrava o
   titulo da condicao para um ponto diferente, deixando a coluna de textos
   serrilhada. Com a largura fixada pela maior, os titulos alinham.
   `text-align: center` para o texto curto nao encostar a esquerda da pilula.
   ⚠️ Em PX, e nao em `ch`: com 13ch a maior etiqueta ("FALTA ATENDER", 13
   caracteres) media 114px e estourava os 95px que o ch dava — maiuscula com
   `letter-spacing` mede bem mais que a largura nominal do caractere. */
.check-marca { flex: none; font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; border-radius: 999px; padding: 3px 10px;
  min-width: 120px; box-sizing: border-box; text-align: center; }
/* Branco sobre acento reprovou na medicao (1,82 no escuro, 2,79 no claro):
   no escuro --ok e --laranja sao CLAROS. O selo passa a ser contorno, com a
   cor forte no texto sobre a superficie do card. */
.check-marca { background: var(--superficie); border: 1px solid var(--borda); }
/* --alerta-fg sobre branco da 4,48 (o ambar fraco ja registrado na Fase 11):
   o texto vai de --navy nos dois selos e o semantico fica na BORDA. */
.check-marca { color: var(--navy); }
.check-item.ok .check-marca { border-color: var(--ok-borda); }
.check-item.pendente .check-marca { border-color: var(--alerta-borda); }
.check-corpo { flex: 1; min-width: 0; }
.check-corpo > b { color: var(--navy); font-size: .92rem; }
.check-detalhe { color: var(--texto-2); font-size: .82rem; margin-top: 4px; line-height: 1.5; }
/* Fase 14: "Como agir" — a instrucao de uso, separada do "o que e" */
.check-agir { color: var(--texto); font-size: .82rem; margin-top: 6px; line-height: 1.5; }
.check-agir > b { color: var(--navy); }
/* Reavaliacao por item: recolhida — desvio decidido mostra a decisao, e
   editar e um clique deliberado */
.reavaliar-linha { margin-top: 8px; }
/* Mesmo defeito de token da 15.8, PRE-EXISTENTE (Fase 14): `--azul-sup` como
   cor de texto reprova AA no tema escuro. Corrigido junto — deixar um link
   sub-AA conhecido enquanto se declara a trava seria trava de mentira. */
.reavaliar-linha > summary { cursor: pointer; font-size: .8rem; font-weight: 600; color: var(--azul); }
.reavaliar-linha > summary small { color: var(--texto-2); font-weight: 400; }
/* Verdito em PAR (PO, 12/08): aprovar e reprovar com o MESMO tamanho, lado
   a lado. Fechado, o Reprovar e um summary com as METRICAS do botao base
   (.botao/button[type=submit]); aberto, ocupa a linha e vira o painel do
   motivo. Par de erro vetado, nunca branco sobre cor forte. */
.verdito { display: flex; align-items: flex-start; gap: 12px; flex-wrap: wrap; }
.reprovar-bloco { margin: 0; flex: 0 0 auto; }
.reprovar-bloco > summary {
  display: inline-flex; align-items: center; gap: 0.45rem;
  padding: 0.62rem 1.25rem; font-size: 0.92rem; font-weight: 600;
  line-height: 1.25; border-radius: var(--r-ctl); cursor: pointer;
  background: var(--erro-bg); color: var(--erro-fg);
  border: 1px solid var(--erro-borda);
  box-shadow: 0 1px 2px rgba(16,24,40,.12);
}
.reprovar-bloco > summary:hover { border-color: var(--erro-fg); }
.reprovar-bloco[open] { flex: 1 1 100%; border: 1px solid var(--erro-borda); border-radius: var(--r-ctl); }
.reprovar-bloco[open] > summary { border: 0; box-shadow: none; width: 100%; border-radius: var(--r-ctl) var(--r-ctl) 0 0; }
.reprovar-bloco .check-form { padding: 0 12px 12px; }
.reprovar-trancado { padding: 0 12px 12px; margin: 0; }
/* Fase 15 — saneamento: chip do ponto de atencao e a caixa de devolucao.
   Pares de estado ja vetados; "observacao que descaracteriza" usa o ambar
   (e alerta, nao recusa declarada). */
.recusa-tipo-obs { display: inline-block; margin-left: 8px; padding: 1px 8px; border-radius: 999px; font-size: .68rem; font-weight: 700; vertical-align: 2px; text-transform: uppercase; letter-spacing: .03em; background: var(--alerta-bg); color: var(--alerta-fg); border: 1px solid var(--alerta-borda); }
.recusa-questionada { border-color: var(--info-borda); }
/* Ponto de atencao no formato de preenchimento (Fase 15). Os chips dizem POR
   QUE o item esta na lista e ficam na celula da descricao — a do numero tem
   52px e nao os comporta. `margin-left` zerado no primeiro: no card eles vinham
   depois do numero, aqui abrem a celula. */
.ponto-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 6px; }
.ponto-chips > span { margin-left: 0; }
/* Lista de observacoes a ler: o texto e o protagonista, entao ele fica em
   destaque e o item vira cabecalho. */
.obs-leitura { display: flex; flex-direction: column; gap: 10px; margin-top: var(--sp-3); }
.obs-leitura-linha { background: var(--superficie-2); border: 1px solid var(--borda); border-left: 4px solid var(--acento); border-radius: var(--r-ctl); padding: 10px 12px; }
.obs-leitura-item { font-size: .84rem; color: var(--texto-2); margin-bottom: 6px; }
.obs-leitura-item b { color: var(--azul); margin-right: 6px; }
.obs-leitura-texto { font-size: .9rem; color: var(--texto); line-height: 1.5; }
.obs-leitura-selo { display: inline-block; margin-left: 8px; padding: 1px 8px; border-radius: 999px; font-size: .66rem; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; background: var(--alerta-bg); color: var(--alerta-fg); border: 1px solid var(--alerta-borda); }
.obs-leitura-req { margin-top: 8px; }
.obs-leitura-req > summary { cursor: pointer; font-size: .78rem; color: var(--azul); }
.obs-leitura-req p { margin: 6px 0 0; font-size: .82rem; color: var(--texto-2); line-height: 1.5; }
.ponto-motivo { font-size: .78rem; color: var(--texto-2); font-style: italic; margin: 6px 0 2px; }
.devolver-bloco { margin-top: 12px; border-color: var(--alerta-borda); }
.devolver-bloco > summary { color: var(--alerta-fg); }
.devolver-bloco .check-form { padding: 0 12px 12px; }
.devolver-itens { display: grid; gap: 6px; margin: 6px 0 10px; }
.devolver-item { display: flex; gap: 8px; align-items: flex-start; font-size: .84rem; color: var(--texto); width: auto; }
.btn-devolver { background: var(--alerta-bg); color: var(--alerta-fg); border: 1px solid var(--alerta-fg); }
.liberar-acao { margin-top: 14px; }
/* Confirmacao de leitura das observacoes quando a IA nao rodou (13/08). */
.liberar-aviso { margin-bottom: 12px; }
.liberar-obs { margin: 8px 0 0; padding-left: 18px; }
.liberar-obs li { margin-bottom: 4px; }
.liberar-obs b { font-variant-numeric: tabular-nums; margin-right: 4px; }
.liberar-confirma { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 12px;
  font-size: .86rem; color: var(--texto); cursor: pointer; }
.liberar-confirma input { margin-top: 2px; flex: none; }
/* Fase 15 — quadro das PROPOSTAS dentro do certame. Herda .kanban/.card-rfp;
   o quadro nao ocupa a tela toda (convive com o resto do drill), entao a
   altura das colunas nao e travada aqui. */
/* O quadro saiu do `.painel-bloco` na validacao da 15: aninhado, ele somava o
   padding do bloco e ficava mais estreito que o conteudo do Painel. Agora ele
   e o conteudo da tela, na mesma largura util. O h2 perde o estilo que vinha
   de `.painel-bloco h2` e ganha o seu. */
.quadro-propostas { margin-bottom: var(--sp-4); }
.quadro-propostas > h2 { margin: 0 0 var(--sp-3); font-size: 1.02rem; letter-spacing: -.01em; }
.quadro-propostas > h2 small { font-weight: 500; color: var(--cinza); font-size: .8rem; margin-left: 8px; }
.quadro-propostas .kanban { background: var(--board-bg); }
.quadro-propostas .kanban-col { max-height: none; }
/* A bolinha da coluna vem do :nth-child generico (1..6), pensado para os
   quadros de 6 colunas. Este quadro tem 5 e herdava a cor por POSICAO — o
   valor calhava de bater, mas qualquer reordenacao (15.7) trocaria as cores
   em silencio. Aqui a cor fica presa ao SIGNIFICADO da coluna. */
.kanban-propostas .kanban-col:nth-child(1) .kanban-col-titulo::before { background: var(--faint); }   /* em preenchimento */
.kanban-propostas .kanban-col:nth-child(2) .kanban-col-titulo::before { background: var(--alerta); }  /* recebidas: a bola esta com a Alcance */
.kanban-propostas .kanban-col:nth-child(3) .kanban-col-titulo::before { background: var(--azul); }    /* analise tecnica */
.kanban-propostas .kanban-col:nth-child(4) .kanban-col-titulo::before { background: var(--laranja); } /* comercial */
.kanban-propostas .kanban-col:nth-child(5) .kanban-col-titulo::before { background: var(--ok); }      /* decidida */
/* Quadro GERAL (validacao da 15): 4 colunas, cor presa ao SIGNIFICADO pelo
   mesmo motivo do quadro das propostas. A 4a posicao herdaria `--laranja` da
   regra generica, que e a cor de menor contraste da paleta no tema claro
   (2,57) -- e "Encerrada" e desfecho, entao verde diz mais que laranja. */
.kanban-certames .kanban-col:nth-child(1) .kanban-col-titulo::before { background: var(--faint); }  /* rascunho */
.kanban-certames .kanban-col:nth-child(2) .kanban-col-titulo::before { background: var(--alerta); } /* recebendo propostas */
.kanban-certames .kanban-col:nth-child(3) .kanban-col-titulo::before { background: var(--azul); }   /* em analise */
.kanban-certames .kanban-col:nth-child(4) .kanban-col-titulo::before { background: var(--ok); }     /* encerrada */
.card-certame { cursor: pointer; }
/* O card INTEIRO abre a proposta (queixa do PO: "ao clicar no card nao abre").
   Nao da para envolver tudo num <a>, porque o botao da etapa e outro <a> --
   HTML invalido e o botao perderia o clique. Entao o link do titulo se ESTICA
   sobre o card por ::after, e a acao sobe por z-index. */
/* Tipografia do card (apontamento do PO: "meio sem graça"). Os tres KPIs
   dividiam a largura em partes iguais e o total quebrava em duas linhas
   ("R$ 48,10 / mi"), o que sozinho ja estragava o card. Agora:
   - a grade da a cada KPI o espaco do seu conteudo, e o numero NAO quebra;
   - hierarquia de verdade: rotulo pequeno e cinza, numero grande e escuro,
     em fonte tabular (colunas de digitos alinhadas entre cards);
   - o total, que e o que se compara, pesa mais que os outros dois. */
.card-proposta .kpi-linha { display: grid; grid-template-columns: auto auto auto;
  justify-content: start; gap: 4px 18px; margin-top: 2px; }
.card-proposta .kpi { display: block; }
.card-proposta .kpi span { display: block; font-size: .64rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: .05em; color: var(--cinza); }
.card-proposta .kpi b { display: block; margin-top: 1px; font-size: .92rem;
  font-weight: 700; color: var(--navy); font-variant-numeric: tabular-nums;
  white-space: nowrap; }
.card-proposta .kpi:first-child b { font-size: 1.02rem; letter-spacing: -.01em; }
.card-proposta .card-rfp-kpis { border-top: 1px solid var(--line2); padding-top: 9px; margin-top: 9px; }
.card-proposta .card-rfp-titulo { font-size: .95rem; letter-spacing: -.01em; }
.card-proposta { position: relative; cursor: pointer; }
.card-proposta:hover { border-color: var(--azul); }
.cardp-abrir { text-decoration: none; }
.cardp-abrir::after { content: ""; position: absolute; inset: 0; z-index: 1; border-radius: inherit; }
.cardp-acoes { position: relative; z-index: 2; }
.cardp-acao { padding: 5px 14px; font-size: .78rem; }
.cardp-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0; }
/* Sinal comercial no card (PO, 18/08): resposta da outra parte deixa de morar
   so no historico. Dois tons, porque o mesmo fato interessa a lados diferentes
   em momentos diferentes: `alerta` quando a bola esta com quem olha, `neutro`
   quando e so situacao. Reusa os tokens de erro e de info, ja medidos nos dois
   temas. */
.cardp-comercial { display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 9px; border-radius: 999px; font-size: .72rem; font-weight: 700;
  white-space: nowrap; }
.cardp-comercial.alerta { background: var(--alerta-bg); color: var(--alerta-fg); border: 1px solid var(--alerta-borda); }
.cardp-comercial.neutro { background: var(--info-bg); color: var(--azul-escuro); border: 1px solid var(--info-borda); }
.cardp-quest { background: var(--info-bg); color: var(--info-fg); border: 1px solid var(--info-borda); border-radius: 999px; padding: 1px 8px; font-size: .68rem; font-weight: 700; }
.cardp-acoes { display: flex; flex-wrap: wrap; gap: 4px 12px; margin-top: 10px; padding-top: 8px; border-top: 1px solid var(--borda); }
/* TRAVA de contraste (15.8): era `--azul-sup`, que da 2,78 sobre o card no tema
   ESCURO — reprova AA para texto. `--azul-sup` e token de FUNDO (botao,
   cabecalho de tabela, avatar, bolha do chat), sempre com texto branco por
   cima; como cor de TEXTO ele nunca foi pensado. `--azul` e o de primeiro
   plano: identico no tema claro (7,04 — nada muda ali) e claro o bastante no
   escuro (6,00). */
.cardp-acoes a { font-size: .76rem; font-weight: 600; color: var(--azul); text-decoration: none; }
.cardp-acoes a:hover { text-decoration: underline; }
/* Confirmacoes pos-acao (mensagens do Django) — pares de estado vetados */
.mensagens { margin-bottom: 14px; display: grid; gap: 8px; }
.msg { border-radius: var(--r-ctl); padding: 10px 14px; font-size: .88rem; border: 1px solid; }
.msg-success { background: var(--ok-bg); color: var(--ok-fg); border-color: var(--ok-borda); }
.msg-warning { background: var(--alerta-bg); color: var(--alerta-fg); border-color: var(--alerta-borda); }
.msg-error { background: var(--erro-bg); color: var(--erro-fg); border-color: var(--erro-borda); }
.msg-info { background: var(--info-bg); color: var(--info-fg); border-color: var(--info-borda); }
.btn-reprovar { background: var(--erro-bg); color: var(--erro-fg); border: 1px solid var(--erro-fg); }
.check-form { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.check-form label { display: block; width: 100%; font-size: .8rem; color: var(--texto-2); }
.check-form textarea { width: 100%; margin-top: 4px; }
/* Campo em bloco, botao a direita (pedido do PO): o textarea estreito ao lado
   do texto explicativo ficava apertado e desalinhado. */
.check-form-linha { display: flex; gap: 10px; align-items: flex-end; width: 100%; }
.check-form-linha textarea { flex: 1; }
.check-form-linha .btn { flex: none; }
@media (max-width: 700px) { .check-form-linha { flex-direction: column; align-items: stretch; } }
/* Decisao do desvio (Fase 14): radios lado a lado, quebra no estreito */
.check-decisao { display: flex; gap: 14px; flex-wrap: wrap; font-size: .84rem; }
.check-decisao label { display: flex; gap: 6px; align-items: center; width: auto; color: var(--texto); }
/* A recusa inteira na tela: requisito + resposta do fornecedor */
.recusa { margin-top: 12px; border: 1px solid var(--borda); border-radius: var(--r-ctl); padding: 12px 14px; background: var(--superficie); }
.recusa-cab { color: var(--navy); font-size: .88rem; line-height: 1.45; }
.recusa-cab b { margin-right: 6px; }
.recusa-grade { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: var(--sp-3); margin: 10px 0; }
/* Par descricao x requisito nas telas de CARTAO. Grade propria, com duas
   colunas FIXAS de largura igual: no `.recusa-grade` (auto-fit) uma terceira
   celula subiria para a mesma fileira e o par deixaria de ser par. Reempilha no
   mesmo corte de 900px da tabela — um so ponto de quebra no portal. */
.recusa-escopo { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); margin: 10px 0; }
@media (max-width: 900px) { .recusa-escopo { grid-template-columns: 1fr; } }
.recusa-grade span, .recusa-escopo span { display: block; font-size: .68rem; color: var(--cinza); text-transform: uppercase; letter-spacing: .04em; }
.recusa-grade p, .recusa-escopo p { margin: 4px 0 0; font-size: .84rem; color: var(--texto-2); line-height: 1.5; }
.recusa-na { color: var(--erro-fg); font-weight: 700; }
/* Fase 14: inabilitada por descumprimento tecnico + chips do desvio. Os chips
   usam o PAR erro-bg/erro-fg (vetado nos 2 temas) — nunca branco sobre cor
   forte, que ja reprovou em contraste duas vezes nesta base. */
.aviso-erro { background: var(--erro-bg); border: 1px solid var(--erro-borda); }
.aviso-erro .aviso-ic { background: var(--erro-bg); color: var(--erro-fg); font-weight: 700; }
.aviso-erro .aviso-txt strong { color: var(--erro-fg); }
.recusa-inabilitada { border-color: var(--erro-borda); }
.recusa-essencial, .recusa-nao-essencial, .recusa-veredito, .recusa-veredito-ok { display: inline-block; margin-left: 8px; padding: 1px 8px; border-radius: 999px; font-size: .68rem; font-weight: 700; vertical-align: 2px; text-transform: uppercase; letter-spacing: .03em; }
.recusa-essencial { background: var(--erro-bg); color: var(--erro-fg); border: 1px solid var(--erro-borda); }
/* O NAO essencial e o oposto de um alerta: ele DIMINUI a gravidade do ponto
   ("um NA aqui nao vira red flag"). Por isso e neutro e discreto — pintado de
   vermelho passaria a mensagem contraria. A classe `.recusa-essencial` fica: o
   selo vermelho volta se o PO decidir marcar os dois lados. */
.recusa-nao-essencial { background: var(--superficie-2); color: var(--texto-2); border: 1px solid var(--borda); }
.recusa-veredito { background: var(--erro-bg); color: var(--erro-fg); border: 2px solid var(--erro-fg); }
.recusa-veredito-ok { background: var(--ok-bg); color: var(--ok-fg); border: 2px solid var(--ok-fg); }
.recusa-aceita { border-color: var(--ok-borda); }
/* Parecer na linha do item (vista integral): aceito herda o tom OK; nao
   aceito o par de erro; sem decisao (legado) fica neutro — sempre por token. */
.obs-box.parecer-aceito { border-color: var(--ok-borda); }
.obs-box.parecer-aceito .cab { color: var(--ok-fg); }
.obs-box.parecer-nao-aceito { border-color: var(--erro-borda); }
.obs-box.parecer-nao-aceito .cab { color: var(--erro-fg); }
/* Situacao em uma palavra, no cabecalho */
.rot-situacao { letter-spacing: .03em; }
.check-acao { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.check-nota { color: var(--texto-2); font-size: .82rem; }
.check-quem { display: block; color: var(--cinza); font-size: .72rem; margin-top: 4px; }
/* Explicacao de cada condicao: o rotulo curto sozinho nao se entendia */
/* SEM teto de largura: o teto de 78ch cortava frase de uma linha no meio e
   deixava palavra orfa embaixo. Medida de leitura serve a paragrafo longo,
   nao a micro-copy de duas frases dentro de um cartao. */
.check-explica { color: var(--texto-2); font-size: .82rem; line-height: 1.55; margin-top: 6px; }
.check-estado { font-weight: 600; color: var(--navy); }
.check-consequencia { color: var(--texto-2); font-size: .8rem; font-style: italic; margin-top: 4px; }
/* Sequencia dos estagios: a tela diz onde esta e para onde vai */
.fluxo { list-style: none; display: flex; gap: 10px; flex-wrap: wrap; margin: 0 0 var(--sp-3); padding: 0; }
.fluxo-etapa { flex: 1 1 150px; border: 1px solid var(--borda); border-radius: var(--r-ctl); padding: 10px 12px; background: var(--superficie); }
.fluxo-etapa b { display: block; color: var(--texto-2); font-size: .86rem; }
.fluxo-etapa small { color: var(--cinza); font-size: .7rem; text-transform: uppercase; letter-spacing: .04em; }
.fluxo-fase { display: block; font-size: .66rem; color: var(--cinza); text-transform: uppercase; letter-spacing: .06em; font-weight: 700; }
.fluxo-etapa.concluida { background: var(--ok-bg); border-color: var(--ok-borda); }
.fluxo-etapa.concluida b { color: var(--navy); }
.fluxo-etapa.atual { background: var(--info-bg); border-color: var(--azul); }
.fluxo-etapa.atual b { color: var(--navy); font-weight: 700; }
.fluxo-etapa.na { opacity: .72; }
/* Ambar sobre fundo verde/azul deu 3,96 no claro (medido). Inconsistencia de
   dado e alerta de verdade: tom de erro, que tambem contrasta. */
.fluxo-alerta { margin-top: 6px; font-size: .72rem; line-height: 1.4; color: var(--erro-fg); border-top: 1px solid var(--erro-borda); padding-top: 6px; }
.fluxo-nota { color: var(--texto-2); font-size: .84rem; line-height: 1.55; margin: 0; }

/* Fase 13.5 — telas da negociacao */
/* Refeita depois do apontamento do PO: os campos ficavam desalinhados e os
   rotulos de ajuda cortados. Grade com colunas de largura minima, rotulo em
   cima e ajuda embaixo -- nada compete pelo mesmo espaco. */
.neg-form { display: flex; flex-direction: column; gap: var(--sp-4); }
.neg-grade { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: var(--sp-3); }
/* SEIS por linha (PO, 14/08). Com `auto-fit, minmax(280px,1fr)` o numero de
   colunas saia da largura da janela: numa tela larga davam 7 na primeira linha
   e 5 na segunda, e a grade ficava torta com os 12 blocos tipicos. Fixando em
   6, os 12 caem em duas linhas cheias.

   O rotulo do bloco e longo e passou a quebrar em duas linhas; `align-items:
   end` mantem os CAMPOS alinhados entre si mesmo quando um rotulo ocupa uma
   linha a mais que o vizinho — sem isso a fileira de campos fica serrilhada,
   que e o mesmo defeito de outra forma. */
.neg-grade-blocos { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--sp-3); margin-top: var(--sp-3); align-items: end; }
@media (max-width: 1500px) { .neg-grade-blocos { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 1100px) { .neg-grade-blocos { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 760px)  { .neg-grade-blocos { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.neg-campo { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
/* CESTA do desconto por item (PO, 14/08): escolhe bloco -> item, empilha e
   envia tudo junto. O valor fica em CADA linha, porque cada item tem o seu. */
.neg-itens { margin-top: var(--sp-3); }
.neg-item-escolha { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) auto; gap: var(--sp-3); align-items: end; }
@media (max-width: 900px) { .neg-item-escolha { grid-template-columns: 1fr; } }
.neg-item-lista { display: flex; flex-direction: column; gap: 8px; margin-top: var(--sp-3); }
/* 4 colunas desde 17/08: a UNIDADE entrou antes do valor, porque o tipo passou
   a ser por item (PO: "posso querer uns itens colocar valor e outros %").
   Ela vem antes do numero, que e a ordem em que se le — "R$ 1.500,00", "7,5%". */
.neg-item-linha { display: grid; grid-template-columns: minmax(0, 1fr) 76px 140px auto; gap: 10px; align-items: center;
  background: var(--superficie-2); border: 1px solid var(--borda); border-radius: var(--r-ctl); padding: 8px 10px; }
@media (max-width: 760px) { .neg-item-linha { grid-template-columns: minmax(0, 1fr) 76px 110px auto; } }
.neg-item-rot { font-size: .84rem; color: var(--texto); min-width: 0; overflow-wrap: break-word; }
/* O valor do item embaixo da descricao (PO, 17/08): "ajuda no entendimento
   do desconto a ser solicitado". Em bloco proprio para nao competir com a
   descricao, e menor porque e referencia e nao o dado que se edita. */
.neg-item-desc { display: block; }
.neg-item-base { display: block; font-size: .76rem; font-weight: 600; color: var(--texto-2); margin-top: 2px; }
.neg-item-base:empty { display: none; }
.neg-item-linha input, .neg-item-unid { width: 100%; max-width: none; box-sizing: border-box; }
/* Fonte um ponto acima do resto do controle: "R$" e "%" sao dois caracteres e
   precisam ser lidos de relance, ao lado de um numero comprido. */
.neg-item-unid { font-weight: 600; text-align: center; }
.neg-item-tirar { border: 1px solid var(--borda); background: var(--superficie); color: var(--texto-2);
  width: 30px; height: 30px; border-radius: 8px; font-size: 1.05rem; line-height: 1; cursor: pointer; }
.neg-item-tirar:hover { border-color: var(--erro-fg); color: var(--erro-fg); }
.neg-item-vazio { color: var(--texto-2); font-size: .84rem; margin: var(--sp-3) 0 0; }
/* Marcador da unidade DENTRO do campo do desconto (PO, 17/08: "quero que
   apareça o campo formatado ou pelo menos uma indicacao antes do campo,
   similar ao que e feito no valor unitario da RFP. E tem que ser mutavel
   conforme seleciono o tipo").

   Mesmo principio do `.vu-moeda`: ELEMENTO irmao, nunca pseudo. A diferenca e
   que aqui o embrulho tem EXATAMENTE a caixa do input, entao `top: 0; bottom: 0`
   com flex centra o rotulo sozinho — sem repetir padding e metrica de fonte a
   mao, que foi o que deu "aparece o R$ mas esta desalinhado" da outra vez.

   R$ vai a ESQUERDA e % a DIREITA porque e assim que se le cada um; o padding
   do input abre so do lado ocupado. */
.neg-unid { position: relative; display: block; }
.neg-unid-marca { position: absolute; top: 0; bottom: 0; display: flex; align-items: center;
  font-size: .84rem; font-weight: 600; color: var(--texto-2); pointer-events: none; }
.neg-unid[data-unid="valor"] .neg-unid-marca { left: 11px; }
.neg-unid[data-unid="percentual"] .neg-unid-marca { right: 12px; }
.neg-unid[data-unid="valor"] input { padding-left: 36px; }
.neg-unid[data-unid="percentual"] input { padding-right: 30px; }
.neg-rot { font-size: .76rem; font-weight: 600; color: var(--navy); }
.neg-ajuda { font-size: .72rem; color: var(--cinza); line-height: 1.4; }
.neg-campo select, .neg-campo input { width: 100%; }
.neg-blocos > summary { cursor: pointer; font-size: .86rem; font-weight: 600; color: var(--azul); }
.neg-blocos > summary small { font-weight: 400; color: var(--cinza); margin-left: 6px; }
.neg-acao { display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
/* Botao presente mas bloqueado: mantem o padrao da tela e o cursor avisa */
.botao.bloqueado, .botao-secundario.bloqueado { opacity: .55; cursor: not-allowed; pointer-events: auto; }
/* O form comercial usa .neg-* (refeito na Fase 13.5); as .comercial-form/
   -linha/-grade/-blocos ficaram para tras e sairam na faxina da Fase 15. */
/* Decisao do fornecedor em PAR (apontamento do PO na validacao da Fase 15).
   Antes: Aceitar era um botao cheio e Recusar um `▸` cinza do tamanho de um
   link -- o desenho empurrava para o aceite, numa tela em que ele assume um
   preco. Agora os dois tem o MESMO tamanho e peso, e cada um abre o painel do
   proprio ato, com a consequencia escrita e o botao que executa la dentro.
   Herda `.verdito` (o par Aprovar/Reprovar da analise tecnica). */
.comercial-decisao { margin-top: var(--sp-4); }
/* DECISAO COMERCIAL — tela sobreposta e CENTRADA, uma por ato (PO, 14/08).
   Antes eram blocos que se expandiam na propria pagina: mesmo exclusivos, a
   decisao disputava a leitura com o resto da tela. Sobreposta, ela fica sozinha
   — que e o que se quer de um ato que NAO SE DESFAZ.

   Mesma tecnica da tratativa do item: `position: fixed` no conteudo do
   <details>, veu no ::before. O conteudo continua DENTRO do <form>, entao o
   csrf e o campo `rodada` vao junto no POST. */
/* Cancelar a solicitacao (PO, 17/08): reusa a tela sobreposta do aceite/recusa
   porque e o mesmo tipo de ato — nao se desfaz. O `name` do <details> e outro
   (`decisao-admin`) so para nao competir com os do fornecedor, que vivem noutra
   tela. */
.neg-cancelar { margin-top: var(--sp-3); }
.neg-avisar { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin-top: var(--sp-3); font-size: .86rem; cursor: pointer; }
.neg-avisar input { width: auto; flex: none; }
.neg-avisar small { flex-basis: 100%; color: var(--texto-2); font-size: .74rem; }
.decisao-modal { margin: 0; }
.decisao-modal > summary { list-style: none; cursor: pointer; }
.decisao-modal > summary::-webkit-details-marker { display: none; }
.decisao-modal[open]::before { content: ""; position: fixed; inset: 0; z-index: 79; background: var(--veu-modal); }
.decisao-modal[open] > .modal-caixa {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 80;
  width: min(560px, calc(100vw - 32px)); box-sizing: border-box;
  max-height: 86vh; overflow-y: auto;
  background: var(--superficie); border: 1px solid var(--borda); border-radius: var(--r-card);
  box-shadow: 0 24px 60px rgba(0,0,0,.45); padding: 0 20px 20px;
}
.modal-topo { position: sticky; top: 0; display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: var(--superficie); border-bottom: 1px solid var(--line); margin: 0 -20px 16px; padding: 16px 20px 12px; }
.modal-topo b { color: var(--navy); font-size: 1rem; }
.modal-caixa p { font-size: .88rem; line-height: 1.55; color: var(--texto-2); margin: 0 0 14px; }
.modal-caixa label { display: block; font-size: .84rem; color: var(--texto-2); margin-bottom: 14px; }
.modal-caixa textarea { width: 100%; max-width: none; box-sizing: border-box; margin-top: 6px; }
/* Os NUMEROS do aceite em destaque: e sobre eles que a decisao e tomada. */
.modal-numeros { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-3); margin: 0 0 16px; }
.modal-numeros > div { background: var(--superficie-2); border: 1px solid var(--borda); border-radius: var(--r-ctl); padding: 10px 12px; }
.modal-numeros span { display: block; font-size: .68rem; color: var(--cinza); text-transform: uppercase; letter-spacing: .04em; }
.modal-numeros b { font-size: 1.02rem; color: var(--navy); font-variant-numeric: tabular-nums; }
/* Confirmar e Voltar lado a lado: a saida tem de ser tao visivel quanto o ato. */
.modal-acoes { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.decisao-corpo { padding: 12px 14px 14px; }
.decisao-corpo p { margin: 0 0 12px; font-size: .86rem; line-height: 1.5; }
.decisao-corpo label { display: block; margin: 0 0 12px; font-size: .8rem; color: var(--texto-2); }
.decisao-corpo label small { font-weight: 400; }
.decisao-corpo textarea { width: 100%; max-width: 520px; margin-top: 4px; }
.btn-recusar { background: var(--erro-bg); color: var(--erro-fg); border: 1px solid var(--erro-fg); }

/* ===== Bloco de red flags: rola por dentro, não estica a página ===== */
/* Pedido do PO: com muitas flags o bloco definia a altura da página e empurrava
   o comparativo para fora da tela. Cor sempre por token. */
.bloco-flags-n { font-weight: 700; font-size: .78rem; color: var(--cinza); }
.bloco-flags > .flags {
  overflow-y: auto; overscroll-behavior: contain; padding-right: 4px;
  /* Largura cheia (tela do contratante): teto de viewport, sem vizinho para seguir */
  max-height: 70vh;
}
@media (min-width: 901px) {
  /* Lado a lado no painel: a altura vem da TABELA vizinha. O bloco vira coluna
     flex esticada e a lista ocupa o que sobra — com flex-basis 0 e min-height 0
     a lista não empurra a altura da linha do grid. */
  .grid2 > .bloco-flags { display: flex; flex-direction: column; align-self: stretch; min-height: 0; }
  .grid2 > .bloco-flags > .flags { flex: 1 1 0; max-height: none; min-height: 220px; }
}
/* Impressão: teto e rolagem cortariam flags do papel. */
@media print {
  .bloco-flags > .flags { max-height: none; overflow: visible; }
}

/* ==========================================================================
   PORTAL DE BM — a tela de preenchimento (Fase 5, etapa 5b)

   Desenho aprovado ANTES do HTML: `docs/bm/tela-de-preenchimento-do-bm.md`.
   Critérios: `docs/bm/15-criterios-fase-5.md`.

   ⚠️ Usa SÓ os tokens que já existem acima, medidos nos dois temas. Cor nova
   aqui seria cor não medida — e a armadilha 8 do CLAUDE.md diz o que acontece
   com quem mede contraste sem forçar os dois temas.
   ========================================================================== */

.tabela-de-medicao {
  width: 100%;
  border-collapse: separate;   /* `collapse` quebra o sticky: a borda da célula
                                  fixa fica desenhada pela tabela, não pela
                                  célula, e ela some ao rolar. */
  border-spacing: 0;
  font-size: 14px;
}

.tabela-de-medicao thead th {
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--superficie);
  border-bottom: 1px solid var(--borda);
  text-align: left;
  padding: 8px 10px;
  white-space: nowrap;
}

.tabela-de-medicao td {
  padding: 6px 10px;
  border-bottom: 1px solid var(--line2);
  vertical-align: top;
}

/* ⚠️ AS DUAS COLUNAS CONGELADAS — e é `position: sticky`, NÃO uma segunda
   tabela. Congelar coluna duplicando a tabela quebraria a ordem do Tab: o campo
   da linha 1 levaria ao código da linha 2 (desenho §2.5). Aqui a ordem do DOM
   permanece a ordem visual, e o Tab funciona de graça. */
.tabela-de-medicao .col-codigo,
.tabela-de-medicao .col-descricao {
  position: sticky;
  background: var(--superficie);
  z-index: 2;
}
.tabela-de-medicao .col-codigo    { left: 0;     min-width: 90px; }
.tabela-de-medicao .col-descricao { left: 90px;  min-width: 280px; }
.tabela-de-medicao thead .col-codigo,
.tabela-de-medicao thead .col-descricao { z-index: 4; }

.tabela-de-medicao .col-descricao small {
  display: block;
  color: var(--texto-3);
}

.tabela-de-medicao .col-dinheiro,
.tabela-de-medicao .col-ja-medido,
.tabela-de-medicao .col-contagem {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;   /* dígito de largura fixa: coluna de
                                           dinheiro que dança ao trocar de valor
                                           é onde o olho perde a linha. */
}

.tabela-de-medicao .campo-medicao {
  width: 8ch;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* ⚠️ A LINHA EM FOCO — barra de acento de 6px, NAS DUAS PONTAS.
   Fundo colorido está nos "becos sem saída" do CLAUDE.md: o melhor tingimento
   desta paleta dá 1,27 (escuro) e 1,14 (claro), invisível. A barra dá 6,0/7,04.
   E são as duas pontas porque numa linha larga a barra da esquerda sai do campo
   de visão de quem está digitando na coluna do meio (desenho §2.4). */
.tabela-de-medicao .linha-do-bm:focus-within .col-codigo {
  box-shadow: inset 6px 0 0 var(--acento);
}
.tabela-de-medicao .linha-do-bm:focus-within .col-estado {
  box-shadow: inset -6px 0 0 var(--acento);
}

.tabela-de-medicao .linha-do-bm[data-estado="salvando"] .col-estado {
  color: var(--texto-3);
}

/* ⚠️ TRÊS CANAIS no estado de falha — cor, ícone e texto —, porque é o estado
   que não pode passar despercebido (`15` §2). E ele não some sozinho com o
   tempo: some quando o salvamento der certo. */
/* ⚠️ ESCOPADOS sob `.tabela-de-medicao` de propósito. Este arquivo é
   COMPARTILHADO com a RFP, que está em produção — e `.estado-erro` é nome
   genérico o bastante para alguém criar um igual lá amanhã. Regra de portal
   novo não pode vazar para tela em uso. */
.tabela-de-medicao .estado-erro,
.tabela-de-medicao .estado-conflito {
  color: var(--erro-fg);
  background: var(--erro-bg);
  border: 1px solid var(--erro-borda);
  border-radius: var(--r-ctl);
  padding: 1px 6px;
  font-weight: 600;
  white-space: normal;
}
.tabela-de-medicao .estado-salvo { color: var(--ok); white-space: nowrap; }

.tabela-de-medicao .linha-com-erro .col-codigo {
  box-shadow: inset 6px 0 0 var(--erro);
}

.tabela-de-medicao .linha-do-recado td {
  background: var(--erro-bg);
  border-bottom: 1px solid var(--erro-borda);
}

/* ⚠️ Os totais ficam colados na base da janela: quem digita a linha 300 precisa
   ver o total sem rolar até o fim de 411 linhas. */
.tabela-de-medicao tfoot td {
  position: sticky;
  bottom: 0;
  background: var(--superficie);
  border-top: 1px solid var(--borda);
  z-index: 3;
}
.tabela-de-medicao .total-do-bm td { font-size: 15px; }
.tabela-de-medicao .composicao-do-liquido td {
  color: var(--texto-2);
  font-size: 13px;
}

/* ==========================================================================
   PORTAL DE BM — a tela do SM (Fase 6, etapa 6b)

   Desenho aprovado ANTES do HTML: `docs/bm/tela-do-sm.md`.

   ⚠️ Escopado sob `.tabela-de-medicao`, pelo mesmo motivo do bloco da Fase 5:
   este arquivo é COMPARTILHADO com a RFP, que está em produção.
   ========================================================================== */

/* ⚠️ O valor lançado pelo Construtor é TEXTO, e o CSS reforça a diferença de
   NATUREZA que o HTML já faz — não a substitui. Se um dia virar campo, quem
   pega é `test_a_tela_NAO_TEM_campo_de_percentual_do_CONSTRUTOR`, não isto. */
.tabela-de-medicao .col-lancado {
  text-align: right;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  background: var(--line2);
}
.tabela-de-medicao .col-lancado small {
  display: block;
  color: var(--texto-2);
  font-weight: 400;
}

.tabela-de-medicao .col-proposta { min-width: 220px; }
.tabela-de-medicao .campo-proposta {
  width: 8ch;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.tabela-de-medicao .campo-justificativa {
  display: block;
  width: 100%;
  margin-top: 4px;
}

/* ⚠️ O CRITÉRIO ESCRITO, e ele é informação — não é o destaque. O `16` §1:
   "«40% de salto sobre a média dos BMs anteriores» é informação; destaque
   colorido sem explicação é enfeite." Por isso o sinal é TEXTO legível, e a cor
   só o separa da descrição. */
.tabela-de-medicao .sinal-de-risco {
  display: block;
  color: var(--alerta-fg);
  font-weight: 600;
}
.tabela-de-medicao .sinal-de-risco[data-sinal="fecha_a_linha"] {
  color: var(--erro-fg);
}

.abas-da-analise strong { border-bottom: 3px solid var(--acento); }
.abas-da-analise a { margin-left: var(--sp-4); }

/* ⚠⚠ A QUEBRA DO «RESPONDIDOS» na tela de envio — entrega 1, etapa 4.

   O número sai do SERVIDOR e NÃO acrescenta bloqueio: a trava de 100% já
   existia. Ele TORNA A TRAVA LEGÍVEL — antes o botão sumia sem dizer por quê.
   Por isso a aparência é de INFORMAÇÃO e não de alerta: sem cor de erro, sem
   ícone. Quem avisa que está bloqueado é o cartão de pendências, logo abaixo. */
.quebra-respondidos .quebra-total {
  margin: 0 0 var(--sp-2, 0.5rem);
  font-size: 1.05rem;
}
.quebra-respondidos .quebra-baldes {
  list-style: none;
  margin: 0;
  padding-left: var(--sp-3, 0.75rem);
}
.quebra-respondidos .quebra-baldes li {
  display: flex;
  gap: var(--sp-2, 0.5rem);
  max-width: 22rem;
  padding: 0.15rem 0;
}
/* O ponto do desenho ("· com preço 274"), e ele é decoração: fica no CSS,
   fora do HTML, para nao virar texto que leitor de tela anuncia. */
.quebra-respondidos .quebra-baldes li::before {
  content: "·";
  color: var(--borda);
}
.quebra-respondidos .quebra-baldes span {
  flex: 1 1 auto;
}
.quebra-respondidos .quebra-baldes b {
  font-variant-numeric: tabular-nums;
}
