/* ============================================================================
   EcoEsfera PWA — sistema de design F17 "Minimalista Moderna" (handoff
   Claude Design). Claro-e-quente (fundo #f7f5ee, bordas areia) com
   superfícies VERDE-NOITE pontuais (sidebar, faixa-horizonte, painel de
   marca do login). Campo, uma mão, sob sol (alvos ≥52px, foco visível) ×
   mesa (banco/SPO) × operação (admin). Vanilla, sem build (ADR-007).
   Fontes AUTO-HOSPEDADAS (offline-first, ADR-005 — nunca fonts.googleapis):
   Bricolage Grotesque (display) · Instrument Sans (corpo/UI) ·
   IBM Plex Mono (dados/CAR/hash).
   ========================================================================== */

/* ------------------------------------------------- fontes auto-hospedadas */
@font-face {
  font-family: "Bricolage Grotesque";
  src: url("/app/fonts/bricolage-grotesque-var.woff2") format("woff2-variations"),
       url("/app/fonts/bricolage-grotesque-var.woff2") format("woff2");
  font-weight: 400 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Instrument Sans";
  src: url("/app/fonts/instrument-sans-var.woff2") format("woff2-variations"),
       url("/app/fonts/instrument-sans-var.woff2") format("woff2");
  font-weight: 400 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/app/fonts/ibm-plex-mono-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "IBM Plex Mono";
  src: url("/app/fonts/ibm-plex-mono-500.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}

/* ---------------------------------------------------------------- tokens */
:root {
  color-scheme: light;
  /* paleta F17 (handoff): verde-noite/marca/ação + terras e areias */
  --verde-noite: #0d160f;   /* superfícies escuras (sidebar/faixa/aside)  */
  --verde: #1f4632;         /* verde-marca (identidade, botão primário)    */
  --verde-acao: #2c6e49;    /* verde ação (links, acentos)                 */
  --verde-folha: #7fce8f;   /* acento claro SOBRE superfícies escuras      */
  --verde-badge: #4cae63;   /* badge "concluído"                           */
  --terra: #9c6b30;         /* eyebrow terra, régua, chip piloto           */
  --areia: #f3e8d5;         /* fundo do chip piloto / atenção              */
  --ambar: #e9d9b8;         /* estado "em andamento" sobre verde-noite     */
  --pontilhado: #3c5a42;    /* linha pontilhada da faixa-horizonte         */
  --verde-claro: var(--verde-acao);  /* alias histórico (componentes)      */
  /* F21/v8: o azul do banco vira AZUL DE MESA (#2a5b86) — o #1d4ed8 anterior
     era azul de link genérico, forte demais ao lado das areias; o v8 o
     rebaixa ao tom de mesa de decisão (design/handoff-v8/TOKENS.md) */
  --azul: #2a5b86;          /* semântica preservada: o que é DO BANCO      */
  --azul-noite: #0c1520;    /* nav escura das superfícies de mesa           */
  --azul-chip: #e7eef4;     /* fundo de chip/realce na mesa                 */
  --cinza: #57674f;         /* texto-2                                     */
  --texto-3: #8a988c;       /* texto-3 (v8)                                */
  --erro: #b42318;          /* v8 — divergência de auditoria e erro REAL   */
  --fundo: #f7f5ee; --texto: #22301f;
  --toque: 52px;

  /* DARK MODE — tokens de SUPERFÍCIE (o dark re-declara tokens, não regra) */
  --superficie: #fff;        /* cartão, nav-mobile, top bar do shell        */
  --input-fundo: #fbfaf6;    /* fundo dos campos                            */
  --texto-botao: #f5f2ea;    /* texto sobre a ação primária                 */
  --icone-mascara: #fff;     /* "furo" dos ícones que mascaram o traço      */

  /* nomes semânticos (aliases; os antigos continuam válidos) */
  --cor-marca: var(--verde);          /* header, landing, identidade       */
  --cor-primaria: var(--verde);       /* ação primária (#1f4632)           */
  --cor-primaria-escura: var(--verde-acao);  /* hover da ação (clareia)    */
  --cor-info: var(--azul);            /* informação, "do banco"            */
  --cor-erro: var(--erro);            /* reservado: erro/divergência       */
  --cor-link: var(--verde-acao);      /* links (par dark: verde-folha)     */
  /* atenção terra/areia (pendência/prazo — nunca erro) */
  --cor-atencao: #8a5c26;             /* texto/borda de pendência          */
  --cor-atencao-fundo: var(--areia);
  --cor-atencao-faixa: #9c6b30;       /* faixa de atenção/pendência (terra) */
  /* acentos por papel (RBAC também na apresentação) */
  --acento-campo: var(--verde-acao);
  --acento-banco: var(--azul);
  --acento-operacao: #3f4a54;         /* grafite do admin (v8)             */
  --grafite-noite: #161b1e;           /* nav escura da operação (v8)       */
  --acento: var(--acento-campo);      /* redefinido pela superfície ativa  */
  /* neutros de estrutura (areias) */
  --borda: #e6e2d4;
  --borda-2: #dfe2d4;
  --borda-forte: #d8d4c6;
  --sombra-1: 0 1px 2px rgba(30, 45, 32, .06);
  --sombra-2: 0 20px 44px -24px rgba(30, 45, 32, .35);   /* cartão claro   */
  --sombra-img-escuro: 0 10px 24px -12px rgba(0, 0, 0, .7);
  /* escala de espaço (4/8pt) */
  --esp-1: 4px; --esp-2: 8px; --esp-3: 12px; --esp-4: 16px;
  --esp-5: 24px; --esp-6: 32px;
  /* raios F17: imagens 8 · inputs/botões/nav 9-10 · cartões 12-14 ·
     faixas/cartões grandes 16 · chips 999 */
  --raio-img: 8px; --raio-cartao: 14px; --raio-controle: 10px;
  --raio-interno: 9px; --raio-faixa: 16px;
  /* papéis tipográficos (html { font-size:16px } é a base F17) */
  --fonte-display: "Bricolage Grotesque", system-ui, sans-serif;
  --fonte-corpo: "Instrument Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --fonte-mono: "IBM Plex Mono", ui-monospace, Consolas, monospace;
  --tipo-display: 700 clamp(1.7rem, 5vw, 2rem)/1.2 var(--fonte-display);
  --tipo-titulo: 700 1.45rem/1.3 var(--fonte-display);
  --tipo-corpo: 400 .95rem/1.5 var(--fonte-corpo);
  --tipo-detalhe: 600 .84rem/1.4 var(--fonte-corpo);
  --tipo-dado: 500 .95rem/1.4 var(--fonte-mono);
  /* foco visível (obrigatório em TUDO) */
  --anel-foco: 3px solid var(--cor-info);
  /* navegação persistente */
  /* F21/v8: a barra inferior SÓ existe no celular, então há UMA altura, não
     duas. Era 60px aqui e 74px cru no offset do FAB (app.css, camada mobile)
     — o TOKENS.md §Espaçamento fixa 74px, que também dá folga ao alvo de
     toque ≥44px. Token único; o 74 cru virou var(). */
  --nav-altura: 74px;                 /* barra inferior (campo)            */
  --nav-largura: 256px;               /* barra lateral (≥1024px) — v8      */
  /* F14.4b — breakpoint desktop ÚNICO (media query não lê var(); o valor
     1024px está fixado nas @media abaixo e no matchMedia do app.js) */
  --bp-desktop: 1024px;

  /* cores da cerca (landing) como TOKEN — retonalizadas às areias F17 */
  --cerca-trilho: #d8d4c6; --cerca-mourao: #aca894;

  /* ======================================================================
     F21 · camada v8 (design/handoff-v8/TOKENS.md) — ADITIVA
     Os tokens F17 acima seguem válidos; estes preenchem o que o v8 nomeia e
     o F17 não tinha. Token novo NASCE AQUI e no TOKENS.md do pacote, ou não
     nasce (regra do guardiao-design-ecoesfera).
     ====================================================================== */
  --texto-titulo: #10231a;      /* h1/h2 display (mais escuro que o corpo) */
  --divisoria: #f0eee7;         /* linha interna de cartão/lista            */
  --cartao-sutil: #fbfaf6;      /* cabeçalho de tabela, ladrilho de KPI     */
  --positivo: #1d6b43;          /* texto de estado positivo                 */
  --positivo-fundo: #e3efe6;    /* fundo do chip positivo                   */
  --erro-fundo: #fbeceb;        /* fundo de divergência (nunca pendência)   */
  --erro-sobre-fundo: #7a2019;  /* texto sobre --erro-fundo                 */
  --fundo-mesa: #f6f7f9;        /* app do banco/SPO   · borda --borda-mesa  */
  --borda-mesa: #e2e6ec;
  --fundo-operacao: #f6f7f7;    /* app do admin       · borda --borda-oper. */
  --borda-operacao: #e4e7e7;
  --sombra-shell: 0 24px 60px -30px rgba(30, 45, 32, .45);
  --areia-celular: #f3e9d6;     /* §Terra "Fundo (celular)" — 7b, 8h, 8i    */
  --porteira-atual-borda: #c9a45f;  /* marcador da porteira atual (era cru) */
  --azul-escuro: #7fb2e0;       /* §Azul de mesa "Azul no escuro"           */
  --azul-escuro-2: #9ecbf0;     /* idem, variante clara                     */
  /* F21.2.1 — texto SOBRE painel escuro. A trilha de porteiras (faixa do PC
     e trilha vertical do celular) fica sobre --verde-noite nos DOIS temas,
     então não pode usar --texto/--cinza (que invertem). Os quatro valores
     são os do §Modo escuro do TOKENS.md; nasceram aqui por estarem crus e
     repetidos em .porteira-h.* e no style= inline de .tv-*. */
  --painel-escuro-texto: #f5f2ea;             /* §Modo escuro · primário    */
  --painel-escuro-texto-2: #9db3a0;           /* §Modo escuro · secundário  */
  --painel-escuro-texto-3: #7c8f80;           /* §Modo escuro · terciário   */
  --painel-escuro-borda: rgba(255, 255, 255, .2);  /* §Modo escuro · borda  */
  /* medidas do v8 que a escala --esp-* não cobre (§Espaçamento e forma) */
  --pad-main-pc: 36px 44px 44px;
  --pad-nav-lateral: 24px 16px;
  --pad-linha-tabela: 18px 24px;
  --pad-linha-total: 16px 24px;
  --gap-secao: 22px;              /* a escala tem 24; o v8 usa 22 em seção  */
  --raio-controle-celular: 11px;  /* botão no celular (PC = --raio-interno) */
  --raio-destaque-celular: 18px;  /* cartão de destaque no celular          */
  --raio-painel: 20px;            /* painel/shell                           */
  /* trilha pontilhada das porteiras (horizontal no PC, vertical no celular) */
  --trilha-pontilhada-h:
    repeating-linear-gradient(90deg, var(--pontilhado) 0 10px, transparent 10px 22px);
  --trilha-pontilhada-v:
    repeating-linear-gradient(180deg, var(--pontilhado) 0 7px, transparent 7px 16px);
}

/* superfícies (classe no <body>, definida pelo app.js após o login) */
body.superficie-campo    { --acento: var(--acento-campo); }
body.superficie-mesa     { --acento: var(--acento-banco); }
body.superficie-operacao { --acento: var(--acento-operacao); }

/* ------------------------------------------------------------------ base */
:focus-visible { outline: var(--anel-foco); outline-offset: 2px; border-radius: 4px; }
* { box-sizing: border-box; }
/* o atributo hidden SEMPRE vence display:flex/grid de autor (sem isto, o
   header/nav "hidden" aparecia na landing pré-login) */
[hidden] { display: none !important; }
html { font-size: 16px; }
body {
  margin: 0; font: var(--tipo-corpo);
  background: var(--fundo); color: var(--texto); line-height: 1.5;
  padding-bottom: 88px;
}
/* logado: abre espaço para a barra inferior + safe-area (uma mão, polegar) */
body.superficie-campo, body.superficie-mesa, body.superficie-operacao {
  padding-bottom: calc(var(--nav-altura) + env(safe-area-inset-bottom, 0px) + var(--esp-5));
}
h1 { font: var(--tipo-titulo); letter-spacing: -.02em; margin: var(--esp-3) 0 var(--esp-4); text-wrap: balance; }
h2 { font-family: var(--fonte-display); font-size: 1.15rem; font-weight: 600;
  margin: var(--esp-5) 0 var(--esp-2); text-wrap: balance; }
h3 { font-family: var(--fonte-display); font-size: 1rem; font-weight: 600;
  margin: var(--esp-4) 0 var(--esp-1); }
/* subtítulo de tela (abaixo do h1 — segue heading para leitores de tela,
   mas com voz de apoio) */
h2.subtitulo-tela {
  font: 400 .95rem/1.5 var(--fonte-corpo); color: var(--cinza);
  margin: var(--esp-1) 0 0;
}
p  { margin: .5rem 0; }
main { padding: var(--esp-4); max-width: 480px; margin: 0 auto; width: 100%; }
body.pre-login main { max-width: 640px; }

/* movimento: transform/opacity apenas; a ÚNICA animação orquestrada é a
   porteira abrindo (§1.2). Quem pediu menos movimento, recebe menos. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* ------------------------------------------------------------------ topo */
#topo {
  display: flex; justify-content: space-between; align-items: center;
  gap: .5rem; padding: .75rem 1rem; background: var(--cor-marca); color: #fff;
  border-bottom: 1px solid rgba(255, 255, 255, .12);
}
#topo #quem { font-weight: 600; font-size: .9rem; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.marca-topo { display: flex; align-items: center; gap: .5rem;
  font-family: var(--fonte-display); font-weight: 700; font-size: 1.05rem;
  flex: 0 0 auto; }
.marca-icone { width: 30px; height: 30px; border-radius: 8px;
  box-sizing: border-box; flex: 0 0 auto;
  filter: drop-shadow(0 0 6px rgba(143, 206, 159, .25)); }
/* Nota "ambiente de demonstração · valores simulados" — o rótulo ADR-007
   (emenda 2026-07-24, Chefe: "redesenhar discreto"). Deixou de ser pílula
   laranja/marca-d'água: agora é NOTA NEUTRA discreta (sem preenchimento, cor
   suave, peso normal — legenda, não selo de alerta). Visível em TODA tela: no
   header do shell logado (PC e mobile) e no cartão do pré-login
   (.chip-piloto-auth). O rótulo nunca some; "(valor simulado)" segue nos valores. */
.chip-piloto {
  display: inline-flex; align-items: center; flex: 0 0 auto;
  background: none; color: var(--texto-3); border-radius: 999px;
  font-size: .72rem; font-weight: 400; padding: .28rem .2rem;
  white-space: nowrap; letter-spacing: .01em;
}
/* no pré-login o chip fica no alto do cartão, à ESQUERDA (o canto direito é do
   botão flutuante de tema — evitar a colisão no mobile), discreto */
.chip-piloto-auth { align-self: flex-start; margin-bottom: var(--esp-2); }

/* marca COMPACTA no topo do cartão de login — SÓ no mobile (o aside verde-noite
   de marca some <1024px). No PC fica oculta (o aside já traz a marca). */
.auth-marca-compacta {
  display: flex; align-items: center; gap: 12px; margin-bottom: var(--esp-4);
}
.auth-marca-compacta > img {
  width: 40px; height: 40px; object-fit: contain; flex: 0 0 auto;
  filter: drop-shadow(0 0 6px rgba(143, 206, 159, .25));
}
.auth-marca-compacta-wm {
  display: block; font-family: var(--fonte-display); font-weight: 700;
  font-size: 22px; line-height: 1.1; letter-spacing: -.01em;
}
.auth-marca-compacta-wm .wm-eco { color: var(--verde-acao); }
.auth-marca-compacta-wm .wm-esfera { color: var(--texto); }
.auth-marca-compacta-slogan {
  display: block; margin-top: 3px; font-size: 10px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--texto-3);
}
.topo-dir { display: flex; align-items: center; gap: .6rem;
  flex: 1 1 auto; min-width: 0; justify-content: flex-end; }
.topo-dir #btn-sair { flex: 0 0 auto; }
#btn-sair { width: auto; min-height: 40px; margin: 0; padding: .4rem .8rem;
  background: rgba(255, 255, 255, .18); border: 1px solid rgba(255, 255, 255, .35);
  font-size: .9rem; }
#btn-sair:hover { background: rgba(255, 255, 255, .28); }
/* F15.1 — badge de avisos não lidos no header (sino + contagem) */
#badge-avisos {
  display: inline-flex; align-items: center; gap: .25rem; flex: 0 0 auto;
  color: #fff; text-decoration: none; min-height: 40px; padding: .3rem .55rem;
  background: rgba(255, 255, 255, .18); border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, .35);
}
#badge-avisos:hover { background: rgba(255, 255, 255, .28); }
#badge-avisos .icone svg { width: 18px; height: 18px; display: block; }
#badge-avisos .badge-num { font-weight: 700; font-size: .85rem; }

/* F15.1 — itens do inbox: NÃO lido em negrito; lido some do destaque */
.cartao.aviso.lido strong { font-weight: 400; }
.cartao.aviso.nao-lido { border-left: 4px solid var(--cor-marca, #1f4632); }
.aviso-acoes { display: flex; align-items: center; gap: .75rem;
  margin-top: .4rem; }
.aviso-acoes button { width: auto; margin: 0; padding: .35rem .7rem;
  font-size: .85rem; min-height: 36px; }

/* ------------------------------------------------- navegação persistente */
/* barra INFERIOR (campo sempre; mesa/operação abaixo de 1080px) — §1.3 */
#nav-app {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 20;
  display: flex; overflow-x: auto; background: var(--superficie);
  border-top: 1px solid var(--borda);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  box-shadow: 0 -2px 10px rgba(30, 45, 32, .08);
}
#nav-app a {
  flex: 1 1 0; min-width: 68px; min-height: var(--nav-altura);
  display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: 2px; padding: var(--esp-1) var(--esp-1);
  font-size: .75rem; font-weight: 700; color: var(--cinza);
  text-decoration: none; border-top: 3px solid transparent;
  white-space: nowrap;
}
#nav-app a[aria-current="page"] { color: var(--acento); border-top-color: var(--acento); }
#nav-app .icone svg { width: 24px; height: 24px; display: block; }

/* o aviso offline convive com a barra: sobe para faixa acima dela (§1.3) */
#rodape-offline {
  position: fixed; bottom: 0; left: 0; right: 0; z-index: 25;
  background: var(--cinza); color: #fff; text-align: center; padding: .75rem;
  font-weight: 600;
}
body.superficie-campo #rodape-offline,
body.superficie-mesa #rodape-offline,
body.superficie-operacao #rodape-offline {
  bottom: calc(var(--nav-altura) + env(safe-area-inset-bottom, 0px));
}

/* barra LATERAL (todas as superfícies logadas, ≥1024px) — F14.4b/F16.0:
   shell de app desktop. A mesma marcação, outro layout: nav full-height à
   esquerda (marca no topo, usuário + Sair no rodapé) + TOP BAR de contexto
   (título da tela à esquerda, identidade à direita) + área de conteúdo larga.
   F16.0 aposenta o quadro-440px do campo: produtor/fornecedor usam o MESMO
   esqueleto — a identidade (acento verde, largura calma, densidade menor)
   vem dos tokens por superfície e do bloco 3) CAMPO, abaixo. O item ativo
   usa var(--acento): azul na mesa, VERDE no campo, por construção. */
@media (min-width: 1024px) {
  body.superficie-campo, body.superficie-mesa, body.superficie-operacao {
    display: grid; min-height: 100vh; padding-bottom: 0;
    --altura-topo: 75px;   /* altura real do top bar (F17.9: âncora do sticky) */
    grid-template-columns: var(--nav-largura) minmax(0, 1fr);
    grid-template-rows: auto 1fr;
    grid-template-areas: "nav topo" "nav main";
  }
  /* top bar de contexto F17: fundo #f7f5ee, borda inferior areia, título de
     contexto discreto à esquerda; chip piloto + sino à direita. STICKY no topo
     (F17.9: a faixa laranja saiu — antes ela cobria o topo; agora o próprio top
     bar fica fixo ao rolar, sem deixar vão branco). */
  body.superficie-campo #topo, body.superficie-mesa #topo, body.superficie-operacao #topo {
    grid-area: topo; background: var(--fundo); color: var(--texto);
    border-bottom: 1px solid var(--borda); padding: 15px 44px;
    position: sticky; top: 0; z-index: 6;
  }
  body.superficie-campo #topo .marca-topo,
  body.superficie-mesa #topo .marca-topo,
  body.superficie-operacao #topo .marca-topo { display: none; }
  body.superficie-campo #titulo-contexto,
  body.superficie-mesa #titulo-contexto, body.superficie-operacao #titulo-contexto {
    display: block; font-family: var(--fonte-corpo); font-weight: 600;
    font-size: .875rem; color: var(--cinza);
  }
  body.superficie-campo #topo #quem,
  body.superficie-mesa #topo #quem, body.superficie-operacao #topo #quem {
    color: var(--texto-3); font-size: .8rem;
  }
  /* chip "Piloto · simulado" (areia/terra, raio 999) só no shell de PC */
  body.superficie-campo .chip-piloto,
  body.superficie-mesa .chip-piloto, body.superficie-operacao .chip-piloto {
    display: inline-flex; align-items: center; flex: 0 0 auto;
    background: var(--areia); color: var(--terra); border-radius: 999px;
    font-size: .75rem; font-weight: 700; padding: .3rem .7rem;
    white-space: nowrap;
  }
  /* o pill do sino (avisos) na top bar clara: borda areia + fundo branco;
     a contagem em verde ação */
  body.superficie-campo #badge-avisos,
  body.superficie-mesa #badge-avisos, body.superficie-operacao #badge-avisos {
    background: var(--superficie); border-color: var(--borda-2);
    color: var(--texto);
  }
  body.superficie-campo #badge-avisos .badge-num,
  body.superficie-mesa #badge-avisos .badge-num,
  body.superficie-operacao #badge-avisos .badge-num {
    color: var(--verde-acao);
  }
  body.superficie-campo #badge-avisos:hover,
  body.superficie-mesa #badge-avisos:hover, body.superficie-operacao #badge-avisos:hover {
    background: var(--fundo);
  }
  /* o Sair vive no rodapé da barra lateral (nav-rodape) nesta composição —
     INC-F5: o menu de perfil do header (gatilho + painel) é só do celular */
  body.superficie-campo #btn-sair, body.superficie-mesa #btn-sair, body.superficie-operacao #btn-sair,
  body.superficie-campo .menu-perfil, body.superficie-mesa .menu-perfil, body.superficie-operacao .menu-perfil { display: none; }
  body.superficie-campo main, body.superficie-mesa main, body.superficie-operacao main { grid-area: main; }
  /* F17 — sidebar VERDE-NOITE (todas as personas: campo/mesa/operação
     compartilham o mesmo shell; o que muda por papel é o menu, não a casca).
     Fundo #0d160f, padding 24px 16px; itens raio 10; ativo em par
     verde-folha translúcido; hover branco-6%. Idêntica nos DOIS temas. */
  body.superficie-campo #nav-app, body.superficie-mesa #nav-app, body.superficie-operacao #nav-app {
    grid-area: nav; position: sticky; top: 0; align-self: start;
    min-height: 100vh; max-height: 100vh;
    overflow-y: auto; overflow-x: hidden;
    display: flex; flex-direction: column;
    border-top: 0; border-right: 0;
    box-shadow: none; padding: 24px 16px;
    background: var(--verde-noite); z-index: 5;
  }
  /* o hover vem ANTES do aria-current de propósito: mesma especificidade,
     o ativo vence por ordem */
  body.superficie-campo #nav-app a, body.superficie-mesa #nav-app a, body.superficie-operacao #nav-app a {
    flex: 0 0 auto; flex-direction: row; justify-content: flex-start;
    gap: var(--esp-3); min-height: 44px; min-width: 0;
    padding: 10px 14px; font-size: .875rem; font-weight: 500;
    color: #9db3a0; border-top: 0; border-left: 0;
    border-radius: var(--raio-controle); margin: 2px 0;
    transition: background-color .15s ease, color .15s ease;
  }
  body.superficie-campo #nav-app a:hover,
  body.superficie-mesa #nav-app a:hover, body.superficie-operacao #nav-app a:hover {
    background: rgba(255, 255, 255, .06); color: #f5f2ea;
  }
  body.superficie-campo #nav-app a[aria-current="page"],
  body.superficie-mesa #nav-app a[aria-current="page"],
  body.superficie-operacao #nav-app a[aria-current="page"] {
    background: rgba(127, 206, 143, .14); color: var(--verde-folha);
    font-weight: 600;
  }
  /* marca no topo e usuário+Sair no rodapé da barra (só nesta composição) */
  body.superficie-campo #nav-app .nav-extra,
  body.superficie-mesa #nav-app .nav-extra,
  body.superficie-operacao #nav-app .nav-extra { display: flex; }
  .nav-marca {
    align-items: center; gap: 10px;
    padding: var(--esp-2) var(--esp-2) var(--esp-5);
  }
  .nav-marca img {
    width: 36px; height: 36px; flex: 0 0 auto;
    filter: drop-shadow(0 0 6px rgba(143, 206, 159, .25));
  }
  .nav-marca-texto { display: flex; flex-direction: column; min-width: 0; }
  .nav-wordmark {
    font-family: var(--fonte-display); font-weight: 700; font-size: 19px;
    line-height: 1.15; letter-spacing: -.01em;
  }
  .wm-eco { color: var(--verde-folha); }
  .wm-esfera { color: #f5f2ea; }
  .nav-slogan {
    font-size: 10px; font-weight: 700; letter-spacing: .16em;
    text-transform: uppercase; color: #5f7a64; margin-top: 2px;
    white-space: nowrap;
  }
  /* rodapé: cartão translúcido com o responsável logado sempre à vista
     (RBAC também na apresentação) + Sair outline */
  .nav-rodape {
    margin-top: auto; flex-direction: column; gap: var(--esp-2);
    background: rgba(255, 255, 255, .06); border-radius: 12px;
    padding: var(--esp-3);
  }
  .nav-usuario {
    font-size: 13px; font-weight: 600; color: #f5f2ea; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .nav-papel {
    font-size: 12px; color: #9db3a0; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .nav-rodape button, .nav-rodape button.secundario {
    margin: 0; min-height: 40px; font-size: .875rem;
    background: none; color: #f5f2ea;
    border: 1px solid rgba(255, 255, 255, .2); box-shadow: none;
  }
  .nav-rodape button:hover, .nav-rodape button.secundario:hover {
    background: rgba(255, 255, 255, .08); border-color: rgba(255, 255, 255, .35);
  }
  body.superficie-campo #rodape-offline, body.superficie-mesa #rodape-offline, body.superficie-operacao #rodape-offline { bottom: 0; }
}

/* --------------------------------------------------------------- larguras
   campo = telas curtas (≤480px, atual); mesa = tabelas largas (900px+). */
@media (min-width: 720px) {
  body.superficie-mesa main, body.superficie-operacao main {
    max-width: 960px; padding: var(--esp-5) var(--esp-6);
  }
  .duas-colunas { grid-template-columns: 1fr 1fr; }
}

/* -------------------------------------------------------------- controles */
button, .botao {
  display: block; width: 100%; min-height: var(--toque);
  font-size: .95rem; font-weight: 700; border: 0;
  font-family: var(--fonte-corpo);
  border-radius: var(--raio-controle);
  padding: .75rem 1rem; margin: .6rem 0; cursor: pointer; text-align: center;
  background: var(--cor-primaria); color: var(--texto-botao); text-decoration: none;
  box-shadow: var(--sombra-1);
  transition: background-color .15s ease, box-shadow .15s ease, transform .1s ease;
}
button:hover, .botao:hover { background: var(--cor-primaria-escura); }
button:active, .botao:active { transform: translateY(1px); box-shadow: none; }
button.secundario, .botao.secundario {
  background: var(--superficie); color: var(--texto); border: 1px solid var(--borda-forte);
  box-shadow: none;
}
button.secundario:hover, .botao.secundario:hover { background: var(--fundo); border-color: var(--cinza); }
button:disabled { opacity: .5; cursor: not-allowed; transform: none; }
input, select, textarea {
  width: 100%; min-height: var(--toque); font-size: .95rem;
  font-family: inherit; color: var(--texto); background: var(--input-fundo);
  padding: .65rem .75rem; border: 1px solid var(--borda-forte);
  border-radius: var(--raio-interno); margin: .3rem 0 1rem;
  transition: border-color .15s ease;
}
input:focus-visible, select:focus-visible, textarea:focus-visible {
  border-color: var(--cor-info); outline-offset: 0;
}
/* F17.3 — o reset acima (largura 100% + alvo 52px) é para campo de texto;
   checkbox/radio vivem inline em labels flex (mini-licitação, assistente de
   marcos): tamanho próprio ≥22px e o verde da marca no estado marcado
   (accent-color lê o token — par dark por construção) */
input[type="checkbox"], input[type="radio"] {
  width: 22px; height: 22px; min-height: 22px; flex: 0 0 auto;
  margin: 0; padding: 0; accent-color: var(--verde-acao);
}
label { font-weight: 650; font-size: .84rem; display: block; margin-top: .5rem; }

/* dados comparáveis (CAR, CNPJ, hash, valores): mono + dígito tabular §1.2 */
.dado, .campo-doc {
  font: var(--tipo-dado); font-variant-numeric: tabular-nums;
  letter-spacing: .02em; word-break: break-all;
}
input.campo-doc { font-size: 1rem; text-transform: none; }

/* ============ F21 · primitivas de DADO do v8 (pares de app.js) ============
   `.dado` (acima) quebra em qualquer caractere (`break-all`) — bom para um CAR
   de 47 caracteres num cartão estreito, RUIM para data e valor, que o v8 manda
   nunca quebrar. Por isso a primitiva nova é separada em vez de alterar a
   antiga: `.dado-v8` é nowrap por padrão e só flui com `.quebra`. */
.dado-v8 {
  font-family: var(--fonte-mono); font-weight: 500;
  font-variant-numeric: tabular-nums; letter-spacing: .02em;
  white-space: nowrap;
}
.dado-v8.quebra { white-space: normal; word-break: break-all; }
/* em flex, a coluna de dado não encolhe: só o texto descritivo flui (v8 §D) */
.linha-dado { display: flex; gap: var(--esp-3); align-items: baseline; }
.linha-dado > .dado-v8 { flex: 0 0 auto; }

/* ladrilho de KPI (v8 8a/8e) — sempre dentro de .grade-kpi, nunca solto */
.grade-kpi {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 1px; background: var(--borda); border: 1px solid var(--borda);
  border-radius: var(--raio-cartao); overflow: hidden;
}
.kpi-ladrilho { background: var(--cartao-sutil); padding: 16px 18px; }
.kpi-rotulo {
  font-size: .69rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--texto-3);
}
.kpi-valor {
  font-family: var(--fonte-mono); font-weight: 500; font-size: 1.5rem;
  font-variant-numeric: tabular-nums; white-space: nowrap;
  color: var(--verde); margin-top: 6px;
}
.kpi-valor.positivo { color: var(--positivo); }   /* 8d, ladrilho "Saque disponível" */
.kpi-valor.atencao { color: var(--cor-atencao-faixa); }
.kpi-valor.erro { color: var(--erro); }
.kpi-apoio { font-size: .69rem; color: var(--texto-3); margin-top: 2px; }
/* o sotaque da superfície pinta o número; os TONS semânticos (positivo/
   atenção/erro) sempre vencem — por isso os três `:not()`, não dois. Sem o
   `:not(.positivo)`, um ladrilho positivo numa tela de mesa sairia azul. */
body.superficie-mesa .kpi-valor:not(.atencao):not(.erro):not(.positivo) { color: var(--azul); }
body.superficie-operacao .kpi-valor:not(.atencao):not(.erro):not(.positivo) { color: var(--acento-operacao); }

/* "Ver detalhes técnicos" — o que é ilegível para leigo fica recolhido aqui */
.detalhes-tecnicos { margin-top: var(--esp-3); }
.detalhes-tecnicos > summary {
  cursor: pointer; font-size: .8rem; font-weight: 600; color: var(--cinza);
  padding: 6px 0; list-style: none; display: flex; align-items: center; gap: 6px;
  min-height: 44px;   /* alvo de toque (regra E do guardião) */
}
.detalhes-tecnicos > summary::-webkit-details-marker { display: none; }
.detalhes-tecnicos > summary::before {
  content: "▸"; font-size: .7rem; transition: transform .15s;
}
.detalhes-tecnicos[open] > summary::before { transform: rotate(90deg); }
.detalhes-tecnicos > summary:hover { color: var(--cor-link); }
.dt-corpo {
  border-left: 2px solid var(--borda); padding: var(--esp-2) 0 var(--esp-2) var(--esp-3);
  display: flex; flex-direction: column; gap: var(--esp-2);
  font-family: var(--fonte-mono); font-size: .72rem; color: var(--texto-3);
  word-break: break-all;
}

/* ---------------------------------------------------------------- cartões */
.cartao {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio-cartao);
  padding: var(--esp-4); margin: var(--esp-3) 0; box-shadow: var(--sombra-1);
}
.cartao > h2:first-child, .cartao > h3:first-child { margin-top: 0; }
/* cartão inteiro como alvo de navegação (lista → detalhe) */
.cartao-link {
  display: block; color: inherit; text-decoration: none;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.cartao-link:hover { border-color: var(--acento); box-shadow: var(--sombra-2); }
.cartao.do-produtor { border-left: 4px solid var(--verde-claro); }
.cartao.do-banco { border-left: 4px solid var(--azul); }
.cartao.atencao { border-left: 4px solid var(--cor-atencao); background: #fffdf5; }

/* INC-F3 — MINI-CARD (design-system-agro): a moldura única das telas de
   detalhe read-only (evidências, marcos do projeto, veredito do imóvel).
   Mesma base visual do .cartao (fundo/borda/raio/sombra) + um cabeçalho
   título↔selo em linha — o selo é sempre o badge JÁ existente da tela
   (.estado.* / .marco-status.*), nunca uma cor nova. */
.mini-card {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio-cartao);
  padding: var(--esp-4); margin: var(--esp-3) 0; box-shadow: var(--sombra-1);
}
.mini-card.atencao { border-left: 4px solid var(--cor-atencao); background: #fffdf5; }
[data-theme="dark"] .mini-card.atencao { background: #221c0c; }
.mini-card-cabeca {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: .5rem .75rem;
}
.mini-card-cabeca > strong { font-size: 1rem; }
.mini-card-cabeca .estado, .mini-card-cabeca .marco-status { margin-top: 0; }
.mini-card-sub { color: var(--cinza); font-size: .8rem; margin-top: .3rem; }
.mini-card > *:last-child { margin-bottom: 0; }

/* notas e textos de apoio (substitui o .vazio desalinhado das telas velhas) */
.nota { color: var(--cinza); font-size: .9rem; text-align: left; margin: .5rem 0; }
.nota-fina { color: var(--cinza); font-size: .8rem; text-align: left; margin: .4rem 0; }
.eyebrow { font: var(--tipo-detalhe); color: var(--cinza);
  letter-spacing: .08em; text-transform: uppercase; margin-top: var(--esp-6); }

/* --------------------------------------------------------------- badges */
.estado {
  display: inline-block; font-weight: 700; padding: .25rem .6rem;
  border-radius: 999px; font-size: .9rem; margin-top: .4rem;
}
.estado.criado, .estado.entrega_confirmada { background: #dbeafe; color: var(--azul); }
.estado.carimbado { background: #e0e7ff; color: #3730a3; }
.estado.retido { background: #e3efdd; color: var(--verde); }
.estado.liberado, .estado.sacavel { background: #d3e9cf; color: var(--verde); }
.estado.contestado, .estado.verificacao_nao_concluida {
  background: var(--cor-atencao-fundo); color: var(--cor-atencao); }
.estado.divergencia_detectada { background: #fee2e2; color: var(--erro); }
/* F14.2 — vereditos do imóvel: atendido=verde (positivo), em_processamento=
   neutro azul (é fila, não veredito — ADR-004) */
.estado.pre_requisitos_atendidos { background: #e3efdd; color: var(--verde); }
.estado.em_processamento { background: #dbeafe; color: var(--azul); }
/* F15.3 — dossiê da mesa: vereditos do edital e sinais backend-only.
   satisfeito/sem-sinal=verde (fato positivo); sinal_detectado=atenção
   (SINAL informativo ao banco — nunca veredito de crédito, ADR-004) */
.estado.criterio_satisfeito, .estado.sem_sinal_relevante {
  background: #e3efdd; color: var(--verde); }
.estado.sinal_detectado {
  background: var(--cor-atencao-fundo); color: var(--cor-atencao); }
/* F15.5 — fila de vistoria: status do relatório do SPO. sem_relatorio =
   neutro (fato: nada submetido); com_relatorio = positivo factual;
   com_discrepancias = atenção (divergência auditor × sistema — a leitura é
   do banco/SPO, ADR-004) */
.estado.sem_relatorio { background: #ece8dc; color: var(--cinza); }
.estado.com_relatorio { background: #e3efdd; color: var(--verde); }
.estado.com_discrepancias {
  background: var(--cor-atencao-fundo); color: var(--cor-atencao); }
.erro { color: var(--erro); font-weight: 600; }
.vazio, .carregando { color: var(--cinza); text-align: center; padding: 2rem 0; }

/* estado vazio COM AÇÃO (§1.3): convite, não beco */
.vazio-acao {
  text-align: center; padding: var(--esp-6) var(--esp-4);
  background: var(--superficie); border: 1px dashed var(--borda-forte);
  border-radius: var(--raio-cartao); margin: var(--esp-4) 0;
}
.vazio-acao p { color: var(--cinza); margin: var(--esp-2) 0 var(--esp-4); }
.vazio-acao .icone svg { width: 44px; height: 44px; margin: 0 auto; color: var(--cinza); }

/* F19.3 — painel de agregados (SPO): grade de estatísticas HONESTAS (números
   reais do piloto, nunca inflados). Vale em PC e mobile. */
.painel-stats {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 0 0 16px;
}
.painel-stat {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: 14px; padding: 16px 18px;
}
.painel-stat-num {
  font-family: var(--fonte-display); font-weight: 700; font-size: 26px;
  color: var(--texto); line-height: 1.1; font-variant-numeric: tabular-nums;
}
.painel-stat-rot { font-size: 12px; color: var(--cinza); margin-top: 4px; }
@media (min-width: 1024px) {
  .painel-stats { grid-template-columns: repeat(4, 1fr); }
}

/* F19.4 — campo de busca client-side (imóveis) */
.busca-campo {
  width: 100%; box-sizing: border-box; margin: 0 0 var(--esp-3);
  background: var(--superficie); border: 1px solid var(--borda-forte);
  border-radius: 12px; padding: 12px 15px; font-size: 15px; color: var(--texto);
}

/* zona de upload (§1.3): alvo grande, toque abre o picker */
.zona-upload {
  display: block; min-height: 96px; background: var(--superficie);
  border: 2px dashed var(--borda-forte); border-radius: var(--raio-cartao);
  padding: var(--esp-4); text-align: center; color: var(--cinza);
  cursor: pointer; margin: .3rem 0 1rem;
}
.zona-upload:hover { border-color: var(--cor-primaria); }

/* cartão de fornecedor (§1.3 — diretório F14.3) */
.cartao-fornecedor strong { font-size: 1.1rem; display: block; }

#qr-grande { width: 100%; max-width: 320px; margin: 1rem auto; display: block; }
.valor-simulado::after { content: " (valor simulado)"; font-size: .8em; color: var(--cinza); }

/* F15.3 — carteira da mesa do banco (composição de campo <1024: linhas
   empilhadas dentro de um cartão; na mesa >=1024 vira .tabela-mesa) */
.carteira-linha {
  display: flex; justify-content: space-between; align-items: center;
  gap: .6rem; flex-wrap: wrap; padding: .45rem 0;
  border-top: 1px solid var(--borda);
}
.carteira-linha:first-child { border-top: 0; padding-top: 0; }
.carteira-linha .estado { margin-top: 0; }
.carteira-numeros { white-space: nowrap; }
.carteira-total { font-weight: 700; }

/* F15.3 — dossiê do projeto (banco/SPO) */
.dossie-cena { margin-top: .5rem; }

/* F15.3 — relatório K.1 renderizado (markdown SEGURO — logica.js) */
.relatorio-md { margin: .5rem 0; }
.relatorio-md h1 { font-size: 1.25rem; margin: .8rem 0 .3rem; }
.relatorio-md h2 { font-size: 1.1rem; margin: .8rem 0 .3rem; }
.relatorio-md h3, .relatorio-md h4 { font-size: 1rem; margin: .6rem 0 .2rem; }
.relatorio-md p, .relatorio-md li { font-size: .92rem; line-height: 1.45; }
.relatorio-md ul { padding-left: 1.2rem; margin: .3rem 0; }
.relatorio-md code {
  font-family: var(--fonte-mono);
  font-size: .85em; word-break: break-all;
}

/* ------------------------------------------- trilha de porteiras (a
   ASSINATURA do produto — §0.2/§4b): o caminho do crédito como 3 porteiras
   numa cerca. Abre por DADO do servidor, nunca por clique. */
.trilha { margin: var(--esp-4) 0 var(--esp-5); }
.trilha-cerca { display: block; width: 100%; height: auto; margin-bottom: var(--esp-2); }
.porteira {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: var(--raio-cartao); padding: var(--esp-4);
  margin: var(--esp-3) 0; min-height: 64px; box-shadow: var(--sombra-1);
}
.porteira-rotulo {
  font: var(--tipo-detalhe); letter-spacing: .05em; text-transform: uppercase;
  display: flex; align-items: center; gap: var(--esp-2); margin-bottom: var(--esp-1);
}
.porteira-rotulo .icone svg { width: 18px; height: 18px; }
.porteira h3 { margin: 0 0 .2rem; font-size: 1.1rem; }
.porteira p { margin: .2rem 0 0; color: var(--cinza); font-size: .95rem; }
.porteira .botao { margin-bottom: 0; }
.porteira.aberta { border-left: 4px solid var(--cor-primaria); }
.porteira.aberta .porteira-rotulo { color: var(--verde); }
.porteira.atual {
  border: 3px solid var(--cor-primaria); box-shadow: var(--sombra-2);
  animation: porteira-abre .4s cubic-bezier(.16, 1, .3, 1) both;
}
.porteira.atual .porteira-rotulo { color: var(--verde); }
.porteira.fechada { border-style: dashed; box-shadow: none; }
.porteira.fechada .porteira-rotulo, .porteira.fechada h3 { color: var(--cinza); }
@keyframes porteira-abre {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

/* --------------------------------------------------- F5.1 painel do banco:
   a fronteira do ADR-004 em duas colunas visualmente distintas (o sistema
   informa × o banco decide). Empilha no celular. */
.duas-colunas { display: grid; gap: .75rem; grid-template-columns: 1fr; }
/* a coluna de decisões do banco: destaque de que o ato é humano */
.duas-colunas .cartao:last-child { border-left: 4px solid var(--azul); }

/* tabelas densas (mesa): dígito tabular, linhas zebradas discretas */
table { width: 100%; border-collapse: collapse; font-size: .9rem;
  font-variant-numeric: tabular-nums; }
th { text-align: left; font: var(--tipo-detalhe); color: var(--cinza);
  padding: .5rem .6rem; border-bottom: 2px solid var(--borda); }
td { padding: .5rem .6rem; border-bottom: 1px solid var(--borda); }

/* -------------------------------------------- F7.2 edital interativo:
   selos de perfil (separação produtor × banco na LEITURA — o que é do banco
   vem em azul, design-system-agro) e texto oficial em transcrição literal. */
.selo { display: inline-block; font-weight: 700; padding: .15rem .5rem;
  border-radius: 999px; font-size: .8rem; margin: .3rem .3rem 0 0; }
.selo.produtor { background: #e3efdd; color: var(--verde); }
.selo.banco { background: #dbeafe; color: var(--azul); }
.selo.informativo { background: #ece8dc; color: var(--cinza); }
.texto-oficial { white-space: pre-wrap; font-size: .95rem; }
.hash-fonte { font-family: var(--fonte-mono); font-size: .75rem;
  word-break: break-all; color: var(--cinza); }
.filtros { display: flex; gap: .4rem; }
.filtros button { width: auto; flex: 1; font-size: .9rem; min-height: 48px;
  padding: .5rem .4rem; margin: .4rem 0; }

/* -------------------------------------------- F8 Módulo B — marcos: status
   FACTUAL do marco (pendente/cumprido/em atraso — nunca decisão, ADR-004). */
.marco-status { display: inline-block; font-weight: 700; padding: .25rem .6rem;
  border-radius: 999px; font-size: .9rem; margin: .3rem 0; }
/* F21.2.5 — `pendente` sai do cinza e vira TERRA, e `cumprido` passa ao par
   positivo do v8. O TOKENS.md separa três significados que o cinza embaralha:
   positivo é verde (--positivo/--positivo-fundo), PENDÊNCIA é terra
   (--terra/--areia) e o vermelho fica reservado a divergência de auditoria e
   erro real — que é o caso, legítimo, de `fonte_do_edital_nao_resolvida`
   abaixo (fail-closed: o marco cita uma seção que o corpus não confirma). */
.marco-status.pendente { background: var(--areia); color: var(--terra); }
.marco-status.cumprido { background: var(--positivo-fundo); color: var(--positivo); }
.marco-status.em_atraso { background: var(--cor-atencao-fundo); color: var(--cor-atencao); }
.marco-status.fonte_do_edital_nao_resolvida { background: #fee2e2; color: var(--erro); }

/* F11-E.2 Módulo E — bloco de CUMPRIMENTO do marco (fato factual, nunca
   decisão de crédito/auditoria — ADR-004). Verde de campo, aninhado. */
.cumprimento {
  background: #eff5ea; border-left: 4px solid var(--verde-claro);
  border-radius: var(--raio-interno); padding: .6rem .75rem; margin-top: .6rem;
  font-size: .9rem;
}
.cumprimento strong { color: var(--verde); }

/* ===================== F21.2.5 — a lista viva de marcos (8b) ==============
   Título com a contagem à direita; corpo do marco em três colunas rotuladas
   (rótulo caixa alta 11px + dado em mono tabular abaixo, TOKENS.md
   §Tipografia); rodapé com a fonte no edital à esquerda e a prova registrada
   à direita. Só hierarquia — os dados são os mesmos de antes. */
.lista-viva-cab {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--esp-4); flex-wrap: wrap;
}
.lista-viva-cab h2 { margin-bottom: 0; }
.lista-viva-contagem { font-size: .8rem; color: var(--texto-3); }

.marco-grade {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--esp-3) var(--esp-4); margin: var(--esp-3) 0;
}
.marco-col { min-width: 0; }
.marco-col-rot {
  display: block; font-size: 11px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--texto-3); margin-bottom: 3px;
}
.marco-col-val { font-size: .9rem; font-weight: 600; color: var(--texto); }

.marco-rodape {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--esp-3); flex-wrap: wrap;
  border-top: 1px dashed var(--divisoria); padding-top: var(--esp-3);
  margin-top: var(--esp-3); font-size: .8rem;
}
.marco-fonte { display: flex; align-items: center; gap: var(--esp-2);
  flex-wrap: wrap; min-width: 0; }
.marco-fonte .marco-col-rot { display: inline-block; margin-bottom: 0; }
.chip-fonte {
  background: var(--positivo-fundo); color: var(--positivo);
  border-radius: var(--raio-interno); padding: 2px 7px; font-size: .78rem;
}
.marco-fonte-hash { color: var(--texto-3); font-size: .78rem; }
.marco-prova { color: var(--cinza); flex: 0 0 auto; }

/* ================= F21.2.6 — pedido e mini-licitação (8c) =================
   Cabeçalho com o valor em destaque, e os orçamentos como LISTA de dado:
   nome à esquerda (pode fluir), valor à direita em mono tabular e `nowrap`,
   pé com a faixa menor·maior sobre um fio na cor do sotaque.
   `.pedido-cab`/`.pedido-valor` (o wrapper de PC) moram no
   `@media (min-width:1024px)` junto de `.detalhe-pc` — são classes que só
   nascem no DOM quando `emDesktop()` monta `cabecalhoPedido` (guardião de
   design: mesma disciplina de `.detalhe-pc`, que já vive lá). Aqui ficam só
   `.pedido-valor-num`/`.pedido-valor-rot`, que são COMPARTILHADAS: o mesmo
   par de classes veste o número/rótulo tanto dentro de `.pedido-valor` (PC)
   quanto dentro de `.pedido-valor-heroi` (celular, abaixo) — mover as duas
   para dentro do media query desligaria o rótulo em caixa alta no celular. */
.pedido-valor-num {
  font-size: 2rem; font-weight: 700; line-height: 1.1;
  color: var(--acento);
}
.pedido-valor-rot {
  font-size: 11px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--texto-3);
}
.pedido-ident { color: var(--cinza); font-size: .875rem; }

/* Celular (8i): o valor vira PAINEL — mesmo fundo `--verde-noite` da
   `.trilha-vert`, para não estrear superfície escura nova. Rótulo em caixa
   alta acima, número grande no meio, "simulado · fornecedor X" no pé. Os
   três textos vivem sobre painel escuro nos DOIS temas, então usam os
   tokens `--painel-escuro-*` (e não `--texto`/`--cinza`, que invertem). */
/* Teto de dígitos (pergunta do guardião na 2ª passada, DECIDIDA): o número é
   `nowrap` e não encolhe. Cabe folgado nos valores do piloto (até ~47.500 em
   ~200px dos ~240px internos a 320px); um pedido de sete dígitos apertaria.
   Fica como está de propósito: é o MESMO comportamento de `.kpi-valor` e de
   todo número mono do v8, nenhum dos quais tem `clamp()` — resolver só aqui
   criaria uma exceção sem regra. Se houver ticket dessa ordem no piloto, a
   decisão é de escala tipográfica do pacote inteiro, não desta peça. */
.pedido-valor-heroi {
  background: var(--verde-noite); border-radius: var(--raio-destaque-celular);
  padding: 18px 20px; margin: 0 0 var(--esp-4);
  display: flex; flex-direction: column; gap: 6px;
}
.pedido-valor-heroi .pedido-valor-rot { color: var(--verde-folha); }
.pedido-valor-heroi .pedido-valor-num {
  font-size: 2.1rem; font-weight: 700; line-height: 1.05;
  color: var(--painel-escuro-texto);
}
.pedido-valor-apoio {
  font-size: 13.5px; color: var(--painel-escuro-texto-2);
}

.orcamentos { list-style: none; margin: var(--esp-3) 0 0; padding: 0; }
.orcamento {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--esp-3); padding: 12px 0;
  border-bottom: 1px solid var(--divisoria);
}
.orcamento:last-child { border-bottom: 0; }
.orc-nome { min-width: 0; display: flex; align-items: baseline;
  gap: var(--esp-2); flex-wrap: wrap; }
.orc-valor { flex: 0 0 auto; }
.orc-marca {
  font-size: .72rem; font-weight: 700; letter-spacing: .04em;
  background: var(--positivo-fundo); color: var(--positivo);
  border-radius: 999px; padding: 2px 8px;
}
.orcamento.igual-ao-pedido .orc-nome { font-weight: 700; }
.orcamentos-pe {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--esp-3); padding: var(--pad-linha-total);
  padding-left: 0; padding-right: 0;
  border-top: 2px solid var(--acento); margin-top: var(--esp-2);
  font-size: .84rem; color: var(--cinza);
}

/* ============= F21.3.1 — relatório de vistoria do SPO (8f) ================
   A avaliação vira tabela: registro factual × conclusão do auditor lado a
   lado, com o cruzamento na última coluna. Sotaque AZUL DE MESA (a superfície
   é do auditor); o vermelho aparece SÓ na divergência — que aqui é o seu
   significado literal, divergência de auditoria. */
.tabela-vistoria td { vertical-align: middle; }
.tabela-vistoria select { min-width: 15ch; margin: 0; }
.tabela-vistoria label { font-weight: 600; }
/* no CELULAR a mesma informação vem em cartão empilhado (a tabela é só da
   mesa — ver o comentário em telaVistoriaSubmissao): cada linha é rótulo em
   caixa alta à esquerda e o valor à direita */
.vistoria-mob-linha {
  display: flex; align-items: baseline; justify-content: space-between;
  flex-wrap: wrap; gap: var(--esp-3); margin: var(--esp-2) 0;
}
.vistoria-mob-linha .marco-col-rot { margin-bottom: 0; }
.cruzamento {
  font-size: .84rem; font-weight: 700; white-space: nowrap;
  text-align: right;
}
.cruzamento.sem_conclusao { color: var(--texto-3); }
.cruzamento.concorda { color: var(--texto-3); }
.cruzamento.divergencia { color: var(--erro); }
.vistoria-rodape {
  background: var(--erro-fundo); color: var(--erro-sobre-fundo);
  border-radius: var(--raio-interno); padding: var(--esp-3) var(--esp-4);
  margin-top: var(--esp-3); font-size: .875rem;
}
.vistoria-rodape strong { color: var(--erro); }
.contagem-vistoria > div {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--esp-3); padding: 10px 0;
  border-bottom: 1px solid var(--divisoria);
}
.contagem-vistoria > div:last-of-type { border-bottom: 0; }
.contagem-vistoria span {
  font-family: var(--fonte-mono); font-variant-numeric: tabular-nums;
  font-weight: 700; color: var(--acento);
}

/* F21.3.3/3.4 — acervo de documentos e trilha do projeto, no dossiê da mesa.
   Listas de DADO: rótulo legível em cima, metadados em mono abaixo, e o
   sha256 de 64 caracteres recolhido em "Ver detalhes técnicos". */
.docs-projeto, .trilha-projeto { list-style: none; margin: var(--esp-3) 0 0; padding: 0; }
.trilha-projeto { counter-reset: tp; }
.docs-projeto > li, .trilha-projeto > li {
  padding: 12px 0; border-bottom: 1px solid var(--divisoria);
}
.docs-projeto > li:last-child, .trilha-projeto > li:last-child { border-bottom: 0; }
.doc-rotulo, .tp-evento { font-weight: 600; color: var(--texto); }
.docs-projeto .detalhes-tecnicos { margin-top: var(--esp-2); }

/* F21.2.3 — painel "Registrar a prova deste marco" (produtor). Estrutura
   herdada de .nfe-cfi: um botão que revela um formulário dentro do próprio
   cartão do marco, sem trocar de tela nem perder o scroll da lista. */
.cumprir-marco { margin-top: var(--esp-3); }
.cumprir-form {
  margin-top: var(--esp-3); padding-top: var(--esp-3);
  border-top: 1px solid var(--divisoria);
}
.cumprir-form label {
  display: block; font-size: .84rem; font-weight: 700; margin-top: var(--esp-3);
}
.cumprir-form .ajuda-campo { margin-top: 2px; }

/* ------------------------------------------------- F14.1 porta da frente
   (landing pública + criar conta): uma frase honesta, dois botões, três
   porteiras (§2/§4a). A fronteira ADR-004/006 é conteúdo de 1ª classe. */
.landing { padding-top: var(--esp-5); }
.landing-logo { display: block; width: 100%; max-width: 210px; height: auto;
  margin: 0 auto var(--esp-4); }
.landing-marca { font: var(--tipo-detalhe); color: var(--cor-marca);
  letter-spacing: .06em; text-transform: uppercase; margin: 0 0 var(--esp-2); }
.landing-hero { font: var(--tipo-display); margin: 0 0 var(--esp-4); text-wrap: balance; }
.landing p { max-width: 65ch; }
.porteira-passo { display: flex; gap: var(--esp-3); align-items: center;
  margin: var(--esp-3) 0; }
.porteira-passo p { margin: 0; }
.porteira-num { flex: 0 0 44px; }
/* escolha de papel (criar conta): 2 cartões-alvo grandes, seleção por borda
   verde 3px — banco/SPO/admin NÃO aparecem (nem cinza, nem "em breve") */
.escolha-papel { display: grid; gap: var(--esp-3); grid-template-columns: 1fr; }
@media (min-width: 480px) { .escolha-papel { grid-template-columns: 1fr 1fr; } }
.cartao-papel { display: flex; flex-direction: column; gap: var(--esp-2);
  min-height: 96px; text-align: left; background: var(--superficie); color: var(--texto);
  border: 2px solid var(--borda); border-radius: var(--raio-cartao);
  padding: var(--esp-4); font-size: 1rem; font-weight: 400; cursor: pointer;
  box-shadow: none; }
.cartao-papel:hover { background: var(--superficie); border-color: var(--cor-primaria); }
.cartao-papel strong { font-size: 1.1rem; }
.cartao-papel.selecionado { border: 3px solid var(--cor-primaria); }

/* F14.5 — portas de acesso por persona (landing) e cabeçalho do login rotulado.
 * A porta reusa o cartão-papel; vira link (alvo grande) para #entrar/<persona>. */
.portas-acesso { display: grid; gap: var(--esp-3); grid-template-columns: 1fr 1fr;
  margin-top: var(--esp-3); }
.porta-acesso { text-decoration: none; }
.porta-acesso .porta-icone { display: inline-flex; color: var(--cor-primaria); }
.porta-acesso .porta-icone .icone svg { width: 30px; height: 30px; }
.porta-acesso span:last-child { color: var(--cinza); font-size: .9rem; }
.login-cabecalho { display: flex; align-items: center; gap: var(--esp-3);
  margin-bottom: var(--esp-4); }
/* F17: o título da porta no cartão é rótulo, não display (16px 700) */
.login-cabecalho h1 { margin: 0; font: 700 1rem/1.3 var(--fonte-corpo);
  letter-spacing: 0; color: var(--texto); }
.login-selo { display: inline-flex; flex: 0 0 auto; align-items: center;
  justify-content: center; width: 36px; height: 36px; border-radius: 50%;
  background: #e6eee3; color: var(--verde-acao); border: 0; }
.login-selo .icone svg { width: 20px; height: 20px; }
.ajuda-campo { color: var(--cinza); font-size: .85rem; margin: -.6rem 0 .8rem; }
.campo-senha { display: flex; gap: var(--esp-2); align-items: flex-start; }
.campo-senha input { flex: 1; }
.ver-senha { width: auto; flex: 0 0 auto; min-height: var(--toque);
  background: var(--superficie); color: var(--texto); border: 2px solid var(--borda-forte);
  box-shadow: none; }
.ver-senha:hover { background: var(--fundo); }
/* nome histórico (o app.js o usa em toda parte); a cor F17 é o verde ação */
.link-azul { color: var(--cor-link); font-weight: 600; }
/* honeypot (anti-robô sem captcha): invisível ao humano, fora do fluxo de
   tab; robô que o preenche é descartado NO SERVIDOR */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px;
  min-height: 0; opacity: 0; }

/* abas do console admin (parâmetros/usuários/senhas/visão) */
.abas-admin { display: flex; flex-wrap: wrap; gap: .4rem;
  margin-bottom: var(--esp-3); border-bottom: 1px solid var(--borda); }
.abas-admin .aba { width: auto; background: var(--superficie);
  color: var(--texto); border: 1px solid var(--borda-forte);
  border-bottom: 0; padding: .5rem .9rem; box-shadow: none; }
.abas-admin .aba.ativa { background: var(--cor-marca); color: #fff;
  border-color: var(--cor-marca); }
.abas-admin .aba:hover { background: var(--fundo); }
.abas-admin .aba.ativa:hover { background: var(--cor-marca); }

/* ------------------------------------------------ F5.2 verificador: estado
   de INTEGRIDADE (confere/não-confere) — classes PRÓPRIAS, distintas dos
   vereditos de negócio (achado 5 da defesa). */
.resultado-hash { font-weight: 700; border-radius: 999px; padding: .4rem .8rem; display: inline-block; }
.resultado-hash.confere { background: #d3e9cf; color: var(--verde); }
.resultado-hash.nao-confere { background: #fee2e2; color: var(--erro); }
/* F15.0: corrente vazia (nenhum evento ainda) — neutra, não é erro */
.resultado-hash.vazia { background: #ece8dc; color: var(--texto); }

/* bloco de comando (nível C do verificador): superfície verde-noite (a
   mesma família das cascas escuras F17), texto verde-névoa, mono da casa */
pre { overflow-x: auto; background: var(--verde-noite); color: #cfdcd2;
  font-family: var(--fonte-mono);
  padding: .6rem .75rem; border-radius: var(--raio-interno); font-size: .85rem; }

/* ícones do conjunto único (traço 2px, cantos arredondados — §0.3) */
.icone { display: inline-flex; flex: 0 0 auto; }
.icone svg { width: 24px; height: 24px; display: block; }

/* ============================================================================
   F14.4b — CAMADA DESKTOP (≥1024px, o --bp-desktop). Web design NATIVO de PC:
   composição própria por superfície, não o mobile esticado. Abaixo de 1024px
   NADA desta camada se aplica — o mobile ratificado permanece intacto.
   1) LANDING: hero em 2 colunas (texto × painel-visual da trilha de
      porteiras) + bandas full-width (passos em 3 colunas, confiança ADR-004/
      006 em verde escuro, rodapé slim).
   2) MESA: dashboard do banco (cartões-resumo + fila como tabela densa) e
      listas como tabelas tabular-nums (o shell da barra lateral + top bar
      vive no bloco ≥1024px da navegação, acima).
   3) CAMPO (F16.0): produtor/fornecedor no MESMO shell de sidebar da mesa
      (o quadro-440px foi aposentado), com identidade própria — acento verde,
      conteúdo calmo a 1080px, densidade menor (headings um passo maiores,
      grades de 2 colunas).
   4) PRIMITIVAS F16.0 (.grade-cartoes, .form-pc, .detalhe-pc): composição
      reutilizável por todas as telas; transparentes abaixo de 1024px.
   ========================================================================== */

/* padrões (mobile e campo): as peças exclusivas do desktop ficam ocultas */
#titulo-contexto { display: none; }
.nav-extra { display: none; }
/* F17.7 — o ícone do Sair (composição nova do app.js) fica OCULTO por
   padrão: no PC o botão do rodapé da sidebar segue só-texto, byte a byte o
   ratificado. Só o bloco móvel (<1024px, fim do arquivo) o exibe. */
.nav-rodape .icone { display: none; }
.landing-visual { display: none; }
.auth-marca { display: none; }  /* painel de marca do pré-login (só PC) */
/* F17.1 — no MOBILE o pré-login é SÓ o cartão de formulário, centrado */
.auth-cartao {
  background: var(--superficie); border: 1px solid var(--borda);
  border-radius: 16px; padding: var(--esp-5);
  box-shadow: var(--sombra-1); margin: var(--esp-4) auto; max-width: 420px;
  display: flex; flex-direction: column;
}

/* F17.9 — seletor de persona no login (chips) — a ENTRADA do /app é o login do
   Claude Design; as 4 personas viram este seletor discreto (aposenta a landing
   "escolha seu acesso"). O papel real vem da credencial (ADR-009). */
.login-personas {
  display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: var(--esp-3);
}
.chip-persona {
  display: inline-flex; align-items: center; padding: .32rem .72rem;
  border: 1px solid var(--borda-2); border-radius: 999px;
  font-size: .8rem; font-weight: 600; color: var(--texto-3);
  background: var(--fundo); text-decoration: none; white-space: nowrap;
}
.chip-persona:hover { border-color: var(--verde-acao); color: var(--verde-acao); }
.chip-persona.ativo {
  background: var(--verde); border-color: var(--verde); color: var(--texto-botao);
}

@media (min-width: 1024px) {
  /* --------------------------------- 0) TIPOGRAFIA de PC (F16.0-design) --
     números SEMPRE comparáveis (dígito tabular) nas superfícies logadas —
     valores, contagens, wei, datas alinham em tabelas e cartões-resumo;
     eyebrow menor e mais espaçado (rótulo de seção considerado — o mesmo
     .14em das bandas da landing); títulos de tela com tracking de display. */
  body.superficie-campo main, body.superficie-mesa main,
  body.superficie-operacao main, #topo, #nav-app {
    font-variant-numeric: tabular-nums;
  }
  /* F17.3 — ação de NÍVEL DE PÁGINA (o "Voltar" e afins, filhos diretos do
     main): largura natural no PC — botão de 1360px não é PC nativo. Dentro
     de cartões/folhas (.form-pc, kit do auditor) a largura cheia permanece.
     <1024px nada muda: o alvo largo de polegar é o ratificado. */
  body.superficie-campo main > .botao, body.superficie-mesa main > .botao,
  body.superficie-operacao main > .botao {
    display: inline-block; width: auto; padding: .7rem 1.4rem;
  }
  .eyebrow { font-size: .78rem; font-weight: 700; letter-spacing: .14em; }
  /* F17.3 — título de tela da mesa/operação um passo acima do --tipo-titulo
     (presença de tela de PC; o campo já usa 2rem no bloco 3) */
  body.superficie-mesa main h1, body.superficie-operacao main h1 {
    font-size: 1.7rem; letter-spacing: -.02em; line-height: 1.2;
  }

  /* ------------------------------------------------- 1) LANDING nativa PC */
  /* full-bleed por banda; o conteúdo centra a ~1200px. :has() restringe à
     landing (login/criar-conta continuam na coluna estreita); navegador sem
     :has degrada para a coluna ratificada — nunca quebra. */
  body.pre-login main:has(> .landing) { max-width: none; padding: 0; }
  .landing { padding-top: 0; display: flex; flex-direction: column; }
  .banda-hero { order: 1; }
  .banda-passos { order: 2; }
  .banda-fronteira { order: 3; }
  .banda-rodape { order: 4; }
  .landing-conteudo {
    max-width: 1200px; width: 100%; margin: 0 auto; padding: 0 var(--esp-6);
  }

  /* hero em 2 colunas: texto (48%) × painel-visual do produto (52%) */
  .banda-hero { padding: 64px 0 72px; }
  .landing-hero-grid {
    display: grid; grid-template-columns: 48fr 52fr; gap: 56px;
    align-items: center;
  }
  .landing-logo { margin: 0 0 var(--esp-5); max-width: 150px; height: auto; }
  .landing-hero {
    font-size: clamp(2.4rem, 3.5vw, 3.4rem); line-height: 1.12;
    letter-spacing: -.02em;
  }
  .landing-col-texto p { max-width: 60ch; font-size: 1.1rem; }
  .landing-ctas { display: flex; gap: var(--esp-3); margin-top: var(--esp-5); }
  .landing-ctas .botao {
    display: inline-block; width: auto; margin: 0; padding: .85rem 1.8rem;
  }

  /* o painel-visual: a trilha de porteiras como herói (assinatura §0.2) */
  .landing-visual {
    display: block;
    background: linear-gradient(165deg, #f1f5ec 0%, #e3efdd 55%, #dcead8 100%);
    border: 1px solid #cbdcc6; border-radius: 20px;
    padding: var(--esp-6);
    box-shadow: 0 24px 48px -20px rgba(30, 45, 32, .28);
  }
  .landing-visual .porteira { margin: var(--esp-3) 0 0; min-height: 0; }
  .landing-visual .porteira p { font-size: .9rem; max-width: none; }

  /* banda ESCOLHA SEU ACESSO: as 4 portas numa faixa de 4 colunas */
  .banda-portas .eyebrow {
    margin-top: 0; text-align: center; letter-spacing: .14em; max-width: none;
  }
  .banda-portas .portas-acesso { grid-template-columns: repeat(4, minmax(0, 1fr)); }

  /* banda COMO FUNCIONA: 3 colunas (ícone grande, passo, descrição) */
  .banda-passos {
    background: var(--superficie); border-top: 1px solid var(--borda);
    border-bottom: 1px solid var(--borda); padding: 56px 0 64px;
  }
  .banda-passos .eyebrow {
    margin-top: 0; text-align: center; letter-spacing: .14em;
    max-width: none;  /* solta o teto de 65ch de .landing p (centro real) */
  }
  .landing-passos {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--esp-6); margin-top: var(--esp-5);
  }
  .landing-passos .porteira-passo {
    flex-direction: column; align-items: center; text-align: center;
    gap: var(--esp-3); margin: 0;
  }
  .landing-passos .porteira-num { flex: 0 0 auto; }
  .landing-passos .porteira-num svg { width: 64px; height: 64px; }
  .landing-passos p { max-width: 34ch; font-size: 1.02rem; margin: 0 auto; }

  /* banda de confiança: a fronteira ADR-004/006 como a seção mais forte */
  .banda-fronteira {
    background: var(--verde); color: #fff; padding: 64px 0;
    text-align: center;
  }
  .banda-fronteira .cartao {
    background: none; border: 0; box-shadow: none; margin: 0; padding: 0;
    /* o <p> traz style inline margin:0 (mobile); flex centra sem tocá-lo */
    display: flex; justify-content: center;
  }
  .banda-fronteira .cartao p {
    max-width: 48ch; margin: 0 auto; font-size: 1.35rem; font-weight: 600;
    line-height: 1.5; text-wrap: balance;
  }

  /* rodapé slim */
  .banda-rodape { padding: 28px 0 40px; }
  .banda-rodape .nota {
    text-align: center; max-width: 70ch; margin: 0 auto; font-size: .9rem;
  }

  /* --------------------------------------------- 2) MESA: conteúdo largo */
  /* F17.3 — padding de tela de PC 36-44px: a borda esquerda do conteúdo
     alinha com o título de contexto do top bar (padding 15px 44px) */
  body.superficie-mesa main, body.superficie-operacao main {
    max-width: 1360px; width: 100%;
    padding: 36px 44px 44px;
  }
  /* operação (admin): console de configurações (F16.4) — 216px de navegação
     secundária + coluna de conteúdo ≈960px (o ~960 de formulário do doc 12
     §6 segue valendo para o CONTEÚDO; a soma dá 1200) */
  body.superficie-operacao main { max-width: 1200px; }
  /* F17.3 — a fronteira em duas colunas (o sistema informa × o humano
     decide) respira no ritmo do PC: gap esp-5, topos alinhados */
  body.superficie-mesa .duas-colunas, body.superficie-operacao .duas-colunas {
    gap: var(--esp-5); align-items: start;
  }
  /* painéis lado a lado (home do SPO); no mobile a div é transparente.
     F16.4: a operação (visão geral do admin) também compõe em painéis */
  body.superficie-mesa .grade-paineis,
  body.superficie-operacao .grade-paineis {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--esp-4); align-items: start;
  }
  body.superficie-mesa .grade-paineis .cartao,
  body.superficie-operacao .grade-paineis .cartao { margin: 0; }
  /* F16.3 — painel de largura cheia DENTRO da grade de painéis (o kit do
     auditor no portal do SPO): ocupa as duas colunas */
  body.superficie-mesa .grade-paineis > .painel-largo { grid-column: 1 / -1; }
  /* F16.3 — leitura do relatório K.1 na mesa: painel largo com MEDIDA de
     leitura (a linha do texto não passa de ~75ch — legível, não esticado) */
  body.superficie-mesa .painel-leitura .relatorio-md { max-width: 75ch; }

  /* dashboard do banco: cartões-resumo (o sistema INFORMA os números;
     o ato é humano — acento azul no que aguarda o banco, ADR-004) */
  .cartoes-resumo {
    display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--esp-4); margin: var(--esp-4) 0 var(--esp-5);
  }
  .cartao-resumo {
    display: flex; flex-direction: column; gap: var(--esp-1);
    margin: 0; padding: var(--esp-4) var(--esp-5);
  }
  .cartao-resumo .resumo-num {
    font-size: 2.1rem; line-height: 1.1; font-weight: 700;
    word-break: normal;
  }
  .cartao-resumo .resumo-rotulo { font: var(--tipo-detalhe); color: var(--cinza); }
  .cartao-resumo.do-banco { border-left: 4px solid var(--azul); }
  .cartao-resumo.do-banco .resumo-num { color: var(--azul); }
  .cartao-resumo.atencao .resumo-num { color: var(--cor-atencao); }

  /* tabela densa da mesa (pedidos, projetos): tabular-nums, zebra leve */
  .tabela-mesa { padding: 0; overflow-x: auto; }
  .tabela-mesa table { font-size: .92rem; }
  .tabela-mesa th {
    padding: .7rem .9rem; background: var(--fundo);
    border-bottom: 1px solid var(--borda-forte); white-space: nowrap;
  }
  .tabela-mesa td { padding: .65rem .9rem; vertical-align: middle; }
  /* valor: o NÚMERO (mono) quebra contido a ~22ch — wei do seed chega a 26+
     dígitos e, sem teto, empurraria Estado/Ação para fora da tela; o sufixo
     "(valor simulado)" (ADR-007) fica no td e só quebra entre palavras */
  .tabela-mesa .dado-tabela {
    display: inline-block; max-width: 22ch; word-break: break-all;
    vertical-align: top;
  }
  .tabela-mesa td.dado { word-break: normal; }
  .tabela-mesa tbody tr:hover { background: #f2efe4; }
  .tabela-mesa tbody tr:last-child td { border-bottom: 0; }
  .tabela-mesa .estado { margin-top: 0; white-space: nowrap; }
  .acao-tabela { font-weight: 700; text-decoration: none; }
  .acao-tabela:hover { text-decoration: underline; }

  /* acesso rápido do dashboard: botões de largura natural, lado a lado */
  .acesso-rapido { display: flex; gap: var(--esp-3); flex-wrap: wrap; }
  .acesso-rapido .botao {
    display: inline-block; width: auto; margin: .4rem 0;
    padding: .7rem 1.2rem; font-size: .95rem;
  }

  /* ------------------- 3) CAMPO (F16.0): identidade no shell de sidebar --
     O esqueleto (grid, nav lateral, top bar) vem do bloco de navegação
     ≥1024px, acima. Aqui só a identidade: app CALMO, não dashboard denso —
     conteúdo a 1080px (a mesa é 1360), mais respiro, tipografia um passo
     maior. O acento verde do item ativo já resolve via var(--acento).
     F16.0-design: linguagem de cartão do campo — respiro esp-5, raio 16
     (aninhamento preservado: controle 12 ≤ 16), sombra TINTADA ao
     verde-marca (nunca preto puro — design-master §5; par dark no fim
     do arquivo re-declara). */
  body.superficie-campo {
    --raio-cartao: 16px;
    --sombra-1: 0 1px 2px rgba(30, 45, 32, .05), 0 2px 10px -4px rgba(30, 45, 32, .10);
    --sombra-2: 0 20px 44px -24px rgba(30, 45, 32, .35);
  }
  body.superficie-campo main {
    max-width: 1080px; width: 100%;
    padding: 36px 44px 52px;  /* F17.3 — alinha com o top bar (44px) */
  }
  /* passo de display para a saudação/título de tela do campo (herdado
     pelas telas F16.1+): maior, tracking negativo leve, linha justa */
  body.superficie-campo main h1 {
    font-size: 2rem; letter-spacing: -.02em; line-height: 1.15;
  }
  body.superficie-campo main h2 { font-size: 1.3rem; letter-spacing: -.01em; }
  body.superficie-campo .cartao, body.superficie-campo .porteira {
    padding: var(--esp-5);
  }
  body.superficie-campo .porteira h3 { font-size: 1.15rem; }
  /* trilha de porteiras (home do produtor — a ASSINATURA, F16.0-design):
     a cerca deixa de ser ilustração compacta e vira estrutura ESPACIAL —
     os trilhos atravessam a largura do conteúdo (sem mourões nas pontas:
     a cerca continua além do quadro) e cada portão fica PLANTADO sobre o
     seu cartão por um poste curto (portão 1 sobre "Imóvel", etc.). O
     alinhamento é por construção: .cerca-pc repete as MESMAS colunas e o
     MESMO gap da grade dos cartões. Exceção deliberada à regra de 2
     colunas do campo: a trilha tem exatamente 3 passos. */
  body.superficie-campo .trilha {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0 var(--esp-5); margin-top: var(--esp-5);
  }
  body.superficie-campo .trilha > div:first-child { grid-column: 1 / -1; }
  body.superficie-campo .trilha .porteira { margin: 0; }
  .cerca-pc {
    position: relative; display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 var(--esp-5);
  }
  /* os 2 trilhos contínuos: straddle do centro dos nós (24px) e leve
     sangria além da grade — pintados antes dos filhos, os portões passam
     por cima naturalmente */
  .cerca-pc::before {
    content: ""; position: absolute; left: calc(-1 * var(--esp-4));
    right: calc(-1 * var(--esp-4)); top: 19px; height: 10px;
    border-top: 2px solid var(--cerca-trilho);
    border-bottom: 2px solid var(--cerca-trilho); pointer-events: none;
  }
  .cerca-pc-no { display: flex; flex-direction: column; align-items: center; }
  .cerca-pc-no svg { width: 48px; height: 48px; display: block; }
  /* o poste do portão: liga o nó ao topo do seu cartão (row-gap 0) */
  .cerca-pc-no::after {
    content: ""; width: 2px; height: 18px; background: var(--cerca-mourao);
  }

  /* --------------- 4) PRIMITIVAS F16.0 (reutilizáveis, F16.1+) -----------
     Transparentes abaixo de 1024px: no mobile as listas continuam cartões
     empilhados, formulários e detalhes empilham como hoje. */
  /* lista de cartões vira grade responsiva (as listas do produtor/
     fornecedor recebem esta classe nas próximas sub-fases) */
  .grade-cartoes {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: var(--esp-4); margin: var(--esp-3) 0;
  }
  .grade-cartoes > * { margin: 0; }  /* o gap dá o ritmo; sem margem dupla */
  /* identidade do campo: densidade menor — 2 colunas, nunca 3-4 */
  body.superficie-campo .grade-cartoes {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  /* formulário não estica à largura toda do shell. F16.1: vira a "folha de
     tarefa" — UM cartão central de superfície (tokens; par dark por
     construção). Sub-cartões dentro da folha perdem sombra e um passo de
     raio (aninhamento: 12 ≤ 16) — elevação única, sem cartão-sobre-cartão. */
  .form-pc {
    max-width: 600px; margin-left: auto; margin-right: auto;
    background: var(--superficie); border: 1px solid var(--borda);
    border-radius: var(--raio-cartao); padding: var(--esp-6);
    box-shadow: var(--sombra-1); margin-top: var(--esp-4);
  }
  .form-pc > h1:first-child { margin-top: 0; }
  .form-pc .cartao, .form-pc .vazio-acao {
    box-shadow: none; border-radius: var(--raio-controle);
  }
  /* tela de detalhe: coluna principal + lateral (resumo/ações); a lateral fica
     sticky ABAIXO do top bar sticky (F17.9: --altura-topo, não mais os 44px da
     faixa aposentada). F16.1: lateral mais alta que a janela rola por DENTRO —
     sem isto o sticky esconderia o fim do formulário de marco. */
  .detalhe-pc {
    display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(280px, 1fr);
    gap: var(--esp-5); align-items: start;
  }
  .detalhe-pc > .col-lateral {
    position: sticky; top: calc(var(--altura-topo) + var(--esp-4));
    max-height: calc(100vh - var(--altura-topo) - var(--esp-5)); overflow-y: auto;
  }
  .detalhe-pc > .col-lateral > .cartao:first-child { margin-top: 0; }
  .detalhe-pc > .col-principal > h2:first-child { margin-top: 0; }
  /* F21.2.6 (8c) — o cabeçalho do pedido: o valor divide a linha do título,
     alinhado à direita, com o rótulo em caixa alta LOGO ABAIXO do número
     (não ao lado) — é a composição do desenho. `align-items: baseline`
     deixaria o bloco do valor pendurado pela primeira linha de um título
     que quebra em duas; `flex-end` o mantém colado ao pé da linha, como no
     PNG. Movido para dentro do media query (achado do
     guardiao-design-ecoesfera): `.pedido-cab`/`.pedido-valor` só nascem no
     DOM quando `emDesktop()` monta `cabecalhoPedido` — a mesma disciplina
     de `.detalhe-pc` acima, que já vivia aqui.

     O `flex-end` fica DECIDIDO (pergunta do guardião na 2ª passada): um
     título que quebra em duas linhas passa a ter o número colado ao pé
     dele, e não ao lado da primeira linha. É o que lê melhor — o número
     acompanha o fim do nome do item, e `flex-start` abriria um vão entre os
     dois. Nenhuma tela do v8 desenha esse caso; se aparecer um título assim
     no piloto, é aqui que se revê. */
  .pedido-cab {
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: var(--esp-4); flex-wrap: wrap;
  }
  .pedido-cab > h1 { margin-bottom: 0; flex: 1 1 16ch; min-width: 0; }
  .pedido-valor {
    display: flex; flex-direction: column; align-items: flex-end;
    flex: 0 0 auto; text-align: right;
  }

  /* ------------- 5) F16.1 — telas do PRODUTOR no shell de PC --------------
     Aplicação das primitivas (o "resto quieto": a assinatura já é a cerca).
     Só tokens — o par dark vem por construção; nada disto existe <1024px. */
  /* título da tela + ação primária na MESMA linha (no mobile o wrapper é
     um div transparente: h1 e botão largo empilham como ratificado) */
  .cabecalho-tela {
    display: flex; align-items: center; justify-content: space-between;
    gap: var(--esp-4); flex-wrap: wrap;
  }
  .cabecalho-tela > .botao {
    display: inline-block; width: auto; flex: 0 0 auto; margin: 0;
    padding: .7rem 1.4rem; font-size: .95rem;
  }
  /* edital em DUAS ÁREAS: trilho de leitura à esquerda (sticky, cartão de
     superfície) × texto à direita. O acento segue a superfície ativa (verde
     no campo, azul na mesa); a fronteira ADR-004 mora no próprio trilho
     ("o que é do produtor" × "o que é do banco"). */
  .edital-pc {
    display: grid; grid-template-columns: minmax(240px, 320px) minmax(0, 1fr);
    gap: var(--esp-5); align-items: start;
  }
  .edital-pc > .col-indice {
    position: sticky; top: calc(var(--altura-topo) + var(--esp-4));
    max-height: calc(100vh - var(--altura-topo) - var(--esp-5)); overflow-y: auto;
    background: var(--superficie); border: 1px solid var(--borda);
    border-radius: var(--raio-cartao); padding: var(--esp-4);
    box-shadow: var(--sombra-1);
  }
  .col-indice .eyebrow { margin-top: 0; }
  .col-indice .filtros { flex-direction: column; }
  .col-indice .filtros button { flex: none; width: 100%; }
  .edital-pc > .col-conteudo > h1:first-child,
  .edital-pc > .col-conteudo > h2:first-child { margin-top: 0; }
  .indice-edital { display: flex; flex-direction: column; gap: 2px; }
  .indice-edital .indice-doc {
    font: var(--tipo-detalhe); color: var(--cinza); letter-spacing: .08em;
    text-transform: uppercase; margin: var(--esp-3) 0 var(--esp-1);
  }
  .indice-edital a {
    display: block; padding: var(--esp-1) var(--esp-2);
    border-left: 3px solid transparent; border-radius: var(--raio-interno);
    color: var(--texto); text-decoration: none; font-size: .88rem;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .indice-edital a:hover { background: var(--fundo); }
  .indice-edital a[aria-current="page"] {
    border-left-color: var(--acento); background: var(--fundo);
    font-weight: 700;
  }

  /* ------------- 6) F16.2 — telas do FORNECEDOR no shell de PC ------------
     O "resto quieto" (a assinatura já é a cerca): mesmas primitivas, acento
     do CAMPO. Nada daqui existe <1024px — classes inertes no mobile. */
  /* abas Ativos × Encerrados: largura natural no topo (no mobile .filtros
     mantém os 2 botões meio-a-meio ratificados) */
  .abas-pc { justify-content: flex-start; }
  .abas-pc button { flex: 0 0 auto; width: auto; padding: .5rem 1.4rem; }
  /* ação de largura natural (a porta "Meus recebíveis" da home do
     fornecedor — botão de 1080px não é PC nativo) */
  .botao-inline-pc {
    display: inline-block; width: auto; padding: .7rem 1.4rem;
    font-size: .95rem;
  }
  /* recebíveis: a tabela densa (nascida na mesa) ENCONTRA o acento do campo
     — é o COFRE do fornecedor, não a mesa do banco: hover verde-tintado e
     ação em verde (tokens; par dark por construção). O padding-0 da tabela
     precisa vencer o esp-5 do cartão de campo por especificidade. */
  body.superficie-campo .cartao.tabela-mesa { padding: 0; }
  body.superficie-campo .tabela-mesa tbody tr:hover {
    background: rgba(22, 163, 74, .06);
  }
  body.superficie-campo .tabela-mesa .acao-tabela {
    color: var(--cor-primaria-escura);
  }
  /* a linha de TOTAL (tfoot): destaque por PESO + fio da marca — sem banner
     cheio; o cofre é calmo */
  .tabela-mesa .linha-total td {
    border-bottom: 0; border-top: 2px solid var(--cor-primaria);
    font-weight: 700; padding-top: .8rem; padding-bottom: .8rem;
  }
  /* conta no banco (.detalhe-pc): alinhar o topo das duas colunas —
     ESCOPADO à tela da conta para não deslocar os detalhes do produtor
     ratificados na F16.1 */
  .conta-pc > .col-principal > .cartao:first-child { margin-top: 0; }

  /* ------------- 7) F17.1 — PRÉ-LOGIN em 2 painéis (pixel-spec 4c) --------
     Um QUADRO central arredondado (raio 20, sombra funda): aside VERDE-NOITE
     (marca + fronteira ADR-004/006 sempre à vista, decisor humano nomeado) ×
     cartão de formulário à direita. Tudo atrás de :has(): navegador sem :has
     degrada para a coluna ratificada — nunca quebra. O gatilho é o CONTEÚDO
     (.auth-pc): cobre as telas pré-login E a troca obrigatória de senha.
     <1024px o aside é display:none e fica só o cartão (centrado). */
  body:has(> main > .auth-pc) { display: block; padding-bottom: 0; }
  body:has(> main > .auth-pc) main {
    max-width: none; padding: 40px clamp(16px, 4vw, 48px) 56px;
    display: grid; place-items: center;
  }
  main:has(> .auth-pc) > .auth-pc {
    display: grid; grid-template-columns: minmax(380px, 44fr) minmax(0, 56fr);
    min-height: 720px; width: 100%; max-width: 1120px;
    background: var(--fundo); border-radius: 20px; overflow: hidden;
    box-shadow: 0 24px 60px -30px rgba(30, 45, 32, .45);
  }
  main:has(> .auth-pc) .auth-marca {
    display: flex; flex-direction: column; justify-content: center;
    background: var(--verde-noite); color: #c8d6ca;
    padding: 56px 52px; position: relative;
  }
  /* no PC o aside acima já traz a marca — a compacta do cartão fica oculta */
  .auth-marca-compacta { display: none; }
  main:has(> .auth-pc) .auth-form {
    display: grid; place-items: center; padding: 40px;
  }
  main:has(> .auth-pc) .auth-cartao {
    width: 100%; max-width: 400px; background: var(--superficie);
    border: 1px solid var(--borda); border-radius: 16px;
    padding: 32px; box-shadow: var(--sombra-2);
  }
  main:has(> .auth-pc) .auth-cartao > h1:first-child { margin-top: 0; }
  /* títulos SEM cabeçalho de porta (criar conta, esqueci, troca obrigatória)
     seguem display, num passo contido */
  main:has(> .auth-pc) .auth-cartao h1 {
    font-size: 1.35rem; letter-spacing: -.015em; line-height: 1.3;
  }
  main:has(> .auth-pc) .auth-cartao .login-cabecalho h1 {
    font-size: 1rem; letter-spacing: 0;
  }
  /* sub-cartões dentro da folha perdem sombra e um passo de raio */
  main:has(> .auth-pc) .auth-cartao .cartao {
    box-shadow: none; border-radius: var(--raio-controle);
  }
  /* campos do cartão no pixel-spec: 14.5px, padding 11px 12px */
  main:has(> .auth-pc) .auth-cartao input,
  main:has(> .auth-pc) .auth-cartao select {
    min-height: 44px; font-size: .906rem; padding: 11px 12px;
  }
  main:has(> .auth-pc) .auth-cartao button,
  main:has(> .auth-pc) .auth-cartao .botao {
    min-height: 46px; font-size: .906rem; padding: 12px;
  }
  /* conteúdo do painel de marca (fora do PC o aside inteiro é display:none —
     sem :has aqui de propósito: sem suporte, nada aparece). O verde-noite é
     literal nos DOIS temas. */
  .auth-marca-inner { max-width: 46ch; position: relative; z-index: 1; }
  .auth-marca-logo { display: flex; align-items: center; gap: 12px; }
  .auth-marca-logo img {
    width: 52px; height: 52px; flex: 0 0 auto;
    filter: drop-shadow(0 0 8px rgba(143, 206, 159, .3));
  }
  .auth-wordmark {
    font-family: var(--fonte-display); font-weight: 700; font-size: 27px;
    letter-spacing: -.01em; line-height: 1;
  }
  /* régua terra + slogan completo (identidade da marca) */
  .auth-marca-regua { width: 26px; height: 2px; background: var(--terra);
    margin-top: 22px; }
  .auth-marca-slogan {
    font-size: 11px; font-weight: 700; letter-spacing: .16em;
    text-transform: uppercase; color: #8fa793; margin: 14px 0 40px;
  }
  .auth-marca-frase {
    font-family: var(--fonte-display); font-weight: 600; font-size: 31px;
    line-height: 1.2; letter-spacing: -.01em; color: #f5f2ea;
    max-width: 15ch; margin: 0 0 var(--esp-4); text-wrap: balance;
  }
  .auth-marca-apoio { margin: 0; font-size: .906rem; color: #9db3a0;
    max-width: 42ch; }
  /* a fronteira ADR-004/006: o que a EcoEsfera NÃO faz, decisores nomeados */
  .auth-marca-fronteira {
    margin: 36px 0 0; padding-top: 22px;
    border-top: 1px solid rgba(255, 255, 255, .12);
    font-size: 13px; color: #7c8f80; max-width: 44ch;
  }
  .auth-marca-fronteira b { color: #9db3a0; }
  /* porteira decorativa (SÓ sobre verde-noite, spec de assets) */
  .auth-marca-porteira {
    position: absolute; right: 28px; bottom: 24px; width: 130px;
    border-radius: var(--raio-img); opacity: .55; pointer-events: none;
  }

  /* ------------- 8) F16.4 — CONSOLE do ADMIN (operação) nativo de PC ------
     Tela de CONFIGURAÇÕES: as mesmas abas do mobile re-compostas como
     navegação secundária vertical à esquerda; conteúdo à direita. O admin
     opera o sistema e NUNCA decide mérito (crédito=banco, auditoria=SPO —
     ADR-004): nenhuma copy muda aqui, só a composição. */
  .admin-pc {
    display: grid; grid-template-columns: 216px minmax(0, 1fr);
    gap: var(--esp-5); align-items: start;
  }
  .admin-pc > .abas-admin {
    flex-direction: column; gap: 2px; margin: 0; border-bottom: 0;
    position: sticky; top: calc(var(--altura-topo) + var(--esp-4));
  }
  .admin-pc > .abas-admin .aba {
    width: 100%; text-align: left; background: none; border: 0;
    border-left: 3px solid transparent; border-radius: var(--raio-interno);
    padding: .55rem .8rem; margin: 0; min-height: 44px; font-size: .95rem;
  }
  /* as abas vivem sobre o FUNDO da página: hover/ativa usam a superfície
     (visível nos dois temas — fundo sobre fundo seria invisível) */
  .admin-pc > .abas-admin .aba:hover { background: var(--superficie); color: var(--texto); }
  .admin-pc > .abas-admin .aba.ativa,
  .admin-pc > .abas-admin .aba.ativa:hover {
    background: var(--superficie); color: var(--texto);
    border: 0; border-left: 3px solid var(--acento);
  }
  /* parâmetros como LINHAS de configuração: identificação + descrição à
     esquerda × campo + valor atual + salvar à direita */
  .param-pc {
    display: grid; grid-template-columns: minmax(0, 1.3fr) minmax(260px, 1fr);
    gap: var(--esp-2) var(--esp-6); align-items: start;
  }
  .param-pc .param-info .nota-fina { max-width: 58ch; }
  .param-pc .param-acao input, .param-pc .param-acao select {
    margin: .3rem 0 .6rem;
  }
  /* provisionar operador: os 3 campos numa linha */
  .campos-3 {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0 var(--esp-4);
  }
  /* ação dentro de tabela densa (reset/descartar): largura natural */
  .btn-tabela {
    width: auto; margin: 0; padding: .4rem .9rem;
    font-size: .85rem; min-height: 36px;
  }
  .tabela-mesa .msg-tabela { margin: .4rem 0 0; }
}

/* ============================================================================
   F17.2 — PRODUTOR·INÍCIO: a ASSINATURA (pixel-spec 4b). A FAIXA-HORIZONTE:
   4 porteiras ilustradas sobre verde-noite, ligadas por linha pontilhada;
   o portão ABRE por DADO do servidor, nunca por clique. Estados idênticos
   nos dois temas (a faixa é verde-noite sempre). ADR-004: a porteira 4
   nomeia o decisor humano (banco) em toda espera.
   ========================================================================== */
.faixa-horizonte {
  background: var(--verde-noite); border-radius: var(--raio-faixa);
  margin-top: 26px; padding: 24px 20px 22px; position: relative;
}
/* a linha pontilhada conectora (só ≥1024px, quando as 4 ficam lado a lado) */
.faixa-linha {
  display: none; position: absolute; left: 7%; right: 7%; top: 82px;
  height: 2px; pointer-events: none;
  background: repeating-linear-gradient(90deg,
    var(--pontilhado) 0 10px, transparent 10px 22px);
}
.faixa-grid {
  position: relative; display: grid; gap: 20px 16px;
  grid-template-columns: repeat(2, minmax(0, 1fr));  /* mobile: 2×2 */
}
.porteira-h { text-align: center; }
.porteira-h img {
  width: 100%; max-width: 170px; height: auto; display: block;
  margin: 0 auto; border-radius: var(--raio-img);
  box-shadow: var(--sombra-img-escuro);
}
.porteira-h-info {
  display: flex; gap: 10px; justify-content: center; align-items: center;
  margin-top: 12px; text-align: left;
}
.ph-badge {
  flex: 0 0 22px; width: 22px; height: 22px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700; border: 1.5px solid transparent;
}
.ph-nome { display: block; font-size: .875rem; font-weight: 700; }
.ph-status { display: block; font-size: .75rem; font-weight: 600; }
/* aberta: check verde-badge, nome claro, "Concluído" verde-folha */
.porteira-h.aberta .ph-badge {
  background: var(--verde-badge); border-color: var(--verde-badge);
  color: var(--verde-noite);
}
.porteira-h.aberta .ph-nome { color: var(--painel-escuro-texto); }
.porteira-h.aberta .ph-status { color: var(--verde-folha); }
/* atual: número em âmbar, "Em andamento" */
.porteira-h.atual .ph-badge {
  background: var(--ambar); border-color: var(--ambar);
  color: var(--verde-noite);
}
.porteira-h.atual .ph-nome { color: var(--painel-escuro-texto); }
.porteira-h.atual .ph-status { color: var(--ambar); }
/* fechada: número vazado, tudo em meia-luz. F21.2.1 — a borda era `#5f7a64`,
   hex que NÃO existe no TOKENS.md; passa à borda declarada do §Modo escuro. */
.porteira-h.fechada .ph-badge {
  background: transparent; border-color: var(--painel-escuro-borda);
  color: var(--painel-escuro-texto-2);
}
.porteira-h.fechada .ph-nome { color: var(--painel-escuro-texto-2); }
.porteira-h.fechada .ph-status { color: var(--painel-escuro-texto-3); }

/* os 2 cartões abaixo da faixa (Porteira atual × Avisos) */
.inicio-grid { display: grid; gap: var(--esp-4); margin-top: var(--esp-4); }
.cartao-inicio { margin: 0; padding: 22px 26px; }
.cartao-inicio .eyebrow { margin-top: 0; font-size: 11px; letter-spacing: .09em; }
.cartao-inicio h3 {
  font-family: var(--fonte-display); font-weight: 600; font-size: 19px;
  margin: var(--esp-2) 0 var(--esp-1);
}
.cartao-inicio.cartao-avisos h3 { font-size: 16px; }
.cartao-inicio p { color: var(--cinza); font-size: .875rem; }
.cartao-inicio .botao { margin-bottom: 0; }
/* avisos aninhados dentro do cartão: perdem sombra e um passo de raio */
.cartao-inicio .cartao {
  box-shadow: none; border-radius: var(--raio-controle);
  padding: var(--esp-3) var(--esp-4); margin: var(--esp-2) 0;
}
.eyebrow.terra { color: var(--terra); }
.eyebrow.oliva { color: #7a8a6e; }
@media (min-width: 1024px) {
  .faixa-horizonte { padding: 30px 36px 26px; }
  .faixa-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 28px; }
  .faixa-linha { display: block; }
  .inicio-grid { grid-template-columns: 1.4fr 1fr; align-items: start; }
}

/* ============================================================================
   DARK MODE (§7-DARK-MODE do doc 12) — segunda paleta DESENHADA, não invertida.
   Mecânica: o :root acima é o tema LIGHT ratificado (intocado); o bloco
   :root[data-theme="dark"] SÓ re-declara tokens + os pares fundo/texto dos
   componentes que usavam par claro (badges, selos, cerca). O atributo
   data-theme é posto pelo script inline do <head> ANTES do 1º paint (sem
   flash) e alternado pelo toggle sol/lua (app.js), que persiste em
   localStorage("ecoesfera-tema") e atualiza <meta name="theme-color">.
   Neutros TINTADOS à marca (viés verde), nunca preto puro (design-master §5);
   no escuro a elevação vem de superfície+borda, não de sombra preta forte.
   ========================================================================== */

/* --------------------------------------------- toggle sol/lua (o controle) */
#btn-tema, #btn-tema-solto {
  display: flex; align-items: center; justify-content: center;
  width: 44px; min-width: 44px; min-height: 44px; padding: 0; margin: 0;
  flex: 0 0 auto; border-radius: var(--raio-interno); box-shadow: none;
  background: rgba(255, 255, 255, .18); border: 1px solid rgba(255, 255, 255, .35);
  color: #fff;
}
#btn-tema:hover { background: rgba(255, 255, 255, .28); }
#btn-tema svg, #btn-tema-solto svg { width: 22px; height: 22px; display: block; }
/* pré-login: botão flutuante no canto superior direito (abaixo da faixa
   ADR-007); só existe na superfície pré-login — o #topo cobre o logado */
#btn-tema-solto {
  display: none; position: fixed; top: 52px; right: 14px; z-index: 15;
  background: var(--superficie); border: 1px solid var(--borda-forte);
  color: var(--texto);
}
body.pre-login #btn-tema-solto { display: flex; }
#btn-tema-solto:hover { background: var(--fundo); }
@media (min-width: 1024px) {
  /* top bar do shell é clara/superfície: o ghost branco sumiria (F16.0: o
     campo também vive no shell de sidebar) */
  body.superficie-campo #btn-tema,
  body.superficie-mesa #btn-tema, body.superficie-operacao #btn-tema {
    background: none; border: 1px solid var(--borda-forte); color: var(--texto);
  }
  body.superficie-campo #btn-tema:hover,
  body.superficie-mesa #btn-tema:hover, body.superficie-operacao #btn-tema:hover {
    background: var(--fundo);
  }
}

/* ------------------- cerca/porteiras: cores por CLASSE (mesmos valores que
   os antigos atributos fill/stroke do app.js — light pixel-idêntico) */
.cerca-trilho { stroke: #d8d4c6; }
.cerca-mourao { stroke: #aca894; }
.cerca-no.aberta { fill: #4cae63; }
.cerca-check { stroke: #fff; }
.cerca-no.atual { fill: #fff; stroke: #2c6e49; }
.cerca-num.atual { fill: #1f4632; }
.cerca-no.fechada { fill: #ece8dc; stroke: #aca894; }
.cerca-num.fechada { fill: #57674f; }
.porteira-num { color: #1f4632; }        /* círculos numerados da landing */
.icone-mascara { fill: var(--icone-mascara); }

/* ------------------------------------------------------- tokens do escuro */
:root[data-theme="dark"] {
  color-scheme: dark;
  /* neutros tintados à marca (viés verde-noite) — nunca preto puro */
  --fundo: #0a110c;          /* página                                      */
  --texto: #f5f2ea;          /* corpo (pixel-spec F17 dark)                 */
  --cinza: #9db3a0;          /* texto-2                                     */
  --texto-3: #7c8f80;        /* texto-3                                     */
  --superficie: #121d15;     /* cartão/nav-mobile/top bar                   */
  --input-fundo: #101a13;
  --borda: #24352a; --borda-2: #24352a; --borda-forte: #33453a;
  /* a marca CLAREIA para contrastar no escuro */
  --verde-acao: #4cae63;     /* alias --verde-claro acompanha              */
  --cor-primaria: #2c6e49;   /* ação primária visível sobre a superfície    */
  --cor-primaria-escura: #4cae63;  /* hover: no escuro clareia              */
  --texto-botao: #f5f2ea;
  --cor-link: #7fce8f;
  --azul: #7fb2e0;           /* info/banco/foco — §Azul de mesa "no escuro" */
  --erro: #f87171;
  --cor-atencao: #e9d9b8; --cor-atencao-fundo: #2a2314;
  --areia: #2a2314; --terra: #d3b285;   /* chip piloto no escuro           */
  /* --cor-atencao-faixa fica #9c6b30: a faixa ADR-007 é idêntica e
     proeminente nos DOIS temas */
  --acento-operacao: #9db3a0;
  --icone-mascara: #121d15;
  --cerca-trilho: #33453a; --cerca-mourao: #4d5f55;
  /* sombras quase somem no escuro: elevação = superfície + borda */
  --sombra-1: 0 1px 2px rgba(0, 0, 0, .45);
  --sombra-2: 0 4px 14px rgba(0, 0, 0, .45);
  --sombra-img-escuro: 0 10px 24px -12px rgba(0, 0, 0, .7);

  /* ---- F21 · pares escuros da camada v8 (TOKENS.md §Modo escuro) ----
     Sem estes, o ladrilho de KPI nasceria quase branco (#fbfaf6) sobre a
     página #0a110c e o número ficaria em #1f4632, ilegível. Achado do
     guardiao-design-ecoesfera na revisão da Fase 1. */
  --cartao-sutil: rgba(255, 255, 255, .06);   /* §Modo escuro, Superfície   */
  --divisoria: rgba(255, 255, 255, .12);      /* §Modo escuro, Borda        */
  --texto-titulo: #f5f2ea;                    /* §Modo escuro, Texto prim.  */
  --positivo: #7fce8f;                        /* §Modo escuro, Verde acento */
  --borda-mesa: rgba(255, 255, 255, .12);
  --borda-operacao: rgba(255, 255, 255, .12);
  --fundo-mesa: #0c1520;                      /* §Azul de mesa, nav escura  */
  --fundo-operacao: #161b1e;                  /* §Grafite, nav escura       */
  /* pastéis: o TOKENS.md é silencioso no escuro; segue a convenção JÁ viva
     deste repositório (blocos de componente logo abaixo), que passou por
     contraste — em vez de derivar por opacidade */
  --positivo-fundo: #052e16;
  --erro-fundo: #450a0a;
  --erro-sobre-fundo: #fecaca;
  --azul-chip: #172554;
}

/* O número do KPI clareia no escuro (o verde-marca #1f4632 é ilegível lá).
   ESCOPADA à superfície de CAMPO de propósito: sem `body.superficie-campo`
   esta regra somava (0,5,0) e vencia as de mesa/operação — por especificidade,
   não por ordem —, pintando de VERDE o KPI de uma tela de banco/SPO no escuro
   (dois sotaques na mesma tela). Hoje as três somam (0,5,1)/(0,5,1)/(0,6,1),
   mas a defesa real é o ESCOPO POR CLASSE, não a corrida numérica: `body` só
   carrega uma superfície por vez, então elas nunca competem. Achado do
   guardiao-design-ecoesfera na 2ª revisão da Fase 1: o bug nasceu da correção
   do 1º achado. Com a classe de superfície, as três regras são mutuamente
   exclusivas e nenhuma disputa cascata. */
[data-theme="dark"] body.superficie-campo .kpi-valor:not(.atencao):not(.erro):not(.positivo) {
  color: var(--verde-folha);
}

/* ------------------- componentes que usavam PAR claro (fundo pastel + texto
   forte): no escuro viram fundo profundo + texto brilhante (≥4,5:1) */
[data-theme="dark"] .estado.criado, [data-theme="dark"] .estado.entrega_confirmada,
[data-theme="dark"] .estado.em_processamento,
[data-theme="dark"] .selo.banco { background: #172554; color: #93c5fd; }
[data-theme="dark"] .estado.carimbado { background: #1e1b4b; color: #a5b4fc; }
[data-theme="dark"] .estado.retido, [data-theme="dark"] .estado.liberado,
[data-theme="dark"] .estado.sacavel, [data-theme="dark"] .selo.produtor,
[data-theme="dark"] .estado.pre_requisitos_atendidos,
[data-theme="dark"] .estado.com_relatorio,
[data-theme="dark"] .marco-status.cumprido,
[data-theme="dark"] .resultado-hash.confere { background: #052e16; color: #86efac; }
[data-theme="dark"] .estado.divergencia_detectada,
[data-theme="dark"] .marco-status.fonte_do_edital_nao_resolvida,
[data-theme="dark"] .resultado-hash.nao-confere { background: #450a0a; color: #f87171; }
[data-theme="dark"] .selo.informativo,
[data-theme="dark"] .resultado-hash.vazia,
[data-theme="dark"] .estado.sem_relatorio { background: #1f2b26; color: var(--cinza); }
/* .estado.contestado, .estado.com_discrepancias e .marco-status.em_atraso
   já leem os tokens de atenção. F21.2.5 — `.marco-status.pendente` SAIU
   deste grupo cinza: a regra base (linha ~813) já usa var(--areia)/
   var(--terra), que o :root[data-theme="dark"] redefine (linha ~1750,
   mesmo par do .chip-piloto). Mantê-la aqui, com hex cru + --cinza, tinha
   especificidade maior ([data-theme] + 2 classes vs. 2 classes) e vencia a
   regra nova sempre — o escuro continuava mostrando pendente em cinza, não
   terra. Achado do guardiao-design-ecoesfera na revisão da F21.2. */

[data-theme="dark"] .cartao.atencao { background: #221c0c; }
[data-theme="dark"] .cumprimento { background: #0f2318; }
[data-theme="dark"] .cumprimento strong,
[data-theme="dark"] .porteira.aberta .porteira-rotulo,
[data-theme="dark"] .porteira.atual .porteira-rotulo,
[data-theme="dark"] .porteira-num,
[data-theme="dark"] .landing-marca { color: #86efac; }
/* a sidebar/nav-marca é verde-noite nos DOIS temas (F17) — sem par dark */
[data-theme="dark"] pre { background: #08110d; color: #cbd5d1;
  border: 1px solid var(--borda); }
[data-theme="dark"] #rodape-offline { background: #1f2b26; color: var(--texto);
  border-top: 1px solid var(--borda); }
[data-theme="dark"] .tabela-mesa tbody tr:hover { background: #1a2921; }

/* cerca no escuro: trilhos discretos, nós legíveis sobre a superfície */
[data-theme="dark"] .cerca-trilho { stroke: #33443b; }
[data-theme="dark"] .cerca-mourao { stroke: #4d5f55; }
[data-theme="dark"] .cerca-no.aberta { fill: #22c55e; }
[data-theme="dark"] .cerca-check { stroke: #052e16; }
[data-theme="dark"] .cerca-no.atual { fill: var(--superficie); stroke: #22c55e; }
[data-theme="dark"] .cerca-num.atual { fill: #86efac; }
[data-theme="dark"] .cerca-no.fechada { fill: #1f2b26; stroke: #4d5f55; }
[data-theme="dark"] .cerca-num.fechada { fill: var(--cinza); }

/* painel-herói da landing (≥1024): gradiente verde vira variante escura */
[data-theme="dark"] .landing-visual {
  background: linear-gradient(165deg, #11241a 0%, #0e1e15 55%, #0c1912 100%);
  border-color: #1e3527;
  box-shadow: 0 24px 48px -20px rgba(0, 0, 0, .6);
}
/* F16.0: o quadro-440px do campo foi aposentado — o shell do campo (sidebar
   + top bar + main) é todo em tokens (--superficie/--borda/--fundo/--acento),
   então o par dark dele vem por construção do :root[data-theme="dark"];
   nenhuma regra escura extra é necessária. */

/* --------------------------------------- F15.4 — fornecedor: linha do tempo
   do pedido (o caminho até receber, do ponto de vista dele). Só tokens do
   tema (funciona no claro e no escuro): feito = trilho verde + check; atual
   = trilho da marca + peso forte; futuro = apagado, mas legível (AA). */
.linha-tempo { list-style: none; margin: .6rem 0 0; padding: 0; }
.linha-tempo li {
  display: flex; gap: .55rem; align-items: flex-start; text-align: left;
  margin-left: .5rem; padding: .5rem 0 .5rem .7rem;
  border-left: 3px solid var(--borda-forte);
}
.linha-tempo li.feito { border-left-color: var(--cor-primaria); }
.linha-tempo li.atual { border-left-color: var(--cor-marca); font-weight: 700; }
.linha-tempo li.futuro { color: var(--cinza); }
.linha-tempo .lt-marca { flex: 0 0 22px; width: 22px; height: 22px; }
.linha-tempo .lt-marca svg { width: 22px; height: 22px; display: block; }
.linha-tempo li.feito .lt-marca { color: var(--cor-primaria-escura); }
.linha-tempo li.atual .lt-marca { color: var(--cor-marca); }
[data-theme="dark"] .linha-tempo li.atual { border-left-color: #86efac; }
[data-theme="dark"] .linha-tempo li.atual .lt-marca { color: #86efac; }

/* INC-F1 — RECUSA da entrega: ramo TERMINAL da logística, distinto do
 * caminho feliz (vermelho SÓ aqui — design-system-agro: reservado a erro/
 * divergência; a recusa é o único desfecho negativo desta timeline). */
.linha-tempo li.recusado {
  border-left-color: var(--erro); font-weight: 700; color: var(--erro);
}
.linha-tempo li.recusado .lt-marca { color: var(--erro); }
[data-theme="dark"] .linha-tempo li.recusado,
[data-theme="dark"] .linha-tempo li.recusado .lt-marca { color: #f87171; border-left-color: #f87171; }
/* INC-F1 — as duas ações do fornecedor lado a lado (empilham no mobile
 * estreito por flex-wrap; sem CSS novo de grade) */
.acoes-logistica {
  display: flex; gap: .6rem; flex-wrap: wrap; margin-top: .5rem;
}

/* ------------------- F16.0-design — pares DARK das peças de PC do campo
   (só ≥1024px; usos de literais light que o token não cobre). A sombra
   verde-tintada do campo é declarada no <body> (mais perto que o :root),
   então o escuro precisa re-declarar aqui os valores de sombra escura. */
@media (min-width: 1024px) {
  [data-theme="dark"] body.superficie-campo {
    --sombra-1: 0 1px 2px rgba(0, 0, 0, .45);
    --sombra-2: 0 4px 14px rgba(0, 0, 0, .45);
  }
  /* a sidebar é verde-noite nos DOIS temas — nenhum par dark de nav aqui */
  /* F16.2 — hover verde-tintado da tabela de recebíveis no escuro (par do
     rgba do light; vence o hover genérico da mesa por especificidade). */
  [data-theme="dark"] body.superficie-campo .tabela-mesa tbody tr:hover {
    background: rgba(134, 239, 172, .07);
  }
}

/* ============================================================================
   F17.7 — CHROME DE APP no CELULAR (<1024px). TODA regra vive dentro desta
   @media: nada aqui alcança o desktop ratificado (≥1024px permanece byte a
   byte o F17.3). Só tokens do tema — par dark por construção; nenhuma
   animação nova (reduced-motion inalterado).
   1) APP BAR limpa: marca à esquerda; sino + tema à direita. O #quem e o
      #btn-sair SAEM do topo (continuam no DOM com o handler ligado — quem
      esconde é o CSS). A identidade segue na árvore de ACESSIBILIDADE pelo
      rodapé da nav (abaixo); nas telas de decisão o decisor é nomeado no
      conteúdo (ADR-004), nunca só no chrome.
   2) SAIR na PONTA da barra inferior (opção (a) do brief): o .nav-rodape —
      que já existe com o botão ligado a sair() — vira o último ladrilho da
      barra, separado por fio e em cor de item INATIVO. Deliberado: sair()
      expurga a fila offline de aceites (ADR-005/LGPD), então o ladrilho é
      visualmente distinto dos destinos de navegação.
   3) Respiro de APP: título de tela num passo de app (não display de site);
      faixa-horizonte proporcionada para o "Porteira atual" alcançar a 1ª
      dobra; alvos ≥52px e safe-area preservados.
   O rótulo ADR-007 (chip "Piloto · simulado" no header do shell) segue
   inescapável nos dois mundos — a faixa laranja foi aposentada (F17.9).
   ========================================================================== */
@media (max-width: 1023px) {
  /* ============ F18 — APP NATIVO de celular (handoff mobile do Claude Design)
     Layout de tela: [status bar do SO] [header por-tela] [conteúdo rolável]
     [tab bar fixa]. Tokens um tom mais quentes que o PC. Desktop ≥1024px
     permanece intocado. =========================================== */
  body { --fundo: #efece6; }
  :root[data-theme="dark"] body { --fundo: #0b120d; }

  /* ---- 1) HEADER por-tela via #topo: no celular a app bar vira o cabeçalho
     do design — TÍTULO da tela (Bricolage) à esquerda + pílula/sino/tema à
     direita. O título vem do item de nav ativo (montarNav → #titulo-contexto).
     Telas com header ESPECIAL (home: "Bem-vindo de volta") marcam body.cab-
     propria e trazem seu próprio .cab-mobile no conteúdo. */
  #topo {
    min-height: 60px; padding: 12px 20px 14px; gap: 10px;
    background: var(--fundo); color: var(--texto); border-bottom: 0;
    position: sticky; top: 0; z-index: 20;
  }
  #topo .marca-topo { display: none; }
  #topo #titulo-contexto {
    display: block; flex: 1; min-width: 0; margin: 0;
    font-family: var(--fonte-display); font-weight: 700; font-size: 21px;
    color: var(--texto); letter-spacing: -.01em;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  #topo #quem { display: none; }
  #topo .topo-dir { flex: 0 0 auto; gap: 9px; }
  #topo #btn-tema { background: var(--superficie); border: 1px solid var(--borda); color: var(--cinza); }
  /* F19.0 + emenda 2026-07-24 — no celular a nota encurta para "ambiente de
     demonstração" (o header tem pouca largura); o "· valores simulados" some (o
     rótulo "(valor simulado)" segue em todo valor — ADR-007 mantido) */
  .chip-simulado { display: none; }
  /* INC-F5 — MENU DE PERFIL no header (fora da zona de toque direto): o
     gatilho #btn-perfil é um ícone circular (mesmo tamanho/posição que o
     antigo #btn-sair bare); o Sair só aparece DENTRO do painel, que exige um
     toque extra para abrir — reduz o risco de toque acidental sem mudar
     sair() nem seu handler. Texto "Sair" fica no DOM p/ leitor de tela;
     sair() continua confirmando (purga rascunhos/fila) no clique real. */
  .menu-perfil { position: relative; flex: 0 0 auto; }
  #topo #btn-perfil {
    display: inline-flex; align-items: center; justify-content: center;
    width: 38px; min-width: 38px; height: 38px;
    padding: 0; margin: 0; border-radius: 999px; flex: 0 0 auto;
    background: var(--superficie); border: 1px solid var(--borda);
    color: #57674f; box-shadow: none;
  }
  #topo #btn-perfil svg { width: 18px; height: 18px; display: block; }
  #topo #btn-perfil[aria-expanded="true"] {
    background: var(--fundo); border-color: var(--cor-primaria);
  }
  .menu-perfil-painel {
    position: absolute; top: calc(100% + 8px); right: 0; z-index: 30;
    min-width: 176px; background: var(--superficie);
    border: 1px solid var(--borda); border-radius: 12px;
    box-shadow: var(--sombra-2, 0 6px 18px rgba(30, 45, 32, .18));
    padding: 8px;
  }
  .menu-perfil-painel #btn-sair {
    display: block; width: 100%; min-height: 44px; margin: 0;
    background: var(--superficie); color: var(--erro, #b91c1c);
    border: 1px solid var(--borda-forte); font-size: .9rem; font-weight: 700;
  }
  .menu-perfil-painel #btn-sair:hover { background: var(--fundo); }
  /* Sair saiu da barra (foi para o menu de perfil do header): esconde o
     BOTÃO e colapsa o container, MAS preserva a identidade sr-only
     (nav-usuario/nav-papel) */
  #nav-app .nav-rodape { border: 0; min-width: 0; margin: 0; padding: 0; flex: 0 0 0; }
  #nav-app .nav-rodape button { display: none; }
  body.cab-propria #topo { display: none; }  /* tela com header próprio */

  /* ---- 2) TAB BAR inferior (padrão do design: ícone 23 + rótulo 10; ativo
     por COR, sem barra de topo; fundo surface; safe-area reservada) */
  #nav-app {
    background: #fbfaf6; border-top: 1px solid var(--borda); box-shadow: none;
    align-items: flex-end;
    padding: 9px 6px calc(16px + env(safe-area-inset-bottom, 0px));
  }
  :root[data-theme="dark"] #nav-app { background: #0d160f; border-top-color: #1c2a1e; }
  #nav-app a {
    flex: 1; min-width: 0; flex-direction: column; align-items: center;
    gap: 4px; padding: 4px 2px; border-top: 0; border-radius: 0;
    color: #9aa79c; font-size: 10px; font-weight: 600;
  }
  :root[data-theme="dark"] #nav-app a { color: #5f7a64; }
  #nav-app a .icone svg { width: 23px; height: 23px; }
  #nav-app a[aria-current="page"] { color: #1d6b43; border-top: 0; }
  :root[data-theme="dark"] #nav-app a[aria-current="page"] { color: #7fce8f; }
  #nav-app a:hover, #nav-app a:active { background: none; }

  /* F19.0 — o Sair saiu da barra inferior (foi para o header, fora da zona do
     polegar, + confirmação). A identidade sr-only continua acessível. */
  #nav-app .nav-usuario, #nav-app .nav-papel {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    border: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
    white-space: nowrap;
  }

  /* ---- 3) HEADER POR TELA (.cab-mobile): título/subtítulo ou voltar+título
     à esquerda; pílula/sino/ações à direita */
  .cab-mobile {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; padding: 6px 2px 14px;
  }
  .cab-mobile-esq { display: flex; align-items: center; gap: 12px; min-width: 0; }
  .cab-mobile-eyebrow { font-size: 12px; color: var(--texto-3); font-weight: 600; }
  .cab-mobile-tit {
    margin: 0; font-family: var(--fonte-display); font-weight: 700;
    font-size: 21px; color: var(--texto); letter-spacing: -.01em;
    overflow: hidden; text-overflow: ellipsis;
  }
  .cab-mobile-acoes { display: flex; align-items: center; gap: 9px; flex: 0 0 auto; }
  .cab-mobile-pill {
    background: none; color: var(--texto-3); border-radius: 999px;
    padding: 5px 4px; font-weight: 400; font-size: 11px; white-space: nowrap;
  }
  :root[data-theme="dark"] .cab-mobile-pill { color: var(--texto-3); }
  .cab-mobile-btn {
    position: relative; width: 38px; height: 38px; border-radius: 999px;
    background: var(--superficie); border: 1px solid var(--borda);
    display: grid; place-items: center; color: var(--cinza); flex: 0 0 auto;
    padding: 0; margin: 0; box-shadow: none; cursor: pointer;
  }
  .cab-mobile-btn svg { width: 18px; height: 18px; }
  .cab-mobile-btn .badge-num {
    position: absolute; top: -2px; right: -2px; min-width: 16px; height: 16px;
    padding: 0 3px; border-radius: 999px; background: var(--verde-acao);
    color: #fff; font-size: 10px; font-weight: 800; display: grid;
    place-items: center; border: 2px solid var(--fundo); box-sizing: border-box;
  }
  .cab-mobile-voltar {
    width: 36px; height: 36px; border-radius: 11px; background: var(--superficie);
    border: 1px solid var(--borda); display: grid; place-items: center;
    color: var(--texto); flex: 0 0 auto; padding: 0; box-shadow: none;
  }
  .cab-mobile-voltar svg { width: 18px; height: 18px; }

  /* ---- 4) TRILHA VERTICAL (stepper): painel escuro + porteira 74px por linha */
  /* F21.2.1 — os valores crus desta caixa viraram token: o fundo é
     --verde-noite (§Verde "Nav escura"), o título --verde-folha ("Verde no
     escuro"), o raio --raio-painel e o pontilhado --trilha-pontilhada-v,
     que a Fase 1 declarou justamente para isto e ainda não tinha consumidor. */
  .trilha-vert {
    background: var(--verde-noite); border-radius: var(--raio-painel);
    padding: 22px 20px;
    box-shadow: 0 16px 40px -22px rgba(0, 0, 0, .6);
  }
  :root[data-theme="dark"] .trilha-vert { border: 1px solid #24352a; }
  .trilha-vert-titulo {
    font-size: 11px; font-weight: 700; letter-spacing: .1em;
    text-transform: uppercase; color: var(--verde-folha); margin-bottom: 16px;
  }
  .trilha-vert-lista { position: relative; display: flex; flex-direction: column; gap: 16px; }
  .trilha-vert-lista::before {
    content: ""; position: absolute; left: 37px; top: 30px; bottom: 30px;
    width: 2px; background: var(--trilha-pontilhada-v);
  }
  .tv-linha { display: flex; gap: 14px; align-items: center; position: relative; z-index: 1; }
  .tv-linha > img { width: 74px; border-radius: 8px; flex-shrink: 0; box-shadow: 0 8px 18px -10px rgba(0, 0, 0, .8); }
  .tv-info { flex: 1; min-width: 0; }
  .tv-cabeca { display: flex; align-items: center; gap: 8px; }
  .tv-badge {
    width: 20px; height: 20px; border-radius: 999px; display: grid;
    place-items: center; font-size: 10px; font-weight: 800; flex-shrink: 0;
    border: 1.5px solid transparent;
  }
  .tv-nome { font-size: 13.5px; font-weight: 700; color: var(--painel-escuro-texto); }
  .tv-status { font-size: 11.5px; font-weight: 600; margin-top: 3px; margin-left: 28px; }
  /* F21.2.1 — estados da trilha VERTICAL. Antes vinham de `style=` inline no
     app.js (15 hex crus, 3 deles fora do TOKENS.md). Agora são as MESMAS
     declarações da faixa horizontal do PC (`.porteira-h.*`, app.css §F17.2):
     uma paleta de trilha, não duas. */
  .tv-linha.aberta .tv-badge {
    background: var(--verde-badge); border-color: var(--verde-badge);
    color: var(--verde-noite);
  }
  .tv-linha.aberta .tv-status { color: var(--verde-folha); }
  .tv-linha.atual .tv-badge {
    background: var(--ambar); border-color: var(--ambar);
    color: var(--verde-noite);
  }
  .tv-linha.atual .tv-status { color: var(--ambar); }
  .tv-linha.fechada .tv-badge {
    background: transparent; border-color: var(--painel-escuro-borda);
    color: var(--painel-escuro-texto-2);
  }
  .tv-linha.fechada .tv-nome { color: var(--painel-escuro-texto-2); }
  .tv-linha.fechada .tv-status { color: var(--painel-escuro-texto-3); }
  /* variante CLARA (detalhe do projeto): painel branco, linha cinza */
  .trilha-vert.clara { background: var(--superficie); border: 1px solid var(--borda); box-shadow: none; }
  .trilha-vert.clara .trilha-vert-titulo { color: var(--terra); }
  .trilha-vert.clara .trilha-vert-lista::before { background: repeating-linear-gradient(180deg, #c9c5bb 0 7px, transparent 7px 16px); }

  /* ---- 5) home mobile: resumo + card porteira atual + avisos */
  body.superficie-campo main h1, body.superficie-mesa main h1,
  body.superficie-operacao main h1 { font-size: 1.35rem; }
  .home-resumo { margin: 0 0 16px; font-size: 13.5px; color: var(--cinza); }
  .cartao-porteira-atual {
    background: var(--superficie); border: 1px solid var(--borda);
    border-radius: 16px; padding: 18px 20px; margin-top: 16px;
  }
  .cartao-porteira-atual .eyebrow {
    font-size: 11px; font-weight: 700; letter-spacing: .09em;
    text-transform: uppercase; color: var(--terra);
  }
  .cartao-porteira-atual h3 {
    margin: 9px 0 5px; font-family: var(--fonte-display); font-weight: 600;
    font-size: 17px; color: var(--texto);
  }
  .cartao-porteira-atual p { margin: 0 0 14px; font-size: 13px; color: var(--cinza); }
  .avisos-mob-cab { display: flex; align-items: baseline; justify-content: space-between; margin: 22px 4px 10px; }
  .avisos-mob-cab .tit { font-size: 14px; font-weight: 700; color: var(--texto); font-family: var(--fonte-display); }
  .avisos-mob-lista { display: flex; flex-direction: column; gap: 10px; }
  .aviso-mob {
    background: var(--superficie); border: 1px solid var(--borda);
    border-radius: 14px; padding: 14px 16px; display: flex;
    flex-direction: column; gap: 5px; text-decoration: none;
  }
  .aviso-mob .aviso-t { font-size: 13.5px; font-weight: 700; color: var(--texto); }
  .aviso-mob .aviso-d { font-size: 12.5px; color: var(--cinza); }

  /* ---- 6) telas de LISTA: o título vive no header (#topo); o h1 do conteúdo
     (.cabecalho-tela) some e a ação primária vira FAB "+" (padrão do design
     7c/7e). O texto do botão fica no DOM (nome acessível preservado). */
  .cabecalho-tela { display: contents; }
  .cabecalho-tela > h1 { display: none; }
  .cabecalho-tela > .botao {
    position: fixed; right: 16px;
    bottom: calc(var(--nav-altura) + env(safe-area-inset-bottom, 0px) + 14px);
    z-index: 15; width: 56px; height: 56px; min-height: 56px; padding: 0;
    margin: 0; border-radius: 999px; font-size: 0; display: grid;
    place-items: center; box-shadow: 0 12px 26px -10px rgba(31, 70, 50, .7);
  }
  .cabecalho-tela > .botao::after {
    content: "+"; font-size: 30px; line-height: 1; font-weight: 400;
  }

  /* ---- 7) telas de DETALHE (pedido/projeto): header próprio com VOLTAR +
     título; marcos como stepper de bolinhas.

     F21.2.1 — `.mini-cards` e `.mini-card{.rot,.val}` foram REMOVIDOS daqui.
     Eram o ladrilho de resumo que a F18 escreveu para uma marcação de celular
     que nunca foi emitida (nenhum JS produz `.mini-cards`/`.rot`/`.val`) — e,
     por herdarem o MESMO nome da primitiva `.mini-card` do INC-F3, venciam-na
     no celular por ordem de cascata: todo cartão de marco de `telaProjeto`
     saía com raio 13px e padding 12/14 em vez do desenho da primitiva. Era
     colisão viva, não código morto inerte. O papel que este bloco queria
     cumprir — a fileira MARCOS / VINCULADO / LEILÃO da 8h — é da primitiva
     `kpiTile()` + `.grade-kpi`, que o v8 define e a Fase 1 já construiu. */
  /* F21.2.5 — as três colunas do marco no celular (8h). O v8 mantém as três
     lado a lado; o que muda é a repartição: PROVA EXIGIDA é a única que PODE
     fluir em várias linhas, então ela leva a folga e PRAZO/VALOR ficam do
     tamanho do próprio dado. Sem isso, `2026-10-23` (que é `nowrap`, por
     regra do TOKENS.md) estouraria o cartão a 320px em vez de quebrar. */
  .marco-grade {
    grid-template-columns: minmax(0, 1.1fr) auto auto;
    gap: var(--esp-2) var(--esp-3);
  }
  .marco-col-val { font-size: 13.5px; }
  .marco-rodape { font-size: 12.5px; }

  /* F21.2.5 — `.marcos-mob`/`.marco-mob` foram REMOVIDOS. Eram a lista de
     marcos de celular que a F18 escreveu esperando um ramo `!emDesktop()` em
     `telaProjeto` que nunca nasceu — nenhum JS os emitiu em nenhum momento.
     A 8h foi construída com o mesmo `miniCard()` do PC (uma gramática de
     cartão, não duas) mais a fileira `.grade-kpi`; estas regras ficariam
     mortas para sempre, e três dos seus valores (`#e9d9b8`, `#c9a45f`,
     `#fff` cru) já viviam fora dos tokens. */

  /* ---- 8) LOGIN 7a nativo de celular: coluna centralizada, marca grande,
     campos, seletor de persona embaixo, rótulo Piloto no rodapé */
  .login-mob {
    max-width: 400px; margin: 0 auto; padding: 8px 10px 24px;
    display: flex; flex-direction: column; min-height: 100%;
  }
  .login-mob-marca {
    display: flex; flex-direction: column; align-items: center;
    text-align: center; gap: 13px; margin: 22px 0 30px;
  }
  .login-mob-marca img { width: 76px; height: 76px; object-fit: contain; }
  .login-mob-wm { font-family: var(--fonte-display); font-weight: 700; font-size: 30px; }
  .login-mob-wm .wm-eco { color: var(--verde-acao); }
  .login-mob-wm .wm-esfera { color: var(--texto); }
  .login-mob-slogan { display: flex; align-items: center; gap: 9px; }
  .login-mob-slogan .tr { width: 20px; height: 2px; background: var(--terra); border-radius: 2px; flex: 0 0 auto; }
  .login-mob-slogan > span:not(.tr) {
    font-size: 9.5px; font-weight: 700; letter-spacing: .1em;
    text-transform: uppercase; color: var(--texto-3);
  }
  .login-mob-lab { font-size: 12px; font-weight: 600; color: var(--cinza); margin: 0 0 6px; }
  .login-mob input {
    width: 100%; box-sizing: border-box; margin: 0 0 14px;
    background: var(--superficie); border: 1px solid var(--borda-forte);
    border-radius: 12px; padding: 13px 15px; font-size: 14px; color: var(--texto);
  }
  .login-mob-entrar { margin-top: 6px; width: 100%; }
  .login-mob-esqueci { text-align: center; margin-top: 14px; font-size: 13px; color: var(--cinza); }
  .login-mob-nota { text-align: center; margin-top: 14px; font-size: 12.5px; color: var(--texto-3); }
  .login-mob-div { display: flex; align-items: center; gap: 12px; margin: 24px 0 15px; }
  .login-mob-div > span:not(.txt) { flex: 1; height: 1px; background: var(--borda-forte); }
  .login-mob-div .txt {
    font-size: 11px; font-weight: 600; color: var(--texto-3);
    text-transform: uppercase; letter-spacing: .08em; white-space: nowrap;
  }
  .login-mob-chips { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }
  .login-mob-piloto {
    text-align: center; margin-top: auto; padding-top: 22px;
    font-size: 11px; color: var(--texto-3); font-weight: 600;
  }
}

/* ── Utilitárias que substituem `style=` inline (achado da passada local,
   2026-07-30) ─────────────────────────────────────────────────────────────
   A CSP da Onda 0 é `style-src 'self'` (sem unsafe-inline), e o navegador
   RECUSA atributo `style=` — inclusive o aplicado via setAttribute pelo
   helper `h()`. Resultado: 8 estilos inline do app.js nunca chegavam à tela
   desde 26/07, em produção, em silêncio. Os dois de `.label-check` eram
   LAYOUT (checkbox e texto desalinhavam), não só refino. */
.dado-mini { font-size: .85rem; }
.texto-esquerda { text-align: left; }
.label-check { display: flex; gap: .5rem; align-items: center; }
.bloco-separado { border-top: 1px solid var(--borda); padding: .5rem 0; }
.badge-compacta { padding: .2rem .5rem; font-size: .9rem; }
