/* ===== TOKENS ===== */
/* ==========================================================================
   Four Cloud Design System — TOKENS (scale + palette).
   The provider-neutral foundation: one --density knob scales type+spacing
   together; one slate accent carries structure; colour is rationed to meaning
   (red = money leaving, green = small positive deltas). Ported from the tested
   statement mockup (bi/static/bi/demo/statement.{scale,tokens}.css).

   This is the TOKENS section — first in custom.css, everything below depends on it.
   ========================================================================== */

:root{
  /* Reto. Sem exceção (dono, 11/09/2026: "quero tudo reto e sóbrio").
     A pílula de 999px vivia em 28 lugares e cada tela a usava com um
     sotaque. Um knob só: mudar aqui muda o sistema inteiro. */
  --raio-chip: 0;
  /* ── scale (no colour) ─────────────────────────────────────────────── */
  --density:1;                 /* THE knob — >1 comfortable, <1 compact */
  --metric-hero:calc(40px*var(--density));
  --metric-kpi: calc(22px*var(--density));
  --metric-sig: calc(24px*var(--density));
  --hero-unit:  calc(17px*var(--density));
  /* Batch6 note: --card-pad-* / --tile-pad-* are SUPERSEDED by the unified card
     contract (header 8/16/8, body 8/16/16 — docs/planos/batch6-card-contract.md §1).
     They are NOT re-pointed to --bi-space-* here because they are density-scaled px
     and re-pointing would strip the --density knob (kept per Batch5 §3) and risk
     reflow on the FCDS faturamento components. The unified padding is applied at the
     component layer (custom.css, owned by Impl-3); these remain the px base
     the --density knob multiplies until that layer re-points them. */
  --card-pad-y:calc(14px*var(--density));  --card-pad-x:calc(18px*var(--density));
  --tile-pad-y:calc(12px*var(--density));  --tile-pad-x:calc(14px*var(--density));  --tile-pad-b:calc(10px*var(--density));
  --gap:calc(0.5rem*var(--density));
  --content-pad-y:calc(16px*var(--density)); --content-pad-x:calc(20px*var(--density));
  --content-pad-b:calc(36px*var(--density));
  --card-hd-mb:calc(10px*var(--density));
  /* component pixel dims — static (NOT density-scaled, to avoid chart reflow) */
  --doughnut:168px; --ring-size:80px; --spark-h:40px; --flow-min:248px;
  --r:var(--bs-border-radius-lg); --r-sm:var(--bs-border-radius); --r-xs:var(--bs-border-radius-sm); --r-full:var(--bs-border-radius-pill);

  /* ── palette ───────────────────────────────────────────────────────── */
  --surface-app:#edf0f4;       /* the canvas — matches shell body gradient base
                                  (custom.css:22); --bi-bg-base re-points here
                                  (Batch 8, single source for #edf0f4 vs #F4F6F8) */
  --bg:#f6f7f9;
  --surf:#ffffff; --surf-2:#f3f4f7; --surf-3:#eceef2;
  --line:#e6e8ec; --line-2:#eef0f3; --line-3:#d8dbe1;
  --ink:#191c22; --ink-2:#5a6171; --ink-3:#6b7280; --ink-4:#aab0bb;  /* ink-3 #8b93a1→#6b7280: was 3.09:1 (fail AA), now ~4.7:1 */
  /* ACENTO DE COMPONENTE — o azul DE FÁBRICA do Bootstrap, sem cor autoral
     nenhuma: os degraus APONTAM para as variáveis do próprio Bootstrap. Quem
     pinta seleção, foco, chip ligado, dia/mês escolhido e página ativa da
     paginação lê daqui. Se um dia o tema do Bootstrap mudar, isto muda junto —
     é esse o objetivo. Cinza só no SHELL, em --shell-acc-* logo abaixo. */
  --acc:var(--bs-primary); --acc-d:var(--bs-link-hover-color); --acc-ink:var(--bs-link-hover-color);
  /* únicos hex: a dupla *-bg-subtle/*-border-subtle nasceu no 5.3 e o bundle é
     5.2.3 — valores de fábrica do upstream, não cor autoral. */
  --acc-soft:#cfe2ff; --acc-line:#9ec5fe;
  /* ACENTO DO SHELL — o cinza DO BOOTSTRAP (secondary + escada gray), a única
     exceção ao azul, por diretiva do usuário. Consumido SÓ pela sidebar e pela
     topbar (§2/§3): item de menu ativo, trilho da esquerda, avatar e botão de
     menu. Não usar em conteúdo de página. */
  --shell-acc:var(--bs-secondary); --shell-acc-ink:var(--bs-gray-700);
  --shell-acc-soft:var(--bs-gray-200); --shell-acc-line:var(--bs-gray-300);

  /* Escada de tinta do Bootstrap com os VALORES DE FÁBRICA do 5.3 (rgba do corpo a
     75% e a 50%), e não com a tinta FCDS: por diretiva do usuário, nenhuma paleta
     de cor de texto é repontada aqui. Os dois tokens continuam declarados só porque
     o bundle vendorizado é 5.2.3 e não os traz — os utilitários que os consomem
     estão portados mais abaixo. NÃO apontar para --ink-*. */
  --bs-secondary-color: rgba(33, 37, 41, 0.75);
  --bs-tertiary-color: rgba(33, 37, 41, 0.5);
  /* Os utilitários que consomem estes dois tokens só nasceram no Bootstrap 5.3 e o
     build vendorizado é 5.2.3 — por isso eles estão portados logo abaixo de
     .num--* neste arquivo. Quando o Bootstrap subir para 5.3, apagar o port: os
     tokens acima já alimentam a versão upstream, sem tocar em nenhum consumidor. */

  /* CANONICAL COLOR SYSTEM — single source of truth for color meaning.
     Reuse everywhere; never hardcode hex. Ref: docs/planos/batch2-semantic-color-contract.md
     Structure tokens (text/surface/border) are above: --ink/--surf/--line/--acc.
     PRIMARY = brand slate for non-semantic UI emphasis. */
  /* AÇÃO — era o azul Four #006BB5. Passa a apontar para o acento de componente,
     ou seja, o azul de fábrica do Bootstrap: os botões sólidos desta família
     (Buscar, .tb-btn--solid) vivem lado a lado com a paginação e
     com os .btn-primary do Bootstrap, e dois azuis quase iguais na mesma tela
     leem como defeito. Um azul só. Os quatro nomes ficam porque 35 regras os
     consomem — repontar aqui alinha todas de uma vez. */
  --brand: var(--acc);
  --brand-strong: var(--acc-d);
  --brand-soft: var(--acc-soft);
  --brand-ink: var(--acc-ink);
  --command: #2b3038;        /* near-black ink for DATA magnitude where charcoal is wanted (sparklines). NOT an action color. */

  /* ── DIRECTION (value valence) ────────────────────────────────────────────
     Two tiers + a bg tint, per direction:
       --x        vivid FILL  — bars, chart datasets, icons, rules, dots.
       --x-text   AA-safe     — small text / numbers on white (≥4.5:1),
                                inclusive --warning-text (#b04c0a, 5,41:1 —
                                o degrau de texto da laranja de atenção).
       --x-subtle BACKGROUND-ONLY tint — badges/chips; never text.
     Color encodes DIRECTION only — never category/type/entity (use --cat-* for that). */
  --positive:#22c55e;  --positive-text:#15803d;  --positive-subtle:color-mix(in srgb, var(--positive-text) 10%, var(--surf));
  --negative:#ef4444;  --negative-text:#ca2a26;  --negative-subtle:#fcecea;
  /* --warning-text aponta para a MESMA laranja do sistema de gráficos: era
     #8a5a00 (mostarda), uma terceira família para dizer "atenção". Regra do
     projeto: indicador de UI e área de gráfico marcam a mesma coisa com a mesma
     família, mudando só o degrau (ver docs/globais/componentes.md). Alimenta
     .badge--warning e .alert-warning — o app inteiro. --warning (o FILL vivo)
     não muda: só o degrau de TEXTO foi unificado. */
  --warning:#f59e0b;   --warning-text:var(--chart-alerta-text);   --warning-subtle:color-mix(in srgb, var(--warning) 14%, var(--surf));
  --neutral:#94a3b8;   --neutral-subtle:color-mix(in srgb, var(--ink-2) 9%, var(--surf));
  --info:#1f9bcf;      --info-text:#15709c;      --info-subtle:color-mix(in srgb, var(--info) 12%, var(--surf));

  /* ── INDICATOR ALIASES (semantic, AA-safe small text) ─────────────────────
     cores.md prescribes these names for inline notices. --warning-text is kept
     vivid (#f59e0b, fails AA at small sizes) so this alias supplies a deeper tone
     for small WARNING note/label text.
     Agora aponta para --chart-alerta-text: o mostarda #8a6d1f que morava aqui era
     uma TERCEIRA laranja, sem parentesco com a do sistema de gráficos. Indicador e
     gráfico marcam a mesma coisa ("faixa de atenção") e passam a marcar com a mesma
     família. Alias mantido porque 8 chamadas o consomem — repontar aqui alinha todas. */
  --color-indicator-warning-text: var(--chart-alerta-text);

  /* ── RANGE (ordered scale, good→bad) ──────────────────────────────────────
     For 3-stop ramps / conditional thresholds. *-normal-1 = best (green),
     *-inverted reverses valence (when high = bad, e.g. cost/aging). */
  --range-normal-1:var(--positive);   --range-normal-2:var(--warning);   --range-normal-3:var(--negative);
  --range-inverted-1:var(--negative); --range-inverted-2:var(--warning); --range-inverted-3:var(--positive);

  /* ── CATEGORY (qualitative identity — NO valence) ─────────────────────────
     Identidade por matiz SÓ FORA DE GRÁFICO (dot do mapa do tracking, cor de
     sala): em gráfico, categorizar é a rampa do azul — paleta de matizes foi
     testada e rejeitada pelo dono em 2026-08-06 (DESIGN.md §2). Charts read
     these via getComputedStyle onde a exceção vale (tracking/salas). */
  --cat-1:#2563eb; --cat-2:#f97316; --cat-3:#16a34a; --cat-4:#9333ea;
  --cat-5:#db2777; --cat-6:#0e7490; --cat-7:#ca8a04; --cat-8:#dc2626;

  /* ── PALETA DE GRÁFICOS ───────────────────────────────────────────────────
     Regras completas em docs/globais/componentes.md §Gráficos e no design
     aprovado em docs/superpowers/specs/2026-07-27-sistema-cor-graficos-design.md.

     São QUATRO cores, e só. Cada uma responde a uma pergunta:
       --chart-azul    QUANTO      magnitude sem sinal (receita, volume, saldo, contagem)
       --positive      POSITIVO    entrada, ganho, acima da meta
       --negative      NEGATIVO    saída, perda, abaixo do mínimo
       --chart-alerta  ATENÇÃO     a faixa antes do vermelho, onde existe limiar

     CATEGORIZAR = opacidade do azul, em quantos passos a série pedir (não há
     teto e não há agregação em "Outros"): biChartConfig.rampaAzul(n). Dois tons
     vizinhos de uma rampa longa são perceptualmente iguais — quem devolve a
     leitura é o SEPARADOR na cor da superfície (3px em fatia de donut, 1,5px
     entre segmentos empilhados) somado ao rótulo. Sem separador, rampa longa é
     ilegível: ele é requisito, não enfeite.

     CINZA não é cor de dado. Sobrevive só em tick, rótulo e borda (--ink-*).

     --chart-alerta #e3660e dá 3,40:1 sobre o card: passa o piso de 3:1 de
     elemento gráfico, mas fica abaixo dos 4,5:1 de texto pequeno — por isso só
     pinta ÁREA (arco, barra, ponto), nunca número. */
  --chart-azul:#2563eb;
  --chart-alerta:#e3660e;
  /* Degrau de TEXTO da mesma laranja (85% de #e3660e): 5,41:1 sobre a superfície,
     em linha com --positive-text (5,02) e --negative-text (5,43). Existe porque
     --chart-alerta é 3,40:1 — passa como ÁREA de gráfico, reprova como texto.
     REGRA: indicador de UI (número, badge, dot) usa o degrau `-text` da família;
     área de gráfico (arco, barra, ponto) usa o degrau base. Mesma família nos
     dois casos — a faixa de atenção da tela é a MESMA laranja da faixa de
     atenção do gráfico, não um mostarda paralelo. */
  --chart-alerta-text:#b04c0a;

  /* Fonte ÚNICA do projeto: Roboto. --mono existe só p/ os números tabulares
     (mesma Roboto + font-variant-numeric:tabular-nums nos usos) — não há 2ª fonte. */
  --sans:'Roboto',ui-sans-serif,'Helvetica Neue',Arial,sans-serif;
  --mono: var(--sans);
  /* --bs-font-monospace REMAPEADO para o Roboto por diretiva do usuário: Roboto
     é a única fonte do projeto. Sem este remap a primitiva do Bootstrap ficava de
     fábrica e a utility `.font-monospace`, <code> e <pre> caíam no stack
     SFMono/Menlo/Consolas — uma 2ª fonte, viva em 8 arquivos (importar-of,
     matriz-acesso, faturamento-fcds, diagnostico-preenchimento, pedidos,
     forecast-comex, catalogo). Como TODO o vazamento passava por esta
     variável, o remap resolve os 8 de uma vez; não há font-family mono
     hardcoded em lugar nenhum deste arquivo. */
  --bs-font-monospace: var(--sans);
  /* all resting shadows removed app-wide (user directive). Only --ring (keyboard
     focus, a11y) survives. Every surface is flat: hairline border + surface ladder. */
  --sh1:none;
  --sh2:none;
  /* anel de foco do Bootstrap (rgba do --bs-primary a 25%) — era o cinza
     rgba(100,107,120,.22), do tempo em que o acento era o slate da marca. */
  --ring:0 0 0 3px rgba(13,110,253,.25);
  /* glass — now OPAQUE. backdrop-filter was removed from card/topbar surfaces
     (per-frame blur was the scroll-jank source); opaque fills preserve the look
     without compositing cost. Over the --bg (#f6f7f9) page the old translucent
     whites already read as near-white, so this is visually ~identical. */
  --glass:#ffffff;                 /* was rgba(255,255,255,.64) */
  --glass-2:#f6f7fa;               /* was rgba(255,255,255,.54) — keeps the lower tier */
  --glass-bd:var(--line);          /* white edge only read against blur; neutral hairline now */
  --blur:saturate(150%) blur(18px);/* retained for any remaining frosted accent; off the scroll path */
  /* fully flat: glass sheen AND drop shadow removed. The soft drop lift read as a
     grey halo around every card — stacked, those halos looked like a "visual effect
     between each component." Cards are now delineated by their 1px hairline border
     and the surface ladder alone (no shadow, no glass). */
  --sh-glass:none;

  /* ═══════════════════════════════════════════════════════════════════════════
     APP (bi/) TOKENS — merged here so EVERY token lives in one file.
     Scale/typography/surface/border/shadow + grayscale ramp. No color *meaning*
     here (that's the canonical block above); these are structure + chart chrome.
     ═══════════════════════════════════════════════════════════════════════════ */

  /* grayscale ramp (neutral structure, no valence) */
  --bi-color-white: #ffffff;

  /* typography — single family: Roboto via --sans (loaded in base_fcds.html). */
  --bi-font-display:   var(--sans);
  --bi-font-mono:      var(--mono);
  --bi-fs-hero:    3rem;
  --bi-fs-display: 2rem;
  --bi-fs-metric:  1.5rem;
  --bi-fs-heading: 1rem;
  --bi-fs-body:    0.875rem;
  --bi-fs-label:   0.875rem;
  --bi-fs-caption: 0.875rem;
  /* Dois degraus abaixo do corpo. Não existiam, e a ausência custou caro: 84
     declarações espalhadas por ~20 telas inventaram 19 tamanhos diferentes
     entre 8,96px e 13,76px, cada uma resolvendo sozinha o mesmo problema.
     A escala não estava sendo desrespeitada — estava incompleta.
       compact — célula de matriz/tabela densa, onde 14px estoura a grade.
       micro   — badge, contador, etiqueta de passo. PISO ABSOLUTO do app:
                 nada abaixo de 12px, e só para texto que acompanha outro
                 elemento, nunca para o dado principal de uma tela. */
  --bi-fs-compact: 0.8125rem;
  --bi-fs-micro:   0.75rem;

  --bi-fw-regular:  400;
  --bi-fw-medium:   500;
  --bi-fw-semibold: 600;
  --bi-fw-bold:     700;
  --bi-lh-tight:  1.15;
  --bi-lh-normal: 1.5;
  --bi-lh-loose:  1.7;

  /* spacing */
  --bi-space-3xs: 0.25rem;
  --bi-space-2xs: 0.25rem;
  --bi-space-xs2: 0.5rem;
  --bi-space-xs:  0.25rem;
  --bi-space-sm:  0.5rem;
  --bi-space-md:  1rem;
  --bi-space-lg:  1.5rem;
  --bi-space-xl:  1.5rem;
  --bi-space-2xl: 3rem;
  --bi-space-3xl: 3rem;

  /* radius, borders, shadows — alias dos primitivos --r* (fonte única) */
  --bi-radius-sm:   var(--r-xs);
  --bi-radius-md:   var(--r-sm);
  --bi-radius-lg:   var(--r);
  --bi-radius-full: var(--r-full);

  /* scroll cap — standard max-height for in-card scroll bodies (ranked lists,
     analysis tables) so side-by-side cards read at one height instead of one
     stretching the page. Responsive: floor 320px, ~46vh, ceiling 460px.
     Applied via the .card-scroll utility (custom.css). */
  --bi-scroll-cap: clamp(320px, 46vh, 460px);
  /* table tier (.tbl-scroll, sticky-header tables) and datatable tier
     (.datatable-scroll, full DataTables grids) — larger caps, distinct from the
     compact card-list tier above. Per-instance override stays via
     --bi-table-scroll-max / --bi-dt-scroll-max. */
  /* O TETO EM PIXEL MORREU (decisão do dono, 08/09/2026: "exclua essa maldita
     restrição e faça sempre ocupar"). Os dois tetos abaixo tinham um limite
     absoluto — 520px e 560px — que parava a grade no meio da janela e deixava
     faixa de chão embaixo em TODA tela de tabela: medido em 900px de janela, a
     grade terminava aos 560 e sobravam ~300px vazios. Dez lugares já haviam
     furado esse teto na mão, sempre com o mesmo `flex:1 1 auto; min-height:0;
     max-height:none` — o padrão real já era ocupar, e o teto é que era a
     exceção mal colocada.
     O limite RELATIVO fica: é ele que impede a grade de estourar a tela num
     celular deitado, mantendo o cabeçalho grudado e a rolagem por dentro. */
  --bi-table-scroll-cap: 82dvh;
  --bi-dt-scroll-cap: 82dvh;
  --bi-border-color:        #e6e8ec;
  --bi-border-color-subtle: #eef0f3;
  --bi-border-color-heavy:  #d8dbe1;
  --bi-border:        1px solid var(--bi-border-color);
  --bi-border-subtle: 1px solid var(--bi-border-color-subtle);
  --bi-border-heavy:  1px solid var(--bi-border-color-heavy);
  --bi-shadow-xs: none;
  --bi-shadow-sm: none;
  --bi-shadow-md: none;
  --bi-shadow-lg: none;

  /* surfaces + text */
  --bi-bg-surface: #ffffff;
  --bi-bg-command: #ffffff;
  --bi-bg-elevated: #ffffff;
  --bi-bg-hover:   #f3f4f7;
  --bi-bg-active:  #eceef2;
  --bi-text-primary:   #191c22;
  --bi-text-secondary: #5a6171;
  --bi-text-muted:     #6b7280;
  --bi-text-on-dark:   #F9FAFB;
  --bi-text-on-accent: #FFFFFF;

  /* transitions + z-index */
  --bi-transition-fast:   150ms ease;
  --bi-transition-normal: 250ms ease;
  --bi-transition-slow:   400ms ease;
  --bi-z-dropdown: 100;
  --bi-z-sticky:   200;
  --bi-z-fixed:    300;
  --bi-z-overlay:  400;
  --bi-z-modal:    500;

  /* ===== ESCALA CANÔNICA DE CAMADAS (chrome + modais do app) =====
     A escala --bi-z-* acima é LEGADA/interna (usada por dropdowns e overlays de
     página); não repointar em massa. A escala --z-* abaixo é a canônica de CHROME
     e MODAL, interleavada com as bandas de VENDOR que NÃO dá pra mover:
       Leaflet:   panes 200–700, controls 1000
       Bootstrap: dropdown 1000 · sticky-top 1020 · fixed-top 1030 · offcanvas 1040/1045
                  · modal-backdrop 1050 · modal 1055 · popover 1070 · tooltip 1080 · toast 1090
     Regra: conteúdo de página < 1000; chrome do app (topbar) acima do conteúdo e
     abaixo do band de modais BS; modais do app >= 1100 (acima do BS modal 1055). */
  --z-scrim:       800;    /* backdrop do drawer mobile — dim do conteúdo, não da topbar */
  --z-topbar:      900;    /* topbar sticky + seus popovers (.pop 60 é ordem interna) */
  --z-drawer:      950;    /* .side mobile aberto — cobre a topbar por design */
  --z-modal:      1100;    /* modalboxes / drawers app / mapa fullscreen (acima do BS modal 1055) */
  --z-modal-inner:1150;    /* select2 / controle aninhado DENTRO de um modal app */
  --z-boot:      13000;    /* splash / #page-loading-overlay — acima de tudo, incl. vendor */

  /* skeleton + loader */
  --bi-skeleton-base:  #E5E7EB;
  --bi-skeleton-shine: #F3F4F6;
  --bi-loader-base: #BFC3C8;
  --bi-loader-bg:   transparent;

  /* chart overlays (read by JS via getComputedStyle) */
  --bi-tooltip-bg:        #191c22;
  --bi-tooltip-fg-title:  #E2E8F0;
  --bi-tooltip-fg-body:   #CBD5E1;
  --bi-chart-datalabel:   #5a6171;
  --bi-chart-axis-tick:   #6b7280;
  --bi-chart-bar-border:  #FFFFFF;
  --bi-chart-axis-border: rgba(0, 0, 0, 0.08);

  /* ─────────────────────────────────────────────────────────────────────────
     PAGE PALETTES — per-page design languages kept distinct from the canonical
     system on purpose (warm Comex theme; metas editor). Defined here so EVERY
     token lives in one file; only consumed by their own pages.
     ───────────────────────────────────────────────────────────────────────── */

  /* Comex — Forecast (same warm language, fuller ramp) */
  /* RE-SKINNED to slate FCDS (Batch F): colours/fonts/shadow repointed to the
     canonical palette; the dense forecast radii/transition kept (tight grid). */
  --fc-page-bg:       var(--surface-app);
  --fc-border:        var(--line);
  --fc-urgent-fg:     var(--negative-text);
  --fc-urgent-border: color-mix(in srgb, var(--negative) 18%, var(--surf));
  --fc-soon-border:   color-mix(in srgb, var(--warning) 18%, var(--surf));
  --fc-ok-border:     color-mix(in srgb, var(--positive) 18%, var(--surf));
  --fc-neutral-bg:    var(--surf-2);
  --fc-radius-sm:     2px;
  --fc-radius:        4px;
  --fc-radius-md:     6px;
  --fc-transition:    0.15s ease;
}

/* ==========================================================================
   BOOTSTRAP PALETTE — REMOVIDA (diretiva do usuário)
   Aqui morava o remap da paleta do Bootstrap para o FCDS: --bs-primary,
   --bs-secondary, --bs-success, --bs-info, --bs-warning, --bs-danger (com os
   pares -rgb), --bs-body-color, --bs-body-bg e --bs-border-color, mais o
   .text-bg-primary. Tudo removido: botão, link, fonte, borda e utilitário de cor
   passam a usar os valores DE FÁBRICA do Bootstrap. O visual de marca sobrevive
   só no SHELL (.stm-shell/.app/.topbar/sidebar) e nos componentes FCDS, que têm
   cor própria e não dependem desta paleta. NÃO reintroduzir nenhum destes.

   O único token --bs-* de cor que resta aqui é o `-bg-subtle` de warning, e não
   por causa da marca: o bundle vendorizado é 5.2.3 e não tem a família *-subtle
   do 5.3. Fica com o VALOR DE FÁBRICA do 5.3, para o utilitário portado logo
   abaixo continuar existindo.
   ========================================================================== */
:root{ --bs-warning-bg-subtle:#fff3cd; }
/* Utility do Bootstrap 5.3 que falta no bundle vendorizado (só a de warning é
   usada hoje; as demais entram quando alguém precisar). */
.bg-warning-subtle{ background-color:var(--bs-warning-bg-subtle)!important; }

/* ===== SHELL ===== */
/* ==========================================================================
   Four Cloud Design System — SHELL.
   The app frame only: gradient body · slim glass topbar · hover-expand glass
   sidebar · content surface · mobile drawer + scrim. Ported 1:1 from the tested
   statement mockup (bi/static/bi/demo/statement.css, shell sections).

   Requires custom.css loaded first. Does NOT style filters or page content
   (page-owned) nor the .stm-* components (custom.css).

     §1 reset + display primitives   §2 app frame + sidebar
     §3 topbar   §4 content surface   §5 scrim + responsive
   ========================================================================== */

/* ── §1 RESET + display primitives ───────────────────────────────────────── */
.stm-shell *{box-sizing:border-box}
html,body{margin:0;height:100%;overflow-x:clip}
body.stm-shell{color:var(--ink);font-family:var(--sans);-webkit-font-smoothing:antialiased;font-size:1rem;
  /* plain flat page bg — the three radial glows were the "effect" on the
     background; removed for a flat surface (user directive). */
  background:var(--surface-app)}
.stm-shell .tnum{font-family:var(--mono);font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1}
/* Button baseline reset — wrapped in :where() so it carries ZERO specificity and
   any component class (.buscar, .fdrop, .filtbtn, .fcds-help, .pill…) overrides
   it. Without :where() this selector (0,2,1) silently clobbered the background of
   every toolbar button, leaving chips/Buscar transparent. */
:where(.stm-shell .app button){font:inherit;color:inherit;background:none;border:none;cursor:pointer}
/* Botões de ação Bootstrap (btn-primary / btn-outline-*) injetados no topbar
   (Salvar, Atualizar…) adotam o formato PÍLULA do FCDS — mesma altura e raio dos
   controles .fdrop/.tb-btn — para o topbar ler como UMA linha consistente.
   .btn-link (ícone de ajuda) fica de fora. Só FORMATO — a cor é a do Bootstrap de
   fábrica (o remap de cor de botão foi removido; ver a seção acima). */
.stm-shell .topbar .btn:not(.btn-link){
  height: 2rem;border-radius:var(--raio-chip);padding:0 1rem;
  display:inline-flex;align-items:center;gap:0.25rem;
  font-size:0.875rem;font-weight:500;line-height:1}
.stm-shell .metric{font-weight:700;font-variant-numeric:tabular-nums}
.stm-shell .metric--sig{font-size:var(--metric-sig);letter-spacing:-.03em;margin:0.5rem 0 0.25rem}

/* ── §2 APP FRAME + SIDEBAR ──────────────────────────────────────────────── */
/* Largura da sidebar ABERTA (hover, foco ou `body.pinned`). Era 14.75rem (236px)
   repetida em dois lugares, e cortava três rótulos do menu em silêncio — a
   `.side` tem overflow:hidden e o texto não tem reticências, então sumia sem
   aviso ("Acompanhamento Inadimplência" terminava em 263px). 17.25rem era o
   mínimo para não cortar; 20rem (320px) é a escolha do dono (14/08/2026), com
   folga de ~57px depois do maior rótulo — respiro, não aperto.

   No hover não custa área de conteúdo: a sidebar aberta COBRE a página (o
   `.main` fica com o margin-left do trilho, 3rem). TRAVADA ela empurra — ver
   `body.pinned .main` abaixo. O piso é ~16,5rem —
   abaixo disso os três rótulos longos voltam a ser cortados em silêncio. */
:root{--side-w-aberta: 20rem}
.app{min-height:100vh}
/* near-opaque so animating width stays smooth (backdrop-filter + width = jank) */
.side{position:fixed;top:52px;left:0;height:calc(100vh - 52px);width: 4rem;z-index:30;overflow:hidden; /* < --z-topbar: sidebar desktop fica sob a topbar */
  display:flex;flex-direction:column;border-right:1px solid var(--line);
  background:var(--surf);will-change:width;
  transition:width .26s cubic-bezier(.22,1,.36,1),box-shadow .26s cubic-bezier(.22,1,.36,1)}
.side:hover,.side:focus-within{width:var(--side-w-aberta)}
.main{margin-left:3rem;min-width:0;min-height:calc(100vh - 52px);
  will-change:margin-left;transition:margin-left .26s cubic-bezier(.22,1,.36,1)}
body.pinned .side{width:var(--side-w-aberta);box-shadow:none}
/* Travada, a sidebar deixa de COBRIR a página e passa a EMPURRAR: o conteúdo
   ganha a margem da barra aberta. É a diferença entre travar e só passar o
   mouse — no hover a barra sobrepõe (nada mexe de lugar), travada ela ocupa
   espaço de verdade. Transição já está no `.main`. */
body.pinned .main{margin-left:var(--side-w-aberta)}
/* collapsed rail (desktop ≥761): true icon-only — labels/headers/chevrons/subs
   LEAVE the layout so nothing is left half-cropped. */
.side .user b,.side .nav a span,.side .navgrp span,.side .nav__g,.side .user div{white-space:nowrap}
@media(min-width:768px){
  body:not(.pinned) .side:not(:hover):not(:focus-within) .nav a,
  body:not(.pinned) .side:not(:hover):not(:focus-within) .navgrp{justify-content:center;gap:0;padding-left:0;padding-right:0}
  body:not(.pinned) .side:not(:hover):not(:focus-within) .nav a span,
  body:not(.pinned) .side:not(:hover):not(:focus-within) .navgrp span,
  body:not(.pinned) .side:not(:hover):not(:focus-within) .nav a .cnt,
  body:not(.pinned) .side:not(:hover):not(:focus-within) .navgrp .chev,
  body:not(.pinned) .side:not(:hover):not(:focus-within) .nav__g,
  body:not(.pinned) .side:not(:hover):not(:focus-within) .user div{display:none}
  /* Recolhida, a barra tem 64px: o Sair espremia o avatar contra a borda e o
     deixava oval. Sai o Sair (ele volta assim que a barra abre) e o avatar
     fica redondo, sozinho e centrado — é ele que abre "Minha conta". */
  body:not(.pinned) .side:not(:hover):not(:focus-within) .user form{display:none}
  body:not(.pinned) .side:not(:hover):not(:focus-within) .user__eu{
    flex:0 0 auto;justify-content:center}
  body:not(.pinned) .side:not(:hover):not(:focus-within) .user .av{flex:0 0 auto}
  body:not(.pinned) .side:not(:hover):not(:focus-within) .user .av__ini{display:block}
  body:not(.pinned) .side:not(:hover):not(:focus-within) .user .av__cfg{display:none}
  body:not(.pinned) .side:not(:hover):not(:focus-within) .subnav{max-height:0!important}
  body:not(.pinned) .side:not(:hover):not(:focus-within) .side__foot .user{justify-content:center;padding:0.25rem 0}
}
/* display:flex+column is explicit so it wins over the legacy styles.css `.nav`
   (SB-Admin/Bootstrap) rule `display:flex;flex-wrap:wrap`, which otherwise lays
   the items out as a wrapping row (collapsed rail → two icons per line). */
/* display:block neutralises the legacy styles.css `.nav` (SB-Admin/Bootstrap)
   `display:flex;flex-wrap:wrap`, which otherwise lays the items out as a wrapping
   row (collapsed rail → two icons per line). Block flow keeps them stacked AND
   lets the nav scroll naturally — a flex column would instead shrink the items to
   fit and clip the lower groups. min-height:0 lets this flex child (of .side)
   shrink below its content so overflow-y:auto can scroll. */
/* Scoped to the sidebar (#nav) — a bare `.nav{display:block}` leaked to every
   Bootstrap `.nav-tabs` (modals), overriding `.nav{display:flex}` and stacking
   tabs vertically. Sidebar keeps block flow; modal tabs get Bootstrap's row. */
#nav{flex:1;min-height:0;display:block;overflow-y:auto;overflow-x:hidden;padding:1rem 0.5rem 0.5rem}
.nav__g{font-size:0.875rem;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3);
  padding:1rem 0.5rem 0.25rem}
.nav a{display:flex;align-items:center;gap:0.5rem;padding:0.5rem 0.5rem;border-radius:var(--r-sm);color:var(--ink-2);
  font-weight:500;text-decoration:none;font-size:0.875rem;margin-bottom:0;transition:background .12s,color .12s}
.nav a svg{width: 1.0625rem;height: 1.0625rem;color:var(--ink-3);flex:0 0 auto}
.nav a i{width: 1.0625rem;font-size:1rem;color:var(--ink-3);flex:0 0 auto;text-align:center}
.nav a:hover{background:var(--surf-2);color:var(--ink)}
.nav a.on,.nav a.active{background:var(--shell-acc-soft);color:var(--shell-acc-ink);font-weight:600;position:relative}
.nav a.on svg,.nav a.active svg,.nav a.on i,.nav a.active i{color:var(--shell-acc)}
.nav a.on::before,.nav a.active::before{content:"";position:absolute;left:-12px;top:7px;bottom:7px;width: 0.1875rem;border-radius: 0 var(--bs-border-radius-sm) var(--bs-border-radius-sm) 0;background:var(--shell-acc)}
.nav a .cnt{margin-left:auto;font-family:var(--mono);font-size:0.875rem;color:var(--ink-3);background:var(--surf-2);
  border-radius:var(--raio-chip);padding:0 0.5rem}
.nav a.on .cnt{background:var(--surf);color:var(--shell-acc-ink)}
.navgrp{display:flex;align-items:center;gap:0.5rem;width:100%;padding:0.5rem 0.5rem;border-radius:var(--r-sm);
  color:var(--ink-2);font-weight:500;font-size:0.875rem;text-align:left;margin-bottom:0;transition:background .12s,color .12s}
.navgrp svg.gi,.navgrp i.gi{width: 1.0625rem;height: 1.0625rem;font-size:1rem;color:var(--ink-3);flex:0 0 auto;text-align:center}
.navgrp:hover{background:var(--surf-2);color:var(--ink)}
.navgrp.has-on{color:var(--ink)} .navgrp.has-on svg.gi,.navgrp.has-on i.gi{color:var(--shell-acc)}
.navgrp .chev{width: 0.8125rem;height: 0.8125rem;font-size:0.875rem;color:var(--ink-3);margin-left:auto;transition:transform .18s}
.navgrp.open .chev{transform:rotate(180deg)}
.subnav{overflow:hidden;max-height:0;transition:max-height .24s ease}
.subnav a{padding-left:1.5rem;font-size:0.875rem;color:var(--ink-3)}
.subnav a i{width: 1rem;font-size:0.875rem;color:var(--ink-4);flex:0 0 auto;text-align:center}
.subnav a:hover i{color:var(--ink-3)}
.subnav a.on,.subnav a.active{color:var(--shell-acc-ink);font-weight:600}
/* `_menu_fcds.html` prefixa TODO ícone de item com `fas` (Solid) — um ícone de
   marca (WhatsApp) precisa de `fa-brands`, e as duas classes juntas colidem
   em font-family/weight. Especificidade igual, a ordem do all.min.css decide
   quem vence — não é pra confiar nisso. Este seletor força a família certa
   sempre que alguém combina `fas` com `fa-brands` no menu. */
.subnav a i.fa-brands, .gi.fa-brands { font-family: "Font Awesome 6 Brands"; font-weight: 400; }
.subnav a.on i,.subnav a.active i{color:var(--shell-acc)}
.subnav a.on::before,.subnav a.active::before{display:none}
.side__foot{border-top:1px solid var(--line-2);padding:0.5rem}
.user{display:flex;align-items:center;gap:0.5rem;padding:0.25rem;border-radius:var(--r-sm)}
.user:hover{background:var(--surf-2)}
.user .av{width: 1.875rem;height: 1.875rem;border-radius:50%;background:var(--shell-acc-soft);color:var(--shell-acc-ink);
  display:grid;place-items:center;font-size:0.875rem;font-weight:600;border:var(--bs-border-width) solid var(--shell-acc-line)}
.user b{font-size:0.875rem;font-weight:600;display:block}.user small{color:var(--ink-3);font-size:0.875rem}
/* O bloco do usuário virou BOTÃO (abre "Minha conta"): mesma aparência de
   antes, com o alvo e o foco que um botão precisa ter. Com a barra recolhida
   sobra só o avatar — a regra do rail esconde o `div` do nome. */
.user__eu{display:flex;align-items:center;gap:0.5rem;flex:1 1 auto;min-width:0;
  background:none;border:0;padding:0;text-align:left;color:inherit;cursor:pointer}
.user__eu:focus-visible{outline:2px solid var(--shell-acc-ink);outline-offset:2px;border-radius:var(--r-sm)}
.user__id{min-width:0}
/* Aberta a barra, o círculo vira engrenagem: o nome já está escrito ao lado,
   então o ícone pode dizer o que o clique faz (abrir a conta) em vez de
   repetir as iniciais. Recolhida, volta a ser o avatar. */
.user .av__ini{display:none}
.user .av__cfg{font-size: var(--bi-fs-compact)}
.user__id b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* Rótulo miúdo do painel da conta — o mesmo tom dos rótulos do shell. */
.conta-rotulo{font-size: var(--bi-fs-compact);font-weight:600;letter-spacing:.08em;
  text-transform:uppercase;color:var(--ink-3)}
.user form{margin:0;margin-left:auto;flex:0 0 auto}
.user .logout{color:var(--ink-3);display:grid;place-items:center;width: 1.75rem;height: 1.75rem;
  border-radius:var(--r-xs);transition:background .12s,color .12s}
.user .logout:hover{background:var(--negative-subtle);color:var(--negative-text)}
.user .logout i,.user .logout svg{width: 0.9375rem;height: 0.9375rem;font-size:1rem}

/* ── §3 TOPBAR (slim glass, sticky) ──────────────────────────────────────── */
/* opaque (was rgba(.7)+backdrop-filter): a sticky element re-blurs its backdrop
   on every scroll frame as content passes behind it — opaque kills that cost. */
.topbar{height: 3.25rem;display:flex;align-items:center;gap:0.5rem;padding:0 1rem;
  background:var(--surf);
  border-bottom:1px solid var(--line);position:sticky;top:0;z-index:var(--z-topbar)}
.topbar .logo{flex:0 0 auto;display:flex;color:var(--ink)}
.topbar .logo svg{width: 1.4375rem;height: 1.4375rem;display:block}
.topbar .menu{display:grid;place-items:center;width: 2.125rem;height: 2.125rem;margin-left:-0.25rem;border-radius:var(--r-sm);
  color:var(--ink-2);flex:0 0 auto;transition:background .14s,color .14s}
.topbar .menu svg,.topbar .menu i{width: 1.125rem;height: 1.125rem;font-size:1rem}
.topbar .menu:hover{background:rgba(255,255,255,.55);color:var(--ink)}
.topbar .menu[aria-pressed="true"]{color:var(--shell-acc-ink);background:var(--shell-acc-soft)}
.crumb{display:flex;align-items:baseline;gap:0.5rem}
.crumb b{font-size:1rem;font-weight:600;letter-spacing:-.01em}
.crumb span{font-size:0.875rem;color:var(--ink-3)}
.topbar .sp{flex:1}

/* ── §4 CONTENT SURFACE ──────────────────────────────────────────────────── */
.content{padding:var(--content-pad-y) var(--content-pad-x) var(--content-pad-b);min-width:0}
/* Grade única esticada (`biUtils.esticarGradeUnica`): o recuo de baixo do
   `.content` (36px) e o do `.page` (24px) caem ABAIXO da paginação, onde não
   separam nada de nada — viram 60px de faixa cinza entre o card e o fim da
   janela, e saem da altura que a lista poderia ocupar. Enquanto a classe está
   posta, quem dá o respiro do rodapé é o próprio cálculo da grade. O
   `!important` só empata com o `!important` de `.page`. */
.content.grade-esticada{padding-bottom:0}
.content.grade-esticada > .page{padding-bottom:0 !important}

/* ── §5 SCRIM + RESPONSIVE ───────────────────────────────────────────────── */
.scrim{position:fixed;inset:52px 0 0 0;background:rgba(22,24,32,.42);opacity:0;pointer-events:none;
  transition:opacity .22s;z-index:var(--z-scrim)}
body.navopen .scrim,body.filtopen .scrim{opacity:1;pointer-events:auto}

/* Mobile chrome: narrow portrait (≤760px) OR short landscape (≤540px tall — a
   landscape phone is ~844px wide so it would otherwise miss the width breakpoint and
   render the desktop rail). Both get the off-canvas drawer + full-width content. */
@media(max-width:767.98px),(max-height:540px){
  .side{transform:translateX(-100%);width: 15rem;z-index:var(--z-drawer);border-right:1px solid var(--line);
    transition:transform .26s cubic-bezier(.22,1,.36,1)}
  .side:hover,.side:focus-within{width: 15rem}
  body.navopen .side{transform:none}
  .main,body.pinned .main{margin-left:0}
  /* `pinned` é conceito de desktop e não é restaurado no celular, mas quem
     encolhe a janela (ou gira o tablet) já com a barra travada chega aqui com a
     classe no body — e `body.pinned .side` (0,2,1) ganha de `.side` (0,1,1),
     media query não soma especificidade. Sem esta linha a gaveta abriria com
     20rem em vez de 15rem. */
  body.pinned .side{width: 15rem}
  .side .nav a span,.side .nav a .cnt,.side .nav__g,.side .user div,.side .navgrp span{opacity:1!important;display:initial}
  /* iOS notch / home-indicator (landscape especially): viewport-fit=cover lets content
     use the whole screen, env() insets keep it off the camera + home bar. max() so a
     non-notched device (env=0) keeps the normal value. */
  /* Goteira lateral própria da superfície: o card não sai mais da caixa por conta
     própria (a antiga quebra de 100vw foi removida), então é o .content que dá o
     respiro das bordas — e o env() mantém tudo fora do notch em paisagem. */
  .content{padding-block:0.5rem max(1.5rem, env(safe-area-inset-bottom));
    padding-inline:max(0.5rem, env(safe-area-inset-left)) max(0.5rem, env(safe-area-inset-right))}
  .side{padding-left:env(safe-area-inset-left)}
  /* topbar: reclaim width at 390px — the breadcrumb carries identity AND is the sole
     drawer trigger on mobile, so drop the redundant logo and remove the hamburger;
     let the breadcrumb ellipsize instead of shoving the filter button */
  .topbar{padding-left:max(0.5rem, env(safe-area-inset-left));padding-right:max(0.5rem, env(safe-area-inset-right));gap:0.5rem}
  .topbar .logo{display:none}
  .topbar .menu{display:none}
  .crumb{min-width:0;cursor:pointer;display:flex;align-items:center;gap:0.5rem;
    margin-left:-0.25rem;padding:0.25rem 0.5rem;border-radius:var(--bs-border-radius-lg);-webkit-tap-highlight-color:transparent}
  .crumb::before{content:"\2630";font-size:1.25rem;line-height:1;color:var(--ink-2);flex:0 0 auto}
  .crumb:active{background:rgba(20,24,32,.06)}
  .crumb b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:42vw;font-size:1rem}
}

/* ===== COMPONENTS ===== */
/* ==========================================================================
   Four Cloud Design System — COMPONENTS.
   The composable card/metric library. Ported 1:1 from the design source
   (bi/static/bi/demo/statement.css component sections). Pages compose FROM
   these — never restyle ad hoc. Depends on the TOKENS + SHELL sections above
   (.metric primitives).

     §1 grid + card/glass   §2 hero+ring   §3 kpi spark tiles
     §4 margin flow cascade  §5 cost doughnut   §6 signals   §7 units ABC table
   ========================================================================== */

/* ── §1 GRID + CARD/GLASS ────────────────────────────────────────────────── */
.grid{display:grid;grid-template-columns:repeat(12,1fr);gap:var(--gap)}
/* Grade FLUIDA — o nº de colunas segue a largura, sem breakpoint escrito à mão.
   A `.grid` de 12 colunas exige que cada filho declare seu span, então o layout
   fica congelado: 2 cartões lado a lado continuam 2 num monitor de 27", só mais
   largos. Aqui os cartões vão encaixando conforme cabem — 4 numa tela larga, 3
   ao estreitar, 2 no notebook, 1 no celular — e cada um tem uma largura MÍNIMA
   digna em vez de uma fração fixa da tela.
   O `--min-card` é o botão de calibragem: é ele que decide em que largura o
   layout troca de nº de colunas. Uma tela pode sobrescrevê-lo inline. */
.grid-fluido{
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(min(var(--min-card, 34rem), 100%), 1fr));
  gap:var(--gap);
  align-items:stretch;
}
/* Cada cartão tem a altura que o SEU conteúdo pede — não a do vizinho mais alto.
   Com `stretch` (o padrão), um cartão de gráfico numa faixa de três forçava os
   dois de texto, de ~120px de conteúdo, a herdarem a caixa dele: era exatamente
   o vão morto que motivou o redesenho. `start` desiste do rodapé alinhado e
   entrega a altura de volta. */
.grid-fluido{ align-items:start; }
/* Faixa em que os cartões DEVEM alinhar rodapé — quando uma das colunas é uma
   pilha de cartões, `stretch` é o que faz a pilha ocupar a altura da coluna e o
   `flex-fill` de cada cartão dividir esse espaço. Sem isto a pilha encolhe para
   o conteúdo e a coluna fica curta ao lado dos gráficos. */
.grid-fluido.align-items-stretch{ align-items:stretch; }

/* Ranking como cartão de faixa: acompanha a altura do gráfico ao lado e rola por
   dentro. A lista é posicionada em ABSOLUTO de propósito — assim ela não
   contribui altura nenhuma para o grid, e quem dita a altura da faixa passa a
   ser o cartão do gráfico. Sem isto, os 14 portadores ditavam a altura e sobrava
   ~650px de vão embaixo do gráfico; capar com `max-height` em rem resolveria
   pela metade, porque o número seria um chute desacoplado da altura real do
   gráfico (que o JS deriva do nº de categorias). */
#cr-board{ position:relative; overflow:hidden; }
#cr-board > .cr-board{ position:absolute; inset:0; overflow-y:auto; }
/* surface recipe — shared by every .card, .tile, and any .glass element.
   backdrop-filter removed: it forced a per-frame blur pass behind every one of
   ~39 cards during scroll (the dominant scroll-jank source). --glass is opaque
   now, so the frosted look is preserved without the compositing cost. */
.glass{
  border:var(--bs-border-width) solid var(--line);border-radius:var(--r);box-shadow:var(--sh-glass)}
/* STANDARDIZED CARD (FCDS canonical) — solid surface, neutral hairline, no shadow.
   Glass is retired: this references the semantic tokens directly (--surf/--line) instead
   of the legacy --glass* aliases (same resolved values, no "glass" naming). Layout props
   (flex column / position) are declared here so the card no longer silently borrows them
   from Bootstrap's .card — load order is now irrelevant. Body pad 8/16/16; header→body
   rhythm via .card-hd margin-bottom (8px). .cardbox (main.css) shares this visual standard. */
.card{
  display:flex;flex-direction:column;position:relative;
  background:var(--surf);border:var(--bs-border-width) solid var(--line);border-radius:var(--r);box-shadow:none;
  padding:var(--bi-space-sm,0.5rem) var(--bi-space-md,1rem) var(--bi-space-md,1rem)}
/* Cartão no modelo estruturado do Bootstrap (.card > .card-header/.card-body): quem
   dá o padding é o filho, então o .card zera o seu — senão o conteúdo recebe o
   padding duas vezes (16px do .card + 16px do .card-body = 32px de recuo). */
.card:has(> .card-body), .card:has(> .card-header){ padding:0; }
.lab{font-size:0.875rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-3)}
.card-hd{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:var(--bi-space-sm,0.5rem)}
.card-hd .n{font-size:0.875rem;color:var(--ink-3)}
.card.empty{display:grid;place-items:center;min-height: 7.5rem;color:var(--ink-3);font-size:0.875rem}
/* scroll-capped card body: ranked lists / analysis tables scroll inside the card
   at a shared max-height (--bi-scroll-cap) so neighboring cards stay equal-height
   instead of one growing unbounded. min-height:0 lets it shrink inside flex/grid. */
.card-scroll{max-height:var(--bi-scroll-cap);overflow-y:auto;min-height:0}
/* Acento do drill: borda PLENA na cor do nível — faixa lateral é banida
   (DESIGN.md §6 Don'ts). O .card já tem 1px de borda; aqui só muda a cor.
   A cor é dinâmica por instância: o drill-panel seta --kpi-tile-accent inline
   (warning/positive por nível) — Bootstrap não tem utility de border-color
   que leia uma variável, por isso o helper de uma propriedade. */
.card-accent-start{border-color:var(--kpi-tile-accent, var(--acc))}

/* skeleton loading */
/* .skb mirrors the canonical .skeleton recipe (B9) — same base/shine tokens, radius
   and timing — but stays self-contained (own keyframes) so it works on pages that load
   fcds.* without bi/main.css (e.g. tracking-comex). */
/* .skb + @keyframes shimmer removidos — skeleton unificado no Bootstrap .placeholder (utils.js). */

/* ── §2 HERO + RING ──────────────────────────────────────────────────────── */
.delta{display:inline-flex;align-items:center;gap:0.25rem;height: 1.625rem;padding:0 0.5rem;border-radius:var(--bs-border-radius-lg);
  font-family:var(--mono);font-size:0.875rem;font-weight:600}
.delta.pos{background:rgba(22,121,74,.10);color:var(--positive-text)}
.delta.neg{background:var(--negative-subtle);color:var(--negative-text)}
.ring{flex:0 0 auto;width:var(--ring-size);height:var(--ring-size);position:relative}
.ring canvas{position:absolute;inset:0}
.ring__lbl{position:absolute;inset:0;display:grid;place-items:center;text-align:center}
.ring__v{font-size:1.25rem;font-weight:700;color:var(--ink)}
/* chart-internal: <12px justified (ring overflow) — batch5 */
.ring__c{font-size:0.875rem;letter-spacing:.14em;text-transform:uppercase;color:var(--ink-3);font-weight:600}

/* ── §3 KPI SPARK TILES ──────────────────────────────────────────────────── */
.kpi{grid-column:span 7;display:grid;grid-template-columns:repeat(3,1fr);gap:var(--gap)}
/* unified card padding (Batch6 Agent B): tile body pad 8/16/16 (was 12/14/10) */
.tile{background:var(--glass-2);padding:var(--bi-space-sm,0.5rem) var(--bi-space-md,1rem) var(--bi-space-md,1rem);
  display:flex;flex-direction:column;position:relative;overflow:hidden}
.tile .lab{font-size:0.875rem}
.md{font-family:var(--mono);font-size:0.875rem;font-weight:600;white-space:nowrap}.md.pos{color:var(--positive-text)}.md.neg{color:var(--negative-text)}
/* margin-left, não um espaço no markup: os dois spans são irmãos colados na
   string de HTML (saía "−37,1%vs mês ant.") e um espaço solto ali se perde na
   primeira reformatação do template. */
.md__ref{font-family:var(--sans);font-size:0.875rem;font-weight:500;color:var(--ink-3);white-space:nowrap;
  margin-left:0.25rem}
/* full-bleed area band at the card's bottom edge (negative margins cancel the tile's x/bottom pad) */
.spark{display:block;position:relative;width:auto;height:var(--spark-h);
  margin:var(--bi-space-sm,0.5rem) calc(-1*var(--bi-space-md,1rem)) calc(-1*var(--bi-space-md,1rem))}
.spark canvas{display:block}

/* ── §4 MARGIN FLOW CASCADE ──────────────────────────────────────────────── */
.flow{grid-column:span 8;display:flex;flex-direction:column}
.flow-cv{position:relative;flex:1;min-height:var(--flow-min);margin-top:var(--bi-space-xs2,0.25rem)}

/* ── §6 OPERATIONAL SIGNALS ──────────────────────────────────────────────── */
/* No left-stripe accent (banned >1px colored border): the cards use the standard
   .card hairline. Direction on Inadimplência is carried by the red value + label,
   not a decorative rule. The signals stack in a span-4 column beside the cascade. */
.sigcol{grid-column:span 4;display:flex;flex-direction:column;gap:var(--gap)}
.sigcol .sig{flex:1;display:flex;flex-direction:column}
.sig__v .u{font-size:1rem;color:var(--ink-3);font-weight:500;margin-left:0.25rem}
.sig.neg .sig__v{color:var(--negative-text)}
/* warning glyph = non-colour backup for the negative (inadimplência) card */
.sig__mark{font-size:.62em;vertical-align:.12em;margin-right:0}
.sig__s{font-size:0.875rem;color:var(--ink-2);margin-top:auto}
/* pin the detail link flush-left across all three signal cards (consistency) */
.sigcol .sig .fcds-siglink{align-self:flex-start}

/* ── §8 FILTERS — topbar chips · glass popovers · month picker · sheet ─────── */
/* Reusable FCDS filter primitives (ported from the statement mockup). A page
   houses its live filter controls inside these; chip labels reflect state. */
.filters{display:flex;align-items:center;gap:var(--bi-space-sm,0.5rem);min-width:0}
.vr{width:1px;height: 1.25rem;background:var(--line);flex:0 0 auto}
.fdwrap{position:relative;flex:0 0 auto}
.fdrop{display:inline-flex;align-items:center;gap:0.5rem;height: 2rem;padding:0 0.5rem;border:var(--bs-border-width) solid var(--line);
  border-radius:var(--raio-chip);background:var(--surf-2);font-size:0.875rem;font-weight:500;color:var(--ink-2);transition:all .12s;white-space:nowrap}
.fdrop:hover,.fdrop.open{background:var(--surf);border-color:var(--line-3)}
.fdrop.on{background:var(--acc-soft);border-color:var(--acc-line);color:var(--acc-ink)}
.fdrop b{color:var(--ink);font-weight:600;max-width: 7.75rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fdrop.on b{color:var(--acc-ink)}
.fdrop svg,.fdrop i{width: 0.8125rem;height: 0.8125rem;font-size:0.875rem;color:var(--ink-3);transition:transform .16s}
.fdrop.open .chev{transform:rotate(180deg)}
/* período/date control — unificado ao formato pílula do .fdrop (mesma altura,
   padding, gap e raio 999px) para o topbar ler como UMA linha consistente. */
.tb-btn{display:flex;align-items:center;gap:0.5rem;height: 2rem;padding:0 0.5rem;border:var(--bs-border-width) solid var(--line);
  border-radius:var(--raio-chip);background:var(--surf-2);font-size:0.875rem;font-weight:500;color:var(--ink-2);transition:all .14s;
  white-space:nowrap;flex:0 0 auto}
.tb-btn:hover,.tb-btn.open{background:var(--surf);border-color:var(--line-3)}
.tb-btn svg,.tb-btn i{width: 0.8125rem;height: 0.8125rem;font-size:0.875rem;color:var(--ink-3)}
.tb-btn .chev{transition:transform .16s}
.tb-btn.open .chev{transform:rotate(180deg)}
.tb-btn b{color:var(--ink);font-weight:600}
/* Régua de toggles no topbar (diagnóstico-preenchimento, permanência-no-porto).
   Sem isto o inline-flex não encolhe: com 9 filtros a régua media 2250px,
   empurrava o botão de ação pra fora e o overflow-x:clip do body escondia
   tudo sem scroll — 4 filtros e o Atualizar ficavam INALCANÇÁVEIS (medido
   em 1536px). flex+min-width:0 deixa encolher; o trilho rola sozinho. */
.pp-topbar-toggles{flex:1 1 auto;min-width:0;overflow-x:auto;scrollbar-width:thin}
/* glass popover */
.pop{position:absolute;top:calc(100% + 8px);left:0;z-index:60;min-width: 14.75rem;max-height:min(70vh,520px);overflow:auto;
  background:var(--surf);border:var(--bs-border-width) solid var(--line);border-radius:var(--r-sm);box-shadow:var(--sh2);padding:0.25rem}
.pop[hidden]{display:none}
.pop--right{left:auto;right:0}
.pop__hd{display:flex;align-items:center;justify-content:space-between;padding:var(--bi-space-2xs,0.25rem) var(--bi-space-sm,0.5rem) var(--bi-space-sm,0.5rem);
  font-size:0.875rem;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-3)}
.pop__hd button{font-size:0.875rem;font-weight:500;color:var(--ink-2);text-transform:none;letter-spacing:0;
  text-decoration:underline;text-underline-offset:2px;text-decoration-color:var(--line-3);background:none;border:0;cursor:pointer}
.pop__hd button:hover{color:var(--negative-text);text-decoration-color:currentColor}
/* Cabeçalho com DUAS ações (todos | limpar): o rótulo empurra as duas para a
   direita e elas ficam lado a lado. Só com `space-between` cada ação ia para uma
   ponta e "todos" lia como se pertencesse ao rótulo. */
.pop__hd{gap:var(--bi-space-sm,0.5rem)}
.pop__hd > span:first-child{margin-right:auto}
/* Vermelho no hover é de destruição — fica só no "limpar". "todos" é aditivo. */
.pop__hd button[data-allpop]:hover{color:var(--ink)}
.short{padding:0.25rem 0.5rem;border-radius:var(--raio-chip);border:var(--bs-border-width) solid var(--line);background:var(--surf-2);
  font-size:0.875rem;font-weight:600;color:var(--ink-2);cursor:pointer}
.short:hover{background:var(--surf-3);color:var(--ink)}
.mcell{padding:0.5rem 0;border-radius:var(--r-xs);border:var(--bs-border-width) solid var(--line);background:var(--surf);
  font-size:0.875rem;font-weight:500;color:var(--ink-2);text-align:center;cursor:pointer}
.mcell:hover{background:var(--surf-2);border-color:var(--acc-line)}
.mcell.on{background:var(--acc);border-color:var(--acc);color:var(--bi-text-on-accent);font-weight:600}
.popftog{border-top:var(--bs-border-width) solid var(--line-2);margin-top:0.25rem;padding:0.5rem 0.5rem 0}
/* option rows (used for segmento/sub/empresa lists) */
.optrow{display:flex;align-items:center;gap:0.5rem;width:100%;padding:0.5rem 0.5rem;border-radius:var(--r-xs);
  font-size:0.875rem;color:var(--ink-2);text-align:left;cursor:pointer;background:none;border:0}
.optrow:hover{background:var(--surf-2)}
.optrow .ck{width: 1.0625rem;height: 1.0625rem;border-radius:var(--bs-border-radius);border:1.5px solid var(--line-3);flex:0 0 auto;
  display:grid;place-items:center;color:var(--bi-text-on-accent);transition:all .12s}
.optrow .ck svg,.optrow .ck i{width: 0.6875rem;height: 0.6875rem;font-size:0.875rem;opacity:0}
.optrow.on .ck{background:var(--acc);border-color:var(--acc)}
.optrow.on .ck svg,.optrow.on .ck i{opacity:1}
.optrow .nm{flex:1;font-weight:500;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* buscar + funnel */
/* stale-results indicator — appears only when a filter change is staged
   (body.fcds-pending). Pairs with the dimmed results region so "os números na
   tela não refletem mais os filtros; clique em Buscar" is unambiguous. Âmbar de
   atenção (warning channel): os dados na tela estão desatualizados — par com o
   verde de ação do botão Buscar. Texto usa --warning-text (#f59e0b) — âmbar vivo,
   saturação priorizada sobre AA (~2.1:1 em texto pequeno). */
.fcds-stale{display:none;align-items:center;gap:0.25rem;flex:0 0 auto;height: 2rem;padding:0 0.5rem;
  border-radius:var(--raio-chip);background:var(--warning-subtle);
  border:var(--bs-border-width) solid color-mix(in srgb, var(--warning) 38%, var(--surf));
  color:var(--warning-text);font-size:0.875rem;font-weight:600;white-space:nowrap}
.fcds-stale svg,.fcds-stale i{width: 0.875rem;height: 0.875rem;font-size:0.875rem;flex:0 0 auto}
body.fcds-pending .fcds-stale{display:inline-flex}
/* tight topbars: drop to icon-only (tooltip carries the text) so it never
   crowds the período picker / Buscar */
@media(max-width:1399.98px){.fcds-stale{padding:0 0.5rem}.fcds-stale__t{display:none}}
/* dim the (now-stale) results while a change is staged; topbar/filters stay live */
body.fcds-pending main .grid{opacity:.5;pointer-events:none;transition:opacity .18s ease-out}
@media(prefers-reduced-motion:reduce){body.fcds-pending main .grid{transition:none}}

.buscar{display:none;align-items:center;gap:0.25rem;height: 2rem;padding:0 1rem;border:var(--bs-border-width) solid var(--brand);
  border-radius:var(--raio-chip);background:var(--brand);color:var(--bi-text-on-accent);font-size:0.875rem;font-weight:600;flex:0 0 auto;box-shadow:var(--sh1);cursor:pointer}
.buscar svg,.buscar i{width: 0.875rem;height: 0.875rem;font-size:0.875rem}
.buscar:hover{background:var(--brand-strong);border-color:var(--brand-strong)}
/* pending = uma mudança de filtro backend espera aplicar (período/empresa). O slate
   de comando não chamava atenção (lia como botão desabilitado), então o CTA de
   atualização ganha verde de ação ("clique para atualizar") + pulso, contrastando
   com o pill âmbar/neutro "Data alterada". Pulsa até o clique. */
.buscar.pending{display:inline-flex;background:var(--positive-text);border-color:var(--positive-text);animation:buscarpulse 1.8s ease-in-out infinite}
.buscar.pending:hover{background:color-mix(in srgb, var(--positive-text) 86%, var(--ink));border-color:color-mix(in srgb, var(--positive-text) 86%, var(--ink))}
@keyframes buscarpulse{0%,100%{box-shadow:0 0 0 0 rgba(21,128,61,0)}50%{box-shadow:0 0 0 4px rgba(21,128,61,.30)}}
/* mobile sheet Buscar segue a mesma semântica (verde de ação) quando há pendência */
body.fcds-pending .fbuscar{background:var(--positive-text);border-color:var(--positive-text)}
body.fcds-pending .fbuscar:hover{background:color-mix(in srgb, var(--positive-text) 86%, var(--ink));border-color:color-mix(in srgb, var(--positive-text) 86%, var(--ink))}
.fbuscar{display:inline-flex;align-items:center;justify-content:center;gap:0.5rem;height: 2.125rem;padding:0 1rem;
  border-radius:var(--raio-chip);background:var(--brand);color:var(--bi-text-on-accent);font-size:0.875rem;font-weight:600;border:var(--bs-border-width) solid var(--brand);cursor:pointer}
.fbuscar:hover{background:var(--brand-strong);border-color:var(--brand-strong)}
.filtbtn{display:none;align-items:center;gap:0.5rem;height: 2.125rem;padding:0 1rem;border:var(--bs-border-width) solid var(--line);
  border-radius:var(--raio-chip);background:var(--surf);font-size:0.875rem;font-weight:500;color:var(--ink-2);flex:0 0 auto;cursor:pointer}
.filtbtn:hover{background:var(--surf-2)} .filtbtn svg,.filtbtn i{width: 0.9375rem;height: 0.9375rem;font-size:1rem;color:var(--ink-3)}
.filtbtn__n{font-family:var(--mono);font-size:0.875rem;font-weight:600;color:var(--bi-text-on-accent);background:var(--acc);border-radius:var(--raio-chip);padding:0 0.25rem}
.sheet-only{display:none}
/* Modo backend-instantâneo (opt-in, ex.: faturamento): período/empresa aplicam
   sozinhos, então os gatilhos de Buscar não existem para o usuário. */
body.bi-backend-instant .btn-buscar-trigger,
body.bi-backend-instant #fcds-buscar,
body.bi-backend-instant .sheet-only .fbuscar{display:none!important}

/* ≤1340: collapse inline filters into a sheet behind the Filtros button */
@media(max-width:1200px){
  .topbar>.vr{display:none}
  .filtbtn{display:inline-flex}
  .filters{position:absolute;top:54px;right:14px;width: 18.75rem;flex-direction:column;align-items:stretch;gap:0.5rem;
    padding:0.5rem;background:var(--surf);border:var(--bs-border-width) solid var(--line);border-radius:var(--r-sm);box-shadow:var(--sh2);
    z-index:60;display:none}
  body.filtopen .filters{display:flex}
  .filters .fdwrap{width:100%}
  .filters .fdrop,.filters .tb-btn{width:100%;justify-content:space-between;border:var(--bs-border-width) solid var(--line);background:var(--surf-2)}
  .filters .sheet-only{display:flex;gap:0.5rem;margin-top:0}
  .filters .sheet-only .fbuscar{flex:1}
  .filters .pop{position:static;box-shadow:none;border:none;padding:0.25rem 0 0;min-width:0;max-height:none;background:transparent}
}
/* Os toggles ("Considerar devoluções", "Formatar número?") quando o celular os
   manda para dentro da folha de filtros — ver `grupoToggles` em
   fcds-filterbar.js. Pilha, não linha: cada rótulo é uma frase inteira e lado a
   lado não cabem nos ~358px úteis da folha. Sem media query de propósito — o
   seletor é o PAI, então a regra vale exatamente quando o JS moveu o grupo, e
   não pode dessincronizar de um breakpoint escrito duas vezes. */
#fcds-filters > #fcds-toggles{flex-direction:column;gap:0.5rem;
  margin:0;padding-top:0.5rem;border-top:var(--bs-border-width) solid var(--line)}
/* O container carrega `.align-items-center` do Bootstrap, que é `!important` e
   centraliza cada switch na coluna — borda esquerda serrilhada. Em vez de
   disputar com um `!important`, os filhos ocupam a linha inteira: aí não sobra
   o que centralizar e os rótulos alinham pela esquerda, como os chips acima. */
#fcds-filters > #fcds-toggles > *{width:100%}

@media(max-width:768px){
  .buscar{display:none!important}
  /* collapse the Filtros pill to icon-only (count badge still shows) + keep the
     sheet inside the viewport on narrow phones */
  .filtbtn{padding:0 0.5rem}
  .filtbtn span:not(.filtbtn__n){display:none}
  .filters{left:8px;right:8px;width:auto}
}

/* ── §9 KPI BAND — compact, data-rich (Receita · ritmo gauge · metrics · breakdown) ── */
/* The KPI band is ONE white card — the same surface recipe as every .card/.glass:
   white background, hairline border, rounded corners (from .glass). Cells are
   sections WITHIN that card, divided by inset hairlines (below), NOT tiles floating
   on a grey backing shown through 1px gaps. The old grey backing was the band's only
   deviation from the component vocabulary and the sole reason a third colour appeared
   at the rounded corners; converging to white makes the band consistent with all
   components and removes the corner artifact by construction (white-on-white clips
   cleanly, exactly like a normal card). */

/* Fixed-count variants for scalar bands (ported from legacy .kpi-band--Ncol):
   hero cell wide, the rest equal. Declared BEFORE the responsive @media blocks at
   the end of §9 so small-viewport stacking still overrides them. */

/* movimentacao drops the "Em Trânsito" cell outside the current month → 6 cols */

/* EXCEPTION (Batch6 Agent B): the unified KPI pad is 8/16/4, but these FCDS kpiband cells
   are tightly tuned to the faturamento fixed-height band — 8/16/4 shortens cell height ~8px
   and would force re-deriving the spark bleed below. Tuned 11/13/9 kept as justified exception. */

/* Cell dividers: FLAT 1px borders on each cell's top + left edge (shared edges →
   one crisp line). box-shadow:inset reads as a soft shadow groove between cells —
   a border is a flat hairline with no shadow. --line matches the band border, so
   the coincident line at the band's own top/left edge reads as the border. */

/* wraps to a 2nd line instead of truncating — "Custos sobre Receita" / "Margem
   Contrib." don't fit the narrow cells on one line, and the band is natural-height
   now (no fixed cap), so a 2-line label is free vertical space, not an overflow. */

/* metric cells (Receita/Líquido/Devoluções/MB/MC) carry a single number → the
   value block CENTERS in the height the band borrows from the breakdown/gauge
   cells, so the number fills the card instead of leaving dead space below. The
   label stays top-aligned across every cell for one clean header row. */

/* every metric cell drops its delta to its own line UNDER the big value (hero
   included) and gives it real presence — the chip reads as a second data point,
   not a footnote crammed beside the number. */

/* caution valences ported from legacy --warning/--previsao: amber value, mirroring
   the pos/neg value-colour mechanism instead of the old 4px coloured bottom-rule */

/* value line: big R$ number + its month-over-month delta chip, baseline-aligned,
   wrapping as a unit on narrow cells (kc__v keeps its top margin as a flex item) */

/* ritmo gauge cell */

/* dois gauges lado a lado (Atingido · Ritmo). Número e subtítulo são desenhados
   DENTRO do canvas por `biChartConfig.gauge` — aqui só se dá a caixa, então não
   há mais overlay de rótulo para manter alinhado. Meio-arco → caixa 2:1. */
/* align-items:flex-start é obrigatório: como item de flex esticado, a caixa
   herdaria a altura da linha e o aspect-ratio seria ignorado (o canvas cresce,
   a linha cresce junto). */
.krings{display:flex;gap:0.75rem;justify-content:center;align-items:flex-start;margin:0.25rem 0 0}
/* altura explícita, não aspect-ratio: o canvas é conteúdo em fluxo e o
   Chart.js escreve style.height nele — com altura automática o box cresceria
   junto e o ratio seria ignorado. */
.kgauge{flex:1 1 0;min-width:0;max-width:11rem;height:6.5rem}
.kgauge--empty{display:grid;place-items:center;width: 6rem;height: 6rem;margin:0.25rem auto 0;
  border-radius:50%;border:2px dashed var(--line-3);color:var(--ink-4);font-family:var(--mono)}

/* R$/dia útil: realizado vs necessário — leitura concreta do Ritmo */

/* scope note — shown only when the selection mixes meta and non-meta segments */

/* A lista de componentes do "Custos sobre Receita" é d-flex/justify-content-between
   do Bootstrap na própria célula — sem componente .kbd próprio. */

/* ── CÉLULA DE KPI (canônica) ───────────────────────────────────────────────
   Rótulo (`.lab`, o mesmo do cabeçalho de card) + valor + apoio. A célula É o
   card: sem `.card-body` no meio, porque `.card` já é flex-column com o padding
   canônico — o corpo extra só zerava um padding para redeclarar outro.

   O tamanho do valor acompanha a LARGURA DA CÉLULA (`cqi`), não a da viewport.
   Uma declaração cobre a faixa inteira sem breakpoint: 8-por-linha em 1440 a
   célula tem ~125px úteis e o número fica nos 20px de hoje (piso do clamp); num
   monitor de 1920 sobe para 28px; empilhada no celular a célula tem ~326px e o
   número também vai ao teto. Fonte fixa não faz isso — ou é pequena no monitor
   ou quebra em duas linhas na faixa estreita (medido).

   Distribuição vertical: como todas as células esticam até a altura da mais alta
   (a do gauge), sobra vão nas curtas. As três âncoras deixam esse vão distribuído
   de propósito em vez de virar um buraco no rodapé — rótulo no topo (uma linha de
   cabeçalho alinhada em toda a faixa), número centrado no vão (`margin-block:auto`)
   e apoio na base. */
.kpic{container-type:inline-size}
/* O `.lab` canônico tem tracking de .1em, que numa célula de ~125px úteis custa
   uma linha inteira ("MARGEM CONTRIB." e "CUSTOS SOBRE RECEITA" quebravam em 2 e
   3 linhas). Na banda ele fica no tracking curto — mesma peça, mesma cor, mesmo
   caixa-alta; só o espaçamento cede à largura da célula. */
.kpic > .lab{letter-spacing:.03em}
.kpic__v{font-size:clamp(1.25rem,16cqi,1.75rem);font-weight:700;line-height:1.05;
  white-space:nowrap;margin-block:auto;padding-block:0.25rem}
.kpi8 .krings{margin-block:auto}
.kpic__s{margin-top:auto;padding-top:0.5rem;font-size:0.875rem;line-height:1.3;color:var(--ink-3)}
/* Celular (célula empilhada, largura de tela inteira): o número sobe para a
   linha do rótulo, encostado à direita. Empilhado na vertical, o cartão gastava
   ~110px de altura com metade da largura vazia; lado a lado ele cai para ~75px e
   a faixa inteira deixa de ser duas telas e meia de rolagem. */
@media(max-width:575.98px){
  .kpic{display:grid;grid-template-columns:1fr auto;align-items:center;column-gap:0.75rem}
  .kpic__v{grid-column:2;grid-row:1;margin-block:0;padding-block:0;text-align:right}
  .kpic__s{grid-column:1/-1;margin-top:0;padding-top:0.25rem}
  .kpi8 .krings{grid-column:1/-1;margin-block:0}
}

/* Banda de KPI do faturamento: as 8 células numa linha só. `row-cols-*` do
   Bootstrap para em 6, então a faixa larga é grid explícito. Cai para 4, 2 e —
   no celular — empilha, que é onde o número ganha a largura toda da tela. */
.kpi8{display:grid;gap:0.75rem;grid-template-columns:minmax(0,1fr)}
@media(min-width:576px){.kpi8{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(min-width:768px){.kpi8{grid-template-columns:repeat(4,minmax(0,1fr))}}
@media(min-width:1400px){.kpi8{grid-template-columns:repeat(8,minmax(0,1fr))}}
/* Numa faixa de 8 colunas a caixa do gauge é o que dita a altura da linha
   inteira — encolhe para não abrir vazio nas outras sete. */
.kpi8 .kgauge{max-width:8rem;height:4.75rem}
/* responsive: wrap the 8 cells */
/* Phone density (narrow portrait OR short landscape): the band was ~669px tall in
   portrait and ~83% of a landscape screen, owning the viewport before any chart or
   table. Shrink the values + padding so content reaches above the fold. The
   max-height clause catches landscape phones (~844px wide, missed by max-width). */
@media(max-width:575.98px), (max-height:540px){

  /* shrink the tallest driver so short tiles stop stretching into dead space:
     o gauge é quem dita a altura da faixa. */

  .krings{gap:0.5rem;margin-top:0}
}

/* ── responsive grid spans ───────────────────────────────────────────────── */
@media(max-width:992px){.hero,.kpi,.flow,.sigcol{grid-column:span 12}.sigcol{flex-direction:row;flex-wrap:wrap}.sigcol .sig{flex:1 1 30%}}
@media(max-width:768px){
  .kpi{grid-template-columns:1fr}.sigcol .sig{flex:1 1 100%}
}

/* ── §9 PARAMETRIC TOOLBAR: relocated biFiltros controls inside topbar chips ──
   Shared by every page whose filters are relocated into the FCDS topbar by
   fcds-filterbar.js. The chip/popover/button PRIMITIVES live in §8 above; here we
   restyle the RELOCATED biFiltros pills + the period inline calendar to the FCDS
   look. Selectors only match relocated-chip DOM, so pages without the toolbar are
   unaffected. Moved here from faturamento-fcds.css so all pages share one source. */
.fcds-filters-host{position:absolute!important;width:1px;height:1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0;padding:0;margin:-0}

/* segmento / sub-segmento / empresa / centro de custo pills inside a popover →
   checkable rows, LEFT-aligned (align-items:stretch overrides the base
   .filter-group__pills{align-items:center}; justify-content:flex-start keeps the
   checkbox+label at the left edge like the original mockup). */
.pop:not(.pop--period) .filter-group__pills{display:flex;flex-direction:column;align-items:stretch;gap:0}

/* === CHECKROW — linha de seleção do popover de filtro ========================
   NÃO é um `.pill`. Pill é chip: pequeno, redondo, alternável. Isto é uma linha
   de checkbox — largura total, alinhada à esquerda, caixa em `::before`, sem
   borda e sem fundo. Vestia `.pill` e passava a vida desfazendo o que pill é;
   como a base `.pill` ganhou `!important` (bloco "statement pill look"), o
   desfazer parou de funcionar e a linha virou chip cinza redondo à revelia.
   Componente próprio → sem escopo defensivo, sem nada para vencer.
   Fábricas: filtros.js `_criarLinhaCheck`, inadimplencia.js (#pills-cc). */
.checkrow{display:flex;align-items:center;justify-content:flex-start;gap:0.5rem;width:100%;height:auto;padding:0.5rem;border:0;
  border-radius:var(--r-xs);background:none;font-size:0.875rem;font-weight:500;color:var(--ink);
  text-align:left;white-space:nowrap;cursor:pointer}
.checkrow::before{content:"";width: 1.0625rem;height: 1.0625rem;border-radius:var(--bs-border-radius);border:1.5px solid var(--line-3);
  flex:0 0 auto;background:no-repeat center/11px 11px;transition:all .12s}
.checkrow:hover{background:var(--surf-2)}
.checkrow:focus-visible{outline:2px solid var(--acc);outline-offset:-2px}
/* Caixa marcada sem preenchimento de acento: some o quadrado quase-preto, fica
   o contorno um degrau mais escuro e o check em ardósia. Preenchimento suave é
   `background-color:var(--acc-d);color:var(--bi-text-on-accent)`. */
.checkrow--on::before{border-color:var(--ink-3);
  content:"\f00c";font-family:"Font Awesome 6 Free";font-weight:900;font-size:0.875rem;color:var(--acc-d);display:flex;align-items:center;justify-content:center}
/* Sem dados no período. A regra antiga (`.pill--oculto`) estava escopada a
   `:is(.command-bar,.secondary-bar)` e o elemento vive em `.pop` — nunca casou,
   nunca renderizou. O tracejado migra para a caixa, já que a linha não tem borda. */
.checkrow--empty{opacity:0.45;font-style:italic}
.checkrow--empty::before{border-style:dashed}
.checkrow--empty:hover{opacity:0.75}

/* período popover: ONE inline flatpickr calendar (.periodo-cal) + presets. */
.pop--period{min-width: 14.75rem}
.pop--period .periodo-cal{display:flex;flex-direction:column;gap:0.5rem}
.pop--period .filter-group__label{font-size:0.875rem;font-weight:600;letter-spacing:.04em;
  text-transform:uppercase;color:var(--ink-3)}
.pop--period .periodo-cal__presets{display:flex;gap:0.25rem;flex-wrap:wrap}
/* Alternador de grão (Mês · Dia). Dois pills lado a lado, o ativo com o mesmo
   preenchimento suave do preset selecionado — é o mesmo vocabulário visual. */
.pop--period .periodo-cal__grao{display:flex;gap:0.25rem}
.pop--period .periodo-cal__grao .pill{flex:1 1 0;padding:0.25rem 0.5rem;font-weight:600;text-align:center}
.pop--period .periodo-cal__grao .pill[aria-pressed="true"]{background:var(--acc-soft);border-color:var(--acc-line);color:var(--acc-ink)}
/* Só o conjunto de atalhos do grão em vigor aparece. Quem marca a classe é o
   filtros.js ao trocar de grão — mostrar/esconder é apresentação, não decisão. */
.pop--period .periodo-cal__presets[hidden]{display:none}
/* Só o que é variante do preset: ocupar a linha, centralizar, peso maior.
   `border`/`background`/`border-radius`/`font-size` saíram — redeclaravam o que a
   base já dá (`--surf-2` é o mesmo #f3f4f7 de `--bi-bg-hover`, `--line` o mesmo
   #e6e8ec de `--bi-border-color`) e só existiam para tentar vencer o `!important`
   que não existe mais. O `:hover` local também saiu: `--surf-3` (#eceef2) diverge
   do hover da base (#ffffff), e o efetivo hoje é o da base. */
.pop--period .periodo-cal__presets .pill{flex:1 1 auto;padding:0.25rem 0.5rem;font-weight:600;
  text-align:center}
/* ATENÇÃO — delta esperado: hoje o preset SELECIONADO renderiza cinza, porque
   esta regra era morta sob o `!important` da base. Com a cascata restaurada ela
   passa a valer e a seleção de período fica visível. É correção, não regressão,
   mas é o único ponto da fase 2 que muda pixel. Verificar ao vivo. */
.pop--period .periodo-cal__presets .pill.pill--active,
.pop--period .periodo-cal__presets .pill.active{background:var(--acc-soft);border-color:var(--acc-line);color:var(--acc-ink)}
.pop--period .periodo-cal__input{display:none}
.pop--period .flatpickr-calendar.inline{margin:0 auto;box-shadow:none;border-color:var(--line-2)}

/* flatpickr calendar → FCDS glass surface + accent (month + day cells). */
.flatpickr-calendar{background:var(--surf);border:1px solid var(--line);border-radius:var(--r-md);
  font-family:var(--sans)}
.flatpickr-calendar:before,.flatpickr-calendar:after{display:none}
.flatpickr-months .flatpickr-month,.flatpickr-current-year,.flatpickr-calendar .numInputWrapper input{color:var(--ink)}
.flatpickr-current-year,.flatpickr-calendar .cur-year{font-family:var(--mono);font-weight:600}
.flatpickr-months .flatpickr-prev-month svg,.flatpickr-months .flatpickr-next-month svg{fill:var(--ink-2)}
.flatpickr-months .flatpickr-prev-month:hover svg,.flatpickr-months .flatpickr-next-month:hover svg{fill:var(--acc)}
.flatpickr-monthSelect-month{color:var(--ink-2);font-weight:500;border-radius:var(--r-xs)}
.flatpickr-monthSelect-month:hover{background:var(--surf-2);color:var(--ink)}
.flatpickr-monthSelect-month.inRange{background:var(--acc-soft);color:var(--acc-ink)}
.flatpickr-monthSelect-month.selected,.flatpickr-monthSelect-month.startRange,
.flatpickr-monthSelect-month.endRange{background:var(--acc);color:var(--bi-text-on-accent);border-color:var(--acc)}
.flatpickr-monthSelect-month.flatpickr-disabled,
.flatpickr-monthSelect-month.flatpickr-disabled:hover{color:var(--ink-4);opacity:.5;background:transparent}
.flatpickr-day{color:var(--ink-2);border-radius:var(--r-xs)}
.flatpickr-day:hover{background:var(--surf-2);color:var(--ink)}
.flatpickr-day.inRange,.flatpickr-day.today.inRange,.flatpickr-day.prevMonthDay.inRange,
.flatpickr-day.nextMonthDay.inRange{background:var(--acc-soft);border-color:var(--acc-soft);
  box-shadow:-5px 0 0 var(--acc-soft),5px 0 0 var(--acc-soft);color:var(--acc-ink)}
.flatpickr-day.selected,.flatpickr-day.startRange,.flatpickr-day.endRange,
.flatpickr-day.selected:hover,.flatpickr-day.startRange:hover,.flatpickr-day.endRange:hover{
  background:var(--acc);border-color:var(--acc);color:var(--bi-text-on-accent)}
.flatpickr-day.today{border-color:var(--acc-line)}
.flatpickr-day.flatpickr-disabled{color:var(--ink-4);opacity:.5}

/* Cabeçalho do calendário igual nos dois motores. O <select> de mês do flatpickr vem
   com `appearance:menulist`: o Chrome respeita o `background:transparent`/`border:none`
   do vendor e desenha texto chapado, o WebKit ignora e pinta o controle nativo do
   sistema (caixa cinza com moldura e seta sólida) — era o elemento mais destoante do
   componente no Safari. Zerar o appearance e desenhar a própria seta resolve nos dois. */
.flatpickr-current-month .flatpickr-monthDropdown-months{
  appearance:none;-webkit-appearance:none;background-color:transparent;border:0;
  border-radius:var(--r-xs);padding:0 0.9rem 0 0.25rem;color:var(--ink);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%236b7280' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 0.2rem center}
/* O ano é <input type=number>: no WebKit ele nasce ~4px mais baixo e ~2px mais estreito
   que o select ao lado (medido), deixando o cabeçalho torto. Alinhar pelo flex e
   neutralizar a métrica própria do campo empata os dois motores. `.flatpickr-current-month`
   também existe no grão mês (monthSelectPlugin, sem <select>) — o `:has()` restringe o
   ajuste ao grão dia, senão o padding-top:0 desloca o "2026" ~2px no grão mês (medido). */
.flatpickr-current-month:has(select.flatpickr-monthDropdown-months){display:flex;
  align-items:center;justify-content:center;gap:0.25rem;padding-top:0}
.flatpickr-current-month:has(select.flatpickr-monthDropdown-months) input.cur-year{
  line-height:normal;padding-top:0;padding-bottom:0}

/* ghost icon help button in the topbar, matching the other topbar controls */
.fcds-help{display:inline-flex;align-items:center;justify-content:center;width: 2rem;height: 2rem;padding:0;
  border:var(--bs-border-width) solid var(--line);border-radius:var(--bs-border-radius-lg);background:var(--surf);color:var(--ink-3);cursor:pointer}
.fcds-help svg,.fcds-help i{width: 1rem;height: 1rem;font-size:1rem}
.fcds-help:hover{background:var(--surf-2);color:var(--acc-ink)}
/* a page that declares no help slug ({% block ajuda_doc %}) gets no button */
.fcds-help[data-ajuda-doc=""]{display:none}

/* NOTIFICATION BELL — same ghost-icon shape as .fcds-help, so the topbar keeps
   one button family. Lives outside {% block topbar_actions %} in base_fcds.html
   (27 of 56 pages override that block), hence it is styled here and not in a
   page section. The bell itself is always present; only the count disappears
   when there is nothing unread, so clearing does not remove the control that
   was just used. */
.fcds-sino{position:relative;flex:0 0 auto}
.fcds-sino__btn{display:inline-flex;align-items:center;justify-content:center;width: 2rem;height: 2rem;padding:0;
  border:var(--bs-border-width) solid var(--line);border-radius:var(--bs-border-radius-lg);background:var(--surf);color:var(--ink-3);cursor:pointer}
.fcds-sino__btn svg,.fcds-sino__btn i{width: 1rem;height: 1rem;font-size:1rem}
.fcds-sino__btn:hover{background:var(--surf-2);color:var(--acc-ink)}
/* the count rides the bell's top-right corner, not a separate column */
.fcds-sino__n{position:absolute;top:-0.25rem;right:-0.25rem;min-width: 1rem;height: 1rem;padding:0 0.25rem;
  display:inline-flex;align-items:center;justify-content:center;border-radius: 1rem;
  background:var(--bs-danger);color:#fff;font-size:0.625rem;font-weight:700;line-height:1}
/* the badge sets its own display, so the UA's [hidden] rule needs help */
.fcds-sino__n[hidden]{display:none}
.fcds-sino__pop{position:absolute;top:calc(100% + 0.5rem);right:0;z-index:1050;width: 24rem;max-width:calc(100vw - 2rem);
  background:var(--surf);border:var(--bs-border-width) solid var(--line);border-radius:var(--bs-border-radius-lg);
  box-shadow:var(--bs-box-shadow);overflow:hidden}
.fcds-sino__topo{display:flex;align-items:center;justify-content:space-between;gap:0.5rem;
  padding:0.5rem 0.75rem;border-bottom:var(--bs-border-width) solid var(--line)}
.fcds-sino__limpar{border:0;background:none;padding:0;color:var(--acc-ink);font-size:0.8125rem;cursor:pointer}
.fcds-sino__limpar:hover{text-decoration:underline}
.fcds-sino__lista{list-style:none;margin:0;padding:0;max-height: 24rem;overflow-y:auto}
.fcds-sino__item{display:flex;flex-direction:column;gap:0.125rem;padding:0.625rem 0.75rem;
  color:var(--ink);text-decoration:none;border-bottom:var(--bs-border-width) solid var(--line);font-size:0.8125rem}
.fcds-sino__lista li:last-child .fcds-sino__item{border-bottom:0}
/* O <span> (notificação sem destino) também é clicável — o clique marca como
   lida —, então os dois recebem o mesmo hover e o mesmo cursor. Sem isto o item
   sem url parece texto morto e ninguém descobre que dá para dispensá-lo. */
.fcds-sino__item{cursor:pointer}
.fcds-sino__item:hover{background:var(--surf-2)}
.fcds-sino__item small{color:var(--ink-3);font-size:0.6875rem}
.fcds-sino__vazio{padding:1.25rem 0.75rem;text-align:center;color:var(--ink-3);font-size:0.8125rem}

/* Busca de cliente/negócio da topbar (item 15, 08/09/2026). O componente é o
   combo buscável do CRM (`crm/js/combo.js`); as regras dele hoje só alcançam
   [data-pagina="crm"|"crm-deal"|"crm-clientes"|"compras"] — nenhuma bate numa
   tela de cockpit ou faturamento. Mesmo precedente de `[data-pagina="compras"]`
   mais abaixo: reusar o COMPORTAMENTO exige repetir a pintura, aqui escopada
   ao host em vez de a uma página. */
.crm-busca-topbar { position: relative; width: 16rem; }
#crm-busca-topbar-host .crm-combo { position: relative; display: block; }
#crm-busca-topbar-host .crm-oculto { display: none !important; }
#crm-busca-topbar-host .crm-lista {
  background: var(--surf); border: var(--bs-border-width) solid var(--line);
  border-radius: var(--bs-border-radius-lg); box-shadow: var(--bs-box-shadow);
  overflow: hidden; overflow-y: auto; }
#crm-busca-topbar-host .crm-lista--flutua {
  position: absolute; left: 0; right: 0; z-index: 1055; max-height: 20rem; }
#crm-busca-topbar-host .crm-lista__item {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  border-bottom: var(--bs-border-width) solid var(--line); padding: .5rem .75rem;
  font-size: .8125rem; color: var(--ink); cursor: pointer; }
#crm-busca-topbar-host .crm-lista__item:last-child { border-bottom: 0; }
#crm-busca-topbar-host .crm-lista__item:hover,
#crm-busca-topbar-host .crm-lista__item:focus,
#crm-busca-topbar-host .crm-lista__item[data-destacado] { background: var(--surf-2); }
#crm-busca-topbar-host .crm-vazio {
  color: var(--ink-3); font-size: .75rem; padding: .6rem .75rem; }

/* GATING — the default topbar filter markup ships on every FCDS page (base_fcds.html)
   but stays dormant until fcds-filterbar.js relocates a #bi-filtros host and sets
   body.fcds-toolbar-on. Until then, hide the empty cluster + its separator so
   non-migrated pages keep a clean topbar. Scoped via :not() so when the toolbar IS
   on, the §8 rules above apply unchanged (no specificity fight). */
body:not(.fcds-toolbar-on) .topbar>.vr,
body:not(.fcds-toolbar-on) .topbar .filters,
body:not(.fcds-toolbar-on) .topbar .filtbtn,
body:not(.fcds-toolbar-on) .topbar .buscar{display:none!important}
/* Ajuda (?) fica visível se a página declara {% block ajuda_doc %} — ex.: telas de
   topbar dormante intencional como comex-kpi-financeiro. Some só quando não há doc. */
body:not(.fcds-toolbar-on) .topbar .fcds-help[data-ajuda-doc=""]{display:none!important}

/* ── TABS ──────────────────────────────────────────────────────────────────
   O skin do tablist NÃO mora aqui. Este bloco declarava-se canônico mas estava
   inteiro dentro de um comentário mal fechado (o `!important{...}` da prosa
   abria chave e o parser só reencontrava o fecho 20 linhas abaixo), então nunca
   foi aplicado. Removido em vez de revivido: reviver mudaria o render, e o vivo
   já é o de .fcds-tabs mais adiante neste arquivo (a declaração com !important
   vence as demais). O anel de foco de teclado também está lá, não se perdeu.
   Consolidar as declarações duplicadas de .fcds-tabs é trabalho do lote 3.   */

/* count badge inside a tab button (e.g. "Notas Fiscais 1.234") */

/* keyboard focus for the filter cluster + popover rows + sheet controls that had
   no visible focus ring (WCAG 2.4.7). Slate accent, matching the FCDS namespace. */
.fdrop:focus-visible,.tb-btn:focus-visible,.buscar:focus-visible,.fbuscar:focus-visible,
.filtbtn:focus-visible,.fcds-help:focus-visible,
.optrow:focus-visible,.short:focus-visible,.mcell:focus-visible{
  outline:2px solid var(--acc);outline-offset:2px;
}

/* ── §10 SHARED PAGE HELPERS ────────────────────────────────────────────────
   Generic compositional helpers promoted here from faturamento-fcds.css so EVERY
   migrated page composes the faturamento card grid without copy-pasting. The JS
   statement cluster (.hero/.kpi/.flow/.sigcol) hardcodes its own spans above;
   these explicit spans drive every OTHER section a page lays out. */
/* explicit grid spans (used with .grid) */
.fcds-span-3{grid-column:span 3}
.fcds-span-4{grid-column:span 4}
.fcds-span-5{grid-column:span 5}
.fcds-span-6{grid-column:span 6}
.fcds-span-7{grid-column:span 7}
.fcds-span-8{grid-column:span 8}
.fcds-span-9{grid-column:span 9}
.fcds-span-12{grid-column:span 12}
.fcds-row-eq{align-items:stretch}   /* equal-height row */
@media(max-width:992px){
  .fcds-span-3,.fcds-span-4,.fcds-span-5,.fcds-span-6,.fcds-span-7,.fcds-span-8,.fcds-span-9{grid-column:span 12}
}

/* segmented in-card toggle (Gráfico/Sazonalidade · Top20/ABC · Cliente/Interm.) */
.fcds-seg{display:inline-flex;gap:var(--bi-space-3xs);padding:var(--bi-space-3xs);
  background:var(--surf-3);border-radius:var(--r-sm)}
.fcds-seg__btn{padding:var(--bi-space-xs) 0.5rem;border:0;border-radius:var(--r-xs);background:none;
  font-size:0.875rem;font-weight:500;color:var(--ink-2);cursor:pointer;transition:background .12s,color .12s}
.fcds-seg__btn:hover{color:var(--ink)}
.fcds-seg__btn.active{background:var(--surf);color:var(--acc-ink);font-weight:600}
.fcds-seg__btn:focus-visible{outline:2px solid var(--acc);outline-offset:2px}

/* mini uppercase label for a chart/sub-block inside a card */
.fcds-mini-lab{font-size:0.875rem;font-weight:600;color:var(--ink-3);text-transform:uppercase;
  letter-spacing:.06em;margin-bottom:var(--bi-space-xs)}

/* quiet text link inside an operational signal (.sig) / card footer */
.fcds-siglink{display:inline-block;margin-top:var(--bi-space-sm);padding:0;border:0;background:none;
  cursor:pointer;font-size:0.875rem;font-weight:600;color:var(--ink-2);
  text-decoration:underline;text-underline-offset:2px}
.fcds-siglink:hover{color:var(--acc-ink)}
.fcds-siglink:focus-visible{outline:2px solid var(--acc);outline-offset:2px;border-radius:var(--bs-border-radius-sm)}

/* generic utility */
.is-hidden{display:none!important}
/* Algarismos tabulares. Numa coluna de 204 pesos, dígito alinhado com dígito é
   o que deixa comparar 1.748 e 1.579 de relance; com a figura proporcional a
   coluna serrilha e a comparação vira leitura. Utilitário do design system, não
   regra de uma página: vale para peso, código, data e qualquer célula numérica. */
.num-tab{font-variant-numeric:tabular-nums}
/* `.font-monospace` herda o mesmo tratamento. Enquanto a primitiva do Bootstrap
   apontava para SFMono/Consolas, a utility alinhava dígito com dígito de graça —
   é fonte de largura fixa. Com `--bs-font-monospace` remapeado para o Roboto ela
   passa a ser proporcional, e as colunas numéricas que a usam (faturamento,
   importar-of, matriz-acesso, diagnóstico) serrilhariam. Os 23 usos da utility
   neste código são todos numéricos, então ela carrega tabular-nums em vez de
   trocarmos 23 chamadas por `.num-tab`. Em <code>/<pre> é inócuo. */
.font-monospace{font-variant-numeric:tabular-nums}

/* ── BOOTSTRAP BUTTON RECONCILIATION — REMOVIDA ─────────────────────────────
   Aqui moravam os remaps de `.btn-primary`, `.btn-outline-primary` e `.btn-link`
   para a marca FCDS. Removidos por diretiva do usuário: botão é Bootstrap
   canônico, com o azul de fábrica (#0d6efd). O segundo remap, gêmeo deste, ficava
   na seção "BOOTSTRAP PALETTE to FCDS" e saiu junto — eram dois, e apagar só um
   não mudaria nada. NÃO reintroduzir nenhum dos dois. */

/* ── ALERT / NOTICE PALETTE — REMOVIDA (diretiva do usuário) ────────────────
   As variantes .alert-success/-info/-warning/-danger voltam às cores de fábrica
   do Bootstrap. Só o RAIO continua vindo do FCDS (geometria, não paleta). */
.alert{--bs-alert-border-radius:var(--r-sm)}

/* ── SHELL FREEZE (shell is untouchable) ────────────────────────────────────
   The shell topbar HOSTS injected Bootstrap action buttons and relies on the
   global --bs-* remap. Now that remap is brand-blue (content actions). Pin the
   topbar's injected buttons back to the slate command tone so the shell rail +
   topbar look is unchanged. custom.css itself stays literally untouched.
   Specificity (0,3,0) beats the global .btn-primary (0,1,0). */
/* B2: topbar-injected buttons now inherit the global brand-blue .btn-primary/-outline
   remap (slate pin removed) — all primary CTAs unified to brand-blue #006BB5. */

/* ── Zero all resting shadows (user directive) ──────────────────────────────
   Bootstrap overlay components read component-scoped --bs-*-box-shadow vars, so
   neutralise the vars AND hard-override the property to win regardless of load
   order. Focus rings (:focus-visible / --bs-*-focus-box-shadow) are untouched =
   a11y preserved; the inset 9999px table-fill trick is not a box-shadow target
   here so zebra/sticky-column backgrounds stay intact. */
:root{
  --bs-box-shadow:none;--bs-box-shadow-sm:none;--bs-box-shadow-lg:none;--bs-box-shadow-inset:none;
  --bs-dropdown-box-shadow:none;--bs-modal-box-shadow:none;--bs-toast-box-shadow:none;
  --bs-popover-box-shadow:none;--bs-offcanvas-box-shadow:none;--bs-card-box-shadow:none;
  --bs-btn-box-shadow:none;--bs-btn-active-shadow:none;
  /* B5/A3: só a GEOMETRIA de modal/dropdown segue o padrão FCDS. As cores de borda
     (--bs-*-border-color) e o tom do backdrop foram removidos por diretiva do
     usuário — ficam os valores de fábrica do Bootstrap. */
  --bs-modal-border-radius:var(--r);
  --bs-dropdown-border-radius:var(--bi-radius-md)}
/* A varredura `box-shadow:none!important` sobre dropdown/modal/toast/popover/
   offcanvas/card/tooltip saiu: cada um lê a sombra do seu `--bs-*-box-shadow`, e
   todos já estão em `none` no bloco de tokens acima — era uma segunda tranca na
   mesma porta. Medido componente a componente depois de tirar: seis dos sete
   continuam em `none`. O sétimo é o `.toast`, que redeclara
   `--bs-toast-box-shadow` no próprio seletor e por isso nunca enxergou o valor do
   `:root`; a sombra volta pelo mesmo canal, sem `!important`. */
.toast{--bs-toast-box-shadow:none}

/* ==========================================================================
   MERGED FROM bi/static/bi/css/main.css (P6 — two-layer collapse). Loads here
   (after the original FCDS rules) exactly where it loaded per-page before.
   ========================================================================== */

/* ==========================================================================
   main.css — "Editorial Finance" component system for bi/ app
   Uses ONLY tokens from tokens.css. ZERO literal color values.
   ZERO !important (except clearly marked DataTables overrides).

   Sections:
    1.  Reset / Base
    2.  Command Bar (dark filter strip)
    3.  KPI Band (top metric strip)
    4.  Section Anchor (editorial dividers)
    5.  Layout helpers
    6.  Card
    7.  KPI (operational cards)
    8.  Badge
    9.  Variation
   10.  Table + DataTables overrides
   11.  Chart
   12.  Waterfall
   13.  Heatmap
   14.  Gauge
   15.  Pills / Filters
   16.  Risco de Caixa
   17.  Toggle Devoluções
   18.  Progress Margin
   19.  Modal
   20.  Accordion
   21.  Skeleton
   22.  Error + Empty
   23.  Accessibility
   24.  Animations
   25.  Responsive
   ========================================================================== */

/* ==========================================================================
   1. RESET / BASE
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

.page {
  font-family: var(--sans);
  font-size: var(--bi-fs-body);
  font-weight: var(--bi-fw-regular);
  line-height: var(--bi-lh-normal);
  color: var(--bi-text-primary);
  background-color: var(--surface-app);
  /* SEM min-height:100vh. A .page vive DENTRO do .content, que já está abaixo da
     topbar (52px) e tem padding — forçar 100vh aqui garantia 52px + 100vh + padding
     > viewport, ou seja, uma barra de rolagem fantasma na PÁGINA, em toda tela do
     app, com tabela ou sem. Encher a tela já é papel do `.main`
     (min-height: calc(100dvh - 52px), custom.css). */
  /* padding movido p/ a def global com !important (5373, mesmo valor) — morto aqui */
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* ==========================================================================
   2. COMMAND BAR
   Fundo claro, borda inferior — filtros compactos e modernos
   ========================================================================== */

/* (.command-bar container removido — não renderizado; a raiz é .command-bar__filters.) */

/* Linha de filtros — coluna com 3 rows */
.command-bar__filters {
  display: flex;
  flex-direction: column;
  gap:var(--bi-space-2xs);
}
.command-bar__row {
  display: flex;
  align-items: center;
  gap:var(--bi-space-sm);
  flex-wrap: wrap;
}

.filter-group {
  display: flex;
  align-items: center;
  gap:var(--bi-space-xs);
}

.filter-group__label {
  font-size: 0.875rem;
  font-weight: var(--bi-fw-semibold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bi-text-muted);
  line-height: 1;
  white-space: nowrap;
}

.filter-group__pills {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap:0.25rem;
}

/* Pills no command bar */
/* Só o que diverge da base: família, tamanho e a transição por propriedade.
   `border-radius`/`border`/`color`/`background` saíram — eram mortos (a base
   `!important` os vencia) e reintroduzi-los agora MUDARIA o visual da barra,
   que hoje é o da base. O `:hover` local saiu pelo mesmo motivo. */
:is(.command-bar, .secondary-bar) .pill {
  font-family: var(--sans);
  font-size: 0.875rem;
  font-weight: var(--bi-fw-medium);
  padding:var(--bi-space-3xs) 0.5rem;
  cursor: pointer;
  transition:
    background var(--bi-transition-fast),
    color var(--bi-transition-fast),
    border-color var(--bi-transition-fast);
  white-space: nowrap;
  user-select: none;
  line-height: 1.4;
}

/* (`.pill--disabled` removido — zero usos em JS/template, código morto.
   `.pill--oculto` removido — migrou para `.checkrow--empty` §CHECKROW; a regra
   aqui nunca casou, o elemento vive em `.pop`, fora destas barras.) */

/* "pending search" state — unified onto the FCDS green-pulse standard
   (.buscar.pending, custom.css:256) so the same logical state reads
   identically across both filterbars. */
/* NOTE: NOT scoped under .command-bar — the live filterbar root is
   .command-bar__filters (no bare .command-bar element exists in the DOM),
   so an ancestor scope here would never match. !important to beat the base
   .btn-buscar-trigger{background:--brand!important} at ~L5772. */
.btn-buscar-trigger.btn-buscar--pending {
  color: var(--bi-text-on-accent);
  background: var(--positive-text) !important;
  border-color: var(--positive-text) !important;
  font-weight: var(--bi-fw-semibold);
}

.btn-buscar-trigger.btn-buscar--pending:hover {
  background: color-mix(in srgb, var(--positive-text) 86%, var(--ink)) !important;
  border-color: color-mix(in srgb, var(--positive-text) 86%, var(--ink)) !important;
  color: var(--bi-text-on-accent);
}

/* ==========================================================================
   3. KPI BAND
   Faixa horizontal de 5 métricas sem cards individuais
   ========================================================================== */

.kpi-band {
  display: grid;
  grid-template-columns: 1.2fr 1.4fr 1fr 1fr 1fr 1fr 1fr;
  background: var(--bi-bg-surface);
  border: var(--bi-border);
  border-radius: var(--bi-radius-md);
  box-shadow: var(--bi-shadow-sm);
  overflow: hidden;
  /* No horizontal margin:the band aligns flush to its section/card width like
     every .cardbox. .page already supplies the page side padding, so a
     horizontal margin here double-inset the band (was 3rem narrower than cards
     across all pages). Standardized 2026-06 — see docs/planos/pilot-page-refactor.md.
     KPI band → content gap promoted to --bi-space-md (Batch 6 §2, Agent C). */
  margin: 0 0 var(--bi-space-md);
  animation: bi-fadeIn var(--bi-transition-normal) ease both;
}

/* Aging table — pct bar overlay */
.faixa-dot {
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--bi-dot-cor, var(--ink-4));
  margin-right:var(--bi-space-xs2);
  vertical-align: middle;
}

/* Shared, page-agnostic KPI accent modifiers — every KPI page tags cells by
   value DIRECTION via these (no inline category accents). Bottom-rule only. */

/* Legacy alias (despesas_comex used --previsao) → same as warning. */

.kpi-band__label {
  font-size: var(--bi-fs-label);
  font-weight: var(--bi-fw-semibold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bi-text-muted);
  margin-bottom:var(--bi-space-xs);
  line-height: 1;
}

.kpi-band__value {
  /* Shared (Step 3 contract): KPI numbers are tabular on every page — the number
     is the data, dark, no colour fill. Use --mono (Roboto, loaded in
     base_fcds.html) to MATCH faturamento's .kc__v numerals; Roboto
     (official numeral font, --mono) is the canonical numeral family — the old
     --bi-font-mono fell back to a system mono that diverged from the reference.
     Roboto is also narrower → less mobile clipping. */
  font-family: var(--mono); /* --mono always resolves; dead --bi-font-mono fallback dropped */
  font-weight: var(--bi-fw-bold);
  color: var(--bi-text-primary);
  line-height: var(--bi-lh-tight);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

.kpi-band__secondary {
  font-family: var(--bi-font-display);
  font-size: var(--bi-fs-body);
  font-weight: var(--bi-fw-medium);
  color: var(--bi-text-secondary);
  margin-top:var(--bi-space-3xs);
  font-variant-numeric: tabular-nums;
}

/* Trend badge — variação vs mês anterior */
.kpi-band__trend {
  display: flex;
  align-items: center;
  gap:0.25rem;
  font-family: var(--sans);
  font-size: var(--bi-fs-caption);
  font-weight: var(--bi-fw-semibold);
  margin-top:var(--bi-space-xs);
  min-height: 0.875rem;
}

/* ==========================================================================
   4. SECTION ANCHOR
   Separador editorial horizontal com label centralizado
   ========================================================================== */

.section-anchor {
  display: flex;
  align-items: center;
  gap:var(--bi-space-sm);
  margin:var(--bi-space-sm) var(--bi-space-lg) var(--bi-space-xs);
}

.section-anchor::before,
.section-anchor::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--bi-border-color);
}

.section-anchor__label {
  font-family: var(--bi-font-display);
  font-size: 0.875rem;
  font-weight: var(--bi-fw-semibold);
  letter-spacing: 0.12em;
  color: var(--bi-text-muted);
  white-space: nowrap;
  text-transform: uppercase;
}

/* KPI strip para cards operacionais (ritmo, PMP, PMR). O seletor desta regra foi
   perdido: a linha abria comentário e nunca fechava, engolindo a declaração
   `padding:0 var(--bi-space-lg)` e o banner da seção 6. Como o nome do seletor
   foi truncado junto, não há o que restaurar — a declaração órfã foi removida. */

/* ==========================================================================
   6. CARD
   ========================================================================== */

/* Accent na borda superior do card */

/* Accent na borda esquerda */

/* 0.5rem floor for Bootstrap badges + inline code (batch5 type contract).
   Bootstrap's .badge ships font-size:0.75em (em-relative → renders 8-0.5rem on
   small parents); force the 12px absolute floor. Chart-internal ring labels
   (.ring__c/.kring__sub) are the only justified sub-12px exception. */
.badge {
  font-size: 0.875rem;   /* 12px */
}
code {
  font-size: 0.875rem;   /* 12px floor */
}

/* Badge de contagem no header do card */

/* ==========================================================================
   7. KPI — a célula canônica é components/_kpi_cell.html (card Bootstrap).
   A classe .kpi-tile que morava aqui era legado sem markup vivo (nenhum
   template do tree renderiza class="kpi-tile"; os id="kpi-tiles" são
   containers, outra coisa) — removida em 2026-08-06 na varredura DESIGN.md §6.
   ========================================================================== */

/* ==========================================================================
   8. BADGE
   ========================================================================== */

.badge {
  display: inline-flex;
  align-items: center;
  gap:var(--bi-space-3xs);
  font-size: var(--bi-fs-caption);
  font-weight: var(--bi-fw-semibold);
  padding:var(--bi-space-3xs) var(--bi-space-sm);
  border-radius: var(--raio-chip); /* B6: canonical soft-pill (the one badge shape) */
  line-height: var(--bi-lh-tight);
  white-space: nowrap;
  background: var(--bi-bg-elevated);
  color: var(--bi-text-secondary);
  border: var(--bi-border);
}

/* Direction badges → canonical indicator tokens (text) + *-subtle (bg). */
.badge--success  { background: var(--positive-subtle); color: var(--positive-text);      border-color: var(--positive-text); }
.badge--danger   { background: var(--negative-subtle); color: var(--negative-text);      border-color: var(--negative-text); }
.badge--warning  { background: var(--warning-subtle);  color: var(--warning-text);  border-color: var(--warning); }
/* --info is categorical (not a value direction) → neutral, no direction hue. */
.badge--info     { background: var(--neutral-subtle);  color: var(--ink-2);       border-color: var(--ink-2); }
/* --neutro: o estado TERMINADO, que não pede nada de ninguém. Existe porque
   "concluído" não é "sucesso": pintar de verde tudo o que já foi faturado põe a
   cor mais forte da paleta no que ninguém pode mais mexer, e deixa a única linha
   viva como a mais apagada da lista. Sem cor de direção, sem borda forte. */
.badge--neutro   { background: var(--surf-2);          color: var(--ink-3);               border-color: var(--line-3); }
/* --primary is categorical accent (in-flight / active) → slate accent, no direction hue. */
.badge--primary  { background: var(--acc-soft);        color: var(--acc-ink);             border-color: var(--acc-line); }
/* --brand is the Four heritage blue identity (masthead codes, not a value direction). */
.badge--brand    { background: var(--brand-soft);      color: var(--brand-ink);           border-color: var(--brand); }

/* Densidade — modificador compartilhado p/ grids densos (ex.: despesas_comex). */
.badge--sm { font-size: 0.875rem; padding:var(--bi-space-3xs) var(--bi-space-xs2); }

/* Dot modifier — categorical identity whose hue varies per data value (grupo/segmento),
   supplied at runtime via --dot on the element. Label stays fixed --ink-2 for legibility;
   only the leading dot carries the category hue (cat tokens aren't AA-safe as text). */
.badge--dot { color: var(--ink-2); }
.badge--dot::before {
  content: "";
  width: 0.4375rem;
  height: 0.4375rem;
  border-radius: 50%;
  background: var(--dot, var(--ink-3));
  flex: 0 0 auto;
}

/* ==========================================================================
   9. VARIATION (inline up/down indicator)
   ========================================================================== */

/* ==========================================================================
   10. TABLE (tbl wrapper + DataTables overrides)
   ========================================================================== */

.tbl-wrapper {
  border-radius: var(--bi-radius-md);
  /* Sem borda própria: o .tbl-wrapper sempre mora dentro de um .card (convenção
     FCDS: section.card > .tbl-wrapper), e o card já desenha o contorno do
     componente. Uma borda aqui virava linha dupla em todas as telas de tabela. */
  /* MOBILE: wide ERP tables must scroll inside the card, not clip at its edge.
     (datatable adds .datatable-scroll for DataTables; this covers bare/non-DT
     wrappers — e.g. contas_a_pagar + fluxo-bancario TD tables.) */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.tbl {
  width: 100%;
  font-size: var(--bi-fs-body);
  color: var(--bi-text-primary);
  margin-bottom:0;
  border-collapse: collapse;
}

.tbl thead th {
  background-color: var(--surf-2);
  border-bottom: 2px solid var(--bi-border-color);
  font-size: var(--bi-fs-label);
  font-weight: var(--bi-fw-semibold);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--bi-text-secondary);
  white-space: nowrap;
  padding:var(--bi-space-sm) var(--bi-space-md);
}

.tbl tbody td {
  padding:var(--bi-space-sm) var(--bi-space-md);
  border-bottom: var(--bi-border-subtle);
  vertical-align: middle;
}

/* Estado de linha usa o motor do Bootstrap (overlay translúcido `--bs-table-accent-bg`,
   styles.css:2047), não um hex opaco. Hex opaco colide com qualquer faixa que use o
   mesmo valor — `--bi-bg-hover` e `--surf-2` são ambos #f3f4f7, e o hover sumia em
   cima da faixa. O overlay compõe sobre a base, então o hover é sempre mais escuro
   que a linha, seja ela branca ou faixada. */
.tbl tbody tr:hover td {
  --bs-table-accent-bg: var(--bs-table-hover-bg);
}

.tbl__numeric {
  font-family: var(--bi-font-mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
  white-space: nowrap;
}

/* (removed `.tbl--sticky-first` — superseded by the unified `.stickcols`
   system; pedidos + fluxo-bancário migrated.) */

/* Total row */
.tbl .tbl__total-row td {
  font-weight: var(--bi-fw-bold);
  border-top: 2px solid var(--bi-border-color-heavy);
  background-color: var(--surf-2);
}

/* Densidade — modificador compartilhado p/ tabelas de muitas colunas (ex.: as 27
   colunas do despesas_comex). Reduz padding/line-height das células e encolhe o
   checkbox de linha. Aplique `.tbl--compact` no <table>. */
.tbl--compact thead th,
.tbl--compact tbody td {
  padding:var(--bi-space-xs) var(--bi-space-sm);
  line-height: 1.25;
}
.tbl--compact thead th {
  white-space: normal;
  line-height: 1.2;
}
.tbl--compact .form-check-input {
  width: 0.875rem;
  height: 0.875rem;
}

/* --- DataTables padrão BI — opt-in via .datatable no wrapper --- */

/* Toolbar: B (buttons) à esquerda, l (length) + f (filter) à direita */
.datatable .datatable-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap:var(--bi-space-md);
  flex-wrap: wrap;
  padding:var(--bi-space-sm) var(--bi-space-md);
  border-bottom: 1px solid var(--bi-border-color);
}
.datatable .datatable-toolbar__left,
.datatable .datatable-toolbar__right {
  display: inline-flex;
  align-items: center;
  gap:var(--bi-space-sm);
}

/* Copiar e Colunas são ações independentes — não devem parecer um segmented
   control. Gap real entre os botões + neutraliza o margin-left:-0 que o
   .btn-group (Colunas) herda do bootstrap (border-collapse de grupo). */
.datatable .dt-buttons {
  display: inline-flex;
  gap:var(--bi-space-sm);
}
.datatable .dt-buttons > .btn-group {
  margin-left:0;
}
/* Neutraliza btn/btn-secondary herdado de buttons.bootstrap5 */
.datatable .dt-buttons .btn {
  all: unset;
}
/* Suprime outline de foco sem destruir layout (all:unset no :focus teria espec. 0,4,0 > .pill 0,3,0) */
.datatable .dt-buttons .pill:focus {
  outline: none !important;
  box-shadow: none !important;
}
/* a11y: restaura anel de foco visível por teclado (espelha §23 .pill:focus-visible) */
.datatable .dt-buttons .pill:focus-visible {
  outline: 2px solid var(--positive) !important;
  outline-offset: 2px;
  box-shadow: none !important;
}
.datatable .dt-buttons .pill {
  display: inline-flex !important;
  align-items: center;
  gap:0.25rem;
  padding:var(--bi-space-2xs) 0.5rem;
  font-size: var(--bi-fs-label);
  font-weight: var(--bi-fw-medium);
  /* Estes quatro NÃO são redundantes com a base, apesar de a base dar os mesmos
     valores: o elemento é `btn btn-secondary pill` (DataTables/bootstrap5), e o
     `.btn`/`.btn-secondary` do Bootstrap disputa fundo, borda e raio com a base
     `.pill` (0,1,0). Enquanto a base tinha `!important` isso não aparecia; sem
     ele, o botão caía para o visual do Bootstrap (fundo transparente, raio 0).
     Repetidos aqui em (0,3,0) com os MESMOS valores da base — preserva o
     computado que a tela sempre teve. Medido, não deduzido. */
  background: var(--bi-bg-hover);
  border: var(--bs-border-width) solid var(--bi-border-color);
  border-radius: var(--raio-chip);
  color: var(--bi-text-secondary);
  cursor: pointer;
  line-height: 1.4;
  height: 1.75rem;
  box-sizing: border-box !important;
  overflow: hidden;
  transition:
    background var(--bi-transition-fast),
    color var(--bi-transition-fast),
    border-color var(--bi-transition-fast);
}
/* O botão vive num `.btn-group`, e o Bootstrap zera os cantos internos com
   `.btn-group > .btn:not(:last-child):not(.dropdown-toggle)` — (0,4,0), que vence
   o bloco acima (0,3,0) e devolvia `800px 0 0 800px`. Empate em (0,4,0) resolvido
   pela ordem: custom.css carrega depois de styles.css. Sem `!important`. */
.datatable .dt-buttons .pill.btn { border-radius: var(--raio-chip); }
.datatable .dt-buttons .pill:hover {
  background: var(--bi-bg-hover) !important;
  color: var(--bi-text-primary) !important;
  border-color: var(--line-3) !important;
  box-shadow: none !important;
  transform: none !important;
}
.datatable .dt-buttons .pill:active {
  background: var(--bi-bg-hover) !important;
  color: var(--bi-text-primary) !important;
  border-color: var(--line-3) !important;
  box-shadow: none !important;
  transform: none !important;
  filter: brightness(0.92);
}
/* Spans injetados por buttons.bootstrap5 — sem herdar font-size de nenhum estado */
.datatable .dt-buttons .pill span {
  font-size: inherit !important;
  line-height: inherit !important;
  font-weight: inherit !important;
  padding:0 !important;
  margin:0 !important;
  transform: none !important;
  display: inline !important;
}
.datatable .dt-buttons .pill i {
  font-size: 0.875rem;
  opacity: 0.7;
}
.datatable .dt-buttons .dropdown-toggle::after {
  content: '\f078'; font-family:'Font Awesome 6 Free'; font-weight:900; font-size: .625rem; vertical-align: .1em;
  margin-left:var(--bi-space-2xs); border: 0;
}

/* <details> sem a seta nativa do navegador: o chevron do app, que gira ao abrir
   (dono, 15/09 — chevron é ícone em todo lugar). Uma regra só para os cinco
   disclosures que ainda mostravam o triângulo do sistema. */
:is(.cl-relatorio details, .ret-avancado, #modalbox-nf-notes-card, .reportar-historico, .tf-detalhe__historico) > summary {
  list-style: none;
}
:is(.cl-relatorio details, .ret-avancado, #modalbox-nf-notes-card, .reportar-historico, .tf-detalhe__historico) > summary::-webkit-details-marker {
  display: none;
}
:is(.cl-relatorio details, .ret-avancado, #modalbox-nf-notes-card, .reportar-historico, .tf-detalhe__historico) > summary::before {
  content: '\f054'; font-family:'Font Awesome 6 Free'; font-weight:900; font-size: .625rem;
  display: inline-block; width: 1em; margin-right: .4em; text-align: center; vertical-align: .1em;
  transition: transform .15s ease;
}
:is(.cl-relatorio details, .ret-avancado, #modalbox-nf-notes-card, .reportar-historico, .tf-detalhe__historico)[open] > summary::before {
  transform: rotate(90deg);
}
/* Raia recolhível da Permanência no Porto (só no celular): o chevron vira com o
   `aria-expanded` que o collapse do Bootstrap mantém no cabeçalho. */
.pp-lane__chevron { transition: transform .15s ease; }
.pp-lane__head[aria-expanded="true"] .pp-lane__chevron { transform: rotate(180deg); }

/* ColVis dropdown */
.datatable .dt-button-collection {
  background: var(--bi-bg-surface);
  border: var(--bi-border);
  border-radius: var(--bi-radius-sm);
  box-shadow: var(--bi-shadow-md);
  padding:var(--bi-space-2xs) 0;
  font-size: var(--bi-fs-label);
}
.datatable .dt-button-collection .dt-button {
  padding:0.25rem 1rem;
  color: var(--bi-text-primary);
  background: transparent;
  border: 0;
  width: 100%;
  text-align: left;
  cursor: pointer;
}
.datatable .dt-button-collection .dt-button:hover {
  background: var(--bi-bg-hover);
}
.datatable .dt-button-collection .dt-button.active {
  color: var(--positive-text);
  font-weight: var(--bi-fw-semibold);
}

/* Length + Search inputs alinhados com pills (28px) */
.datatable .dataTables_length,
.datatable .dataTables_filter {
  margin:0;
}
.datatable .dataTables_length label,
.datatable .dataTables_filter label {
  display: inline-flex;
  align-items: center;
  gap:var(--bi-space-xs2);
  margin:0;
  font-size: var(--bi-fs-label);
  color: var(--bi-text-secondary);
  font-weight: var(--bi-fw-medium);
  white-space: nowrap;
}
.datatable .dataTables_length select,
.datatable .dataTables_filter input {
  height: 1.75rem !important;
  min-height: unset !important;
  padding:0 0.5rem !important;
  font-size: var(--bi-fs-label) !important;
  background: var(--bi-bg-hover) !important; /* align to the .dataTables_wrapper filter rule (was --bi-bg-surface) — removes the white-vs-grey conflict */
  border: var(--bi-border) !important;
  border-radius: var(--bi-radius-sm) !important;
  color: var(--bi-text-primary) !important;
  transition: border-color var(--bi-transition-fast);
  box-sizing: border-box;
}
.datatable .dataTables_filter input {
  min-width: 11.25rem;
}
.datatable .dataTables_length select:focus,
.datatable .dataTables_filter input:focus {
  outline: none;
  border-color: var(--acc-line); /* was --positive (green) — neutral controls focus slate, not green */
  box-shadow: var(--ring);
}

/* Scroll horizontal isolado: só conteúdo + thead, não a toolbar nem bottom bar */
.datatable .datatable-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.datatable table.dataTable {
  min-width: 100%;
}

/* Bottom bar: info + paginate */
.datatable .datatable-bottom {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding:var(--bi-space-sm) var(--bi-space-md);
  border-top: 1px solid var(--bi-border-color);
}
.datatable .datatable-bottom .dataTables_info,
.datatable .datatable-bottom .dataTables_paginate {
  padding-top:0;
  margin:0;
  font-size: var(--bi-fs-label);
  color: var(--bi-text-secondary);
}

/* Paginação: nenhuma regra. Ver o bloco "PAGINAÇÃO: sem regra nenhuma" mais
   abaixo — o .pagination do Bootstrap responde por cor, borda, raio e solda. */

/* Filtros de coluna multi-seleção (Pedidos): trigger + painel flutuante.
   Antes só existia em demo/components-v2.css (não carregado em produção), então
   o controle vinha sem estilo. Portado para o FCDS: acento slate (não brand-blue),
   raio igual aos controles da toolbar (--bi-radius-sm). O painel é position:fixed
   (posicionado no abrir por pedidos-colfilter.js) para escapar do overflow do
   .datatable-scroll, que recortava a lista quando havia scroll horizontal. */
.colfilter-multi { position: relative; }
.colfilter-multi__trigger {
  display: inline-flex; align-items: center; justify-content: space-between;
  gap:var(--bi-space-xs2); width: 100%;
  font-size: var(--bi-fs-label); font-weight: var(--bi-fw-regular);
  color: var(--bi-text-primary); background: var(--bi-bg-surface);
  /* Borda e raio do PRÓPRIO Bootstrap (--bs-border-color / --bs-border-radius-sm),
     não os tokens FCDS: este gatilho vive lado a lado com `.form-control-sm` numa
     linha de filtros, e os dois cinzas (#e6e8ec do FCDS × #dee2e6 do Bootstrap)
     ficaram visivelmente diferentes quando o remap de --bs-border-color foi
     removido. Amarrado ao token do Bootstrap, o contorno acompanha os campos
     vizinhos aconteça o que acontecer com o tema. */
  border: var(--bs-border-width) solid var(--bs-border-color);
  border-radius: var(--bs-border-radius-sm);
  padding:var(--bi-space-3xs) var(--bi-space-xs2); cursor: pointer; white-space: nowrap;
  transition: border-color var(--bi-transition-fast), color var(--bi-transition-fast);
}
.colfilter-multi__trigger:hover { border-color: var(--bi-border-color-heavy); }
/* Foco e "tem seleção" no MESMO azul dos demais controles (o --bs-primary de
   fábrica do Bootstrap), e não no quase-preto --acc: o contorno escuro lia como um
   controle de outra família ao lado dos campos e botões da linha de filtros. */
.colfilter-multi__trigger:focus-visible { outline: none; border-color: var(--bs-primary); }
.colfilter-multi__trigger > i { font-size: 0.7em; opacity: 0.6; }
.colfilter-multi__ico { font-size: 0.72em; color: var(--bi-text-secondary); flex-shrink: 0; }
.colfilter-multi--ativo .colfilter-multi__trigger {
  border-color: var(--bs-primary); color: var(--bs-primary); font-weight: var(--bi-fw-medium);
}
.colfilter-multi__panel {
  position: fixed; z-index: var(--bi-z-dropdown, 100);
  min-width: 11.5rem; width: max-content; max-height: 18.75rem; overflow-y: auto;
  background: var(--bi-bg-surface);
  border: var(--bs-border-width) solid var(--bi-border-color);
  border-radius: var(--bi-radius-md);
  /* Elevação real: um menu flutuante precisa se separar do conteúdo abaixo
     (exceção de popover ao depth-flat do FCDS). Sombra suave, sem dureza. */
  box-shadow: 0 10px 28px -10px rgba(25, 28, 34, 0.22), 0 2px 8px -3px rgba(25, 28, 34, 0.12);
  padding:var(--bi-space-3xs);
  animation: biColfilterIn 0.13s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Picker "Tipo de Documento" do modal de anexos (_modais_titulo.html): o painel
   é o .colfilter-multi__panel com busca fixa no topo e lista rolando embaixo.
   Vinha de um <style> inline no template — CSS autoral só mora aqui. */
.df-anexo-tipo-picker__panel { display: flex; flex-direction: column; max-height: 20rem; padding:0; }
.df-anexo-tipo-picker__panel .input-group { flex: 0 0 auto; }
#df-anexo-tipo-opcoes { flex: 1 1 auto; overflow-y: auto; }
@keyframes biColfilterIn {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .colfilter-multi__panel { animation: none; }
}
.colfilter-multi__opt {
  display: flex; align-items: center; gap:var(--bi-space-xs);
  padding:var(--bi-space-xs2) var(--bi-space-sm); margin:0;
  border-radius: var(--bi-radius-sm);
  font-size: var(--bi-fs-label); font-weight: var(--bi-fw-regular); color: var(--bi-text-primary);
  white-space: nowrap; cursor: pointer; text-transform: none; letter-spacing: 0;
  transition: background var(--bi-transition-fast);
}
.colfilter-multi__opt:hover { background: var(--bi-bg-hover); }
.colfilter-multi__opt input {
  cursor: pointer; accent-color: var(--acc);
  width: 0.875rem; height: 0.875rem; flex-shrink: 0;
}
/* Painel de INTERVALO (biUtils.colfilterRange): dois inputs de/até empilhados.
   Reusa a casca .colfilter-multi__panel; só arruma o layout dos campos. */
.colfilter-range__panel {
  min-width: 11.25rem; padding:var(--bi-space-xs);
  display: flex; flex-direction: column; gap:var(--bi-space-xs2);
}
.colfilter-range__field {
  display: flex; align-items: center; gap:var(--bi-space-xs); margin:0;
  font-size: var(--bi-fs-label); font-weight: var(--bi-fw-regular);
  color: var(--bi-text-secondary); text-transform: none; letter-spacing: 0;
}
.colfilter-range__field > span { width: 2.2em; flex-shrink: 0; }
.colfilter-range__field input {
  flex: 1; min-width: 0;
  font-size: var(--bi-fs-label); color: var(--bi-text-primary);
  background: var(--bi-bg-surface); border: var(--bs-border-width) solid var(--bi-border-color);
  border-radius: var(--bi-radius-sm); padding:var(--bi-space-3xs) var(--bi-space-xs2);
}
.colfilter-range__field input:focus-visible { outline: none; border-color: var(--acc); }

.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  padding:0;
  border: none;
  background: transparent;
  border-radius: var(--bi-radius-sm);
  color: var(--bi-text-secondary);
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.btn-icon:hover {
  background: var(--bi-bg-hover);
  color: var(--bi-text-primary);
}
.chart canvas{
  width: 100%;
}

/* Degrau extra da escada, para gráfico de DOIS PAINÉIS empilhados (histórico de
   preços: preço em cima, volume embaixo). Em 25rem os dois painéis somados, menos
   a faixa dos rótulos de mês inclinados, deixavam ~11rem para o preço — apertado
   demais para uma linha com rótulo em cada ponto. */
.chart--xl     { height: 34rem; }
.chart--tall   { height: 25rem; }
.chart--medium { height: 18.75rem; }
.chart--short  { height: 17.5rem; }

/* ==========================================================================
   12. WATERFALL
   ========================================================================== */

/* Mapa UF — card e corpo preenchem a altura definida pelo align-items-stretch da row */
[data-bi-section="mapa-uf"] .card {
  display: flex;
  flex-direction: column;
}
[data-bi-section="mapa-uf"] .card-body {
  flex: 1;
  min-height: 0;
}
[data-bi-section="mapa-uf"] .mapa {
  height: 100%;
}

/* Cascata de Margens — estica para igualar altura da tabela UN */

[data-bi-section="cascata"] .card {
  display: flex;
  flex-direction: column;
}
[data-bi-section="cascata"] .card-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 17.5rem;
}

/* (`.pill--empresa` removido — bloco 100% morto. Declarava fundo preenchido
   `--command` e ativo `--positive`; media-se cinza da base em produção, porque a
   base `.pill` do bloco "statement pill look" tinha `!important` (removido na
   fase 2 do saneamento). O "visual
   diferenciado" nunca chegou à tela. As linhas de empresa são `.checkrow` como
   as demais. Decisão do Elyan em 2026-07-29: apagar, não ressuscitar. */

/* ==========================================================================
   13. HEATMAP
   ========================================================================== */

.heatmap-grid {
  overflow-x: auto;
}

.heatmap-table {
  border-collapse: separate;
  border-spacing: 3px;
  font-size: var(--bi-fs-caption);
  min-width: 100%;
}

.heatmap-table th {
  padding:var(--bi-space-2xs) var(--bi-space-sm);
  font-weight: var(--bi-fw-semibold);
  color: var(--bi-text-secondary);
  white-space: nowrap;
  text-align: center;
}

.heatmap-table th:first-child {
  text-align: left;
}

.heatmap-table td {
  padding:var(--bi-space-xs2) var(--bi-space-sm);
  border-radius: var(--bi-radius-sm);
  text-align: center;
  white-space: nowrap;
  font-family: var(--bi-font-mono);
  font-variant-numeric: tabular-nums;
  transition: filter 0.15s;
}

.heatmap-table td:first-child {
  font-family: var(--sans);
  font-weight: var(--bi-fw-semibold);
  color: var(--bi-text-secondary);
  background: transparent !important;
  text-align: left;
}

.heatmap-table td:hover {
  filter: brightness(0.88);
}

/* Célula do Ritmo: padding reduzido para acomodar o gauge */

/* ==========================================================================
   15. PILLS / FILTERS (light background variants)
   ========================================================================== */

/* Versão padrão (fundo claro) — usada fora do command bar */

/* === PILL — base única =======================================================
   Chip de filtro/ação. Cor, fundo, borda e raio moravam num bloco `!important`
   lá embaixo ("filter chips → statement pill look"), o que invertia a cascata:
   `!important` num seletor (0,1,0) vencia TODA regra mais específica, e cada
   contexto que precisava divergir tinha de empilhar o seu próprio `!important`
   depois. Voltaram para cá, sem `!important` — contexto (0,2,0)/(0,3,0) e estado
   voltam a vencer por especificidade, como o CSS já faria sozinho.
   As linhas de seleção do popover NÃO são pill: ver §CHECKROW. */
.pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding:var(--bi-space-3xs) 0.5rem;
  font-size: var(--bi-fs-label);
  font-weight: var(--bi-fw-medium);
  border: var(--bs-border-width) solid var(--bi-border-color);
  background: var(--bi-bg-hover);
  color: var(--bi-text-secondary);
  border-radius: var(--raio-chip);
  cursor: pointer;
  transition: all .12s;
  white-space: nowrap;
  user-select: none;
  line-height: 1.4;
}

.pill:hover {
  background: var(--bi-bg-surface);
  border-color: var(--bi-border-color-heavy);
  color: var(--bi-text-primary);
}

/* (`.pill--active` base removido: era 100% morto — declarava fundo `--command`
   e perdia para o `!important` da base. Ressuscitá-lo como regra global pintaria
   de ativo contextos que hoje NÃO pintam, mudando pixel. O estado ativo continua
   escopado aos três contextos que realmente o usam, mais abaixo.) */

/* ==========================================================================
   16. RISCO DE CAIXA — caixas coloridas por threshold
   ========================================================================== */

/* ==========================================================================
   17. TOGGLE DEVOLUÇÕES
   ========================================================================== */

/* Os switches "Considerar devoluções" e "Formatar número?" vivem no MESMO grupo,
   à direita do topbar (#fcds-toggles, montado por fcds-filterbar.js). São
   .form-check.form-switch do Bootstrap puros, agrupados por utilitários
   (d-flex/gap-3/ms-auto) — nenhuma regra própria aqui. */

.mov-toggle-caption {
  font-size: var(--bi-fs-caption);
  color: var(--bi-text-secondary);
  margin-left:var(--bi-space-xs);
  font-family: var(--bi-font-mono);
}

/* ==========================================================================
   18. PROGRESS MARGIN — colunas MB% e MC% na tabela de NFs
   ========================================================================== */

/* (variantes --sucesso/--aviso/--perigo removidas — o JS só emite
   progress-margin--neutral; nunca as coloridas.) */

/* neutral: MB/MC % carry no value direction — pct in ink, bar in the slate accent */

/* Desktop: tuck the MB/MC margin cell into the right-aligned numeric rhythm (its cell is
   text-align:right) and tighten it for the denser desktop table — keeps the magnitude bar.
   Mobile keeps the centered, roomier layout above. */
@media (min-width:768px){

}

/* ==========================================================================
   19. MODAL — Detalhes da Nota Fiscal
   ========================================================================== */

/* Chrome de `.modalbox` removido — todos os modais usam o shell Bootstrap
   (biUtils.abrirModal). Sobrevive só a classe de CONTEÚDO `.modalbox__subtitulo`
   (subtítulo no header, usada por faturamento e pedidos). */
.modalbox__subtitulo {
  font-size: var(--bi-fs-body);
  color: var(--bi-text-secondary);
  margin-top:var(--bi-space-3xs);
  font-family: var(--bi-font-mono);
}

/* ==========================================================================
   20. ACCORDION — removido (colapse de seções não é necessário)
   ========================================================================== */

/* (accordion removed) */

/* ==========================================================================
   21. SKELETON (loading placeholders)
   ========================================================================== */

/* .skeleton / .skeleton--chart / .skeleton--text removidos — skeleton unificado no
   Bootstrap .placeholder (utils.js SKELETON_HTML + carregando/carregandoSecao). */

/* ==========================================================================
   21b. LOGO LOADER (Four Group signature loading state — used em F.BI)
   ========================================================================== */

/*
 * Loader em modo overlay: o container alvo recebe data-bi-loading="<size>",
 * que aplica position:relative + min-height. O loader em si fica sobreposto
 * com inset:0, deixando o conteúdo embaixo intacto (apenas escondido pelo bg).
 *
 * Estrutura HTML (injetada via biUtils.aplicarLoaderEm):
 *   <div class="logo-loader" role="status" aria-busy="true" aria-live="polite">
 *     <div class="logo-loader__base"></div>
 *     <div class="logo-loader__mask"><div class="logo-loader__fill"></div></div>
 *   </div>
 */

[data-bi-loading]            { position: relative; }
[data-bi-loading="banda"]    { /* KPI band: altura natural das células, sem reserva */ }
[data-bi-loading="tape"]     { min-height: 11.75rem; }
[data-bi-loading="chart"]    { min-height: 22.5rem; }
[data-bi-loading="board"]    { min-height: 30rem; }

.logo-loader {
  position: absolute;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;   /* clipa o logo em containers baixos (faixa KPI, modo banda) */
  background: var(--bi-bg-surface);
  border-radius: var(--bi-radius-md);
}

/* Logo "4" dimensionado pela ALTURA do container (não largura fixa): escala
   sozinho em todo modo — proeminente em board/chart, encolhe e cabe na faixa
   KPI (banda). aspect-ratio casa o logo.svg real (1311×1316). O wrapper próprio
   do despesas_comex sobrescreve width/height (100%) com specificity maior. */
.logo-loader__base,
.logo-loader__mask {
  position: absolute;
  width: auto;
  height: min(46%, 150px);
  aspect-ratio: 1311 / 1316;
  -webkit-mask-image: url("../img/logo.e911c70f8d2a.svg");
          mask-image: url("../img/logo.e911c70f8d2a.svg");
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: center;
          mask-position: center;
}

.logo-loader__base {
  background: var(--bi-loader-base);
}

.logo-loader__mask {
  overflow: hidden;
}

.logo-loader__fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 0%;
  /* PRETO, e dito aqui: a logo do carregamento é a marca, não um acento nem um
     dado — não segue a cor de ação do app. Lia --command (tinta de magnitude de
     DADO), que por sua vez estava aliasado ao acento; era esse encadeamento que
     fazia a logo mudar de cor junto com botão e paginação. */
  background: var(--ink);
  animation: logo-loader-trickle 2.2s ease-in-out 0.15s infinite alternate;
}

@keyframes logo-loader-trickle {
  0%   { width: 8%; }
  100% { width: 88%; }
}

@media (prefers-reduced-motion: reduce) {
  .logo-loader__fill {
    animation: none;
    width: 50%;
  }
}

/* ==========================================================================
   22. ERROR + EMPTY STATE
   ========================================================================== */

.state-error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap:var(--bi-space-sm);
  padding:var(--bi-space-lg);
  text-align: center;
  color: var(--bi-text-secondary);
}

.state-error[role="alert"] {
  /* Borda plena na cor da família + tinta -subtle — sem faixa lateral
     (o caso literal do banimento, DESIGN.md §6). */
  border: 1px solid var(--negative-text);
  border-radius: var(--bi-radius-md);
  background: var(--negative-subtle);
}

.state-error__mensagem {
  font-size: var(--bi-fs-body);
  color: var(--bi-text-secondary);
}

.state-error__botao-retry {
  display: inline-flex;
  align-items: center;
  gap:0.25rem;
  padding:var(--bi-space-xs) var(--bi-space-md);
  font-size: var(--bi-fs-label);
  font-weight: var(--bi-fw-semibold);
  /* AÇÃO usa o azul de ação — o verde aqui dizia "deu certo" dentro de um
     erro (critique 2026-08-07: retry na família positive). */
  color: var(--acc-ink);
  background: transparent;
  border: var(--bs-border-width) solid var(--acc);
  border-radius: var(--bi-radius-sm);
  cursor: pointer;
  transition: background var(--bi-transition-fast), color var(--bi-transition-fast);
}

.state-error__botao-retry:hover {
  background: var(--acc);
  color: var(--bi-text-on-accent);
}

.state-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap:var(--bi-space-sm);
  padding:var(--bi-space-2xl) var(--bi-space-md);
  text-align: center;
  color: var(--bi-text-muted);
  font-size: var(--bi-fs-body);
}

/* Canonical empty state inside a table body — see biUtils.mostrarEmptyLinha */
.state-empty-row {
  text-align: center;
  color: var(--bi-text-muted);
  font-size: var(--bi-fs-body);
  padding:var(--bi-space-lg) var(--bi-space-md);
}
/* ── Badge de frescor ("atualizado em X") — dot + texto ──────────────────────
   Compartilhado; substitui .gc-fresh/.mi-fresh page-scoped. */
.fresh { display: inline-flex; align-items: center; gap:0.25rem; font-size: var(--bi-fs-caption); color: var(--bi-text-secondary); }
.fresh[hidden] { display: none; }
.fresh__dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--positive-text); flex-shrink: 0; }

/* ── Mercado de Importação — específico da tela ──────────────────────────────
   Rebranding como "briefing competitivo" (inspiração: o deck de preços Logcomex
   FOUR×AWA×South Service): masthead do relatório → veredito de preço (a tese) →
/* ── Masthead: identidade do relatório (produto em display condensado) + faixa
   de tamanho do mercado como antetítulo. Substitui a antiga banda de 6 KPIs que
   "parecia planilha": aqui os totais são contexto editorial.
   O seletor desta regra foi perdido — a linha acima abria comentário sem fechar
   e engolia tanto o nome do seletor quanto as declarações (display/flex-wrap/
   padding-bottom/border-bottom), que nunca foram parseadas. Órfãs, removidas. */

/* Rótulos de banda: agrupam a estrutura do mercado abaixo do veredito competitivo
   (Quem importa → De onde vem). Espaçamento generoso no topo cria a hierarquia
   (sem régua/borda — a linha dura é o tell do ERP legado que rejeitamos). Mesma
   convenção page-scoped por página. */

/* ==========================================================================
   23. ACCESSIBILITY
   ========================================================================== */

.pill:focus-visible,
.state-error__botao-retry:focus-visible,
:is(.command-bar,
.secondary-bar) .pill:focus-visible{
  outline: 2px solid var(--positive);
  outline-offset: 2px;
}

/* drill-down rows are now keyboard-operable (role=button + tabindex via JS);
   give them the same focus ring instead of the black UA default. */
.seg-row:focus-visible,
[data-canal]:focus-visible {
  outline: 2px solid var(--positive);
  outline-offset: -2px;
  border-radius: var(--bs-border-radius-lg);
}

/* controls that previously had no visible keyboard focus (WCAG 2.4.7):
   icon buttons, modal close, map sort toggles, keyboard-operable map ranking
   rows, cockpit's quiet drill-down triggers (dropping .btn-link to de-blue
   them also dropped Bootstrap's --bs-btn-focus-shadow-rgb ring). */
.btn-icon:focus-visible,
#mapa-sort-desc:focus-visible,
#mapa-sort-asc:focus-visible,
.cockpit-drill-btn:focus-visible {
  outline: 2px solid var(--positive);
  outline-offset: 2px;
}
.mapa-ranking__item:focus-visible {
  outline: 2px solid var(--positive);
  outline-offset: -2px;
  border-radius: var(--bs-border-radius);
}

/* visually-hidden, screen-reader-only (table captions, etc.) */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding:0; margin:-0;
  overflow: hidden; clip: rect(0, 0, 0, 0);
  white-space: nowrap; border: 0;
}

/* ==========================================================================
   24. ANIMATIONS
   ========================================================================== */

@keyframes bi-fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes bi-slideUp {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* @keyframes bi-shimmer removido — sem consumidores (skeleton unificado no Bootstrap). */

/* ==========================================================================
   26. DRE TOGGLE RESUMIDO/DETALHADO
   ========================================================================== */

/* ==========================================================================
   27. MAPA DE FATURAMENTO POR ESTADO
   ========================================================================== */

.mapa {
  display: grid;
  grid-template-columns: 3fr 2fr;
  gap:var(--bi-space-lg);
  align-items: stretch;
}

/* map column fills the card height so the choropleth is tall (not a wide-short
   strip) at full width; the legend is docked over the map's bottom-left as a
   compact chip (não mais uma barra solta de largura total abaixo do mapa). */
.mapa__map-col {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.mapa__map-wrap {
  flex: 1 1 auto;
  min-height: 17.5rem;
  border-radius: var(--bi-radius-md);
  overflow: hidden;
  /* Cria CONTEXTO DE EMPILHAMENTO. Sem ele, os panes do Leaflet (z-index 400) e
     seus controles (1000) são resolvidos contra a raiz da página e cobrem a
     topbar: dropdowns de filtro e o calendário do flatpickr abrem por baixo do
     mapa. `overflow:hidden` NÃO cria contexto — `position` + `z-index`
     numérico criam. Corrige /faturamento/ pelo mesmo caminho. */
  position: relative;
  /* z-index:0 + position:relative = SC deliberado: confina panes Leaflet (400) e
     controls (1000) abaixo do conteúdo. NÃO remover position/z — reabre o vazamento. */
  z-index: 0;
  /* Confina as panes do Leaflet (overlayPane z-index 400) num stacking context
     próprio, abaixo do command-bar sticky (z-index 200). Sem isto o choropleth
     pinta sobre os filtros ao rolar a página. */
  isolation: isolate;
}

#mapa-map-wrap.leaflet-container,
#mapa-map-wrap {
  background: var(--bi-bg-surface) !important;
  border-radius: var(--bi-radius-md);
  font-family: var(--bi-font-sans);
}

/* Fullscreen map — class-driven (.is-fullscreen), set by faturamento.js. The
   class (not :fullscreen) carries the layout so it works on every device incl.
   iOS Safari, where the Fullscreen API can't target a <div>. #card-mapa IS the
   FCDS .card (no descendant .cardbox / .cardbox__body); it holds .card-hd + .mapa. */
#card-mapa.is-fullscreen {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  margin:0;
  width: auto;
  height: auto;
  max-width: none;
  border-radius: 0;
  display: flex;
  flex-direction: column;
  background: var(--bi-bg-surface);
  padding:var(--bi-space-md);
  overflow: hidden;
}

#card-mapa.is-fullscreen .mapa {
  flex: 1;
  min-height: 0;
  align-items: stretch;
}

#card-mapa.is-fullscreen .mapa__map-wrap {
  height: 100%;
}

#card-mapa.is-fullscreen .mapa__ranking {
  height: 100%;
  overflow-y: auto;
}

.mapa__tooltip {
  font-size: var(--bi-fs-caption);
  min-width: 10rem;
  line-height: 1.5;
}

.mapa__tooltip-uf {
  font-weight: var(--bi-fw-bold);
  font-size: var(--bi-fs-body);
  margin-bottom:var(--bi-space-3xs);
}

.mapa__pills {
  display: flex;
  gap:var(--bi-space-xs);
  margin-bottom:var(--bi-space-md);
}

.mapa__ranking {
  display: flex;
  flex-direction: column;
  gap:var(--bi-space-2xs);
  overflow-y: auto;
}

.mapa-ranking__item {
  display: flex;
  align-items: center;
  gap:var(--bi-space-xs2);
  min-width: 0;
}

.mapa-ranking__uf {
  width: 1.5rem;
  flex-shrink: 0;
  font-weight: var(--bi-fw-semibold);
  font-size: var(--bi-fs-caption);
  color: var(--bi-text-primary);
  text-align: right;
}

/* ── Barra de proporção ──────────────────────────────────────────────────────
   Trilho + preenchimento com largura em %. Componente compartilhado: três telas
   (contas-a-receber, inadimplência, mapa) escreviam a sua com os MESMOS tokens
   (--line-2, radius -sm) divergindo só em altura, cor e duração da transição —
   divergências que ninguém decidiu, resultado de terem sido escritas em dias
   diferentes por quem não sabia da outra.

   NÃO cobre `.mx-h2h__track` nem `.mb-cell__bar`: essas duas montam sobre o
   `.progress` do Bootstrap e só o tematizam. Já são reuso; trocá-las por CSS
   próprio andaria para trás.

   Calibragem por custom property, não por classe modificadora — a altura e a
   cor variam por chamador, e criar `.barra--fina`/`.barra--verde` só moveria o
   problema para o nome. */
.barra {
  height: var(--barra-altura, 0.25rem);
  background: var(--line-2);
  border-radius: var(--bs-border-radius-sm);
  position: relative;
  min-width: 0;
}
/* Valor NEGATIVO num ranking: mesma magnitude, sentido contrário. Ancorada à
   direita e listrada — a cor continua a mesma de propósito, porque valência
   nunca é só cor (chart-config.js:145) e quem carrega o sinal é o número ao
   lado; a barra carrega a direção. */
.barra__fill--contra {
  margin-left: auto;
  background-image: repeating-linear-gradient(
    -45deg, transparent 0 3px, rgba(255, 255, 255, 0.55) 3px 6px);
}

.barra__fill {
  height: 100%;
  max-width: 100%;
  border-radius: inherit;
  background: var(--barra-cor, var(--command));
  /* 0,4s: as três divergiam (0,5s / 300ms / nenhuma). Um valor só, no meio. */
  transition: width 0.4s ease;
}

.mapa-ranking__bar-wrap { --barra-altura: 0.5rem; flex: 1; overflow: hidden; }

/* ranking rows are now a keyboard-operable proxy for the choropleth */
.mapa-ranking__item {
  cursor: pointer;
  padding:0 0.25rem;
  border-radius: var(--bs-border-radius);
  transition: background .12s;
}
.mapa-ranking__item:hover { background: var(--bi-bg-hover); }
.mapa-ranking__rank {
  width: 1.625rem; flex-shrink: 0; text-align: right; white-space: nowrap;
  font-family: var(--bi-font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--bi-fs-caption); color: var(--bi-text-muted);
}
.mapa-ranking__share {
  width: 2.625rem; flex-shrink: 0; text-align: right;
  font-family: var(--bi-font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--bi-fs-caption); color: var(--bi-text-muted);
}

/* metric colour legend for the choropleth (added for WCAG 1.4.1) */
/* map loading / empty / error overlay — covers the map area only (sibling of the
   map-wrap inside the position:relative map-col). Map-shaped, not a generic block. */
.mapa__state {
  position: absolute; inset: 0; z-index: 520;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap:var(--bi-space-sm); padding:var(--bi-space-lg);
  background: var(--bi-bg-surface);
  border-radius: var(--bi-radius-md);
  text-align: center;
}
.mapa__state[hidden] { display: none; }
/* Forma orgânica do loader do mapa; a pulsação vem do Bootstrap .placeholder-glow
   (mapa.js adiciona .placeholder a este elemento) — sem @keyframes mapa-shimmer. */
.mapa__state-skel {
  width: min(62%, 300px); aspect-ratio: 1 / 1; border-radius: 50% 46% 48% 52% / 44% 50% 50% 56%;
  background: var(--line-2);
}
.mapa__state-cap { font-size: var(--bi-fs-caption); color: var(--bi-text-muted); display: flex; align-items: center; gap:0.25rem; }
.mapa__state-msg { display: flex; flex-direction: column; align-items: center; gap:0.5rem; color: var(--bi-text-secondary); font-size: var(--bi-fs-body); max-width: 18.75rem; }
.mapa__state-msg i { font-size: 1.5rem; color: var(--bi-text-muted); }

.mapa__state-retry {
  margin-top:0.25rem; padding:0.25rem 0.5rem; border: var(--bs-border-width) solid var(--bi-border-color);
  border-radius: var(--bi-radius-sm); background: var(--bi-bg-surface);
  font-size: var(--bi-fs-caption); font-weight: var(--bi-fw-semibold); color: var(--bi-text-secondary); cursor: pointer;
}
.mapa__state-retry:hover { background: var(--bi-bg-hover); }

/* docked over the map (bottom-left), compact chip — not a full-width orphan bar */
/* Docked as a slim horizontal strip BELOW the map (in flow), not an absolute overlay:
   the overlay covered the populated south (SP/RS/SC/PR) and clipped the max value.
   Row layout wraps gracefully and gives the mono numbers room. */
.mapa__legend {
  display: flex; flex-flow: row wrap; align-items: center;
  gap:0.25rem var(--bi-space-md);
  margin-top:var(--bi-space-xs2);
  padding:0;
  font-size: var(--bi-fs-caption);
}
.mapa__legend[hidden] { display: none; }
.mapa__legend-title { font-weight: var(--bi-fw-semibold); color: var(--bi-text-secondary); }
.mapa__legend-scale { display: flex; align-items: center; gap:0.25rem; }
.mapa__legend-ramp { flex: 1; min-width: 6rem; height: 0.5rem; border-radius: var(--bs-border-radius-sm); border: var(--bs-border-width) solid var(--bi-border-color); }
.mapa__legend-min, .mapa__legend-max { font-family: var(--bi-font-mono); color: var(--bi-text-muted); white-space: nowrap; }
.mapa__legend-nodata { display: inline-flex; align-items: center; gap:0.25rem; color: var(--bi-text-muted); }
.mapa__legend-swatch { width: 0.75rem; height: 0.75rem; border-radius: var(--bs-border-radius-sm); border: var(--bs-border-width) solid var(--bi-border-color); display: inline-block; flex-shrink: 0; }

.mapa-ranking__valor {
  flex-shrink: 0;
  font-size: 0.875rem;
  font-family: var(--bi-font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--bi-text-secondary);
  text-align: right;
  min-width: 3rem;
}

/* ==========================================================================
   29. TABELA FATURAMENTO POR SEGMENTO (Visão Operacional)
   ========================================================================== */

/* .table.table-sm do Bootstrap; sobra o corpo tipográfico da tela. */
.seg-table { font-size: var(--bi-fs-caption); }

.seg-table thead th {
  padding:var(--bi-space-xs2) 0.5rem;
  font-family: var(--bi-font-display);
  font-size: var(--bi-fs-label);
  font-weight: var(--bi-fw-semibold);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--bi-text-secondary);
  border-bottom: 2px solid var(--line);
  white-space: nowrap;
  background: var(--bi-surface-card);
}

.seg-row td {
  padding:var(--bi-space-sm) 0.5rem;
  border-bottom: var(--bs-border-width) solid var(--line);
  vertical-align: middle;
}

.seg-row:last-child td {
  border-bottom: none;
}

.seg-row:hover td {
  background: var(--surf-2);
}

.seg-name {
  font-family: var(--bi-font-display);
  font-weight: var(--bi-fw-semibold);
  font-size: var(--bi-fs-body);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--bi-text-primary);
  white-space: nowrap;
}

/* .progress do Bootstrap; só a geometria (altura fina, largura máx, raio) fica
   aqui — width e cor da barra (.progress-bar) são data-driven por linha (JS). */
.seg-progress {
  height: 0.1875rem;
  max-width: 6.25rem;
  --bs-progress-bg: var(--line-2);
  --bs-progress-border-radius: var(--bs-border-radius-sm);
}

/* Linha TODOS */
.seg-todos .seg-name {
  font-weight: 700;
}

.seg-todos td {
  border-bottom: 2px solid var(--line);
  background: var(--surf-2);
}

/* ==========================================================================
   30. TABELA UN — SELEÇÃO PARA CASCATA DE MARGENS
   ========================================================================== */

.seg-row {
  cursor: pointer;
}

.seg-row:hover td {
  background: var(--surf-2);
}

/* Hint no cabeçalho da tabela UN */

/* ==========================================================================
   31. RESPONSIVE
   ========================================================================== */

/* ── Mobile: command bar não é sticky + Row 1 não quebra linha ────────────
   Breakpoint 767.98px = Bootstrap md − 0.02 (alinha com d-md-none/d-md-flex).
   Estender position:static até aqui evita o bloco sticky em landscape phone. */
@media (max-width: 767.98px) {
  /* Row 1 (título + período + buscar + filtros) não pode quebrar linha:
     6 colunas sticky + elementos de controle já consomem toda a tela.
     overflow-x:auto garante acesso sem layout quebrado. */
  .command-bar__filters > .command-bar__row:not(.command-bar__row--colapsavel) {
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .command-bar__filters > .command-bar__row:not(.command-bar__row--colapsavel)::-webkit-scrollbar {
    display: none;
  }

  /* Título pode encolher para caber ao lado dos controles */

  /* Rows 2–3 (UN + Sub-seg): ocultas por padrão, abertas pelo botão "Filtros" */
  .command-bar__row--colapsavel {
    display: none;
  }
  .command-bar__row--colapsavel.is-show {
    display: flex;
  }
}

/* ── Viewport baixo (landscape phone): barra de filtros não pode comer a tela ─
   Celular deitado é largo (>768px → layout desktop) mas baixo (~390px). A barra
   desktop (grade multi-ano + UN + sub-segmento) chega a 92% da altura e, sticky,
   nunca sai de cena. Aqui tiramos o sticky e damos teto + scroll interno, sem
   tocar markup nem as classes d-md-* (que são por largura). */

@media (max-width: 576px) {
  .command-bar__filters {
    gap:var(--bi-space-xs);
  }

  /* Esconder labels de filtro — pills são autoexplicativas */
  .filter-group__label {
    display: none;
  }

  /* Título redundante em portrait phone — aba do browser já identifica a página */

  /* ── DataTables toolbar: stack vertical, search ocupa largura total ─────── */
  .datatable .datatable-toolbar {
    flex-direction: column;
    align-items: stretch;
    gap:var(--bi-space-xs);
  }
  .datatable .datatable-toolbar__right {
    display: flex;
    gap:var(--bi-space-xs);
  }
  /* Length select ("Mostrar N entradas") irrelevante em mobile — esconder */
  .datatable .dataTables_length {
    display: none;
  }
  .datatable .dataTables_filter {
    flex: 1;
  }
  .datatable .dataTables_filter label {
    display: flex;
    width: 100%;
    white-space: normal;
  }
  .datatable .dataTables_filter input {
    flex: 1;
    min-width: 0 !important;
    width: 100% !important;
  }
  /* Bottom bar: info + paginação empilhados */
  .datatable .datatable-bottom {
    flex-direction: column;
    align-items: flex-start;
    gap:var(--bi-space-xs);
    padding:var(--bi-space-xs) var(--bi-space-sm);
  }
  /* ─────────────────────────────────────────────────────────────────────── */

  .kpi-band {
    grid-template-columns: 1fr 1fr;
    margin:0 0 var(--bi-space-md);
  }

  .section-anchor {
    margin:var(--bi-space-lg) var(--bi-space-sm) var(--bi-space-sm);
  }
}

/* ==========================================================================
   26. ESTOQUE — Drill panels, badges, treemap interativo
   ========================================================================== */

/* Badge entrada/saída (movimentos) — Entrada/Saída is a record TYPE, not a value
   direction, so these carry no direction hue (neutral, per Step 3 contract). */

/* Badges de cobertura (risco visual): canonical .badge--success/danger/warning/info
   already defined above (~L725) with identical tokens — duplicate block removed. */

/* Drill panels — slide-in, agora .card (bg/border/radius/sombra do primitivo +
   .card-accent-start p/ a faixa dinâmica; .card-header/.card-body no template
   cobrem o cabeçalho/corpo, ver movimentacao.js). Residual: a animação de
   entrada e a margem entre painéis (sem primitiva Bootstrap p/ nenhum dos 2). */
.drill-panel {
  animation: biDrillSlideIn 300ms ease-out both;
  margin:var(--bi-space-sm) var(--bi-space-lg);
}

.drill-panel__titulo {
  font-family: var(--bi-font-display);
  font-size: var(--bi-fs-label);
  font-weight: var(--bi-fw-semibold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bi-text-secondary);
}

@keyframes biDrillSlideIn {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Drill breadcrumb — botão voltar */
.drill-back {
  cursor: pointer;
  color: var(--bi-text-secondary);
  font-family: var(--sans);
  font-size: var(--bi-fs-label);
  font-weight: var(--bi-fw-medium);
  background: none;
  border: none;
  padding:0;
  transition: color var(--bi-transition-fast);
}
.drill-back:hover { color: var(--bi-text-primary); }
.drill-back > i { font-size: .75em; margin-right: .15rem; }
/* Variante de ACENTO. O `.drill-back` padrão nasce em tinta fraca porque vive
   dentro de um drill, onde já há um título forte ao lado. Quando ele é o
   PRIMEIRO controle de uma superfície — a saída de uma tela de trabalho — a
   tinta fraca o faz ler como desabilitado. Aqui ele é um caminho, e caminho tem
   a cor do acento. */
.drill-back--acento { color: var(--acc-ink); font-weight: 600; }
.drill-back--acento:hover { color: var(--acc); }
.drill-back--acento:focus-visible { outline: 2px solid var(--acc); outline-offset: 2px; border-radius: var(--r-sm); }

/* Drill close button */
.drill-close {
  cursor: pointer;
  background: none;
  border: none;
  color: var(--bi-text-muted);
  font-size: 1rem;
  line-height: 1;
  padding:var(--bi-space-3xs);
  border-radius: var(--bi-radius-sm);
  transition: color var(--bi-transition-fast), background var(--bi-transition-fast);
}
.drill-close:hover {
  color: var(--negative-text);
  background: var(--negative-subtle);
}

/* Table row clicável (drill) */
.row-clickable {
  cursor: pointer;
  transition: background var(--bi-transition-fast);
}
.row-clickable:hover {
  background: var(--bi-bg-hover);
}

.row-clickable:active td {
  background: var(--bi-bg-active);
}

/* Drill hint — instrução progressiva no L0 */
.drill-hint {
  font-size: var(--bi-fs-caption);
  color: var(--bi-text-muted);
  text-align: center;
  padding:var(--bi-space-xs) 0;
  min-height: 1.5em;
  transition: opacity var(--bi-transition-fast);
}

/* Barra secundária de controles (período / toggles / busca) — já era a receita
   exata do .card (glass/sh-glass = surf/none, ver tokens), então virou
   .card.card-body + utilities Bootstrap direto no template (d-flex/flex-row/
   align-items-center/gap-2/flex-wrap/mb-3). Zero residual: a classe
   `.secondary-bar` só permanece na marcação porque `:is(.command-bar,
   .secondary-bar) .pill` (acima) e a regra mobile de `.vr` (abaixo) a usam
   como seletor ancestral. */

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
  .drill-panel { animation: none; }
}

/* ==========================================================================
   25. RESPONSIVE (original section continues)
   ========================================================================== */

@media (max-width: 768px) {
  .kpi-band {
    grid-template-columns: repeat(2, 1fr);
    margin:0 0 var(--bi-space-md);
  }

  /* MOBILE: step KPI numbers down + let grid cells shrink, so values stop
     clipping the cell edge (hero was 3rem / secondary 2rem — far too large in a
     ~185px cell). Page-agnostic: helps every .kpi-band page at once. */
  .kpi-band__cell { min-width: 0; }

  /* divisor vertical do topbar de filtros (Bootstrap .vr): esconder quando
     a linha quebra (flex-wrap) — evita traço solto entre grupos empilhados. */
  .command-bar__row .vr,
  .secondary-bar .vr {
    display: none;
  }
}

@media (max-width: 1200px) {
  .kpi-band {
    grid-template-columns: 1.2fr 1.4fr 1fr 1fr;
  }
}

/* MOBILE: the multi-col KPI band variants (5/4/3-col, used by estoques /
   inadimplencia / despesas_comex / fluxo via _kpi_cell.html) must ALSO collapse
   to 2-col on phones. Without this they kept their desktop column count at 390px
   and the secondary cells overlapped ("LIBERADOBLOQUEADO"). Placed after the
   ≤1200 block so it wins by source order. */

/* ==========================================================================
   26. FATURAMENTO — scoped overrides
   All rules here are gated by [data-pagina="faturamento"] so they do not
   leak to sister BI pages. See plan: /root/.claude/plans/inherited-toasting-kahn.md
   ========================================================================== */

/* --- Card header density --- */
.page[data-pagina="faturamento"] .card-header {
  padding:var(--bi-space-xs2) var(--bi-space-md);
}

/* --- Linha TOTAL da tabela de sub-segmento ---
   `.table-group-divider` do Bootstrap desenha uma régua de 2px no topo do
   <tfoot>, e a linha de total encostava nela com inset 0. A folga vai na
   classe própria `.fcds-tot` (emitida por faturamento-fcds.js) em vez de no
   `.table-group-divider`, que é do Bootstrap e serve outras páginas. */
.page[data-pagina="faturamento"] .fcds-tot > tr > * {
  padding-top:var(--bi-space-xs);
}

/* Sinais Operacionais: o override de .kpi-tile que morava aqui morreu junto
   com a classe (nenhum markup vivo — ver a nota na seção 7). */

/* --- Evolução Temporal: tighten chart heights --- */
.page[data-pagina="faturamento"] [data-bi-section="evolucao-faturamento"] .chart--short {
  height: 13.75rem;
}
.page[data-pagina="faturamento"] [data-bi-section="evolucao-margem"] .chart--short {
  height: 10rem;
}

/* --- Top Produtos: chart fills the row height (driven by the Evolução stack),
       no fixed cap → no dead whitespace. See the flex-fill block below. --- */

/* --- Top Clientes + Mapa: the data-bi-section element IS the FCDS .card
       (card-hd + content). Height-bounded in block (f); make both flex columns so
       the list / map+ranking fill or scroll within — no dead whitespace, equal
       heights. --- */
.page[data-pagina="faturamento"] [data-bi-section="mapa-uf"] {
  display: flex;
  flex-direction: column;
}
.page[data-pagina="faturamento"] [data-bi-section="mapa-uf"] > .mapa {
  flex: 1 1 auto;
  min-height: 0;
}
.page[data-pagina="faturamento"] [data-bi-section="mapa-uf"] .mapa {
  grid-template-columns: 2fr 1fr;
}

/* --- Mapa por Estado: responsive header wrap --- */
.page[data-pagina="faturamento"] .mapa__header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap:var(--bi-space-sm) var(--bi-space-md);
}

.page[data-pagina="faturamento"] .mapa__controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap:var(--bi-space-sm);
  margin-left:auto;
}

@media (max-width: 991.98px) {
  .page[data-pagina="faturamento"] .mapa__controls {
    margin-left:0;
    width: 100%;
    justify-content: flex-start;
  }
  .page[data-pagina="faturamento"] .mapa__actions {
    margin-left:auto;
  }
}

/* :hover base removido — 100% coberto pela def global (5495: color !important) */

/* Canonical active indicator: accent-soft pill (not an underline).
   color/background movidos p/ def global !important (5496); só border-radius sobrevive. */

/* ============================================================
   Contas a Receber — Treasury Board
   ============================================================ */

/* KPI band -------------------------------------------------- */
/* O tape de 3 pilares virou a row de cartões canônica do app (Bootstrap
   .row > .col > .card, igual a despesas/faturamento) — layout, empilhamento no
   mobile e valência de cor saem de utilities. A antiga `.cr-chart-band` (15rem)
   existia porque nenhum degrau da escala canônica servia; hoje a altura sai do
   nº de buckets via biChartConfig.alturaPorCategoria, e a classe saiu. */

/* Board ----------------------------------------------------- */
.cr-board {
  display: flex;
  flex-direction: column;
  gap:0;
}

/* Row ------------------------------------------------------- */
.cr-row {
  display: grid;
  grid-template-columns: 16.25rem 1fr 10rem;
  align-items: center;
  padding:0.5rem var(--bi-space-md);
  border-bottom: var(--bi-border-subtle);
  background: var(--bi-bg-surface);
  transition: background 0.1s;

  animation: cr-row-enter 0.25s ease both;
  animation-delay: calc(var(--i, 0) * 35ms);
}

@keyframes cr-row-enter {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .cr-row { animation-duration: 0ms !important; }
}

.cr-row:hover { background: var(--surf-2); }

/* Direção da linha por TINTA DE FUNDO da família (-subtle), não faixa
   lateral (banimento — DESIGN.md §6). O rgba esmeralda hardcoded que vivia
   aqui saiu junto: valência só via token. Hover (.cr-row:hover) vence e
   vira feedback — a direção continua no rótulo da linha. */
.cr-row--abaixo  { background: var(--negative-subtle); }
.cr-row--acima   { background: var(--positive-subtle); }

/* Identity column */
.cr-row__identity { min-width: 0; }

.cr-row__name-wrap {
  display: flex;
  align-items: center;
  gap:var(--bi-space-xs2);
}

.cr-row__name {
  font-family: var(--bi-font-display);
  font-size: 1rem;
  font-weight: 600;
  color: var(--command);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cr-row__meta {
  font-family: var(--bi-font-mono);
  font-size: 0.875rem;
  color: var(--bi-text-muted);
  margin-top:var(--bi-space-3xs);
  font-variant-numeric: tabular-nums;
}

/* Visual column */
.cr-row__visual { padding:0 var(--bi-space-md); }

.cr-row__valor {
  font-family: var(--bi-font-mono);
  font-size: 1rem;
  font-variant-numeric: tabular-nums;
  color: var(--command);
  margin-bottom:0.25rem;
}

.cr-row__meter-wrap {
  position: relative;
  margin-top:var(--bi-space-3xs);
  height: 0.25rem;
}

/* Extras da tela sobre a .barra compartilhada: o marcador de estouro e o
   rótulo de mínimo, que só o ranking de portadores tem. */
.cr-row__meter { --barra-altura: 0.25rem; --barra-cor: var(--positive-text); overflow: visible; }

.cr-row__meter[data-overflow="true"]::after {
  content: '';
  position: absolute;
  right: -2px;
  top: -2px;
  bottom: -2px;
  width: 0.125rem;
  background: var(--positive-text);
  border-radius: 0 var(--bs-border-radius-sm) var(--bs-border-radius-sm) 0;
}

.cr-row__meter-label {
  position: absolute;
  right: 0;
  top: -14px;
  font-family: var(--bi-font-mono);
  font-size: 0.875rem;
  color: var(--bi-text-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* Status column */
.cr-row__status { text-align: right; }

.cr-row__diff {
  display: block;
  font-family: var(--bi-font-display);
  font-size: 1rem;
  font-weight: 600;
  margin-top:var(--bi-space-3xs);
  font-variant-numeric: tabular-nums;
}

.cr-row__diff--acima  { color: var(--positive-text); }
.cr-row__diff--abaixo { color: var(--negative-text); }

/* Toggle Vencimentos (Não desc. ↔ Descontado) — variante azul, não vermelha */

/* Chart subtitle */
.cr-chart-subtitle {
  font-family: var(--bi-font-mono);
  font-size: 0.875rem;
  color: var(--bi-text-muted);
  letter-spacing: 0.04em;
  margin-top:0;
}

/* Row valor display with filho breakdown */
.cr-row__valor-wrap {
  display: flex;
  align-items: baseline;
  gap:var(--bi-space-sm);
  margin-bottom:0;
}

.cr-row__valor {
  font-family: var(--bi-font-mono);
  font-size: 1rem;
  font-variant-numeric: tabular-nums;
  color: var(--command);
}

.cr-row__valor-proprio {
  font-family: var(--bi-font-mono);
  font-size: 0.875rem;
  font-variant-numeric: tabular-nums;
  color: var(--bi-text-muted);
}

/* ============================================================
   Contas a Receber — Layout Containment (proportion refactor)
   ============================================================ */

/* A barra de participação tem teto PRÓPRIO: é limite de componente (uma barra
   de 1.500px não comunica proporção melhor que uma de 480px), não de página.
   Nada mais capa largura — a tela ocupa o espaço disponível. */
.cr-row__meter-wrap {
  max-width: 30rem;
}

/* Títulos a vencer: a grade embaixo do painel, como Produtos e Previsão de
   caixa — sem cartão em volta (dono, 15/09/2026: sem moldura), a folha branca e
   o bloco da grade na altura da janela, para só as linhas rolarem. */
.content:has(> .page[data-pagina="contas_a_receber"]),
.page[data-pagina="contas_a_receber"] { background: #fff; }
.page[data-pagina="contas_a_receber"] .cr-titulos {
  display: flex; flex-direction: column; height: calc(100dvh - 52px); min-height: 420px;
}
/* Teto nas colunas de texto livre: sem ele Representante e Cliente abriam até
   caber o nome inteiro (600px) e a lista rolava o dobro de lado. */
.page[data-pagina="contas_a_receber"] .cr-col-texto { max-width: 12rem; }

/* ============================================================
   Contas a Pagar — grade da casa
   ============================================================ */

/* Mesmo teto do gêmeo Contas a Receber: sem ele Fornecedor e Observação
   abririam até caber o texto inteiro e a lista rolaria de lado. */
.page[data-pagina="contas_a_pagar"] .cp-col-texto { max-width: 12rem; }

/* ============================================================
   Inadimplência — grade da casa (Títulos em Aberto)
   ============================================================ */

/* Mesmo teto dos gêmeos Contas a Pagar/Receber: sem ele Cliente, Representante
   e Observação abririam até caber o texto inteiro e a lista rolaria de lado. */
.page[data-pagina="inadimplencia"] .in-col-texto { max-width: 12rem; }

/* A lista rola DENTRO do cartão. O `max-height: none` da grade é para a tela
   que É a lista (Pedidos, Notas); aqui há o painel de aging e os cartões acima,
   e sem teto os 344 títulos viravam uma página de 13.900px — ninguém alcança o
   pé. Mesmo teto de qualquer lista dentro de cartão. */
.page[data-pagina="inadimplencia"] .grade .datatable-scroll {
    max-height: var(--bi-dt-scroll-cap);
}

/* Atraso em vermelho: toda linha aqui já está vencida — a cor escala a
   urgência de cobrar, o mesmo token de severidade que o Aging já usa nesta
   página (--negative-text). */
.page[data-pagina="inadimplencia"] .in-col-atraso {
    color: var(--negative-text);
    font-weight: 600;
}

/* ============================================================
   DESPESAS FINANCEIRAS (PSQ014)
   ============================================================ */

.df-venc--perigo {
    color: var(--negative-text);
    font-weight: 600;
}
.df-venc--aviso {
    color: var(--warning-text);
    font-weight: 600;
}
/* Mapa de cor semântica: perigo->danger, aviso->warning, neutro->info,
   primary->primary. Emitters re-classed in despesas_comex.js. */

/* Refresh button spinner state */
.btn-icon--loading i {
    animation: bi-spin 1s linear infinite;
}
@keyframes bi-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
    .btn-icon--loading i { animation: none; }
}

/* Despesas — doughnut + legenda: deixa a legenda quebrar/encolher no mobile para a
   coluna de % não cortar. (Veio do <style> inline do template, removido na migração
   do KPI band para cards Bootstrap.) */
@media (max-width: 768px) {
    /* legenda do doughnut (despesas + despesas_logistica usam os mesmos IDs) */
    #bi-distribuicao-container { flex-wrap: wrap; }
    #bi-distribuicao-legenda { min-width: 0; font-size: 0.875rem; }
}

/* Override KPI band: 4 colunas iguais (vs default 7) — evita overflow em 1024 */
[data-pagina="despesas_comex"] .kpi-band {
    grid-template-columns: repeat(5, 1fr);
}

@media (max-width: 992px) {
    [data-pagina="despesas_comex"] .kpi-band {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* Painel de progresso determinado (df-progress) — substitui o loader durante o
   pipeline longo do despesas_comex; construído sobre .logo-loader. Consumidor
   único → namespaced global .df-progress* (sem escopo de página). */
.df-progress {
    position: absolute;
    inset: 0;
    z-index: 20;
    background: var(--bi-bg-surface);
    border-radius: var(--bi-radius-md);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    gap:var(--bi-space-sm);
    padding:clamp(3rem, 8vh, 3rem) var(--bi-space-lg);
    text-align: center;
}
.df-progress__logo-wrap {
    position: relative;
    width: clamp(120px, 22vw, 220px);
    aspect-ratio: 2048 / 342;
}
.df-progress__logo-wrap .logo-loader__base,
.df-progress__logo-wrap .logo-loader__mask {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}
.df-progress__title {
    font-family: var(--bi-font-display);
    font-size: var(--bi-fs-heading);
    font-weight: var(--bi-fw-bold);
    color: var(--bi-text-primary);
    letter-spacing: 0.02em;
    text-transform: uppercase;
    margin-top:var(--bi-space-sm);
}
.df-progress__message {
    font-size: 1rem;
    color: var(--bi-text-secondary);
    min-height: 1.2em;
    transition: opacity 0.2s;
}
.df-progress__logo-wrap .logo-loader__fill[data-determinate="true"] {
    animation: none;
    transition: width 0.4s ease;
}
.df-progress__meta {
    display: flex;
    gap:var(--bi-space-md);
    font-size: 0.875rem;
    color: var(--bi-text-muted);
    font-variant-numeric: tabular-nums;
    margin-top:var(--bi-space-xs);
}
.df-progress__hint {
    font-size: 0.875rem;
    color: var(--bi-text-muted);
    font-style: italic;
    margin-top:var(--bi-space-sm);
    max-width: 23.75rem;
    line-height: 1.4;
}

/* ── Drawer Lote Atual (despesas comex) ────────────────────────────── */
#df-lote-drawer {
  --bs-offcanvas-width: 22.5rem;
}

/* Células de estado por linha (favorito/borderô/pago) — consumidor único
   despesas_comex → namespaced global .df-col-*. */
.df-col-favorito,
.df-col-bordero,
.df-col-pago {
    white-space: nowrap;
    min-width: 2.5rem;
    text-align: center;
}
.df-col-bordero .form-check-input,
.df-col-pago .form-check-input {
    cursor: pointer;
    width: 1rem;
    height: 1rem;
    margin:0;
}
.df-col-bordero .form-check-input:disabled,
.df-col-pago .form-check-input:disabled {
    cursor: default;
}

/* Botão estrela de favorito (df-btn-fav) — consumidor único → global. */
.df-btn-fav {
    background: none;
    border: none;
    cursor: pointer;
    color: var(--ink-4);
    font-size: 1rem;
    padding:0 var(--bi-space-3xs);
    line-height: 1;
    flex-shrink: 0;
    transition: color 0.15s;
}
.df-btn-fav:hover { color: var(--warning); }
.df-btn-fav:disabled { opacity: 0.5; cursor: default; }
.df-btn-fav.df-fav--ativo { color: var(--warning); }

/* Faturamento NF tables freeze identity-only (Ações·Data·NF) via `.stickcols`.
   Keep horizontal drag from scrolling the page on touch. */
@media (max-width:767.98px) {
  .datatable .datatable-scroll { overscroll-behavior-x: contain; }
}
/* Fluxo Bancário: as tabelas usam o primitivo .stickcols canônico (stick--1/
   stick--edge no JS) — border-collapse, offset, divisor, hover, striped e
   total-row vêm todos de lá. Sem regras de coluna congelada por página. */
/* Cor semântica de número ± — CANÔNICA e compartilhada. Substitui a cópia
   ad-hoc .fb-num--* (e é a alvo p/ aposentar .delta.pos/neg, .md.pos/neg,
   .sig.neg, .cr-row__diff--*). */
/* `!important` porque isto é UTILITÁRIO, não componente: a convenção do Bootstrap
   para utilitário de cor (.text-danger e cia. também são !important). Sem isso
   qualquer regra de componente declarada DEPOIS no arquivo vencia por ordem de
   fonte — foi o que aconteceu com .pp-card__dias-num, que anulava o semáforo em
   silêncio (sem erro, sem teste vermelho). */
/* ── Rankings com drill (despesas / despesas-logística) ─────────────────────
   Critique 2026-08-07: o alvo de drill era DIV com cursor:pointer e nada mais —
   sem hover, sem foco, sem teclado. O JS agora emite role="button" + tabindex;
   aqui entram o sinal visual de clicável e o preenchimento da barra, que era
   `transition: width` INLINE (propriedade de layout + inalcançável para
   prefers-reduced-motion — estilo inline não responde a media query). */
.top-item{border-radius:var(--r-xs);transition:background .14s ease}
.top-item:hover{background:var(--surf-2)}
.top-item:focus-visible{outline:2px solid var(--acc);outline-offset:2px;background:var(--surf-2)}
.rank-bar__fill{transition:width .5s ease}
@media (prefers-reduced-motion: reduce){ .rank-bar__fill{transition:none} }
/* Linha única de ranking (redesign 2026-08-07) — mesma anatomia do ranking do
   mapa do faturamento: rank e % em mono/tabular, barra fina `.barra` de
   largura fixa (comprimento comparável entre linhas, não entre cards). */
.toplist__rank{width:1.25rem;flex-shrink:0;text-align:right;font-family:var(--bi-font-mono);font-variant-numeric:tabular-nums;font-size:var(--bi-fs-caption);color:var(--bi-text-muted)}
.toplist__share{width:2.875rem;flex-shrink:0;text-align:right;font-family:var(--bi-font-mono);font-variant-numeric:tabular-nums;font-size:var(--bi-fs-caption);color:var(--bi-text-muted)}
.toplist__bar{width:64px;flex-shrink:0}
/* Detalhamento em demonstrativo (redesign 2026-08-07): um card, hierarquia
   por tipografia + indentação — grupo é linha forte com faixa, contas
   indentadas, TOTAL com régua no pé (assinatura de demonstrativo). */
/* Anel hairline: os passos claros da rampa (Gerenciais ~16% de opacidade)
   sumiam no fundo — o anel dá contorno sem trair a cor da legenda. */
.gblo__dot{width:9px;height:9px;border-radius:50%;display:inline-block;flex-shrink:0;box-shadow:inset 0 0 0 1px rgba(15,23,42,.18)}
.dstm__grupo{display:flex;align-items:center;gap:.5rem;padding:.4375rem .625rem;margin-top:.25rem;background:var(--surf-2);border-radius:var(--r-xs);cursor:pointer}
.dstm__grupo:first-child{margin-top:0}
.dstm__grupo:focus-visible{outline:2px solid var(--acc);outline-offset:-2px}
.dstm__grupo-nome{font-size:.8125rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em}
.dstm__grupo-total{margin-left:auto;font-size:1rem;font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap}
.dstm__conta{padding:.5rem 0 .5rem 2.25rem;border-bottom:var(--bi-border);border-radius:var(--r-xs);cursor:pointer;transition:background .14s ease}
.dstm__conta:hover{background:var(--surf-2)}
.dstm__conta:focus-visible{outline:2px solid var(--acc);outline-offset:-2px;background:var(--surf-2)}
.dstm__contas > .dstm__conta:last-of-type{border-bottom:0}
.dstm__valor{font-size:.8125rem;font-weight:600;text-align:right;min-width:4.25rem;flex-shrink:0;font-variant-numeric:tabular-nums}
.dstm__itens{background:var(--surf-2);padding:0 12px 8px;margin-left:2.25rem;border-radius:var(--r-xs)}
.dstm__total{display:flex;justify-content:space-between;align-items:center;gap:1rem;margin-top:.5rem;padding:.5rem .625rem 0;border-top:1px solid var(--ink-2);font-weight:600;font-size:.8125rem;text-transform:uppercase;letter-spacing:.04em}
/* Bloco colapsado: controles do header apontariam para corpo escondido. */
.card.is-colapsado [data-oculta-colapsado]{display:none}
/* Destaques do período: tira de callout por severidade, sem card nem
   cabeçalho — fundo -subtle, título -text, descrição rebaixada na mesma
   linha (Regra do Degrau: fill=área, -text=texto, -subtle=fundo). */
.destaque{display:flex;align-items:baseline;gap:.5rem;padding:.4375rem .75rem;border-radius:var(--r-sm);font-size:.8125rem;background:var(--surf-2)}
.destaque__dot{width:8px;height:8px;border-radius:50%;flex-shrink:0;align-self:center;background:var(--ink-3)}
.destaque__desc{color:var(--bi-text-muted)}
.destaque--negative{background:var(--negative-subtle)}
.destaque--negative .destaque__dot{background:var(--negative)}
.destaque--negative strong{color:var(--negative-text)}
.destaque--warning{background:var(--warning-subtle)}
.destaque--warning .destaque__dot{background:var(--warning)}
.destaque--warning strong{color:var(--warning-text)}
.destaque--positive{background:var(--positive-subtle)}
.destaque--positive .destaque__dot{background:var(--positive)}
.destaque--positive strong{color:var(--positive-text)}
/* Números comparáveis verticalmente pedem dígito tabular (A Regra do Número
   Tabular) — a tela inteira é coluna de número. */
[data-pagina="despesas"]{font-variant-numeric:tabular-nums}
/* Banda da despesas: 5 células .kpic (herói · variação · 3 grupos) no mesmo
   grid .kpi8 do faturamento — o breakpoint de 8 colunas não serve para 5. */
[data-pagina="despesas"] .despesas-band{margin-bottom:0}
@media(min-width:992px){[data-pagina="despesas"] .despesas-band{grid-template-columns:repeat(5,minmax(0,1fr))}}
[data-pagina="despesas"] .kpic .spark-linha{opacity:.85}
/* Micro-barra de composição do herói (Realizado × Não Contabilizado). */
.despesas-compo{height:6px;border-radius: var(--raio-chip);background:var(--surf-2);overflow:hidden;display:flex;margin-top:.4rem}
.despesas-compo > div{height:100%}

.num--pos { color: var(--positive-text) !important; }
.num--neg { color: var(--negative-text) !important; }
/* Faixa de atenção (entre o verde e o vermelho) — mesma laranja dos gráficos, no
   degrau de TEXTO: .num--* pinta número, e o degrau base (3,40:1) só serve p/ área. */
.num--alerta { color: var(--chart-alerta-text) !important; }

/* PORT do Bootstrap 5.3 (o build vendorizado é 5.2.3, onde estes utilitários ainda
   não existem). Nomes e semântica idênticos aos de upstream, alimentados pelos
   tokens --bs-secondary-color/--bs-tertiary-color, que apontam para a escada de
   tinta do FCDS. Existem para que `color: var(--ink-3)` deixe de ser declarado
   dentro de cada componente: são ~99 declarações no arquivo que colapsam em dois
   utilitários. Ao subir para o Bootstrap 5.3, APAGUE este bloco — o upstream passa
   a fornecer as mesmas regras a partir dos mesmos tokens. */
.text-body-secondary { color: var(--bs-secondary-color) !important; }
.text-body-tertiary  { color: var(--bs-tertiary-color) !important; }
/* `.fw-medium` também só existe a partir do 5.3 — sem o port ela é no-op
   SILENCIOSA: a classe entra no HTML, ninguém reclama, e o peso cai para 400. */
.fw-medium { font-weight: 500 !important; }
/* Escalas do 5.3 na íntegra (0–5 = 0/.25/.5/1/1.5/3rem), não só os passos usados
   hoje: utilitário pela metade é no-op silenciosa no primeiro consumidor novo. */
.row-gap-0 { row-gap:0 !important; }
.row-gap-1 { row-gap:0.25rem !important; }
.row-gap-2 { row-gap:0.5rem !important; }
.row-gap-3 { row-gap:1rem !important; }
.row-gap-4 { row-gap:1.5rem !important; }
.row-gap-5 { row-gap:3rem !important; }
.column-gap-0 { column-gap:0 !important; }
.column-gap-1 { column-gap:0.25rem !important; }
.column-gap-2 { column-gap:0.5rem !important; }
.column-gap-3 { column-gap:1rem !important; }
.column-gap-4 { column-gap:1.5rem !important; }
.column-gap-5 { column-gap:3rem !important; }
.overflow-y-auto { overflow-y: auto !important; }
.overflow-y-hidden { overflow-y: hidden !important; }
.overflow-y-visible { overflow-y: visible !important; }
.overflow-y-scroll { overflow-y: scroll !important; }
.overflow-x-auto { overflow-x: auto !important; }
.overflow-x-hidden { overflow-x: hidden !important; }
.overflow-x-visible { overflow-x: visible !important; }
.overflow-x-scroll { overflow-x: scroll !important; }

/* ── .caps-label — micro-rótulo em CAIXA ALTA ────────────────────────────────
   O mesmo rótulo (0.875rem + uppercase + tracking + tinta secundária) está
   escrito 58 vezes neste arquivo, com 12 valores diferentes de letter-spacing:
   cabeçalho de tabela, rótulo de filtro, título de painel, rótulo de KPI…
   Uma peça só, com o tracking parametrizado por `--caps-track` para o caso
   raro em que a densidade do bloco pede outro valor. Peso e cor seguem
   utilitário (`fw-bold`, `text-body-secondary`) quando divergem do padrão. */
.caps-label {
  font-size:0.875rem;
  font-weight: 600;
  line-height: 1.3;
  text-transform: uppercase;
  letter-spacing: var(--caps-track, .04em);
  color: var(--ink-3);
}

/* ════════════════════════════════════════════════════════════════════════
   TD dos bancos — pivot drill-down (conta corrente → conta financeira)
   Linha-pai expansível (negrito + caret), linha-filha indentada, Total Geral
   no rodapé. Fiel ao Excel "TD dos bancos".
   ════════════════════════════════════════════════════════════════════════ */
/* Conta-pai: negrito; expansível = clicável */
.fb-td-conta > td {
    font-weight: var(--bi-fw-semibold);
}
.fb-td-conta--expansivel {
    cursor: pointer;
}
.fb-td-conta--expansivel:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: -2px;
}
/* Caret: reserva largura fixa em todas as contas-pai → rótulos alinhados,
   tenham filhas ou não. Sinal só nas expansíveis: + recolhido, − expandido. */
/* Caret = pílula .drill-plus canônica, dirigida pelo aria-expanded da linha
   (sem JS extra). Linhas-pai não-expansíveis viram espaçador 16px p/ alinhar. */
.fb-td-caret {
    display: inline-flex; align-items: center; justify-content: center;
    width: 1rem; height: 1rem; margin-right:0.35em; vertical-align: middle; flex: 0 0 auto;
}
.fb-td-conta--expansivel .fb-td-caret {
    color: var(--ink-2); cursor: pointer;
}
.fb-td-conta--expansivel:hover .fb-td-caret { color: var(--ink); }
.fb-td-conta--expansivel .fb-td-caret { position: relative; }
.fb-td-conta--expansivel .fb-td-caret::before,
.fb-td-conta--expansivel .fb-td-caret::after {
    content: ""; position: absolute; inset: 0; margin: auto; background: currentColor;
    border-radius: 1px; transition: transform .15s ease;
}
.fb-td-conta--expansivel .fb-td-caret::before { width: 11px; height: 2px; }
.fb-td-conta--expansivel .fb-td-caret::after { width: 2px; height: 11px; }
.fb-td-conta--expansivel[aria-expanded="true"] .fb-td-caret::after { transform: scaleY(0); }
@media (prefers-reduced-motion: reduce){ .fb-td-conta--expansivel .fb-td-caret::before, .fb-td-conta--expansivel .fb-td-caret::after { transition: none } }
/* Conta financeira (filha): indentada, peso normal, tom secundário */
.fb-td-cf > td:first-child {
    padding-left:var(--bi-space-xl);
    font-weight: var(--bi-fw-normal);
    color: var(--bi-text-secondary);
}
/* Total Geral: célula congelada casa o cinza do total-row → agora coberto pelo
   primitivo .stickcols tr.tbl__total-row (ver §stickcols). */
/* Botão "Expandir tudo" no header do card */
.fb-td-toggle-all {
    font-size: var(--bi-fs-label);
    text-decoration: none;
    white-space: nowrap;
}

/* === Promoted from statement-theme.css (Batch 8) — permanent ownership ===
   These component rules are appended at the END of main.css (the last content
   stylesheet in the per-page load order) so they keep winning over earlier
   main.css + custom.css rules exactly as statement-theme.css did when
   it loaded last. !important and selectors are preserved verbatim. The 4
   SAFE-TO-DROP duplicates (font @import, --color-indicator-*, --color-chart-cat-*, soft borders
   -------------------------------------------------------------------------- */
/* .cardbox saiu daqui — seu base (§6 .cardbox) já define surf/line/--r/none
   idênticos; o !important era resíduo de quando este bloco era statement-theme.css
   (arquivo separado carregado depois). .kpi-band FICA: o !important sobrescreve
   de propósito o raio/sombra do base dela pra casar o "statement glass". */
.kpi-band{
  background:var(--surf) !important;
  border:var(--bs-border-width) solid var(--line) !important;
  border-radius:var(--r) !important;
  box-shadow:none !important;
}

.command-bar__filters{   /* .command-bar (bare) saiu — container não renderizado */
  background:var(--glass) !important;
  /* backdrop-filter removed — see note on .cardbox above */
  border:var(--bs-border-width) solid var(--line) !important;
  border-radius:var(--bi-radius-lg) !important;
  box-shadow:var(--sh-glass) !important;
}

/* `.btn-limpar` mantém o look statement aqui; `.pill` saiu deste bloco e voltou
   para a sua base (§PILL), sem `!important` — era este `!important` que invertia
   a cascata do componente inteiro. O `.btn-limpar` fica como estava: não é pill,
   e desestabilizá-lo não faz parte deste saneamento. */
.btn-limpar{
  border:var(--bs-border-width) solid var(--bi-border-color) !important;
  background:var(--bi-bg-hover) !important;
  color:var(--bi-text-secondary) !important;
  border-radius:var(--raio-chip) !important;
  font-weight:500;
  transition:all .12s;
}
.btn-limpar:hover{ background:var(--bi-bg-surface) !important; border-color:var(--bi-border-color-heavy) !important; color:var(--bi-text-primary) !important; }

/* Estado ativo. Sem `!important`: (0,2,0) já vence a base (0,1,0). */
.pill.active,
.pill.selected,
.pill[aria-pressed="true"]{
  background:var(--acc-soft); border-color:var(--acc-line); color:var(--acc-ink);
}

/* ── LINHA SELECIONADA (list-group) ───────────────────────────────────────────
   Mesmo trio de tokens do `.pill.active` acima: uma só ideia de "isto está
   selecionado" na app inteira. Antes eram três — importar-of caía no
   `.list-group-item.active` de fábrica (fill #0d6efd sólido, texto branco),
   metas tinha override próprio (fill --acc, texto branco) e histórico-preços
   usava `--surf-2` via `.is-focused`.

   Fundo suave + texto escuro em vez de fill sólido + texto branco não é só
   gosto: com texto branco, qualquer regra de hover que clareie o fundo apaga o
   conteúdo — foi exatamente o bug que o override do metas existia para contornar.
   Com texto escuro essa classe de bug não existe. A barra inset marca a linha
   escolhida sem depender de contraste de fundo, igual ao item ativo da sidebar.

   Especificidade (0,2,0) empata com a do Bootstrap e vence por ordem de arquivo
   (custom.css carrega depois de styles.css) — inclusive sobre
   `.list-group-item-action:hover`, que também é (0,2,0) e vem antes. */
.list-group-item.active{
  background:var(--acc-soft);
  border-color:var(--acc-line);
  color:var(--ink);
  box-shadow:inset 3px 0 0 var(--acc);
}
/* Linha inerte: o texto acinzentado do Bootstrap sozinho não diz "não clicável".
   Vale tanto para `.disabled` quanto para o atributo `disabled` de <button>. */
.list-group-item:disabled,
.list-group-item.disabled{ background:var(--surf-2); cursor:not-allowed; }
/* O modificador BEM `.pill--active` continua ESCOPADO aos três contextos que o
   usam. Uma regra global `.pill--active` pintaria de ativo lugares que hoje não
   pintam — mudaria pixel, e o alvo desta fase é cascata, não visual. */
:is(.command-bar, .secondary-bar) .pill--active{
  background:var(--acc-soft); border-color:var(--acc-line); color:var(--acc-ink);
  font-weight:var(--bi-fw-semibold);
}
:is(.command-bar, .secondary-bar) .pill--active:hover{
  background:var(--acc-soft); border-color:var(--acc-line);
}
.mapa__pills .pill--active,
.mapa__actions .pill--active{
  background:var(--acc-soft); border-color:var(--acc-line); color:var(--acc-ink);
}
.fcds-modal .pill--active{
  background:var(--acc-soft); border-color:var(--acc-line); color:var(--acc-ink);
}
.fcds-modal .pill--active:hover{
  background:var(--acc-soft); border-color:var(--acc-line);
}
.mapa__actions .pill--active:hover{
  background:var(--acc-line); border-color:var(--acc-line);
}
.btn-buscar-trigger{
  background:var(--brand) !important; border:var(--bs-border-width) solid var(--brand) !important; color:var(--bi-text-on-accent) !important;
  border-radius:var(--raio-chip) !important;
}
.btn-buscar-trigger:hover{ background:var(--brand-strong) !important; border-color:var(--brand-strong) !important; }

/* toggle switch → statement */

/* tables, mono numerals */
.tbl,
.dataTable,
table.datatable{ font-family:var(--sans); }
.tnum,[class*="-value"],[class*="__value"]{ font-family:var(--bi-font-mono); font-variant-numeric:tabular-nums; }

/* --------------------------------------------------------------------------
   6. SEGMENTED ABC badges + deltas → statement semantic
   -------------------------------------------------------------------------- */
.text-success{ color:var(--positive-text) !important; }
.text-danger{ color:var(--negative-text) !important; }
/* A terceira, que faltava desde sempre. Sem ela `.text-warning` cai no #ffc107
   de fábrica do Bootstrap — 1,63:1 sobre branco, ilegível como número — e era
   isso que apagava o KPI de R$ 16,4M da previsão de caixa, o "Em breve" do
   forecast e o ponto de alteração pendente da matriz de acesso. `.text-warning`
   é utilitário de TEXTO por definição: não existe uso legítimo dele como
   preenchimento, então o remap é seguro. Ver cores.md §4. */
.text-warning{ color:var(--warning-text) !important; }

/* ==========================================================================
   10. PAGE COHERENCE — give the legacy .cardbox sections the statement glass
   look + an aligned, evenly-inset grid (one visual language across the page).
   ========================================================================== */
/* a) horizontal alignment: inset everything from the page edge equally.
   Gutter applied ONCE: a casca do FCDS (`.content`) já paga os 20px laterais,
   então a `.page` fica sem recuo horizontal (era 24px) para não somar 20+24=44.
   A `.page` guarda só o recuo de baixo.

   Sem `!important` (18/08/2026): a trava impedia qualquer página de repor o
   próprio recuo e obrigava quem precisava a responder com outro `!important`
   (inadimplência) ou a desviar para `margin-right` (dre-gerencial).
   Especificidade normal basta — quem quiser repor, repõe. */
.page{ padding:0 0 var(--bi-space-lg); }
/* MORREU em 18/08/2026: `.page > section{padding-left/right:0 !important}`.
   Existia para a tabela poder encostar nas bordas do cartão, mas atingia 34
   seções em 19 telas — 26 delas sem tabela nenhuma — e colava rótulo, cabeçalho
   e filtro na borda (medido: "Pedidos separados" a 1px em /consulta-separacao/).
   Nenhuma tabela pedia por isso: o `.tbl-wrapper` documenta que sempre vive
   dentro de um `.card` e que o card é quem desenha o contorno, e nenhuma das
   seções medidas rolava na horizontal. Sangria agora é local, no bloco de quem
   a quer, com o par `margin-inline`/`padding-inline`. */
.page .row.g-2{
  --bs-gutter-x:var(--bi-space-md) !important; --bs-gutter-y:var(--bi-space-md) !important;
}

/* c) card header → statement label (small, muted, airy); drop heavy border/accent */

/* tame the section title labels too */

/* d) density caps: tall lists/tables scroll inside the card instead of stretching
   the page. Caps come from FCDS tokens (custom.css) so every scroll tier is
   defined in one place: card-list (--bi-scroll-cap / .card-scroll), table
   (--bi-table-scroll-cap), datatable (--bi-dt-scroll-cap). */
/* Reusable scroll-capped table (shared pattern): a long table scrolls inside its
   card and keeps its column header pinned, instead of stretching the page.
   Vertical sticky header — the metas grid is the reference.
   Override the cap per table with `--bi-table-scroll-max`. */
.tbl-scroll{ max-height:var(--bi-table-scroll-max, var(--bi-table-scroll-cap)); overflow:auto; }
.tbl-scroll thead th{ position:sticky; top:0; z-index:2; background:var(--bi-bg-surface); }
/* Every DataTable renders inside a .datatable-scroll wrapper (the toolbar above it stays
   put). Cap it so long / large-page grids scroll inside the card instead of stretching
   the page, and pin the column-label header row. `thead tr:last-child th` is
   grouped-header-safe: a multi-row (grouped) header pins only the label row, so the
   rows never stack/overlap at top:0. z:10 sits above the body's left-column-sticky
   cells (z 5-9); each page's own col-sticky header rules keep the corner cell on top.
   Override the cap per table with --bi-dt-scroll-max.
   (Replaces the old dead `[data-bi-section="transacoes"] .cardbox__body` cap — the
   FCDS markup has no such element, so the NF grid was stretching the page.) */
.datatable-scroll{ max-height:var(--bi-dt-scroll-max, var(--bi-dt-scroll-cap)); isolation:isolate; }
/* !important: DataTables' own CSS sets `position:relative` on the sort header and
   `.tbl.dataTable thead th{background:transparent !important}` — both would
   otherwise beat this on pages without a left-column-sticky rule. (Sticky still acts
   as the containing block for the sort-arrow ::after, so sorting is unaffected.) */
/* TODAS as linhas do thead grudam, não só a última. Onde há uma 2ª linha (os
   filtros por coluna), `tr:last-child` prendia só ela e deixava a linha de
   TÍTULOS rolar embora — o usuário ficava com as caixas de filtro flutuando sem
   os nomes das colunas em cima. A 2ª linha desce pela altura da 1ª, medida em JS
   (biUtils.recalcularColunasTravadas → --thead-linha1-altura), porque a altura
   depende de fonte/zoom/quebra e não dá para fixar em CSS. Tabela de uma linha
   só: nth-child(2) não casa e nada muda. */
.datatable-scroll thead tr th{ position:sticky !important; z-index:10; background:var(--bi-bg-surface) !important; }
.datatable-scroll thead tr:first-child th{ top:0 !important; }
.datatable-scroll thead tr:nth-child(2) th{ top:var(--thead-linha1-altura, 0px) !important; z-index:9; }
/* Painel de filtro de coluna ABERTO tem de flutuar acima da chrome sticky. Ele é
   `position:fixed` com coordenadas de viewport (biUtils.ancorarDropdown), mas mora
   dentro do <th> — e DOIS ancestrais o prendiam num contexto de empilhamento, o que
   torna o `z-index:100` dele inútil: resolvia lá dentro, pintando no nível do
   ancestral (9) e sumindo atrás da topbar (--z-topbar 900).
     1. .datatable-scroll — `isolation:isolate` (acima), sem z-index → confina tudo
        no nível 0 da página;
     2. o próprio <th> — `position:sticky` + z-index.
   Os dois só relaxam ENQUANTO há painel aberto, então fora disso o empilhamento da
   grade é exatamente o de antes. `overflow` fica intocado de propósito: elemento
   `fixed` não é recortado por overflow de ancestral, só por transform/filter. */
.datatable-scroll:has(.colfilter-multi__panel:not([hidden])){ isolation:auto; }
.datatable-scroll thead tr th:has(.colfilter-multi__panel:not([hidden])){
  z-index:calc(var(--z-topbar) + 1);
}
[data-bi-section="transacoes"] .dataTables_wrapper{ font-size:0.875rem; }

/* e) calm the coloured table cells to the soft palette (already via tokens, but
   force the inline green/red used in transações to the statement tones) */
[data-bi-section="transacoes"] .text-success,
.tbl .text-success{ color:var(--positive-text) !important; }
[data-bi-section="transacoes"] .text-danger,
.tbl .text-danger{ color:var(--negative-text) !important; }

/* ==========================================================================
   11. FULL REFINEMENT — legacy charts, tables, tabs, lists to statement grade
   ========================================================================== */
/* --- tabs (transações) → canonical accent-soft pill (same as fcds.components) --- */

/* Título dentro do header do card: rótulo em caixa alta (era .cardbox__title) */
.card-header .card-title{ font-size:0.875rem; font-weight:600; letter-spacing:.1em;
  text-transform:uppercase; color:var(--bi-text-secondary); margin:0; }

/* Célula de margem (MB/MC) = .progress do Bootstrap; só a geometria responsiva
   da barrinha e o tamanho do rótulo ficam aqui (utilitário do BS não cobre). */
.mb-cell__bar{ height: 0.25rem; width: 3.75rem;
  /* magnitude é neutra de propósito (sem valência verde/âmbar/vermelho): mantém o
     slate do --command em vez do primary azul que o .progress-bar traz por padrão */
  --bs-progress-bar-bg: var(--command); }
.mb-cell__pct{ font-size:var(--bi-fs-body); }
@media (min-width:768px){
  .mb-cell__bar{ width: 3rem; }
  .mb-cell__pct{ font-size:var(--bi-fs-label); }
}

.form-control:focus, .form-select:focus{ border-color:var(--acc-line); box-shadow:0 0 0 2px var(--acc-soft); }

/* Checkbox/radio/switch = Bootstrap ORIGINAL (styles.css), sem recolor FCDS.
   O accent-recolor foi removido a pedido do usuário — NÃO restaurar. */

/* Tabs = .nav-pills do Bootstrap, temadas pela API de variáveis dele (substituem .fcds-tabs) */
/* Só GEOMETRIA e tipografia: as três variáveis de COR (--bs-nav-link-color,
   -hover-color e o par --bs-nav-pills-link-active-*) foram removidas por diretiva
   do usuário — a pill ativa volta ao azul de fábrica do Bootstrap. */
.nav-pills{
  --bs-nav-link-padding-y: var(--bi-space-xs2);
  --bs-nav-link-padding-x: var(--bi-space-md);
  --bs-nav-link-font-size: 0.875rem;
  --bs-nav-link-font-weight: 500;
  --bs-nav-pills-border-radius: var(--r-sm, 11px);
  gap:var(--bi-space-xs2);
  margin-bottom:var(--bi-space-xs);
}
.nav-pills .nav-link.active{ font-weight: 600; }
.nav-pills .nav-link .badge{ font-size:0.875rem; font-weight:600; border-radius:var(--raio-chip); padding:0 0.5rem; margin-left:var(--bi-space-xs); }

/* --- DataTables → statement table styling --- */
.tbl.dataTable thead th{
  font-size:0.875rem !important; font-weight:600 !important; letter-spacing:.08em; text-transform:uppercase;
  color:var(--bi-text-muted) !important; background:var(--bi-bg-surface) !important; border-bottom:1px solid var(--bi-border-color) !important;
  padding:var(--bi-space-xs2) calc(var(--bi-space-sm) + var(--bi-space-xs2)) var(--bi-space-sm) !important;
}
.tbl.dataTable tbody td{
  font-size:0.875rem !important; color:var(--bi-text-secondary); border-top:1px solid var(--bi-border-color-subtle) !important; border-bottom:0 !important;
  padding:var(--bi-space-sm) calc(var(--bi-space-sm) + var(--bi-space-xs2)) !important; vertical-align:middle;
}
/* `:not()` cobre os DOIS painéis congelados. Só a esquerda estava excluída, e a
   célula congelada à DIREITA caía aqui: fundo transparente + a listra do
   Bootstrap, que é um overlay de 5% de preto — não fundo opaco. Resultado
   medido na fila de separação: `background-color: rgba(0,0,0,0)` nas linhas
   `.odd`, com a data da coluna de trás aparecendo através do botão. */
.tbl.dataTable.table-striped > tbody > tr:nth-of-type(odd)
  > *:not([class*="stick--"]):not([class*="stick-r--"]){ background:transparent !important; }
/* Ver a nota do hover em `.tbl tbody tr:hover td`: o estado é overlay do Bootstrap,
   não fundo opaco. Sem `!important` porque não há mais fundo opaco pra vencer. */
.tbl.dataTable tbody tr:hover > *{ --bs-table-accent-bg: var(--bs-table-hover-bg); }

/* Cabeçalho de bloco do rowGroup (hoje só a inadimplência agrupa: um bloco por
   cliente). O CSS do CDN pinta a linha com rgba(0,0,0,.1) — tarja escura que, em
   clientes de 1-2 títulos, cai quase a cada duas linhas e o olho lê como zebra
   quebrada. O bloco passa a ser marcado por hierarquia e espaço: nome do cliente
   com peso, filete de início de bloco e ar acima. Cor não carrega essa informação. */
.tbl.dataTable tbody tr.dtrg-group,
.tbl.dataTable tbody tr.dtrg-group th{
  background:var(--bi-bg-surface) !important;
  color:var(--bi-text-primary) !important;
  font-size:0.875rem !important; font-weight:600 !important;
  border-top:1px solid var(--bi-border-color) !important;
  padding:var(--bi-space-md) calc(var(--bi-space-sm) + var(--bi-space-xs2)) var(--bi-space-xs2) !important;
}
.tbl.dataTable tbody tr.dtrg-group:first-child th{ border-top:0 !important; padding-top:var(--bi-space-xs2) !important; }
/* O hover marca a linha de título (a unidade acionável). O cabeçalho não é clicável. */
.tbl.dataTable tbody tr.dtrg-group:hover > *{ --bs-table-accent-bg: transparent; }
.tbl.dataTable .tnum,
.tbl.dataTable td[class*="valor"],.tbl.dataTable td[class*="margem"]{ font-family:var(--bi-font-mono); font-variant-numeric:tabular-nums; }

/* Espaço à direita do rótulo para a seta de ordenação do DataTables. As setas
   são ::before/::after absolutas em right:10px; o padding shorthand acima só
   reservava ~8px, então a seta colidia/sobrepunha o texto do cabeçalho. Vale
   para QUALQUER DataTables (mobile e desktop) — especificidade maior que as
   regras de padding acima, então ganha sem depender da ordem. */
.tbl.dataTable thead th.sorting,
.tbl.dataTable thead th.sorting_asc,
.tbl.dataTable thead th.sorting_desc,
.tbl.dataTable thead th.sorting_disabled{
  padding-right:calc(var(--bi-space-sm) + 1rem) !important;
}

/* SETA DE ORDENAÇÃO TORTA — defeito global, medido em 02/09/2026.
   O `dataTables.bootstrap5` desenha ▲/▼ como ::before/::after com
   `font-size:.8em` e `line-height:9px` FIXO. Os 9px foram escolhidos para o
   cabeçalho pequeno do tema do fornecedor; o cabeçalho da FCDS tem 14px, então
   o glifo sai com 11,2px dentro de uma caixa de linha de 9px. Ele transborda
   ~2,2px, e como o ▲ ancora em `bottom:50%` e o ▼ em `top:50%`, as duas caixas
   se sobrepõem sobre a linha média — o par vira um borrão alongado. Vale para
   TODA tabela do app (medido igual em /contas-a-receber/ e /processos-comex/).

   `line-height:1` faz a caixa da linha valer o próprio glifo: o par volta a
   empilhar simétrico em torno do meio. Não é escolha de estilo — é a métrica do
   fornecedor casando com a escala de tipo da casa. */
/* Escopo = o MESMO do fornecedor, sem exigir `.tbl`: só parte das tabelas do
   app carrega essa classe (medido — `#cr-drill-tabela`, `#bi-tabela-registros`,
   `.sim-lista` e outras não carregam), e a métrica errada é do DataTables, não
   da `.tbl`. Escopar em `.tbl` consertava uma parte das telas e deixava a outra
   torta.

   `.dataTable.dataTable` NÃO é redundância: o `<link>` do DataTables é incluído
   no `{% block styles %}` (base_fcds.html linha 38) e portanto carrega DEPOIS do
   custom.css (linha 36). Com a mesma especificidade do seletor do fornecedor
   (0,2,5) quem vence é ele, por ordem. A classe repetida sobe para (0,3,5) e a
   correção passa a valer independente da ordem de carga — sem `!important`. */
table.dataTable.dataTable thead > tr > th.sorting::before,
table.dataTable.dataTable thead > tr > th.sorting::after,
table.dataTable.dataTable thead > tr > th.sorting_asc::before,
table.dataTable.dataTable thead > tr > th.sorting_asc::after,
table.dataTable.dataTable thead > tr > th.sorting_desc::before,
table.dataTable.dataTable thead > tr > th.sorting_desc::after,
table.dataTable.dataTable thead > tr > th.sorting_asc_disabled::before,
table.dataTable.dataTable thead > tr > th.sorting_desc_disabled::after,
table.dataTable.dataTable thead > tr > td.sorting::before,
table.dataTable.dataTable thead > tr > td.sorting::after,
table.dataTable.dataTable thead > tr > td.sorting_asc::before,
table.dataTable.dataTable thead > tr > td.sorting_asc::after,
table.dataTable.dataTable thead > tr > td.sorting_desc::before,
table.dataTable.dataTable thead > tr > td.sorting_desc::after{
  line-height:1;
  font-size:.7em;
}
/* A seta de ordenação é o ícone do app, não o par de glifos ▲▼ do DataTables
   (dono, 15/09): o mesmo `fa-sort`/`fa-sort-up`/`fa-sort-down` da grade da casa,
   num ícone só, no lugar do par. A grade tem o desenho dela e fica de fora. */
table.dataTable.dataTable:not(.grade-tabela) thead > tr > :is(th, td):is(.sorting, .sorting_asc, .sorting_desc)::before{
  content:none;
}
table.dataTable.dataTable:not(.grade-tabela) thead > tr > :is(th, td):is(.sorting, .sorting_asc, .sorting_desc)::after{
  content:'\f0dc'; font-family:'Font Awesome 6 Free'; font-weight:900;
  top:50%; bottom:auto; transform:translateY(-50%); line-height:1; font-size:.75em; opacity:.3;
}
table.dataTable.dataTable:not(.grade-tabela) thead > tr > :is(th, td).sorting_asc::after{ content:'\f0de'; opacity:.8; }
table.dataTable.dataTable:not(.grade-tabela) thead > tr > :is(th, td).sorting_desc::after{ content:'\f0dd'; opacity:.8; }
/* Coluna com um sentido só: o DataTables mostrava só a metade do par que vale. */
table.dataTable.dataTable:not(.grade-tabela) thead > tr > :is(th, td):is(.sorting_asc_disabled, .sorting_desc_disabled)::before{ content:none; }
table.dataTable.dataTable:not(.grade-tabela) thead > tr > :is(th, td):is(.sorting_asc_disabled, .sorting_desc_disabled)::after{
  content:'\f0dd'; font-family:'Font Awesome 6 Free'; font-weight:900; display:block;
  top:50%; bottom:auto; transform:translateY(-50%); line-height:1; font-size:.75em; opacity:.3;
}
table.dataTable.dataTable:not(.grade-tabela) thead > tr > :is(th, td).sorting_desc_disabled::after{ content:'\f0de'; }

/* Desktop refinement (≥768px): standardize the four faturamento DataTables on FCDS type
   tokens + symmetric, tighter padding (recovers the horizontal room a 4–6 col freeze needs),
   right-align numeric headers over their values, and width-cap the long descriptive columns
   to 2 lines. The base rules above are left intact, so mobile renders exactly as before. */
@media (min-width:768px){
  /* Typography unified app-wide on the base .tbl tokens (12px/600 heads, --bi-fs-body
     body, .06em letter-spacing). Only the LAYOUT refinements (tighter symmetric padding,
     numeric right-align) stay here; the former 13px/700 + .04em escape hatch was removed. */
  .tbl.dataTable thead th{
    padding:var(--bi-space-xs2) var(--bi-space-sm) !important;
  }
  .tbl.dataTable thead th.tbl__numeric{ text-align:right; }
  .tbl.dataTable tbody td{
    line-height:1.3;
    padding:var(--bi-space-xs2) var(--bi-space-sm) !important;
  }
  /* Cap the long descriptive columns at the TD level so the table can't park its
     fill-the-container slack as one big inter-column gap on wide screens (the columns
     ballooned to ~283px at 2560px). The table still fills (width:100%); residual slack
     spreads thinly across the remaining columns. */
  .tbl.dataTable td.col-text{ max-width: 15rem; }
  /* 2-line clamp for long text (cliente, representante, sub-segmento, histórico). Lives on an
     inner <div> — `display:-webkit-box` on the <td> itself would drop table-cell layout. Fills
     the (capped) cell so text no longer floats left inside a wider TD. Full value via title (hover). */
  .tbl.dataTable td .cell-clamp2{
    display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2;
    overflow:hidden; max-width:100%; white-space:normal; overflow-wrap:anywhere;
  }
  /* (Removed escape hatch: the 7-table 13px/700 head override + numeric font-family
     override. Heads/body now follow the unified base .tbl tokens — auditoria P5/ruling 4.) */
  /* Despesas-comex tem cabeçalhos de 2 palavras que quebram em 2 linhas e preenchem a
     largura — reserva uma calha à direita p/ as setas de ordenação (▲▼ em right:10px)
     não sobreporem o texto. Escopo só nas 3 tabelas para não mexer no Faturamento. */
  #df-tabela-previsoes thead th, #df-tabela-abertos thead th, #df-tabela-pagos thead th{
    padding-right:1rem !important;
  }
  
  /* Valor Bruto stays semibold on mobile (the JS span keeps `fw-semibold` so mobile is untouched);
     on desktop force it to the uniform 400. !important needed to beat Bootstrap's .fw-semibold. */
  #bi-tabela-notas td .fw-semibold, #bi-tabela-notas-maes td .fw-semibold,
  #bi-tabela-devolucoes td .fw-semibold{ font-weight:var(--bi-fw-regular) !important; }
  /* KILL THE INTER-COLUMN GAP. The table was forced to fill its container (`.tbl{width:100%}`
     + `.datatable table.dataTable{min-width:100%}` + Bootstrap `w-100`), so on screens wider
     than the content the slack inflated columns into gaps (and the col-text max-width couldn't
     hold against width:100%). Size the table to its CONTENT instead: width:max-content (so columns
     are tight and the col-text caps actually apply), max-width:100% so it still scrolls when the
     content is wider than the area. On an ultra-wide monitor the table ends and the rest of the
     card is blank — that is the cost of "no gaps". Desktop-only; mobile keeps the full-bleed w-100. */
  #bi-tabela-notas, #bi-tabela-devolucoes, #bi-tabela-despesas-fundo, #bi-tabela-notas-maes{
    width:max-content !important; max-width:100%; min-width:0;
  }
}

/* ============================================================================
   STICKY / FROZEN COLUMNS — unified
   Replaces the old per-page engines (faturamento `bi-col-sticky` +
   despesas_comex `df-col-sticky`). The visual contract (opacity, z ladder, edge,
   isolation) is pure CSS; only the per-column `left` offset is data-driven, set
   as `--stick-left-N` by biUtils.recalcularColunasTravadas. That helper is
   wired into the standard DataTable `drawCallback` (utils.js), so it recomputes on
   EVERY draw — init, sort, page, filter, AND column-visibility (ColVis) — plus a
   shared resize listener. That `draw.dt` coupling is the fix for the old engine,
   which only re-fired on init/resize/tab-switch and so misaligned after ColVis.
   (Pure-CSS calc() offsets were ruled out: in table-layout:auto a <td>'s width is
   only a hint, so declared widths don't hold and the cumulative lefts drift.)

   Usage: add `stickcols` to the <table>; tag each frozen cell `stick--N`
   (1-based, contiguous from the left) and the LAST frozen cell also `stick--edge`.
   `.datatable-scroll` carries `isolation:isolate` so this z ladder can't fight page
   dropdowns/modals. Placed AFTER the striped/hover rules above so frozen cells read
   opaque by source order, not by an !important pile-up. ======================== */
table.stickcols{ border-collapse:separate; border-spacing:0; }
/* opaque cells so scrolled content never shows through the frozen panel */
.stickcols > tbody > tr > td[class*="stick--"]{ position:sticky; background:var(--bi-bg-surface); }
/* position !important: DataTables sets `position:relative` on SORTABLE sort-headers
   (para a seta ::after), o que vence a sticky e faz a coluna congelada do CABEÇALHO
   scrollar horizontalmente (só a não-ordenável escapava). Mesma armadilha já tratada
   p/ o header vertical em .datatable-scroll (ver acima). Sticky segue como bloco
   contêiner da seta, ordenação intacta. */
.stickcols > thead > tr > th[class*="stick--"]{ position:sticky !important; background:var(--bi-bg-surface); }
/* Célula congelada NÃO repinta no hover: ela mantém a surface opaca (que é o que
   impede o conteúdo rolado de aparecer por baixo) e recebe o mesmo overlay de hover
   da linha, igual às demais. Repintar aqui com o hex antigo empilhava overlay sobre
   #f3f4f7 e deixava a coluna congelada mais escura que o resto da linha. */
/* striped: célula congelada casa a faixa zebra do Bootstrap .table-striped
   (senão a coluna sticky mostra a surface e "quebra" a listra). Genérico. */
.stickcols.table-striped > tbody > tr:nth-of-type(odd) > td[class*="stick--"]{ background:var(--surf-2); }
/* espelho da regra acima para o painel congelado à DIREITA. Faltava: o bloco do
   `stick-r--` foi escrito depois e herdou tudo menos a listra, então a coluna
   fixa ficava branca (ou transparente, sob o DataTables) contra a faixa zebra. */
.stickcols.table-striped > tbody > tr:nth-of-type(odd) > td[class*="stick-r--"]{
  background:var(--surf-2); }
/* linha de total: célula congelada casa o cinza do .tbl__total-row */
.stickcols tr.tbl__total-row > td[class*="stick--"]{ background:var(--surf-2); }
/* per-column left offset — JS-measured (biUtils.recalcularColunasTravadas) */
.stickcols .stick--1{ left:var(--stick-left-1, 0px); }
.stickcols .stick--2{ left:var(--stick-left-2, 0px); }
.stickcols .stick--3{ left:var(--stick-left-3, 0px); }
.stickcols .stick--4{ left:var(--stick-left-4, 0px); }
.stickcols .stick--5{ left:var(--stick-left-5, 0px); }
/* z ladder — leftmost paints over next, header over body, corner wins */
.stickcols > tbody > tr > .stick--1{ z-index:5; }
.stickcols > tbody > tr > .stick--2{ z-index:4; }
.stickcols > tbody > tr > .stick--3{ z-index:3; }
.stickcols > tbody > tr > .stick--4{ z-index:2; }
.stickcols > tbody > tr > .stick--5{ z-index:1; }
.stickcols > thead > tr > th.stick--1{ z-index:15; }
.stickcols > thead > tr > th.stick--2{ z-index:14; }
.stickcols > thead > tr > th.stick--3{ z-index:13; }
.stickcols > thead > tr > th.stick--4{ z-index:12; }
.stickcols > thead > tr > th.stick--5{ z-index:11; }
/* Frozen-panel right edge: hairline PLANO, marcando onde o congelamento acaba.
   Sem sombra — o dono pediu a tela plana e a sombra saiu dos cinco usos.
   Drawn with a ::after pseudo (NOT box-shadow on the cell): Bootstrap `.table-striped`
   paints its zebra with `box-shadow: inset 0 0 0 9999px` on every cell, which would
   override a cell box-shadow and make the divider vanish on striped rows. The pseudo
   is immune. The cells are position:sticky (positioned), so ::after anchors to them. */
.stickcols td.stick--edge::after{
  content:""; position:absolute; top:0; right:0; bottom:0; width:1px; pointer-events:none;
  background:var(--bi-border-color);
}
/* NO CABEÇALHO a borda NÃO pode usar ::after: ele já é do DataTables, que
   desenha ali a seta ▼ (`content:"▼"; top:50%`). Um elemento tem um ::after só,
   e as propriedades se misturavam — o `content` vinha do DataTables (0,2,5) e o
   `bottom:0`, `width:1px`, `background` e `box-shadow` vinham daqui. A seta
   virava um risco vertical de 1px COM SOMBRA, do meio até o fim do th. Era
   isso, e não a métrica da fonte, o borrão que aparecia em toda tabela com
   coluna congelada (medido em 02/09/2026: `::after` de 17,6px de altura na
   coluna de borda contra 9,8px nas demais).

   No th não há zebra do Bootstrap — que é o motivo de o ::after existir nas
   células do corpo —, então borda e sombra no próprio elemento resolvem sem
   disputar o pseudo. */
.stickcols th.stick--edge{
  border-right:1px solid var(--bi-border-color);
}

/* ── RIGHT-edge frozen columns (mirror of the left freeze) ──────────────────────
   For wide worksheet/matrix tables that pin a trailing TOTAL column. Tag each frozen
   cell `stick-r--N` (1-based, contiguous from the RIGHT; --1 = rightmost) and the
   leftmost right-frozen cell also `stick-r--redge` (draws the divider on its LEFT).
   JS sets `--stick-right-N`, accumulated right→left, in the same single pass as the
   left offsets (biUtils.recalcularColunasTravadas). Selectors are disjoint from the
   left set ("stick-r--" never contains "stick--"). ============================ */
.stickcols > tbody > tr > td[class*="stick-r--"]{ position:sticky; background:var(--bi-bg-surface); }
.stickcols > thead > tr > th[class*="stick-r--"]{ position:sticky; background:var(--bi-bg-surface); }
/* Sem repintura no hover — mesma razão da coluna congelada à esquerda (ver acima). */
.stickcols .stick-r--1{ right:var(--stick-right-1, 0px); }
.stickcols .stick-r--2{ right:var(--stick-right-2, 0px); }
.stickcols .stick-r--3{ right:var(--stick-right-3, 0px); }
/* z ladder — right panel sits above body cells and above the left stack's edges */
.stickcols > tbody > tr > .stick-r--1{ z-index:8; }
.stickcols > tbody > tr > .stick-r--2{ z-index:7; }
.stickcols > tbody > tr > .stick-r--3{ z-index:6; }
.stickcols > thead > tr > th.stick-r--1{ z-index:18; }
.stickcols > thead > tr > th.stick-r--2{ z-index:17; }
.stickcols > thead > tr > th.stick-r--3{ z-index:16; }
/* divider on the LEFT edge of the right-frozen panel */
.stickcols td.stick-r--redge::before{
  content:""; position:absolute; top:0; left:0; bottom:0; width:1px; pointer-events:none;
  background:var(--bi-border-color);
}
/* Espelho do defeito da borda esquerda: aqui o pseudo é o `::before`, que o
   DataTables usa para a seta ▲. No cabeçalho a borda vai no próprio elemento. */
.stickcols th.stick-r--redge{ border-left:1px solid var(--bi-border-color); }

/* ── Standard drill/expand affordance ──────────────────────────────────────────
   The system-wide cue that an element opens a drill/detail panel. Put `.drill-plus`
   on a <button> (or span[role=button]) inside the drillable header/row/cell. Subtle by
   default, accent on hover/focus; keyboard-focusable. One affordance, every surface. */
/* Sem caixa: o dono vetou a pílula com borda — o símbolo fica nu, cor
   rebaixada que sobe pra ink no hover da linha/foco. Área de clique segue
   16px (e a linha inteira também é clicável em todo caller). */
.drill-plus{
  display:inline-flex; align-items:center; justify-content:center;
  width: 1rem; height: 1rem; padding:0; flex:0 0 auto; cursor:pointer;
  border:0; border-radius:var(--bs-border-radius);
  background:transparent; color:var(--ink-2);
  transition:color .15s ease;
}
/* Ícone canônico: cruz DESENHADA em CSS (dois traços de 1.5px, cor herdada) —
   o dono quer o símbolo +, mas o glifo FA 900 era gordo demais. Ao abrir, o
   traço vertical colapsa (morph + → −). Estado pela classe .is-open. */
.drill-plus{ position:relative; }
.drill-plus::before, .drill-plus::after{
  content:""; position:absolute; inset:0; margin:auto; background:currentColor;
  border-radius:1px; transition:transform .15s ease;
}
.drill-plus::before{ width:11px; height:2px; }
.drill-plus::after{ width:2px; height:11px; }
.drill-plus.is-open::after{ transform:scaleY(0); }
/* O mesmo morph dirigido pelo estado NATIVO, sem classe: <details open> e
   aria-expanded (no próprio controle ou no ancestral que o contém). É o que
   deixa o CRM inteiro — blocos da ficha, linha do histórico, detalhe do
   acompanhamento, raia do funil no telefone — usar UM vocabulário de
   "abre isto" (19/08/2026: o dono vetou os chevrons e os ▸). */
details[open] > summary .drill-plus::after,
[aria-expanded="true"] .drill-plus::after,
.drill-plus[aria-expanded="true"]::after{ transform:scaleY(0); }
@media (prefers-reduced-motion: reduce){ .drill-plus::before, .drill-plus::after{ transition:none } }
.drill-plus:hover{ color:var(--ink); }
.drill-plus:focus-visible{ outline:2px solid var(--info); outline-offset:1px; color:var(--ink); }

/* ── Directional cell tint (cores.md DIRECTION channel) ─────────────────────────
   Worksheet/matrix result cells whose value carries good/bad meaning. Background uses
   the *-subtle tint, text the AA-safe *-text token (warning uses the deeper indicator
   alias for small-text contrast). ALWAYS pair with a non-color backup (sign/icon) in
   the cell content — never hue alone (cores.md §5, colorblind-safe). ================ */

/* ── Faturamento wide tables (Notas Fiscais / Notas Mães): RESPONSIVE TIERED FREEZE ──
   Desktop-only. Identity Ações·Data·NF (--1..--3) freeze from 768px; Valor Bruto (--4)
   joins at 1024px; MB·MC (--5·--6) join at 1360px. Columns release from the right edge
   inward as the viewport narrows, keeping the frozen panel ≲40% of the table at every
   width. NF keeps `stick--edge` (its mobile identity pin); on desktop the frozen-panel
   divider is hidden on NF and redrawn on the LAST frozen column of the active tier.
   The phone block below (≤767px OR ≤540px height) is UNCHANGED: every tier here carries
   `and (min-height: 33.8125rem)` so short-landscape phones never hit it, and none use
   `!important`, so the phone block's `!important` always wins there. The cumulative
   `--stick-left-N` offsets are set for ALL six cols by biUtils.recalcularColunasTravadas
   regardless of tier; a column rendered `static` simply ignores its unused `left`.
   Reusable divider recipe is duplicated per tier (CSS can't @apply a pseudo). */
@media (min-width:768px) and (min-height:541px){
  /* extra left offsets (cols 1–4 left come from the base rules above) + full z ladder */
  #bi-tabela-notas .stick--5,#bi-tabela-notas-maes .stick--5{ left:var(--stick-left-5,0px); }
  #bi-tabela-notas .stick--6,#bi-tabela-notas-maes .stick--6{ left:var(--stick-left-6,0px); }
  #bi-tabela-notas > tbody > tr > .stick--4,#bi-tabela-notas-maes > tbody > tr > .stick--4{ z-index:3; }
  #bi-tabela-notas > tbody > tr > .stick--5,#bi-tabela-notas-maes > tbody > tr > .stick--5{ z-index:2; }
  #bi-tabela-notas > tbody > tr > .stick--6,#bi-tabela-notas-maes > tbody > tr > .stick--6{ z-index:1; }
  #bi-tabela-notas > thead > tr > th.stick--4,#bi-tabela-notas-maes > thead > tr > th.stick--4{ z-index:13; }
  #bi-tabela-notas > thead > tr > th.stick--5,#bi-tabela-notas-maes > thead > tr > th.stick--5{ z-index:12; }
  #bi-tabela-notas > thead > tr > th.stick--6,#bi-tabela-notas-maes > thead > tr > th.stick--6{ z-index:11; }
  /* NARROW (768–1023): only identity frozen — Valor·MB·MC scroll with the data.
     Only `position:static` (static cells ignore `left`); we must NOT clear `left` here, or the
     wide tier — which re-sets position:sticky but inherits `left` from above — would lose its
     offset and fail to pin. */
  #bi-tabela-notas .stick--4,#bi-tabela-notas .stick--5,#bi-tabela-notas .stick--6,
  #bi-tabela-notas-maes .stick--4,#bi-tabela-notas-maes .stick--5,#bi-tabela-notas-maes .stick--6{
    position:static;
  }
}
/* MID (≥1024): freeze Valor Bruto (--4); divider moves to after Valor, off NF */
@media (min-width:992px) and (min-height:541px){
  #bi-tabela-notas .stick--4,#bi-tabela-notas-maes .stick--4{ position:sticky; left:var(--stick-left-4,0px); }
  #bi-tabela-notas .stick--edge::after,#bi-tabela-notas-maes .stick--edge::after{ display:none; }
  #bi-tabela-notas td.stick--4::after,#bi-tabela-notas th.stick--4::after,
  #bi-tabela-notas-maes td.stick--4::after,#bi-tabela-notas-maes th.stick--4::after{
    content:""; position:absolute; top:0; right:0; bottom:0; width:1px; pointer-events:none;
    background:var(--bi-border-color);
  }
}
/* WIDE (≥1360): also freeze MB·MC (--5·--6); divider moves to after MC%, off Valor */
@media (min-width:1400px) and (min-height:541px){
  #bi-tabela-notas .stick--5,#bi-tabela-notas .stick--6,
  #bi-tabela-notas-maes .stick--5,#bi-tabela-notas-maes .stick--6{ position:sticky; }
  #bi-tabela-notas td.stick--4::after,#bi-tabela-notas th.stick--4::after,
  #bi-tabela-notas-maes td.stick--4::after,#bi-tabela-notas-maes th.stick--4::after{ display:none; }
  #bi-tabela-notas td.stick--6::after,#bi-tabela-notas th.stick--6::after,
  #bi-tabela-notas-maes td.stick--6::after,#bi-tabela-notas-maes th.stick--6::after{
    content:""; position:absolute; top:0; right:0; bottom:0; width:1px; pointer-events:none;
    background:var(--bi-border-color);
  }
}
/* Phones (narrow portrait OR short landscape): collapse the frozen panel to just
   the edge/identity column so it stops eating the viewport. The other frozen cols
   go static and scroll with the data; only `.stick--edge` (the NF number — the
   row identity) stays pinned at left:0. The max-height clause catches landscape
   phones, whose width (~844px) would otherwise miss a max-width breakpoint. */
@media (max-width:767.98px), (max-height: 540px){
  /* Body cells of the non-edge frozen cols scroll horizontally (free the width). */
  .stickcols > tbody > tr > td[class*="stick--"]:not(.stick--edge){ position:static !important; }
  /* Header cells must KEEP their vertical pin (top:0) — only drop the horizontal
     freeze (left:auto). Forcing them static killed the sticky header row. */
  .stickcols > thead > tr > th[class*="stick--"]:not(.stick--edge){ left:auto !important; }
  .stickcols .stick--edge{ left:0 !important; }
}

/* REMOVIDO — `.content .card{width:100vw;margin-inline:calc(50% - 50vw)}` no mobile
   (0185647c). Valia quando toda seção do celular era UM card de linha inteira; quando as
   bandas de KPI viraram GRADE de cards (`row row-cols-2` em 12 telas, `.kpi8` aqui), a
   mesma regra passou a estourar card de meia linha: 100vw dentro de trilha de ~189px =
   duas cartas sobrepostas, a da esquerda fora da tela. `body{overflow-x:clip}` engolia o
   estouro sem barra de rolagem, então só se via conteúdo decepado. NÃO reintroduzir: o
   card no mobile é o card canônico, e a goteira lateral é do `.content` (§5). */

/* ── Faturamento mobile layout (rides on the full-width drawer shell) ─────────
   Gate matches the shell mobile gate (760/540) so it's active in both orientations. */
@media (max-width:767.98px), (max-height: 540px){
  /* UF map: stack map over ranking — side-by-side clips the ranking values at phone
     width. Source order is map→ranking, so no `order` (preserves focus order). */
  .page[data-pagina="faturamento"] [data-bi-section="mapa-uf"] .mapa{ grid-template-columns:1fr; gap:var(--bi-space-md); }
  .mapa__map-wrap{ min-height: 13.75rem; }
  .mapa-ranking__share{ width:auto; min-width: 2.625rem; }
  #card-mapa.is-fullscreen .mapa{ grid-template-columns:3fr 2fr !important; }
  /* Nem o CARD nem o GAP da grade são retocados aqui: o card fica com o padding
     canônico (8/16/16) em qualquer largura e `--gap` já é 0.5rem — a regra que
     "apertava" o gap no mobile repetia o valor padrão e foi removida. O que o mobile
     ajusta é a goteira da superfície (.content, §5), não o componente. */
  /* The data grids themselves reach the band edges (cancel the card's inset) so the
     table uses the full width; the toolbar/tabs above keep the inset as chrome. The
     band's hairlines still frame the section, so it reads coherent, not detached.
     Applies to every page's table-wrapper / ranking-table wrapper. */
  .content .tbl-wrapper{
    margin-left:calc(-1 * var(--bi-space-md)); margin-right:calc(-1 * var(--bi-space-md));
    /* the wrapper's own 16px radius + side borders would show as rounded corners at the
       band edges — drop them; the band frames the table. */
    border-radius:0; border-left:0; border-right:0;
  }
}

/* DataTables chrome (search / length / info / paginate) → minimal light */
.dataTables_wrapper .dataTables_filter input,
.dataTables_wrapper .dataTables_length select{
  border:1px solid var(--bi-border-color) !important; border-radius:var(--bs-border-radius-lg) !important; background:var(--bi-bg-hover) !important;
  color:var(--bi-text-primary) !important; padding:var(--bi-space-xs) var(--bi-space-sm) !important; font-size:0.875rem; outline:none;
}
.dataTables_wrapper .dataTables_filter input:focus,
.dataTables_wrapper .dataTables_length select:focus{ border-color:var(--acc-line) !important; box-shadow:var(--ring); }
.dataTables_wrapper .dataTables_info,
.dataTables_wrapper .dataTables_length,
.dataTables_wrapper .dataTables_filter{ font-size:0.875rem; color:var(--bi-text-muted); }
/* PAGINAÇÃO: sem regra nenhuma. Moravam aqui ~45 linhas que repintavam link,
   página ativa, hover e desabilitado, e depois soldavam as células com borda
   compartilhada e cantos retos — tudo com !important, e tudo reimplementando o
   que o .pagination do Bootstrap já faz de fábrica (inclusive a solda, via
   `.page-item:not(:first-child) .page-link{margin-left:-1px}`). Apagado por
   diretiva do usuário: a paginação é a do Bootstrap, sem intermediário. */

/* --- charts: give them consistent comfortable heights --- */
.chart{ position:relative; }

/* segment/ABC toggle + small controls in card headers → statement chips */
.card-header .btn{
  border-radius:var(--raio-chip) !important; font-size:0.875rem !important;
}

/* ==========================================================================
   12. LAYOUT REFINEMENT — cards become true flex columns so their charts FILL
   the card (no dead vertical voids), each row's two columns end at the same
   baseline, and one column drives the row height.
   ========================================================================== */

/* b) Top-20 Produtos: the section IS the FCDS .card (card-hd + .chart--xl).
   Make it a flex column so the chart fills the bounded card height
   (maintainAspectRatio:false → 20 bars compress to fit, no whitespace). */
[data-bi-section="top-produtos"]{ display:flex; flex-direction:column; }

/* f) Bound the two mixed-content rows: a tall element (20-bar chart / 20-row
   client list) must not balloon its neighbour (evolução stack / choropleth).
   The data-bi-section element is itself the .card. Fixed row height + internal
   fill/scroll; released on mobile (<993px) where cards stack to span-12. */
@media (min-width:992px) {
  /* Row A — Sub-segmento + Evolução de Faturamento: equal height via the row's
     align-items:stretch (.fcds-row-eq); no fixed height so the capped sub-board
     and the chart match the taller of the two. */
  [data-pagina="faturamento"] [data-bi-section="mapa-uf"] { height: 33.25rem; }
  [data-pagina="faturamento"] [data-bi-section="mapa-uf"] .mapa__ranking { overflow-y: auto; }
}

/* c) Evolução (two stacked cards on the right) FILLS to the Top-20 height:
   each card's body grows and its chart fills it — no more void band. */
[data-bi-section="evolucao-faturamento"] #bi-evolucao-view-grafico,
[data-bi-section="evolucao-faturamento"] #bi-evolucao-view-sazonalidade{ flex:1 1 auto; display:flex; flex-direction:column; min-height:0; }
[data-bi-section="evolucao-faturamento"] .chart,
[data-bi-section="evolucao-margem"] .chart{ flex:1 1 auto; height:auto !important; min-height: 11.875rem; }
[data-bi-section="evolucao-faturamento"] #heatmap{ flex:1 1 auto; }

/* d) Clientes ↔ Mapa row: both fill to equal height; the clientes bar list and
   the map+ranking get matching internal scroll instead of stretching the page. */
[data-bi-section="mapa-uf"] .card-body{ flex:1 1 auto; display:flex; flex-direction:column; min-height:0; }
[data-bi-section="mapa-uf"] .mapa{ flex:1 1 auto; min-height: 21.25rem; }

/* e) section headers with inline toggles align like statement card-hd (label
   left, controls right, shared baseline) instead of wrapping. */

.card-header .card-title{ margin-right:auto; }

/* ==========================================================================
   PAGE-LOCAL STYLES (Fase 3 — extraídos de blocos <style> inline dos templates;
   token-clean, escopados por [data-pagina]/classes próprias. Movidos p/ cá para
   sair do HTML; cascata idêntica — main.css já era carregado por essas páginas).
   ========================================================================== */

/* ── catalogo ── */
.mermaid-container { overflow: auto; min-height: 25rem; }
.mermaid-container .mermaid { background: transparent; text-align: center; }
.catalogo-legenda {
    display: flex; gap:var(--bi-space-md); flex-wrap: wrap;
    font-size: 0.875rem; color: var(--ink-2);
}
.catalogo-legenda span { display: inline-flex; align-items: center; gap:var(--bi-space-2xs); }
.catalogo-legenda i { width: 0.625rem; height: 0.625rem; border-radius: 50%; flex-shrink: 0; }
.catalogo-legenda .swatch-codori  { background: var(--cat-1); }
.catalogo-legenda .swatch-codfam  { background: var(--cat-3); }
.catalogo-legenda .swatch-centro  { background: var(--cat-2); }
#bi-segpills { flex-wrap: wrap; }
.catalogo-empty { color: var(--ink-3); font-style: italic; padding:var(--bi-space-xl); text-align: center; }

/* margem: sem regras de página — larguras de coluna vivem em margem.js
   (columnDefs.width), o scroll horizontal mobile é o próprio .tbl-wrapper. */

/* ── despesas_logistica ── */

/* despesas_logistica: bloco `grid-column:1/-1` removido — os tiles são .card em
   .row row-cols-* (flexbox); grid-column em flex-item é inerte (regra morta). */
/* #bi-distribuicao-* consolidado acima (global; despesas + despesas_logistica) */

/* ── movimentacao ── */
.mov-kpi-cell--transito { border-left: var(--bs-border-width) dashed var(--bi-border-color); }
.mov-kpi-sub--mono { font-family: var(--bi-font-mono); font-size: var(--bi-fs-caption); }
.mov-produto-search--host { position: relative; }

/* As listas do drill rolam DENTRO do painel. O `max-height: none` da grade é
   para a tela que É a lista (Pedidos, Notas); aqui a lista mora num painel
   embaixo dos gráficos, e sem teto o histórico de um produto de muito giro
   (6.723 movimentos, medido em dev) virava uma página de 246 mil px. */
.page[data-pagina="movimentacao"] .grade .datatable-scroll {
    max-height: var(--bi-dt-scroll-cap);
}

/* Grade de movimentos (L3): cor = direção do fluxo. A letra na coluna "E/S" é
   o backup não-cor — a classe nunca é o único jeito de saber a direção. */
.mov-linha-entrada { color: var(--positive-text); }
.mov-linha-saida { color: var(--negative-text); }
/* Grade de entradas futuras (L3): destaque âmbar para processo com data
   prevista ultrapassada — mesmo tom usado no card "Em Trânsito (COMEX)". */
.mov-linha-atrasada { background: color-mix(in srgb, var(--warning) 8%, white); }

.fc-via { white-space: nowrap; }
.fc-via > i {
    margin-right: .4em;
    color: var(--bi-text-muted);
    width: 1em;
    text-align: center;
    flex: none;
}
.fc-sit {
    display: inline-flex;
    align-items: baseline;
    gap:0.4em;
    white-space: nowrap;
}
.fc-zero { color: var(--bi-text-muted); }
.fc-atraso { color: var(--negative-text); font-weight: var(--bi-fw-semibold); }
/* Banner de status do refresh: cantos arredondados como os cards (não a faixa
   full-bleed quadrada herdada do despesas), borda completa + leve sombra. */
.fc-banner {
  border-radius: var(--bi-radius-md);
  box-shadow: 0 1px 2px rgba(16, 24, 40, 0.06);
}

/* ==========================================================================
   MERGED FROM bi/static/bi/css/tokens.css (P6) — ajuda-markdown help-modal styles.
   Font @import moved to base_fcds.html <link> (full Roboto family).
   ========================================================================== */
/* ==========================================================================
   tokens.css — fonts + contextual-help styles for the bi/ app.

   NOTE: all design TOKENS now live in a single file — custom.css
   (canonical color system + scale + app --bi-* tokens). This file no longer
   declares any :root tokens; it only loads the web fonts and styles the
   Markdown-rendered help modal (.ajuda-markdown), using FCDS tokens only.
   ========================================================================== */

/* ==========================================================================
   Ajuda contextual — estilos para HTML gerado pela lib Markdown Python
   (.ajuda-markdown envolve o conteúdo renderizado dentro do modal de ajuda)
   ========================================================================== */

/* ==========================================================================
   AUDITORIA DA TELA (09/08/2026) — o `?` quando a página publica verbetes.
   Não é markdown renderizado: é o envelope daquela carga, então o estilo mora
   aqui (regra dura: nenhum .css novo) e usa os mesmos tokens do resto do app.
   ========================================================================== */
/* O recorte primeiro: sem "qual empresa, qual período" nenhum número abaixo é
   defensável. Grade de pares em vez de frase corrida — é para conferir, não ler. */
/* ── VERBETE NO PONTO DE USO ────────────────────────────────────────────────
   Popover ancorado ao número clicado, no lugar do modal. O modal cobria 52% da
   tela e escurecia o resto: quem apontava um número perdia de vista o número e a
   tabela em volta — o contrário do "abrir o verbete no ponto de uso" que a regra
   pede. `position: fixed` e filho de <body> porque o número pode viver dentro de
   uma tabela que rola, onde um absolute seria recortado. Compartilhado pelas três
   telas que publicam verbetes (cockpit, inadimplência e produtividade). */
.ajuda-pop{
  position:fixed;z-index:var(--z-modal);width:min(24rem,calc(100vw - 1rem));
  background:var(--surf);border:1px solid var(--line-3);border-radius:var(--r);
  box-shadow:0 8px 28px rgba(15,23,42,.16);padding:.75rem .875rem;
  font-size:13px;line-height:1.45;color:var(--ink-2);
}
.ajuda-pop__topo{display:flex;align-items:baseline;justify-content:space-between;gap:.75rem;
  padding-bottom:.4rem;margin-bottom:.5rem;border-bottom:1px solid var(--line)}
.ajuda-pop__titulo{margin:0;font-size:13px;font-weight:600;color:var(--ink)}
/* O valor é o motivo do clique: vem junto do título, não escondido no corpo.
   QUEBRA DE LINHA (09/09/2026): era `nowrap`, que servia enquanto todo valor
   era um número curto ("R$ 8.038.927,61"). O verbete do percentual de
   inadimplência traz a conta inteira ("2,7% — R$ 7,1 mi vencidos … sobre
   R$ 269,3 mi faturados de … a …") e a linha vazava o balão de 24rem por cima
   do board. `wrap` no topo para o valor descer para a própria linha quando não
   couber ao lado do título. */
.ajuda-pop__topo{flex-wrap:wrap}
/* Verbete `resumido` (09/09/2026): sem conceito/fórmula/listas embaixo, a borda
   do topo separaria o título de nada. */
.ajuda-pop__topo--resumido{border-bottom:0;padding-bottom:0;margin-bottom:.35rem}
.ajuda-pop__valor{margin:0;font-family:var(--bi-font-mono);font-variant-numeric:tabular-nums;
  font-size:14px;font-weight:600;color:var(--ink);white-space:normal}
/* O MEMORIAL DE CÁLCULO (09/09/2026). A primeira tentativa foi uma string com
   `\n` em fonte monoespaçada: os três números saíam com o mesmo peso, a prosa
   lia como código e o RESULTADO — que é o que se procura — não se destacava de
   nada. Agora é uma grade de três colunas, que é como demonstrativo financeiro
   se lê: operador num vão estreito, rótulo à esquerda com o detalhe embaixo,
   número alinhado à DIREITA numa coluna só. O filete e o corpo maior separam o
   resultado dos operandos.

   `max-content` na coluna do número (e não `1fr`) porque é ele que dita a
   largura: alinhamento à direita só significa alguma coisa se os três números
   compartilharem a mesma borda direita. */
.ajuda-calc{display:grid;gap:.1rem}
.ajuda-calc__linha{display:grid;grid-template-columns:.9rem 1fr max-content;
  align-items:baseline;gap:.25rem .5rem;padding:.25rem 0}
.ajuda-calc__op{color:var(--ink-3);font-size:12px;text-align:center}
.ajuda-calc__rotulo{display:flex;flex-direction:column;color:var(--ink-2);font-size:12.5px}
.ajuda-calc__detalhe{color:var(--ink-3);font-size:11px;line-height:1.3}
.ajuda-calc__numero{font-variant-numeric:tabular-nums;text-align:right;
  color:var(--ink);font-size:13px;font-weight:600;white-space:nowrap}
/* O RESULTADO é o motivo do clique: ganha o filete que fecha a conta e o corpo
   que os operandos não têm. */
.ajuda-calc__linha--resultado{border-top:1px solid var(--line);margin-top:.15rem;
  padding-top:.4rem}
.ajuda-calc__linha--resultado .ajuda-calc__rotulo{color:var(--ink);font-weight:600}
.ajuda-calc__linha--resultado .ajuda-calc__numero{font-size:16px;font-weight:700}
.ajuda-pop__conceito{margin:0 0 .5rem}
/* A fórmula é literal — monoespaçada, em caixa própria, para não se ler como frase. */
.ajuda-pop__formula{margin:0 0 .5rem;padding:.35rem .5rem;background:var(--surf-2);
  border-radius:var(--bi-radius-xs,.25rem);font-family:var(--bi-font-mono);font-size:12px;color:var(--ink)}
.ajuda-pop__nota{margin:0 0 .4rem;font-size:12px}
.ajuda-pop__nota b{color:var(--ink)}
.ajuda-pop__origem{margin:0;font-size:11.5px;color:var(--ink-3)}
.ajuda-pop__mais{margin-top:.5rem;padding:0;border:0;background:none;font:inherit;font-size:12px;
  color:var(--chart-azul);cursor:pointer;text-decoration:underline}
.ajuda-pop__mais:focus-visible{outline:2px solid var(--chart-azul);outline-offset:2px;border-radius:2px}

.ajuda-recorte{background:var(--surf-2);border:1px solid var(--line);
  border-radius:8px;padding:.6rem .75rem;margin-bottom:.75rem}
.ajuda-recorte__grade{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
  gap:.35rem .75rem;margin:0}
.ajuda-recorte__par{display:flex;gap:.35rem;min-width:0}
.ajuda-recorte__par dt{color:var(--ink-3);font-size:12.5px;font-weight:500}
/* Duas linhas: o eixo sub-segmento vem com 37 nomes no recorte real e sozinho
   empurrava o primeiro verbete para fora da primeira dobra. O valor inteiro
   continua no `title` e no texto que o botão Copiar produz. */
.ajuda-recorte__par dd{margin:0;color:var(--ink);font-size:12.5px;font-weight:600;min-width:0;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.ajuda-recorte__quando{margin:.4rem 0 0;color:var(--ink-3);font-size:11.5px}
.ajuda-auditoria__acoes{display:flex;justify-content:flex-end;margin-bottom:.5rem}
.ajuda-verbete{padding:.85rem 0;border-top:1px solid var(--line)}
.ajuda-verbete:first-of-type{border-top:0;padding-top:.25rem}
.ajuda-verbete__titulo{font-size:1rem;font-weight:700;color:var(--ink);margin:0 0 .25rem}
/* O valor exibido é o que transforma "definição do indicador" em "defesa DESTE
   número": vem em tamanho de número, não de texto. */
.ajuda-verbete__valor{margin:0 0 .35rem;font-size:1.35rem;font-weight:700;color:var(--ink);
  font-variant-numeric:tabular-nums lining-nums}
.ajuda-verbete__valor-nota{font-size:11.5px;font-weight:500;color:var(--ink-3);
  margin-left:.35rem;vertical-align:middle}
.ajuda-verbete__conceito{margin:0 0 .5rem;color:var(--ink-2);font-size:13.5px;line-height:1.5;
  max-width:70ch}
.ajuda-verbete__rotulo{margin:.5rem 0 .2rem;font-size:11.5px;font-weight:700;color:var(--ink-3)}
/* A fórmula é o único bloco largo do modal: `overflow-x:auto` para ela rolar
   DENTRO da própria caixa (medido: transbordava em todas as resoluções, de 390
   a 1920, empurrando a barra lateral do modal), e `overflow-wrap:anywhere` para
   quebrar o token longo — nome de campo do ERP e caminho de arquivo não têm
   espaço onde quebrar. */
/* `.ajuda-markdown pre` (regra do modal de markdown, mesma caixa) fixa
   `white-space:pre` e VENCIA por especificidade (0,1,1 contra 0,1,0) — a
   fórmula não quebrava linha e rolava de lado em toda resolução, de 390 a
   1920. Casar a especificidade resolve sem tocar na regra do markdown, que
   segue valendo para o fallback dos docs. */
.ajuda-auditoria .ajuda-verbete__formula{margin:0;padding:.5rem .65rem;background:var(--surf-2);
  border:1px solid var(--line);border-radius:6px;font-size:12.5px;line-height:1.5;
  color:var(--ink);white-space:pre-wrap;overflow-wrap:anywhere;word-break:normal;
  overflow-x:auto;max-width:100%}
/* Origem e listas carregam caminho de arquivo (bi/services/...py:funcao), que
   não quebra sozinho e estourava a caixa do modal na horizontal. */
.ajuda-verbete__lista li{overflow-wrap:anywhere}
.ajuda-verbete__lista{margin:0;padding-left:1.1rem;color:var(--ink-2);font-size:12.5px;
  line-height:1.5}
.ajuda-verbete__obs{margin:.5rem 0 0;color:var(--ink-2);font-size:12.5px;line-height:1.5;
  max-width:70ch}
/* Chegou pelo clique NUM número: o verbete daquele valor abre marcado, senão o
   operador cai numa lista e procura de novo o que já tinha apontado. */
.ajuda-verbete--destacado{background:var(--info-subtle);border-radius:8px;
  padding-left:.6rem;padding-right:.6rem;box-shadow:0 0 0 1px color-mix(in srgb, var(--info) 22%, var(--surf))}

.ajuda-markdown { color: var(--ink); font-size: 1rem; line-height: 1.6; }

.ajuda-markdown h1 { font-size: 1.2rem; font-weight: 700; margin-bottom:0.5rem; color: var(--ink); }
.ajuda-markdown h2 { font-size: 1rem; font-weight: 700; margin-top:1.5rem; padding-bottom:0.5rem; border-bottom: var(--bs-border-width) solid var(--line); color: var(--ink); }
.ajuda-markdown h3 { font-size: 1rem; font-weight: 600; margin-top:1rem; color: var(--ink-2); }

.ajuda-markdown p { margin-bottom:0.5rem; }
.ajuda-markdown ul, .ajuda-markdown ol { padding-left:1.5rem; margin-bottom:0.5rem; }
.ajuda-markdown li { margin-bottom:0.25rem; }

.ajuda-markdown blockquote {
    border-left: 3px solid var(--line);
    padding:0.5rem 1rem;
    margin:0.5rem 0;
    color: var(--ink-3);
    background: var(--surf-2);
    border-radius: 0 var(--bs-border-radius-sm) var(--bs-border-radius-sm) 0;
}

/* Equação — bloco de definição de KPI (MB, MC etc).
   Label à esquerda, corpo da equação à direita, alinhamento por CSS Grid. */
.ajuda-markdown .equacao {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap:1rem;
    align-items: center;
    background: var(--surf);
    border: var(--bs-border-width) solid var(--line);
    border-left: 3px solid var(--acc);
    border-radius: var(--bs-border-radius);
    padding:1rem 1rem 1rem;
    margin:1rem 0 1rem;
    box-shadow: var(--sh1);
}
.ajuda-markdown .equacao + .equacao { margin-top:0.5rem; }

.ajuda-markdown pre {
    background: var(--surf-2);
    border: var(--bs-border-width) solid var(--line);
    border-radius: var(--bs-border-radius-sm);
    padding:0.5rem 1rem;
    font-size: 0.875rem;
    overflow-x: auto;
    color: var(--ink);
    white-space: pre;
}

.ajuda-markdown code {
    background: var(--surf-2);
    border: var(--bs-border-width) solid var(--line);
    border-radius: var(--bs-border-radius-sm);
    padding:0 0.25rem;
    font-size: 0.82em;
    color: var(--cat-5);
}

.ajuda-markdown pre code {
    background: none;
    border: none;
    padding:0;
    color: inherit;
    font-size: inherit;
}

.ajuda-markdown table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom:1rem;
    font-size: 0.875rem;
    table-layout: auto;
}

.ajuda-markdown th {
    background: var(--surf-2);
    font-weight: 600;
    text-align: left;
    padding:0.5rem 0.5rem;
    border: var(--bs-border-width) solid var(--line);
    color: var(--ink);
}

.ajuda-markdown td {
    padding:0.5rem 0.5rem;
    border: var(--bs-border-width) solid var(--line);
    vertical-align: top;
    color: var(--ink);
    word-break: break-word;
}

.ajuda-markdown td:first-child { text-align: right; color: var(--ink-3); white-space: nowrap; }
.ajuda-markdown td:nth-child(2) { font-weight: 600; }

.ajuda-markdown td code,
.ajuda-markdown th code {
    white-space: pre-wrap;
    font-size: 0.875rem;
    padding:0 0.25rem;
}

.ajuda-markdown tr:nth-child(even) td { background: var(--surf-2); }

.ajuda-markdown a { color: var(--acc); text-decoration: underline; }
.ajuda-markdown a:hover { color: var(--acc-d); }

/* Modal footer separador */

/* ===== MERGED FROM bi/static/bi/css/faturamento-fcds.css (P5 — page-local dissolve) ===== */
/* ==========================================================================
   faturamento-fcds.css — page-owned glue for the Faturamento page on FCDS.
   The GENERIC helpers that used to live here (grid spans .fcds-span-*, equal-
   height .fcds-row-eq, segmented toggle .fcds-seg, the .fcds-tabs underline
   skin, .fcds-mini-lab, .fcds-siglink, .is-hidden) were PROMOTED to the shared
   layer (custom.css §10 + the canonical TABS block) so
   every migrated page composes them without copy-paste. What remains here is
   faturamento-ONLY section choreography. Uses ONLY fcds tokens — no hardcoded
   colours.
   ========================================================================== */

/* P7 — CLS: #fcds-grid starts empty and faturamento-fcds.js injects the KPI band
   after data loads. Reserve the band height while empty so the fill no longer
   collapses→expands (measured CLS ~1.77 → 0.13). */
#fcds-grid { min-height: 10.5rem; }

/* Sinais operacionais como linha full-width (mês corrente): 3 cards lado a lado.
   Fora do mês corrente a .sigcol mantém o padrão vertical (coluna span-4).
   .is-hidden (oculta o Ritmo Diário fora do mês corrente) é compartilhado. */
.sigcol.is-row { flex-direction: row; }
.sigcol.is-row .sig { flex: 1; }
@media (max-width: 992px) {
  .sigcol.is-row { flex-direction: column; }
}

/* Row B — Evolução de Margem (50%) ao lado do Mapa (50%), em altura igual.
   O card vira coluna flex e o gráfico ocupa a altura restante; o canvas é
   posicionado em absoluto para acompanhar essa altura (em vez de uma única
   linha de tendência inflar para ~571px via o loop de aspect-ratio do Chart.js
   quando não há altura definida). Resultado: a linha escala junto com o mapa. */
[data-bi-section="evolucao-margem"] { display: flex; flex-direction: column; }
[data-bi-section="evolucao-margem"] .chart {
  flex: 1 1 auto; height: auto; min-height: 15rem; position: relative;
}
[data-bi-section="evolucao-margem"] .chart canvas {
  position: absolute; inset: 0; height: 100% !important;
}

/* Ritmo Diário — gráfico ocupa toda a altura do card (mesmo padrão da margem),
   acompanhando a altura do board de Sub-segmento ao lado (fcds-row-eq). */
[data-bi-section="corredor-diario"] { display: flex; flex-direction: column; }
[data-bi-section="corredor-diario"] .chart {
  flex: 1 1 auto; height: auto; min-height: 15rem; position: relative;
}
[data-bi-section="corredor-diario"] .chart canvas {
  position: absolute; inset: 0; height: 100% !important;
}


/* Switch de formato numérico (abreviado ↔ completo) injetado no topbar por
   faturamento.js. Reusa o componente global .toggle ("Considerar devoluções");
   aqui só ajustamos o encaixe no topbar (altura, alinhamento, não encolher). */

/* AUTO-SHRINK — números completos ("R$ 16.201.272,89") são bem mais largos que os
   abreviados. Os valores da banda já são nowrap; no modo completo encolhemos o
   font-size com clamp() em unidades cqi (container query inline-size) → o tamanho
   acompanha a LARGURA REAL DA CÉLULA, não a viewport. Isso resolve os dois furos do
   vw anterior: (a) sidebar aberta deixa a viewport larga mas a célula estreita;
   (b) o grid colapsa 8→4→2 colunas. O teto px = tamanho original, então no desktop
   amplo fica praticamente inalterado. Escopo: .kpiband--completo (modo compacto
   intocado). Cada célula vira um container inline-size. */

/* ===== MERGED FROM bi/static/bi/css/gerencial.css (P5 — page-local dissolve) ===== */

/* ============================================================================
   gerencial.css — porte PIXEL-PERFECT do mockup aprovado, responsivo.
   Tokens e valores transcritos do mockup (paleta fria/clara, mono nos números).
   Escopo em .gc (dentro do shell FCDS). Sem legenda de rodapé (decisão do
   usuário). Drills em overlay próprio (.gc-ov), como o mockup.
   ========================================================================== */
.gc {
  /* Paleta Bootstrap literal (spec 2026-07-28 §11). A build vendorizada é
     5.2-era: NÃO existem --bs-tertiary-bg nem as famílias -bg-subtle /
     -border-subtle / -text-emphasis. Só o que está aqui existe.
     PREFIXO --gc- obrigatório (2026-08-06, DESIGN.md §6 Don'ts): este bloco
     redefinia os nomes GLOBAIS --ink/--ink-4/--line…, e todo componente
     compartilhado dentro da página mudava de valor sem aviso (--ink-4 virava
     #ced4da, ~1,6:1). Página cria token PREFIXADO ou consome o global.
     --gc-accent é #0d6efd (BS puro), por decisão do usuário — diverge do
     --brand #006BB5 que o resto do app usa.
     --gc-ink-2/--gc-ink-3 são rgba TRANSLÚCIDOS: usar só em color, nunca como
     fundo de coluna sticky (senão a coluna vaza no scroll horizontal).
     --amber saiu: #ffc107 tem ~1.9:1 em branco, ilegível como texto. O nível
     "alerta" agora é sinalizado por preenchimento, não por cor de número.
     --accent-dim/--steel/--steel-hi saíram: zero uso (auditado 2026-07-28). */
  --gc-panel:var(--bs-body-bg); --gc-panel-3:var(--bs-gray-100);
  --gc-ink:var(--bs-body-color); --gc-ink-2:var(--bs-secondary-color);
  --gc-ink-3:var(--bs-tertiary-color); --gc-ink-4:var(--bs-gray-400);
  --gc-line:var(--bs-border-color); --gc-line-2:var(--bs-border-color-translucent);
  --gc-accent:var(--bs-primary);
  --gc-red:var(--bs-danger); --gc-green:var(--bs-success);
  /* Sem override local de fonte: herda a Roboto única do :root (--sans/--mono). */
  margin:0 auto; display:flex; flex-direction:column; gap:0.5rem;
  color:var(--gc-ink); font-family:var(--sans);
}
/* Rótulos/cabeçalhos herdam a sans do mockup (o shell usa Roboto); números já
   forçam --mono, então continuam monoespaçados. */
.gc, .gc button, .gc input { font-family:var(--sans); }

/* ── Abas de mês ─────────────────────────────────────────────────────────── */
/* Vivem no .card-header do card único (não são mais um card próprio), então
   não têm bordo/fundo/padding próprios; aqui só o residual sem primitiva:
   linha flex das abas + scroll horizontal (a build vendorizada do Bootstrap só
   tem .overflow-auto, que travaria o eixo Y também). */
.gc-months { display:flex; flex-direction: row; gap:0.25rem; align-items:center; overflow-x:auto;
  flex:1 1 auto; min-width:0; }
.gc-months__lbl { font-size:0.875rem; letter-spacing:.16em; text-transform:uppercase; color:var(--gc-ink-3);
  font-weight:700; padding:0 0.5rem 0 0.25rem; white-space:nowrap; }
.gc-mtab { flex:1 1 0; min-width: 2.875rem; text-align:center; padding:0.5rem 0.25rem; border-radius:var(--bs-border-radius-lg); font-size:0.875rem;
  font-weight:600; color:var(--gc-ink-2); cursor:pointer; white-space:nowrap; background:transparent; border:0; }
.gc-mtab:hover:not(.gc-mtab--off):not(.gc-mtab--on) { background:var(--gc-panel-3); }
.gc-mtab--on { background:var(--gc-accent); color:var(--bi-text-on-accent); font-weight:700; cursor:default; }
.gc-mtab--off { color:var(--gc-ink-3); opacity:.45; cursor:default; }

/* ── Nota de mês fechado ─────────────────────────────────────────────────── */
/* Cor/padding vêm de .alert-secondary (Bootstrap); aqui só o layout em linha
   do ícone+texto e o encaixe edge-to-edge dentro do card-body. */
.gc-pastnote { display:flex; flex-direction: row; align-items:center; gap:0.5rem; margin:0;
  border-radius:0; border-left:0; border-right:0; border-top:0;
  font-size:0.875rem; font-weight:600; }
.gc-pastnote i { flex:0 0 auto; }

/* ── Painéis ─────────────────────────────────────────────────────────────── */
/* .gc-panel/.gc-panel__hd (bordo/bg/radius/overflow + layout do cabeçalho)
   viraram .card/.card-header (+ utilities Bootstrap d-flex/justify-content-
   between/align-items-baseline/flex-wrap/gap-2 direto no template). Fica só
   a tipografia "eyebrow" do título, que não tem equivalente Bootstrap. */
/* (.gc-panel__ttl saiu com a tira: o título do saldo virou `.gc-hd__ttl`,
   dentro da própria célula de rótulo do cabeçalho da matriz.) */

/* toggle de ordenação */
.gc-ord { display:inline-flex; align-items:center; gap:0.5rem; }
.gc-ord__lbl { font-size:0.875rem; letter-spacing:.22em; text-transform:uppercase; color:var(--gc-ink-3); font-weight:700; }
/* Controle segmentado ÚNICO da tela — serve o toggle de conjunto (na topbar,
   FORA do `.gc`) e o de ordenação (dentro dele). Eram dois componentes
   idênticos na estrutura e diferentes na cor; o de fora ainda perdia a borda,
   porque `--gc-line`/`--gc-accent` só existem dentro do `.gc` e uma custom
   property indefinida invalida a declaração (a borda caía para currentColor).
   Por isso aqui os tokens são os `--bs-*` que os `--gc-*` já apontam: mesmo
   valor computado, e válido nos dois lados. */
.gc-seg { display:inline-flex; border:var(--bs-border-width) solid var(--bs-border-color); border-radius:var(--bs-border-radius-lg); overflow:hidden; background:var(--bs-body-bg); }
.gc-seg__b { border:0; background:transparent; padding:0.375rem 1rem; font-size:0.875rem; font-weight:600; color:var(--bs-secondary-color); cursor:pointer; }
.gc-seg__b + .gc-seg__b { border-left:var(--bs-border-width) solid var(--bs-border-color); }
.gc-seg__b:hover:not(.gc-seg__b--on) { background:var(--bs-gray-100); }
.gc-seg__b--on { background:var(--bs-primary); color:var(--bi-text-on-accent); font-weight:700; }
/* Toggle de conjunto (Cordoalha ↔ Arame). Vive no topbar, FORA do .gc, então
   NÃO pode usar os tokens locais (--gc-accent etc. ficam indefinidos → branco no
   branco). Usa os tokens globais :root (--brand/--gc-line/--gc-ink). */

/* O card tem raio nos quatro cantos, mas a última linha da matriz (fundo próprio)
   pintava por cima dos dois de baixo: topo arredondado, base em esquadro. Recorta
   o conteúdo na forma do card — nada aqui precisa escapar dele. */
.gc .card { overflow:hidden; }

/* ── Cabeçalho da bitola (era a tira `.gc-strip`) ────────────────────────── */
/* Saldo, barra, rótulo e código na MESMA célula da coluna: o alinhamento passa
   a ser o da tabela (morreram o espaçador de 216px que imitava a coluna de
   rótulo e o `min-width` repetido nos dois componentes) e a bitola é escrita
   uma vez só, não uma na tira e outra no cabeçalho. */
.gc-mx th.gc-bh { vertical-align:bottom; }
/* `nowrap` no NÚMERO (não no rótulo): sem ele o saldo partia no meio — "−17,3"
   virava "−17," / "3" quando a coluna aperta. */
.gc-bh__num { display:block; white-space:nowrap; font-family:var(--mono); font-size: var(--bi-fs-compact); line-height:1.1; font-weight:700;
  font-variant-numeric:tabular-nums; color:var(--gc-green); }
.gc-bh--dn .gc-bh__num { color:var(--gc-red); }
.gc-bh__bar { display:block; position:relative; height: 2.75rem; margin:0.25rem 0 0.375rem; }
.gc-bh__bar i { position:absolute; left:0; right:0; top:50%; border-top:var(--bs-border-width) dashed var(--gc-ink-3); opacity:.45; }
.gc-bh__bar b { position:absolute; left:26%; right:26%; background:var(--gc-green);
  border-radius: var(--bs-border-radius-sm) var(--bs-border-radius-sm) 0 0; }
.gc-bh--dn .gc-bh__bar b { background:var(--gc-red); border-radius: 0 0 var(--bs-border-radius-sm) var(--bs-border-radius-sm); }
/* Desliga a HERANÇA de `word-break:break-word` do `thead th` em vez de PROIBIR a
   quebra: "15,2mm"/"12,7eng" são token único (sem espaço, sem oportunidade de
   quebra) e seguem inteiros — que era o motivo do antigo `nowrap` —, enquanto
   "BWG 18 torcido 10kg" (conjunto Arame, 16 colunas) quebra nos ESPAÇOS dentro
   da própria coluna. Com `nowrap` ele vazava por cima da coluna vizinha em
   qualquer largura de tela. */
.gc-bh__lbl { display:block; white-space:normal; word-break:normal; overflow-wrap:normal;
  font-size: var(--bi-fs-compact); font-weight:700; color:var(--gc-ink); text-transform:none; letter-spacing:0; }
.gc-bh--dn .gc-bh__lbl { color:var(--gc-red); }
.gc-bh__cod { display:block; white-space:nowrap; font-family:var(--mono); font-size: var(--bi-fs-micro); letter-spacing:-0.02em; color:var(--gc-ink-3); }
/* Gerencial, 17/09/2026 (decisão do dono): o CÓDIGO é o nome do produto e o
   apelido da bitola é apoio — o par troca de ordem no HTML e de peso aqui.
   Escopado a `.gc-mx` de propósito: a Curva ABC (`.cabc-mx`) usa as mesmas
   classes na ordem antiga, e mexer na regra-base vazaria para ela.
   O código NÃO ganha corpo maior: fica no mesmo `--bi-fs-compact` que o apelido
   tinha, porque a coluna é fixa em 4.75rem e 8 dígitos já a ocupam quase toda
   (ver o comentário do `.gc-bh__und`). O destaque vem do PESO e da COR, que não
   custam pixel — o `letter-spacing` mais fechado devolve o que o corpo maior
   consumiu. */
.gc-mx .gc-bh__cod { font-size: var(--bi-fs-compact); font-weight:700; color:var(--gc-ink); letter-spacing:-0.04em; }
.gc-mx .gc-bh--dn .gc-bh__cod { color:var(--gc-red); }
.gc-mx .gc-bh__lbl { font-size: var(--bi-fs-micro); font-weight:400; color:var(--gc-ink-2); }
/* O vermelho do saldo negativo fica no código (a identidade da coluna); repeti-lo
   no apelido pintaria a célula inteira de vermelho e diluiria o sinal. */
.gc-mx .gc-bh--dn .gc-bh__lbl { color:var(--gc-ink-2); }
/* Selo de unidade da coluna: aparece em TODA coluna de um conjunto de unidades
   mistas (Cercamento, Fixadores). Fica em LINHA PRÓPRIA, não emendado no código:
   a linha do código é `nowrap` numa coluna de largura fixa (4.75rem) e o código
   de 8 dígitos já a ocupa quase toda — inline, o selo era cortado. */
.gc-bh__und { display:inline-block; margin-top:0.125rem; padding:0 0.25rem; border:var(--bs-border-width) solid var(--gc-line); border-radius:var(--bs-border-radius-sm); font-family:var(--bs-body-font-family); font-size: var(--bi-fs-micro); line-height:1.4; color:var(--gc-ink-2); background:var(--gc-panel-3); }
.gc-bh__skel { display:block; margin:0 auto 0.25rem; }
/* Rótulo da 1ª coluna do cabeçalho: título (botão do resumo geral) + fórmula. */
.gc-hd__ttl { display:block; border:0; background:transparent; padding:0; cursor:pointer; text-align:left;
  font-size:0.875rem; letter-spacing:.15em; text-transform:uppercase; font-weight:700; color:var(--gc-ink-2); }
.gc-hd__ttl:hover { color:var(--gc-accent); }
.gc-hd__sub { display:block; font-size: var(--bi-fs-compact); font-weight:400; letter-spacing:0; text-transform:none; color:var(--gc-ink-3); }
.gc-hd__cap { font-size: var(--bi-fs-micro); letter-spacing:.08em; text-transform:uppercase; font-weight:700; color:var(--gc-ink-3); }

/* ── Runway: para onde o saldo caminha (2ª linha do cabeçalho) ───────────── */
/* A série e o mês da virada vêm prontos do backend (`runway`); aqui só a
   polilinha. Responde "quando falta", que a matriz de um mês só não responde. */
.gc-mx tr.gc-rwrow th { background:var(--gc-panel-3); padding:0.375rem 0.375rem 0.25rem; vertical-align:middle; cursor:default; }
.gc-mx tr.gc-rwrow th.gc-rowh { background:var(--gc-panel-3); }
.gc-rw { display:block; width:100%; height: 1.625rem; }
/* A nota só existe quando há virada; a coluna calma fica em silêncio. O
   `min-height` reserva a linha de texto para as colunas mudas não subirem e
   desalinharem as sparklines vizinhas. */
.gc-mx tr.gc-rwrow th { min-height:0; }
.gc-rw__nota { display:block; white-space:nowrap; font-size: var(--bi-fs-micro); font-weight:700; letter-spacing:0;
  text-transform:none; text-align:center; }
.gc-rw__nota--zera_em { color:var(--gc-red); }
.gc-rw__nota--recupera_em { color:var(--gc-green); }

/* ── Matriz ──────────────────────────────────────────────────────────────── */
/* A matriz rola dentro do card, com cabeçalho grudado: as barras e os rótulos
   de bitola são a referência de leitura de toda linha — se saem de vista ao
   rolar, o número do meio da tabela vira número sem dono. */
.gc-mxwrap { overflow:auto; max-height:calc(100vh - 9.5rem); }
/* O piso acompanha o Nº DE COLUNAS (`--gc-cols`, carimbado no render): 59.25rem
   fixo era calibrado para as 13 bitolas da cordoalha e espremia as 16 do arame
   até o rótulo virar ilegível. Quem rola é o `.gc-mxwrap` (já `overflow:auto`);
   a PÁGINA nunca rola na horizontal. */
table.gc-mx { border-collapse:collapse; width:100%; font-size:0.875rem; table-layout:fixed;
  min-width: calc(14.75rem + var(--gc-cols, 13) * 4.75rem); }
.gc-mx col.gc-c-rowh { width: 14.75rem; }
.gc-mx th, .gc-mx td { padding:0; white-space:nowrap; }
.gc-mx thead th { font-size:0.875rem; color:var(--gc-ink-3);
  font-weight:700; text-align:center; padding:0.5rem 0.375rem 0.375rem; border-bottom:var(--bs-border-width) solid var(--gc-line);
  border-right:var(--bs-border-width) solid var(--gc-line-2);
  vertical-align:bottom; cursor:pointer;
  white-space:normal; line-height:1.15; word-break:break-word;
  position:sticky; top:0; z-index:2; background:var(--gc-panel); }
/* A 2ª linha do cabeçalho (runway) gruda logo ABAIXO da 1ª — a altura é medida
   no cliente (`--gc-hd-h`), não chutada, porque depende da fonte e do zoom. */
.gc-mx tr.gc-rwrow th { top:var(--gc-hd-h, 8.75rem); z-index:2; }
.gc-mx thead th.gc-rowh { z-index:4; }
.gc-mx tr.gc-rwrow th.gc-rowh { z-index:5; }
/* Fundo OPACO obrigatório: a coluna fixa cobre as células que passam por
   baixo no scroll horizontal. Nunca usar --gc-ink-2/--gc-ink-3 aqui (são rgba). */
.gc-mx thead th.gc-rowh { border-right:var(--bs-border-width) solid var(--gc-line-2); text-align:left; padding-left:0.875rem; width: 14.75rem; cursor:default;
  position:sticky; left:0; z-index:3; background:var(--bs-gray-100); }
.gc-mx thead th:not(.gc-rowh):hover { color:var(--gc-accent); background:var(--gc-panel-3); }
/* Ponto de risco no cabeçalho da bitola — canal não-cromático (ADR-006).
   Carrega sozinho o nível "alerta", que perdeu a cor de número quando a
   paleta virou Bootstrap (--bs-warning é ilegível como texto, mas como
   preenchimento de um ponto de 5px tem contraste de sobra). */
.gc-mx thead th .gc-rd { display:inline-block; width: 0.3125rem; height: 0.3125rem; border-radius:50%;
  margin-right:0.25rem; vertical-align:middle; }
.gc-mx thead th .gc-rd--critico { background:var(--bs-danger); }
.gc-mx thead th .gc-rd--alerta  { background:var(--bs-warning); }
/* Régua nos dois eixos (decisão do usuário): a matriz é lida célula a célula
   contra o Sênior, e a coluna precisa ser tão delimitada quanto a linha. */
.gc-mx tbody td { border-bottom:var(--bs-border-width) solid var(--gc-line-2);
  border-right:var(--bs-border-width) solid var(--gc-line-2); }
.gc-mx td.gc-k { border-right:var(--bs-border-width) solid var(--gc-line-2); padding:0.4375rem 0.625rem 0.4375rem 0.875rem; color:var(--gc-ink); font-weight:600; font-size: var(--bi-fs-compact); width: 14.75rem;
  white-space:normal; line-height:1.2; position:sticky; left:0; z-index:2; background:var(--bs-gray-100); }
.gc-mx td.gc-k .gc-kx { display:block; color:var(--gc-ink-3); font-weight:400; font-size: var(--bi-fs-micro); margin-top:0; }
.gc-mx td.gc-cell { text-align:right; padding:0.4375rem 0.625rem; line-height:1.45; }
.gc-cv { font-family:var(--mono); font-variant-numeric:tabular-nums; font-size: var(--bi-fs-compact); }
.gc-cv.gc-z { color:var(--bs-gray-500); }
/* Segunda linha da célula: o dinheiro do pedido firme. Menor e cinza — o peso
   continua sendo a grandeza da tela; o valor é contexto, não concorrente. */
.gc-cr { display:block; font-family:var(--mono); font-size: var(--bi-fs-micro); line-height:1.2;
  font-variant-numeric:tabular-nums; color:var(--gc-ink-3); }
/* Nível ALERTA (saldo positivo, mas abaixo dos pedidos já firmes). Era número
   preto — igual a uma linha qualquer — porque --bs-warning reprova contraste
   como texto; `--warning-text` é o amarelo escurecido do app, feito para isto,
   e o preenchimento suave garante que o nível não dependa só da cor do
   algarismo (ADR-006: o ponto do cabeçalho continua como canal não-cromático). */
.gc-cv.gc-cv--alerta { color:var(--warning-text); font-weight:700; }
/* Precisa vencer `.gc-mx tr.gc-result td` (mesma célula, banda do resultado),
   que é mais específica — sem os dois seletores o preenchimento não aparecia. */
.gc-mx td.gc-cell--alerta,
.gc-mx tr.gc-result td.gc-cell--alerta { background:var(--warning-subtle); }
.gc-bh--alerta .gc-bh__num { color:var(--warning-text); }
/* bandas: zona (forte) e grupo (leve) */
.gc-mx tr.gc-zone td { background:var(--gc-panel-3); color:var(--gc-ink-2); font-size: var(--bi-fs-micro); letter-spacing:.1em;
  text-transform:uppercase; font-weight:700; text-align:left; padding:0.375rem 1rem;
  border-top:var(--bs-border-width) solid var(--gc-line); border-bottom:var(--bs-border-width) solid var(--gc-line); }
/* Rótulo da banda (PASSADO/FUTURO) fixo à esquerda no scroll horizontal. A
   célula é colspan de largura total (sem folga p/ `sticky` nela mesma), então
   quem gruda é o SPAN interno — mais estreito que a célula, ele tem folga p/
   ficar em left:18px (alinhado ao recuo da coluna Indicador) ao arrastar a
   matriz no mobile. O fundo opaco `--gc-panel-3` da célula cobre o que passa por baixo. */
.gc-mx tr.gc-zone td .gc-zone__lbl { position:sticky; left:18px; display:inline-block; }
/* Contexto da banda ("· jul/26, fecha no estoque atual") em caixa normal: a
   faixa inteira em caixa-alta com travessões pesava como título de seção. */
.gc-mx tr.gc-zone .gc-zone__ctx { font-size: var(--bi-fs-compact); font-weight:400; letter-spacing:0;
  text-transform:none; color:var(--gc-ink-3); }
/* Dobradiça (Estoque atual) e resultado (Saldo projetado / se converter) pesam
   por SUPERFÍCIE. As duas réguas vermelhas em volta do saldo gritavam mais que
   os próprios números, que já são a única coisa colorida da matriz. */
.gc-mx tr.gc-hinge td, .gc-mx tr.gc-hinge td.gc-k { background:var(--gc-panel-3); }
.gc-mx tr.gc-hinge td.gc-k { font-weight:700; }
.gc-mx tr.gc-result td, .gc-mx tr.gc-result td.gc-k { background:var(--gc-panel-3); }
.gc-mx tr.gc-result td { border-top:var(--bs-border-width) solid var(--gc-ink-3); }
.gc-mx tr.gc-result td.gc-k { font-weight:700; }
.gc-mx tr.gc-result .gc-cv { font-weight:700; font-size: var(--bi-fs-compact); }
.gc-mx tr.gc-dim td.gc-k { color:var(--gc-ink-2); font-weight:400; }
.gc-mx tr.gc-dim .gc-cv { color:var(--gc-ink-3); }
/* ── Mira ────────────────────────────────────────────────────────────────── */
/* Hover acende a linha inteira e a coluna inteira: em 13 colunas é o que
   impede ler o número de uma bitola na linha de outra. */
/* Classes `bi-mira-*` vêm de `biUtils.ligarMira`, compartilhado com a Curva ABC
   e as Metas por Vendedor; a TINTA é de cada página. */
.gc-mx tbody tr.bi-mira-linha td, .gc-mx tbody tr.bi-mira-linha td.gc-k { background:var(--gc-panel-3); }
.gc-mx tbody td.bi-mira-coluna { background:var(--gc-panel-3); }
.gc-mx thead th.bi-mira-coluna { box-shadow: inset 0 -2px 0 var(--gc-accent); }

/* Divisor do mês corrente na tira de meses: à esquerda fechado, à direita
   projeção. */
.gc-mdiv { flex:0 0 auto; align-self:stretch; width:var(--bs-border-width); background:var(--gc-line); margin:0.25rem 0.375rem; }

/* afford: célula viva clicável (recorte L3) */
.gc-mx td.gc-cell.gc-hot { cursor:pointer; }
.gc-mx td.gc-cell.gc-hot:hover { background:var(--acc-soft); box-shadow: inset 0 0 0 var(--bs-border-width) var(--gc-accent); }
/* Origem do drill: fica acesa enquanto o painel lateral mostra o conteúdo dela. */
.gc-mx td.gc-sel, .gc-mx td.gc-cell.gc-sel { box-shadow: inset 0 0 0 2px var(--gc-accent); }
.gc-mx tbody tr:not(.gc-band):not(.gc-zone):not(.gc-dim) td.gc-k { cursor:pointer; }
.gc-mx tbody tr:not(.gc-band):not(.gc-zone):not(.gc-dim) td.gc-k:hover { color:var(--gc-accent); }

/* ── Linha "carregando" (Task 7) ─────────────────────────────────────────── */
/* A fase que preenche esta linha ainda não chegou (backend manda
   `pendente:true`, sem `valores`) — sem drill, sem hover, só uma barra de
   esqueleto por célula no lugar do número. */
.gc-mx tr.gc-pendente td.gc-k { color:var(--gc-ink-3); font-weight:400; cursor:default; }
.gc-mx tr.gc-pendente td.gc-cell { cursor:default; }
.gc-skel { display:inline-block; width:2.5rem; height:0.625rem; border-radius:var(--bs-border-radius-sm);
  background:linear-gradient(90deg, var(--gc-panel-3) 25%, var(--gc-line) 50%, var(--gc-panel-3) 75%);
  background-size:200% 100%; animation:gc-skel-shimmer 1.4s ease-in-out infinite; }
@keyframes gc-skel-shimmer { 0% { background-position:200% 0; } 100% { background-position:-200% 0; } }
@media (prefers-reduced-motion: reduce) {
  .gc-skel { animation:none; background:var(--gc-panel-3); }
}

/* ── Degradação Conexos ──────────────────────────────────────────────────── */
/* Banner de degradação: cor e contraste vêm de .alert-warning (Bootstrap);
   aqui só o layout em linha e o encaixe edge-to-edge dentro do card. */
.gc-degraded { display:flex; align-items:center; gap:0.5rem; margin:0;
  border-radius:0; border-left:0; border-right:0; border-top:0;
  font-size:0.875rem; font-weight:600; }
.gc-degraded i { flex:0 0 auto; }
/* Aviso de fonte fora do ar colado no subtítulo do cabeçalho ("Conexos
   indisponível"): o único espaço que separava os dois era o do HTML. */
.gc-zwarn { margin-left:0.5rem; }

/* (Overlay/diálogo/tabela de drill `.gc-ov/.gc-dlg/.gc-dt/.gc-drow` removidos —
   o drill agora usa o modal-padrão compartilhado abaixo, `biUtils.gridModal`.) */

/* === MODAL PADRÃO (biUtils.modalPadrao / gridModal) ============================
   Shell Bootstrap único (header/body/footer, título "Assunto — Item") + corpo de
   GRADE ordenável com thead/tfoot fixos. Body-appended → só tokens de :root
   (--gc-ink, --gc-line, --mono e variantes); nada de --gc-panel/--gc-accent (esses são
   .gc-scoped). NÃO escreva "asterisco+barra" dentro de comentário: fecha o
   comentário cedo e a regra seguinte some silenciosamente. */
/* Altura presa à viewport e UM só scroller: a grade. O corpo vira coluna flex que
   não rola; resumo, abas, pills e paginação ficam parados, e a sobra vai para o
   scroller da tabela (`.datatable-scroll` do DataTables ou `.fcds-gm__wrap` do
   gridModal), que rola com `thead` e `tfoot` grudados.
   Esta cadeia é o que sustenta o cabeçalho fixo — sem ela quem rola é o
   `.modal-body`, e aí `position:sticky` do `thead` não tem contra o que grudar e
   o cabeçalho da grade sai de vista. Cada seletor da lista do meio é um container
   intermediário que precisa repassar a altura adiante; um elo de fora e a altura
   morre ali (foi o que aconteceu com o `div` cru do `frameGrade`, que passou a
   levar `.fcds-modal__pane` justamente para entrar aqui). */
.fcds-modal .modal-body { display:flex; flex-direction:column; overflow:hidden; }
.fcds-modal .modal-body > * { flex:0 0 auto; }
.fcds-modal .tab-content,
.fcds-modal .tab-pane.active,
.fcds-modal [data-razao],
.fcds-modal [data-movimentos],
.fcds-modal .tbl-wrapper.datatable,
.fcds-modal .tbl-wrapper.datatable > .dataTables_wrapper,
.fcds-modal .fcds-modal__pane {
  display:flex; flex-direction:column; flex:1 1 auto; min-height:0;
}
.fcds-modal .datatable-scroll,
.fcds-modal .fcds-gm__wrap { flex:1 1 auto; min-height:0; max-height:none; }
/* Enquanto carrega, o alvo do loader recobra a reserva de altura — o
   `min-height:0` do item flex acima esmagaria o logo-loader a zero. */
.fcds-modal [data-bi-loading="tape"] { min-height: 11.75rem; }
/* Ícone de AÇÃO usa a cor de ação, não o cinza do shell: voltar e "mais info"
   são as duas coisas clicáveis do corpo, e vestidas de --gc-ink-3 liam como
   decoração da moldura. */
.fcds-modal__voltar { border:0; background:transparent; color:var(--brand); cursor:pointer; padding:0 0.25rem; font-size:1rem; line-height:1; }
.fcds-modal__voltar:hover { color:var(--brand-ink); }
/* Metadado recua para 13px: antes era 20px, o MESMO tamanho do título, e assunto
   e contexto competiam. Rende mais no drill de estoque, cujo item é a descrição
   inteira do produto e quebrava o header em duas linhas (93px). */
.fcds-modal__item { color:var(--gc-ink-3); font-weight:400; font-size: var(--bi-fs-compact); }
/* (A cifra do header saiu junto com o markup: era o mesmo número do TOTAL do
   rodapé, repetido a dois centímetros de distância.) */
/* (O `padding:0` que fazia a grade sangrar de borda a borda saiu: o corpo usa a
   calha de 1rem do Bootstrap como qualquer outro modal.) */
/* (A regra que escondia o rodapé no corpo de grade saiu: o shell do
   `modalPadrao` não emite mais `.modal-footer` nenhum, então ela não tinha
   sobre o que agir.) */
/* `flex:0 0 auto`: a faixa de abas é irmã do pane dentro de um `.fcds-modal__pane`
   (coluna flex). Sem isto ela encolheria junto com a grade ao faltar altura. */
.fcds-modal__tabs { padding:0.25rem 1rem 0; margin:0; flex:0 0 auto; }
.fcds-modal__tabs .nav-link { font-size: var(--bi-fs-compact); padding:0.25rem 0.625rem; color:var(--gc-ink-3); }
.fcds-modal__tabs .nav-link.active { color:var(--gc-ink); font-weight:700; }
/* (A faixa de escopo saiu: o recorte por bitola virou parte do TÍTULO do painel,
   e "ver todas as bitolas" já era o clique no rótulo da linha na matriz.) */
/* ── Chassi LATERAL (biUtils.gridPainel) ─────────────────────────────────── */
/* Mesmo corpo de grade do modal, moldura diferente: painel ancorado à direita
   que DOCA — `.main` cede a largura em vez de ficar coberto. Nasceu da matriz
   do gerencial, onde o gesto é comparar célula a célula: com modal, cada
   comparação custava abrir-fechar-abrir e a origem do drill ficava tapada.
   Alinhado ao rail lateral (abaixo da topbar sticky, que continua clicável). */
.fcds-lateral { position:fixed; top:52px; right:0; height:calc(100vh - 52px);
  width:var(--fcds-lateral-w, min(32.5rem, 92vw)); z-index:30; visibility:hidden; transform:translateX(100%);
  transition:transform .22s cubic-bezier(.22,1,.36,1), visibility .22s, width .22s cubic-bezier(.22,1,.36,1); }
.fcds-lateral[data-aberto] { transform:none; visibility:visible; }
.fcds-lateral .modal-content { height:100%; background:var(--surf); border:0;
  border-left:var(--bs-border-width) solid var(--gc-line);
  border-radius:0; box-shadow:-1rem 0 2.5rem rgba(16,24,40,.10); }
/* Calhas EXPLÍCITAS. `.fcds-lateral` é um <aside>, não um `.modal`, então as
   custom properties `--bs-modal-*` não resolvem e o padding do header/body do
   Bootstrap cai para zero: título e botão de fechar nasciam colados na borda.
   Uma calha só (1rem) alinha título, chip de escopo e 1ª coluna da grade. */
.fcds-lateral .modal-header { padding:0.875rem 1rem 0.625rem; gap:0.5rem; align-items:flex-start;
  border-bottom:var(--bs-border-width) solid var(--gc-line-2); }
.fcds-lateral .fcds-modal__titulo { margin:0; line-height:1.3; }
.fcds-lateral .btn-close { margin:0.125rem 0 0 auto; flex:0 0 auto; }
/* Corpo sem calha própria: a grade sangra de borda a borda e quem dá o recuo
   é a 1ª/última célula (1rem), senão o texto da tabela ficaria 32px para
   dentro enquanto o título fica em 16px. */
.fcds-lateral .modal-body { padding:0; }
/* No painel a largura é curta: coluna de texto encolhe com reticências em vez
   de empurrar a grade para o scroll horizontal — que jogava o TOTAL do rodapé
   para fora de vista. O texto inteiro fica no `title` da célula. */
.fcds-lateral .fcds-gm td:not(.fcds-gm__num) { max-width:15rem; overflow:hidden; text-overflow:ellipsis; }
.fcds-lateral .fcds-gm thead th { padding-top:0.375rem; padding-bottom:0.375rem; }
.fcds-lateral .fcds-gm tbody td { padding-top:0.3125rem; padding-bottom:0.3125rem; }
.fcds-lateral .fcds-gm tfoot td { padding-top:0.4375rem; padding-bottom:0.4375rem; }
.main { transition:margin-right .22s cubic-bezier(.22,1,.36,1); }
body[data-lateral] .main { margin-right:var(--fcds-lateral-w, min(32.5rem, 92vw)); }
/* Docar exige rail (3rem) + calhas (2.5rem) + o piso da matriz + o painel mais
   largo (42rem) — ~106.75rem. Abaixo disso ceder a largura não "abre espaço",
   espreme: a 1366px sobravam 606px de matriz e a célula que originou o drill
   saía de vista. Então o painel SOBREPÕE, como já fazia no mobile. */
@media (max-width:106.75rem) {
  body[data-lateral] .main { margin-right:0; }
}
@media (prefers-reduced-motion: reduce) {
  /* `.side` e `.subnav` são o SHELL, e não estavam cobertos por nenhum dos
     blocos de reduced-motion do arquivo: `.fcds-lateral` é outra classe, e os
     blocos por página (`[data-pagina="crm-deal"] *`, por exemplo) ficam presos
     à `div.page`, que é descendente do `main` — a sidebar mora fora dela.
     Resultado medido: a sidebar animava `width` (.26s) e cada `.subnav`
     animava `max-height` (.24s) mesmo com o sistema pedindo movimento
     reduzido, em toda página do app. São propriedades de LAYOUT, as que mais
     incomodam quem pediu para reduzir. */
  .fcds-lateral, .main, .side, .subnav { transition:none; }
}

.fcds-gm__wrap { overflow:auto; }
table.fcds-gm { border-collapse:collapse; width:100%; font-size: var(--bi-fs-compact); }
/* `text-align:left` NÃO volta aqui: `td` já é left por default do navegador, e a
   declaração só existia para — sem querer — vencer `.fcds-gm__num` (0,1,1 > 0,1,0).
   Era por isso que Qtd, R$ e data nunca alinharam à direita. O `th` precisa da
   declaração porque `th` é center por default.
   `border-right` também sai: com 7 colunas × 100+ linhas o quadriculado vira ruído.
   Quem separa o bloco numérico do bloco de texto agora é o respiro de §num. */
.fcds-gm th, .fcds-gm td { padding:0.25rem 0.625rem; white-space:nowrap; line-height:1.4;
  border-bottom:var(--bs-border-width) solid var(--gc-line-2); }
.fcds-gm th { text-align:left; }
.fcds-gm tbody td:first-child, .fcds-gm thead th:first-child, .fcds-gm tfoot td:first-child { padding-left:1rem; }
.fcds-gm tbody td:last-child, .fcds-gm thead th:last-child, .fcds-gm tfoot td:last-child { padding-right:1rem; }
/* Coluna numérica ganha 6px a mais à esquerda: é o espaçamento que assume o
   trabalho da régua vertical removida. Sem ele, "12,7mm" cola em "39,6". */
.fcds-gm th.fcds-gm__num, .fcds-gm td.fcds-gm__num { text-align:right; padding-left:1rem;
  font-family:var(--mono); font-variant-numeric:tabular-nums; }
.fcds-gm thead th { position:sticky; top:0; z-index:2; background:var(--surf); cursor:pointer; user-select:none;
  padding-top:0.375rem; padding-bottom:0.375rem;
  font-size: var(--bi-fs-micro); letter-spacing:.09em; text-transform:uppercase; color:var(--gc-ink-3);
  font-weight:700; border-bottom:var(--bs-border-width) solid var(--gc-line); }
.fcds-gm thead th:hover { color:var(--gc-ink); }
.fcds-gm thead th:focus-visible { outline:2px solid var(--acc); outline-offset:-2px; }
/* Seta de ordenação em slot de largura fixa — sem isto o cabeçalho reflowa a cada
   clique, porque a seta era concatenada ao texto. */
.fcds-gm__seta { display:inline-block; width:0.75rem; text-align:center; opacity:0.8; }
/* Total lê como banda: fundo próprio e régua de 1px (era 2px), sem peso extra. */
.fcds-gm tfoot td { position:sticky; bottom:0; z-index:2; background:var(--surf-2); font-weight:700;
  padding-top:0.3125rem; padding-bottom:0.3125rem; border-top:var(--bs-border-width) solid var(--gc-ink); }
.fcds-gm tbody tr:hover td { background:var(--gc-line-2); }
.fcds-gm__acao { width: 2.75rem; text-align:center; }
.fcds-gm__info { border:0; background:transparent; color:var(--brand); cursor:pointer; padding:0; font-size:1rem; line-height:1; }
.fcds-gm__info:hover { color:var(--brand-ink); }

/* ── Responsivo ──────────────────────────────────────────────────────────── */
@media (max-width:575.98px) {
  /* Calha 16px → 12px nas faixas próprias do componente; o cabeçalho ficou com a
     do Bootstrap. As faixas rolam na horizontal em vez de quebrar linha. */
  .fcds-modal__tabs { padding-left:0.75rem; padding-right:0.75rem;
    flex-wrap:nowrap; overflow-x:auto; }
  .fcds-gm th, .fcds-gm td { padding-left:0.5rem; padding-right:0.5rem; }
  .fcds-gm th.fcds-gm__num, .fcds-gm td.fcds-gm__num { padding-left:0.75rem; }
  .fcds-gm tbody td:first-child, .fcds-gm thead th:first-child, .fcds-gm tfoot td:first-child { padding-left:0.75rem; }
  .fcds-gm tbody td:last-child, .fcds-gm thead th:last-child, .fcds-gm tfoot td:last-child { padding-right:0.75rem; }
  .gc-mx td.gc-k, .gc-mx thead th.gc-rowh { width: 9.375rem; }
  .gc-mx col.gc-c-rowh { width: 9.375rem; }
}

/* ── Aba Metas (gerência 26/08): realizado × em negociação × meta ─────────── */
.gc-metas { padding: 1rem 1.25rem 1.25rem; }
.gc-metas__bar { display:flex; align-items:center; gap:0.625rem; flex-wrap:wrap;
  margin-bottom: 0.875rem; }
.gc-metas__ttl { margin: 0.875rem 0 0.375rem; font-size: var(--bi-fs-caption, 0.75rem);
  font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--bs-secondary-color, #6c757d); }
.gc-mtable { max-width: 68.75rem; margin-bottom: 0.25rem; }
.gc-mtable td, .gc-mtable th { vertical-align: middle; }
/* Mesma inversão da matriz: R$ é o número principal, tonelada é a linha de
   apoio (.gc-cr, compartilhada com a célula da matriz). */
.gc-mtv { font-family: var(--mono); font-variant-numeric: tabular-nums; }
.gc-mtotal td { font-weight: 600; border-top: 2px solid var(--bs-border-color, #dee2e6); }

/* ===== MERGED FROM bi/static/bi/css/inadimplencia.css (P5 — page-local dissolve) ===== */
/* ── Foco banner (FCDS inline status / active-filter banner) ─────────────── */

.foco-banner {
  margin:var(--bi-space-sm) var(--bi-space-md);
  padding:var(--bi-space-xs2) var(--bi-space-sm);
  border: var(--bs-border-width) solid color-mix(in srgb, var(--brand, var(--bi-text-primary)) 22%, transparent);
  border-radius: var(--bi-radius-sm);
  background: color-mix(in srgb, var(--brand, var(--bi-text-primary)) 6%, white);
  color: var(--bi-text-primary);
  font-size: var(--bi-fs-caption);
}

.foco-banner__clear {
  margin-left:var(--bi-space-sm);
  padding:0;
  border: 0;
  background: none;
  color: var(--brand, var(--negative-text));
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}

/* ── Ranked list-row component (aging faixas + devedores) ─────────────────── */
/* Generated by inadimplencia.js (renderizarAgingTable / renderizarDevedores);
   this file is the sole definition — do not delete while that markup exists.   */

.top5__row {
  padding:var(--bi-space-sm) var(--bi-space-md);
  border-bottom: var(--bs-border-width) solid var(--line);
  border-left: 3px solid transparent;
  cursor: pointer;
  transition: background 120ms ease, border-left-color 120ms ease;
}

.top5__row:hover {
  background: var(--surf-2);
}

.top5__row--ativo {
  background: color-mix(in srgb, var(--negative-text) 6%, white);
  border-left-color: var(--negative-text);
}

/* Aging active uses per-faixa severity color (--faixa-cor set inline by JS) */
#bi-aging-lista .top5__row--ativo {
  background: color-mix(in srgb, var(--faixa-cor, var(--negative-text)) 8%, white);
  border-left-color: var(--faixa-cor, var(--negative-text));
}

.top5__rank {
  font-size: var(--bi-fs-caption);
  color: var(--bi-text-muted);
  font-weight: var(--bi-fw-semibold);
  flex-shrink: 0;
}

.top5__nome {
  font-size: var(--bi-fs-body);
  font-weight: var(--bi-fw-medium);
  color: var(--bi-text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  min-width: 0;
}

.top5__row--ativo .top5__nome {
  color: var(--negative-text);
}

.top5__valor {
  font-family: var(--sans);
  font-size: 1.25rem;
  font-weight: var(--bi-fw-bold);
  color: var(--negative-text);
  line-height: 1;
  letter-spacing: -0.01em;
  white-space: nowrap;
  flex-shrink: 0;
}

.top5__bar-track { --barra-altura: 0.375rem; --barra-cor: var(--negative-text); margin-top:var(--bi-space-xs2); }

/* ── 2×2 analysis cards: equal-height scroll bodies ──────────────────────── */
/* The aging + devedores list bodies use the shared .card-scroll utility
   (custom.css) so they cap at --bi-scroll-cap and read at one height.
   See bi/templates/bi/inadimplencia.html (#bi-aging-card-body, #bi-top-clientes). */

/* ===== MERGED FROM bi/static/bi/css/mercado-importacao.css (P5 — page-local dissolve) ===== */
/* ============================================================================
   Mercado de Importação — folha de estilo própria da tela (rebuild "do zero").
   NÃO depende de main.css nem dos componentes legados (.card/.rank/.grid).
   Linguagem MODERNA: superfícies brancas macias, muito respiro, tipografia
   confiante (Roboto em numerais e corpo), paleta contida,
   barras desenhadas à mão (sem o visual padrão do Chart.js), micro-motion.

   Perspectiva: briefing competitivo de preço (inspirado no deck Logcomex
   FOUR × AWA × South Service) — veredito de preço como tese, estrutura de
   mercado como apoio. Tudo escopado em `.mx` para não vazar para o resto do app.
   ========================================================================== */

.mx {
  /* superfícies — CONSOLIDADO 2026-08-06 (DESIGN.md §6): os sete tokens de
     estrutura eram cópias a Δ≤10 dos globais; viram alias para matar a deriva
     sem tocar nas ~40 regras da página. --mx-ink-3 era #98a1ae (~2,6:1 como
     texto, reprova AA) e agora lê o --ink-3 global — a única mudança visível. */
  --mx-panel: var(--surf);
  --mx-inset: var(--surf-2);    /* trilhos de barra, insets */
  --mx-ink: var(--ink);
  --mx-ink-2: var(--ink-2);
  --mx-ink-3: var(--ink-3);
  --mx-line: var(--line-2);
  --mx-line-2: var(--line-3);

  /* identidade / papéis (cor com significado — é DADO, fica) */
  --mx-four: #006bb5;           /* FOUR — azul da marca */
  --mx-rival: #d97706;          /* concorrente nomeado — âmbar */
  --mx-other: #7c8aa0;          /* demais importadores — slate sólido (não "disabled") */
  --mx-bar: #2f7dc4;            /* barras de ranking neutras — azul confiante */

  /* veredito = DIREÇÃO: alias da família global (era um rosa-vermelho e um
     esmeralda próprios — terceira família para dizer bom/ruim). Os pares
     *-soft morreram sem uso, junto com --mx-shadow e os -soft de identidade. */
  --mx-up: var(--negative-text);    /* mais cara = ruim */
  --mx-down: var(--positive-text);  /* mais barata = bom */

  /* Raio e sombra próprios REMOVIDOS 2026-08-07 (decisão do dono, DESIGN.md
     §4/A Regra do Plano): raio lê o global, sombra vira borda hairline. */
  --mx-radius: var(--r);
  --mx-radius-sm: var(--r-sm);
  --mx-radius-xs: var(--r-xs);
  --mx-gap:clamp(1rem, 1.4vw + 0.5rem, 1.5rem);

  color: var(--mx-ink);
  font-variant-numeric: tabular-nums;
}

.mx *,
.mx *::before,
.mx *::after { box-sizing: border-box; }

.mx-body[hidden] { display: none; }

/* ── Estado vazio / erro ──────────────────────────────────────────────────── */
.mx-empty {
  margin-top:var(--mx-gap);
  padding:clamp(1.5rem, 6vw, 3rem) 1.5rem;
  background: var(--mx-panel); border-radius: var(--mx-radius);
  border: 1px solid var(--line);
  text-align: center; color: var(--mx-ink-2); font-size: 1rem; line-height: 1.6;
}

/* ════════════════════════════════════════════════════════════════════════════
   MASTHEAD — identidade do relatório + tamanho do mercado
   ════════════════════════════════════════════════════════════════════════════ */
.mx-mast {
  display: flex; align-items: flex-end; justify-content: space-between;
  flex-wrap: wrap; gap:1rem 3rem;
  padding:0.25rem 0 1.5rem;
}
.mx-mast__id { min-width: 0; }
.mx-mast__title {
  margin:0; font-family: var(--bi-font-display); font-weight: 600;
  font-size: clamp(2rem, 1.2rem + 3.2vw, 3.3rem); line-height: 0.98;
  letter-spacing: -0.015em; color: var(--mx-ink); text-wrap: balance;
}
/* faixa de totais do mercado — chips suaves */
.mx-totals { display: flex; flex-wrap: wrap; gap:0.5rem; margin:0; }
.mx-tot {
  display: flex; flex-direction: column; gap:0;
  padding:0.5rem 1rem; background: var(--mx-panel); border-radius: var(--mx-radius-xs);
  border: 1px solid var(--line);
}
.mx-tot__l { font-size: 0.875rem; font-weight: 600; letter-spacing: 0.03em; text-transform: uppercase; color: var(--mx-ink-3); white-space: nowrap; }
.mx-tot__v { font-family: var(--bi-font-display); font-weight: 600; font-size: 1.25rem; line-height: 1; color: var(--mx-ink); white-space: nowrap; }
.mx-tot--lead { background: var(--mx-four); }
.mx-tot--lead .mx-tot__l { color: rgba(255, 255, 255, .78); }
.mx-tot--lead .mx-tot__v { color: var(--bi-text-on-accent); font-size: 1.5rem; }

/* ════════════════════════════════════════════════════════════════════════════
   VEREDITO — a tese da página (assinatura)
   ════════════════════════════════════════════════════════════════════════════ */
/* Bordo/bg/radius/sombra vêm de .card.shadow-sm.border-0 (aplicado no
   template); aqui só o residual sem primitiva: grid interno de 2 colunas +
   espaçamentos responsivos (clamp) que o .card fixo não cobre. */
.mx-verdict {
  display: grid; grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  gap:clamp(1.5rem, 3vw, 3rem);
  margin-top:var(--mx-gap);
  padding:clamp(1.5rem, 2.4vw, 3rem);
}
.mx-verdict__kick {
  display: block; font-size: 0.875rem; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--mx-ink-3); margin-bottom:1rem;
}
.mx-verdict__headline {
  margin:0 0 1.5rem; display: flex; align-items: baseline; flex-wrap: wrap; gap:0 1rem;
  line-height: 0.9;
}
.mx-delta {
  font-family: var(--bi-font-display); font-weight: 700;
  font-size: clamp(3.2rem, 2rem + 6vw, 6rem); line-height: 0.84; letter-spacing: -0.03em;
  color: var(--mx-ink);
}
.mx-delta--up { color: var(--mx-up); }
.mx-delta--down { color: var(--mx-down); }
.mx-delta--brand { color: var(--mx-four); }
.mx-verdict__word {
  font-size: clamp(1.15rem, 0.8rem + 1.1vw, 1.7rem); font-weight: 600; color: var(--mx-ink);
  max-width: 18ch;
}
.mx-verdict__word b { font-weight: 700; }

/* head-to-head: FOUR vs rival mais barato (o callout do deck) */
.mx-h2h { display: flex; flex-direction: column; gap:0.5rem; max-width: 28.75rem; }
.mx-h2h__row { display: grid; grid-template-columns: 4rem 1fr auto; align-items: center; gap:0.5rem; }
.mx-h2h__name { font-size: 0.875rem; font-weight: 700; letter-spacing: 0.02em; text-transform: uppercase; color: var(--mx-ink-2); }
.mx-h2h__row--four .mx-h2h__name { color: var(--mx-four); }
.mx-h2h__row--rival .mx-h2h__name { color: var(--mx-rival); }
.mx-h2h__track { height: 0.875rem; --bs-progress-bg: var(--mx-inset); border-radius: var(--raio-chip); }
.mx-h2h__fill { border-radius: var(--raio-chip); transform-origin: left center; }
.mx-h2h__row--four .mx-h2h__fill { --bs-progress-bar-bg: var(--mx-four); }
.mx-h2h__row--rival .mx-h2h__fill { --bs-progress-bar-bg: var(--mx-rival); }
.mx-h2h__val { font-family: var(--bi-font-display); font-weight: 600; font-size: 1rem; color: var(--mx-ink); white-space: nowrap; }
.mx-h2h__foot { margin:0.25rem 0 0; font-size: 0.875rem; color: var(--mx-ink-3); }

/* coluna direita: fatia + rank */
.mx-verdict__stats {
  display: flex; flex-direction: column; justify-content: center; gap:1.5rem;
  padding-left:clamp(1.5rem, 3vw, 3rem); border-left: var(--bs-border-width) solid var(--mx-line);
}
.mx-stat { display: flex; flex-direction: column; gap:0.25rem; }
.mx-stat__v { font-family: var(--bi-font-display); font-weight: 700; font-size: clamp(2.2rem, 1.4rem + 2.4vw, 3.1rem); line-height: 0.92; letter-spacing: -0.02em; color: var(--mx-ink); }
.mx-stat--share .mx-stat__v { color: var(--mx-four); }
.mx-stat__l { font-size: 0.875rem; color: var(--mx-ink-2); max-width: 22ch; }

/* ════════════════════════════════════════════════════════════════════════════
   PAINEL genérico + cabeçalho
   ════════════════════════════════════════════════════════════════════════════ */
/* Bordo/bg/radius/sombra e a estrutura cabeçalho+corpo vêm de
   .card.shadow-sm.border-0 > .card-header (+ utilities d-flex/justify-
   content-between/align-items-baseline/flex-wrap/gap-2) > .card-body,
   aplicado direto no template. .card já é flex-column e .card-body já é
   flex:1 1 auto (Bootstrap), então os painéis de gráfico (ex-.mx-panel--chart)
   não precisam mais de regra própria — só ganham a classe `d-flex` no
   .card-body para os filhos que crescem (.mx-spark/.mx-transporte, abaixo)
   se esticarem dentro dele. Residual: min-width:0 evita overflow do item
   dentro do CSS Grid (.mx-grid), efeito que o .card sozinho não resolve. */
.mx-panel { min-width: 0; }
.mx-panel__title { margin:0; font-size: 1rem; font-weight: 700; letter-spacing: -0.01em; color: var(--mx-ink); }
.mx-panel__note { font-size: 0.875rem; color: var(--mx-ink-3); }

/* ── Escada de preços (painel destacado) ──────────────────────────────────── */
.mx-ladder { margin-top:var(--mx-gap); }
.mx-legend { display: flex; flex-wrap: wrap; gap:0.5rem 1rem; margin:-0.25rem 0 1rem; }
.mx-legend__i { display: inline-flex; align-items: center; gap:0.5rem; font-size: 0.875rem; color: var(--mx-ink-2); }
.mx-legend__i::before { content: ''; width: 0.6875rem; height: 0.6875rem; border-radius: var(--bs-border-radius-sm); }
.mx-legend__i--four::before { background: var(--mx-four); }
.mx-legend__i--rival::before { background: var(--mx-rival); }
.mx-legend__i--other::before { background: var(--mx-other); }

/* toggle preço/peso — pill segmentado moderno */
.mx-toggle { display: inline-flex; padding:0.25rem; background: var(--mx-inset); border-radius: var(--raio-chip); }
.mx-toggle__b {
  /* borda transparente reserva o 1px do estado ligado — sem pulo de layout */
  appearance: none; border: 1px solid transparent; background: transparent; cursor: pointer;
  font: inherit; font-size: 0.875rem; font-weight: 600; color: var(--mx-ink-2);
  padding:0.25rem 1rem; border-radius: var(--raio-chip); transition: background .18s ease, color .18s ease;
}
.mx-toggle__b[aria-pressed="true"] { background: var(--mx-panel); color: var(--mx-ink); border-color: var(--line-3); }
.mx-toggle__b:focus-visible { outline: 2px solid var(--mx-four); outline-offset: 2px; }

/* barras horizontais da escada */
.mx-bars { display: flex; flex-direction: column; gap:1rem; }
.mx-bar { display: grid; grid-template-columns: minmax(6.875rem, 10.5rem) 1fr; align-items: center; gap:1rem; }
.mx-bar__name { font-size: 0.875rem; color: var(--mx-ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mx-bar--self .mx-bar__name { font-weight: 700; color: var(--mx-four); }
.mx-bar__track { position: relative; display: flex; align-items: center; gap:0.5rem; }
.mx-bar__fill { flex: 0 0 auto; height: 1.625rem; border-radius: var(--bs-border-radius-lg); transform-origin: left center; min-width: 0.1875rem; }
.mx-bar__fill--four { background: var(--mx-four); }
.mx-bar__fill--rival { background: var(--mx-rival); }
.mx-bar__fill--other { background: var(--mx-other); }
.mx-bar__val { font-family: var(--bi-font-display); font-weight: 600; font-size: 1rem; color: var(--mx-ink); white-space: nowrap; }

/* ════════════════════════════════════════════════════════════════════════════
   SEÇÕES + GRID
   ════════════════════════════════════════════════════════════════════════════ */
.mx-sec { display: flex; align-items: baseline; gap:0.5rem; margin:clamp(1.5rem, 4vw, 3rem) 0 0; }
.mx-sec__t { margin:0; font-family: var(--bi-font-display); font-weight: 600; font-size: 1.5rem; letter-spacing: -0.01em; color: var(--mx-ink); }
.mx-sec__s { font-size: 0.875rem; color: var(--mx-ink-3); }

.mx-grid { display: grid; gap:var(--mx-gap); margin-top:var(--mx-gap); }
.mx-grid--8-4 { grid-template-columns: 2fr 1fr; }
.mx-grid--2 { grid-template-columns: 1fr 1fr; }

/* ── Lista ranqueada (própria — substitui .rank) ───────────────────────── */
.mx-rank { display: flex; flex-direction: column; }
.mx-rank__row { padding:0.5rem 0; border-top: var(--bs-border-width) solid var(--mx-line); }
.mx-rank__row:first-child { border-top: 0; }
.mx-rank__top { display: flex; align-items: baseline; gap:0.5rem; margin-bottom:0.5rem; }
.mx-rank__pos { flex-shrink: 0; min-width: 1.375rem; font-family: var(--bi-font-display); font-weight: 600; font-size: 1rem; color: var(--mx-ink-3); }
.mx-rank__name { flex: 1 1 auto; min-width: 0; font-size: 0.875rem; color: var(--mx-ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mx-rank__val { flex-shrink: 0; font-family: var(--bi-font-display); font-weight: 600; font-size: 1rem; color: var(--mx-ink); }
.mx-rank__sub { margin:-0 0 0.5rem 1.5rem; font-size: 0.875rem; color: var(--mx-ink-3); }
.mx-rank__track { height: 0.4375rem; --bs-progress-bg: var(--mx-inset); border-radius: var(--raio-chip); }
.mx-rank__fill { border-radius: var(--raio-chip); --bs-progress-bar-bg: var(--mx-bar); transform-origin: left center; }
.mx-rank__row--self .mx-rank__name { font-weight: 700; color: var(--mx-four); }
.mx-rank__row--self .mx-rank__fill { --bs-progress-bar-bg: var(--mx-four); }
.mx-rank__row--self .mx-rank__pos { color: var(--mx-four); }

/* card-scroll: limita altura de listas longas mantendo painéis alinhados */
.mx-scroll { max-height: 22.5rem; overflow: auto; }
.mx-scroll::-webkit-scrollbar { width: 0.5rem; }
.mx-scroll::-webkit-scrollbar-thumb { background: var(--mx-line-2); border-radius: var(--raio-chip); }

/* ── Tendência mensal (spark de barras verticais — próprio) ───────────────── */
.mx-spark { flex: 1 1 auto; width: 100%; display: flex; align-items: flex-end; justify-content: space-around; gap:clamp(0.5rem, 2vw, 1.5rem); min-height: 13.125rem; padding-top:1.5rem; }
.mx-spark__col { flex: 1 1 0; display: flex; flex-direction: column; align-items: center; gap:0.5rem; height: 100%; justify-content: flex-end; min-width: 0; }
.mx-spark__bar-wrap { flex: 1 1 auto; width: 100%; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; gap:0.25rem; }
.mx-spark__bar { width: min(100%, 60px); border-radius: var(--bs-border-radius-lg) var(--bs-border-radius-lg) 0 0; background: var(--mx-four); transform-origin: bottom center; min-height: 0.1875rem; }
.mx-spark__v { font-family: var(--bi-font-display); font-weight: 600; font-size: 0.875rem; color: var(--mx-ink-2); white-space: nowrap; }
.mx-spark__x { font-size: 0.875rem; color: var(--mx-ink-3); white-space: nowrap; }

/* ── Mapa UF (Leaflet) + ranking ──────────────────────────────────────────── */
.mx-geo { display: grid; grid-template-columns: 1.4fr 1fr; gap:1rem; align-items: start; }
.mx-geo__map { height: 20rem; border-radius: var(--mx-radius-sm); overflow: hidden; background: var(--mx-inset); }
.mx-geo__map .leaflet-container { background: transparent; font: inherit; outline: none; }
.mx-geo__map .leaflet-interactive:focus { outline: none; }

/* ── Donut do modal de transporte (conic-gradient — próprio, sem Chart.js) ── */
/* display:flex + flex:1 1 auto residual: antes vinha de
   `.mx-panel--chart > :last-child` (removido); precisa continuar crescendo
   dentro do .card-body.d-flex e sendo container flex para o .mx-donut-wrap. */
.mx-transporte { width: 100%; display: flex; flex: 1 1 auto; }
.mx-donut-wrap { flex: 1 1 auto; width: 100%; display: flex; align-items: center; justify-content: center; gap:clamp(1rem, 3vw, 3rem); flex-wrap: wrap; }
.mx-donut { --mx-donut-bg: conic-gradient(var(--mx-inset) 0 100%);
  flex-shrink: 0; width: clamp(160px, 14vw, 210px); aspect-ratio: 1; border-radius: 50%;
  background: var(--mx-donut-bg);
  -webkit-mask: radial-gradient(circle 60px at center, transparent 98%, var(--ink) 100%);
          mask: radial-gradient(circle 60px at center, transparent 98%, var(--ink) 100%);
}
.mx-donut-leg { display: flex; flex-direction: column; gap:0.5rem; min-width: 0; }
.mx-donut-leg__i { display: grid; grid-template-columns: 0.75rem 1fr auto; align-items: center; gap:0.5rem; font-size: 0.875rem; }
.mx-donut-leg__dot { width: 0.75rem; height: 0.75rem; border-radius: var(--bs-border-radius-sm); }
.mx-donut-leg__l { color: var(--mx-ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mx-donut-leg__v { font-family: var(--bi-font-display); font-weight: 600; color: var(--mx-ink); }

.mx-mini-empty { padding:1.5rem 0.5rem; text-align: center; color: var(--mx-ink-3); font-size: 0.875rem; }

/* ── Picker no topbar (escopo global, fora de .mx) ────────────────────────── */
.mi-pick { display: flex; align-items: center; gap:0.5rem; min-width: 0; }
.mi-pick__lab { font-size: 0.875rem; font-weight: 600; color: var(--bi-text-secondary); }
.mi-pick__sel { width: auto; min-width: 10.625rem; max-width: 21.25rem; }
.mi-pick__per { font-size: 0.875rem; white-space: nowrap; }

/* ════════════════════════════════════════════════════════════════════════════
   MOTION — entrada suave + crescimento de barras (respeita reduced-motion)
   ════════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: no-preference) {
  .mx-verdict, .mx-ladder, .mx-panel, .mx-mast { animation: mx-rise .5s cubic-bezier(.22, 1, .36, 1) both; }
  .mx-ladder { animation-delay: .04s; }
  @keyframes mx-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

  .mx-bar__fill, .mx-rank__fill, .mx-h2h__fill { animation: mx-grow-x .55s cubic-bezier(.22, 1, .36, 1) both; }
  @keyframes mx-grow-x { from { transform: scaleX(0); } to { transform: scaleX(1); } }
  .mx-spark__bar { animation: mx-grow-y .55s cubic-bezier(.22, 1, .36, 1) both; }
  @keyframes mx-grow-y { from { transform: scaleY(0); } to { transform: scaleY(1); } }
}

/* ════════════════════════════════════════════════════════════════════════════
   RESPONSIVO
   ════════════════════════════════════════════════════════════════════════════ */
@media (max-width:991.98px) {
  .mx-grid--8-4, .mx-grid--2 { grid-template-columns: 1fr; }
  .mx-geo { grid-template-columns: 1fr; }
}
@media (max-width:767.98px) {
  .mx-verdict { grid-template-columns: 1fr; }
  .mx-verdict__stats { flex-direction: row; gap:1.5rem; padding-left:0; border-left: 0; padding-top:1.5rem; border-top: var(--bs-border-width) solid var(--mx-line); }
  .mx-bar { grid-template-columns: 6rem 1fr; }
  .mx-tot--lead { width: 100%; }
}

/* .fresh (badge de frescor) é canônico único acima (§ Badge de frescor) —
   dedup: o bloco duplicado que vivia aqui (hardcode #059669) foi removido. */

/* ===== MERGED FROM bi/static/bi/css/metas.css (P5 — page-local dissolve) ===== */
/* Editor de Metas — master-detail. Classes .met-* globais (namespaced). Tema claro. */
/* Surfaces (.card/.grid), tokens e spans vêm de static/fcds/*. Aqui só o que é
   específico do editor master-detail (roster, grid de metas, célula editável). */

/* O .content de base_fcds.html já fornece o padding da página — não duplicar. */

/* ── toolbar no topbar (empresa/ano + status); sem engine fcds-filterbar pois a
   página não tem biFiltros — os controles vivem nos blocks topbar_filters/_actions ── */
/* empresa/ano vivem dentro do .pop (chip do topbar) — empilhados */
.met-tb-field {
    display: flex;
    flex-direction: column;
    gap:0.25rem;
    font-size: 0.875rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--ink-3);
    margin-bottom:0;
}
.met-tb-field + .met-tb-field { margin-top:0.5rem; }
.met-tb-field select { width: 100%; min-width: 11rem; }
/* no mobile o crumb empurra o chip p/ a direita — ancora o pop pela direita
   p/ não encostar na borda da viewport. */
@media (max-width:575.98px) {
  #met-cfg-pop { left: auto; right: 0; }
}
.met-status {
    font-size: 0.875rem;
    font-weight: 500;
    min-height: 1rem;
    white-space: nowrap;
}

/* ── workspace master-detail (.grid fornece colunas; .card fornece superfície) ── */
.met-workspace {
    align-items: stretch;
    min-height: 65vh;
}
/* roster e detail são .card — zeramos o padding para que listas/grid encostem nas
   bordas; o card-hd recupera o respiro do topo. */
.met-roster,
.met-detail {
    padding:0;
    overflow: hidden;
}
.met-roster {
    align-self: flex-start;
    position: sticky;
    top: 0.5rem;
}
.met-roster .card-hd {
    margin:0;
    padding:var(--bi-space-sm) 0.5rem;
    background: var(--surf-2);
    border-bottom: var(--bs-border-width) solid var(--line);
}
.met-detail {
    display: flex;
    flex-direction: column;
}
.met-list { list-style: none; margin:0; padding:var(--bi-space-xs); }
.met-list__item {
    padding:0.5rem 0.5rem;
    border-radius: var(--bs-border-radius);
    font-size: 0.875rem;
    cursor: pointer;
    color: var(--ink);
    transition: background 0.12s;
}
/* hover (não-ativo): cinza nítido contra o painel branco do roster. */
/* O override de item ativo do met-list saiu daqui: virou a regra canônica
   `.list-group-item.active` na seção de estados de seleção. O bug de texto branco
   sumindo no hover morreu junto — no tratamento canônico o texto é escuro, então
   nenhuma combinação de fundo claro o apaga. */
.met-grid-titulo {
    font-size: 1rem;
    font-weight: 700;
    margin:0;
    color: var(--ink);
}
/* Rola nos 2 eixos DENTRO do painel (altura limitada) — assim o thead (linha de
   cabeçalho) e a 1ª coluna ficam fixos. */
.met-grid-scroll {
    overflow: auto;
    max-height: 72vh;
}

/* ── grid ─────────────────────────────────────────────────────────────────── */
.met-grid {
    border-collapse: separate;
    border-spacing: 0;
    width: 100%;
    font-size: 0.875rem;
}
.met-grid th,
.met-grid td {
    border-bottom: var(--bs-border-width) solid var(--line);
    padding:var(--bi-space-xs) var(--bi-space-xs2);
    white-space: nowrap;
}
.met-grid thead th {
    position: sticky;
    top: 0;
    background: var(--surf-2);
    z-index: 2;
    font-size: 0.875rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--ink-3);
    text-align: center;
}
.met-th-rotulo,
.met-rotulo {
    position: sticky;
    left: 0;
    background: var(--surf);
    z-index: 1;
    text-align: left;
    min-width: 12.5rem;
    box-shadow: 1px 0 0 var(--line);
}
.met-th-rotulo { background: var(--surf-2); z-index: 3; }
.met-rotulo-sub { display: block; font-weight: 600; color: var(--ink); min-height: 0.2rem; }
.met-rotulo-tipo {
    display: flex; align-items: center; gap:var(--bi-space-xs2);
    font-size: 0.875rem; color: var(--ink-3);
}
/* marcador semântico da família do eixo (reforça o rótulo textual, não substitui).
   As 4 famílias usam tokens categóricos distintos p/ não colapsarem em 2 cores. */
.met-rotulo-tipo::before {
    content: ""; flex: none; width: 0.4375rem; height: 0.4375rem; border-radius: var(--bs-border-radius-sm);
    background: var(--ink-3);
}
.met-fam--receita::before { background: var(--cat-1); }
.met-fam--margem::before  { background: var(--cat-4); }
.met-fam--volume::before  { background: var(--cat-6); }
.met-fam--despesa::before { background: var(--cat-7); }
/* Unidade da meta de VOLUME. O rótulo do catálogo é "Volume (kg)" para todo
   mundo, e quatro áreas do STEEL não vendem em peso — a unidade real vem do ERP
   (`unidades_das_areas`) e substitui o "kg" fixo. O seletor só aparece quando há
   escolha a fazer; unidade única é fato, não opção. */
.met-unidade {
    display: block; width: 100%; max-width: 13rem; margin-top: var(--bi-space-xs2);
    font-size: 0.75rem;
}
.met-unidade-aviso {
    display: block; margin-top: var(--bi-space-3xs);
    font-size: 0.75rem; line-height: 1.3; color: var(--ink-3);
}
/* Conflito: a meta foi cadastrada numa unidade e a área passou a vender noutra.
   Não é erro de digitação — é uma decisão que envelheceu, e pede laranja de
   atenção, não vermelho de destruição. */
.met-unidade-conflito { color: var(--warning-text); font-weight: 600; }
/* separador entre sub-segmentos (1ª linha de cada grupo) */
.met-grid tbody tr.met-grupo > td { border-top: 2px solid var(--line); }

.met-td-mes { padding:var(--bi-space-3xs); }
.met-cell{ width:9.5rem; text-align:right; font-variant-numeric:tabular-nums; }
.met-total {
    text-align: right;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--ink);
    background: var(--surf-2);
}
/* total/média em recálculo no backend (debounce pós-edição) — mantém o valor
   anterior visível, só esmaece até a resposta chegar (não bloqueia digitação) */
.met-total--pendente { color: var(--ink-3); }
.met-acao { text-align: center; }
/* ── adicionar linha ──────────────────────────────────────────────────────── */
.met-add {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap:var(--bi-space-sm);
    padding:0.5rem 1rem;
    border-top: var(--bs-border-width) solid var(--line);
    background: var(--surf-2);
}
.met-add__rotulo { font-size: 0.875rem; color: var(--ink-3); }
.met-add select { min-width: 11rem; }

@media (max-width: 992px) {
    .met-roster { position: static; }
}
@media (max-width: 768px) {
    .met-list__item { padding:0.5rem 0.5rem; font-size: 1rem; min-height: 2.75rem; display: flex; align-items: center; }
}

/* ===== MERGED FROM static/css/forecast-comex.css (P5 — page-local dissolve) ===== */
/* ============================================================
   Forecast Comex — FCDS reskin
   Proprietary "FIDS" styling dropped (IBM Plex + bespoke header).
   Now built on the FCDS design language: the page uses the FCDS
   shell (topbar actions + .kpiband stats + .card board); this file
   only styles the board's own grid/rows/badges/obs/modals/drawer,
   all through the FCDS token set (--fc-* are FCDS-aliased tokens).
   ============================================================ */

/* off-screen drawer must not trigger horizontal scroll.
   Escopado à própria tela: como regra global (`body{...}`) vinda de uma folha
   page-local, atingia todas as páginas e podia matar `position:sticky` em
   descendentes. Mesmo padrão `body:has(...)` já usado pela tracking-comex. */
body:has(.page[data-pagina="forecast_comex"]) { overflow-x: hidden; }

/* A BARRA DE MESES É A MESMA DO GERENCIAL (.gc-months/.gc-mtab/.gc-mdiv) —
   pedido do dono, 31/08/2026 ("vamos replicar a barra de meses do gerencial").
   Aquelas regras leem tokens `--gc-*`, que só existem dentro de `.gc`, e uma
   custom property indefinida INVALIDA a declaração (a aba sairia sem cor — a
   mesma armadilha já anotada no bloco do Gerencial). Redeclara aqui só as cinco
   que a barra usa, apontando para as MESMAS fontes `--bs-*`: não é uma segunda
   paleta, é o mesmo alias em outro escopo. */
.page[data-pagina="forecast_comex"] {
  --gc-panel-3: var(--bs-gray-100);
  --gc-ink-2: var(--bs-secondary-color);
  --gc-ink-3: var(--bs-tertiary-color);
  --gc-line: var(--bs-border-color);
  --gc-accent: var(--bs-primary);
}

/* A LISTA É A TELA: ocupa a janela inteira, não os 46vh do teto global.
   `#fids-table-body` é um `.card-scroll`, cujo `max-height:var(--bi-scroll-cap)`
   (clamp(320px,46vh,460px)) existe para listas que dividem a página com outros
   cartões. Aqui a lista é o único conteúdo do cartão e o cartão é o único
   conteúdo da página — o teto só sobrava faixa branca embaixo. A página vira
   coluna flex de altura fixa (mesmo literal 52px da topbar já usado pela
   .wsurface, linha 8031: não existe token de altura de topbar em :root) e a
   lista fica com a sobra, rolando por dentro com o cabeçalho e a legenda parados. */
.page[data-pagina="forecast_comex"] {
  display: flex; flex-direction: column;
  height: calc(100dvh - 52px - var(--content-pad-y) - var(--content-pad-b));
}
.page[data-pagina="forecast_comex"] > .grid.mt-2 { flex: 1; min-height: 0; }
.page[data-pagina="forecast_comex"] > .grid.mt-2 > .card {
  display: flex; flex-direction: column; min-height: 0;
}
.page[data-pagina="forecast_comex"] #fids-table-body {
  max-height: none; flex: 1; min-height: 0;
}

/* shared 5-column grid (Processo · Produto · Chegada · Freetime · Ações).
   Col-headers, rows and skeleton rows MUST stay in lockstep. */
.fids-col-headers,
.fids-row {
  display: grid;
  grid-template-columns: 250px minmax(0, 1fr) 236px 168px 116px;
  gap:0.75rem;
  align-items: start;
}

/* Filtros = .btn-check + .btn do Bootstrap; a barra é utilitária no template. */

/* ── Column headers ────────────────────────────────────────── */
.fids-col-headers {
  padding:0 0.25rem 0.375rem;
  margin-bottom:0;
  border-bottom: var(--bs-border-width) solid var(--fc-border);
}
.fids-col-header {
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-3);
  line-height: 1.2;
}
/* ── Rows ──────────────────────────────────────────────────── */
.fids-row {
  padding:0.375rem 0.25rem;
  border-bottom: var(--bs-border-width) solid var(--fc-border);
  animation: fids-row-in .28s ease both;
  transition: background var(--fc-transition);
}
.fids-row:hover { background: var(--surf-2); }
.fids-row--urgent { box-shadow: inset 3px 0 0 var(--negative); }
@keyframes fids-row-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

.fids-cell { min-width: 0; display: flex; flex-direction: column; gap:0.25rem; }
/* Processo é uma linha que quebra (código · containers · observação), não uma
   pilha: a coluna tem largura para dois desses lado a lado. */
.fids-cell--processo { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap:0.125rem 0.5rem; }
/* A célula é uma coluna flex: sem isto o badge estica na largura toda da coluna
   (o `align-self` vinha dos .fids-*-badge bespoke que viraram .badge). */
.fids-cell > .badge { align-self: flex-start; }
.fids-cell--acoes { flex-direction: row; align-items: flex-start; gap:0.125rem; flex-wrap: wrap; }
/* AÇÃO DA LINHA É ÍCONE, NÃO CAIXA. Eram três `btn-outline-secondary` por
   linha — 114 molduras cinzas na tela —, e cinza aqui quer dizer DESABILITADO,
   que é o contrário do que as três ações são. Mesmo desenho da tela irmã
   `processos-comex`: `btn-link` sem sublinhado, alvo de 1.75rem, e a cor no
   ÍCONE carregando o estado (azul = pendente, verde = etapa registrada). O
   estado nunca fica só na cor: a data continua no `title` de cada botão. */
.fids-acao {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.75rem; height: 1.75rem;
  border-radius: var(--fc-radius);
  text-decoration: none;
}
.fids-acao:hover, .fids-acao:focus-visible { background: var(--surf-2); text-decoration: none; }

.fids-processo-head { display: inline-flex; align-items: baseline; gap:0.375rem; }
.fids-transport-icon { color: var(--ink-3); font-size: 0.875rem; width: 1rem; text-align: center; flex-shrink: 0; }
.fids-processo-code { font-family: var(--bi-font-mono); font-weight: 600; font-size: 0.875rem; color: var(--ink); word-break: break-word; }

.fids-produto-item { display: flex; flex-wrap: wrap; align-items: baseline; gap:0 0.5rem; }
.fids-produto-item + .fids-produto-item { margin-top:0.125rem; }
/* A observação do produto fica na PRÓPRIA linha, não espremida no fim da
   descrição (pedido do dono): dentro da descrição ela lia como parte do nome. */
.fids-produto-item > .fids-obs-secao { flex: 0 0 100%; }
.fids-produto-item-desc { font-size: 0.875rem; color: var(--ink); line-height: 1.3; }
.fids-produto-item-qty { font-family: var(--bi-font-mono); font-size: 0.875rem; color: var(--ink-3); white-space: nowrap; }

/* ── Date pair (Chegada: previsão de entrega / chegada real) ── */
.fids-date-pair { display: flex; flex-direction: column; gap:0.125rem; }
.fids-date-linha { display: flex; align-items: baseline; gap:0.375rem; }
.fids-date-prev-label {
  flex: 0 0 2.5rem;
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.fids-date-prev { font-family: var(--bi-font-mono); font-size: 0.875rem; color: var(--ink-2); }
.fids-date-real { font-family: var(--bi-font-mono); font-size: 0.875rem; font-weight: 600; color: var(--ink); }
.fids-date-real--empty { color: var(--ink-3); font-weight: 400; }
.fids-eta-ts { font-family: var(--bi-font-mono); font-size: 0.875rem; font-weight: 400; color: var(--ink-4); letter-spacing: 0; white-space: nowrap; }

/* ── Badges (urgência) — pill FCDS: bg sutil + dot + texto ──── */

.fids-badge-dot { width: 0.375rem; height: 0.375rem; border-radius: 50%; background: currentColor; flex-shrink: 0; }

/* ── Freetime ──────────────────────────────────────────────── */
.fids-cell--freetime { gap:0.25rem; }
/* "Falta cadastrar demurrage / free time" não cabe nos 168px da coluna e o
   nowrap do .badge do Bootstrap fazia o texto invadir a coluna Ações. */
.fids-cell--freetime .badge { white-space: normal; text-align: left; }
.fids-freetime-prazo { font-family: var(--bi-font-mono); font-size: 0.875rem; color: var(--ink-2); }
.fids-freetime-na { color: var(--ink-3); font-size: 0.875rem; }
/* ── Observação inline ─────────────────────────────────────── */
.fids-obs-secao { align-self: flex-start; max-width: 100%; }
.fids-obs-container { display: flex; flex-direction: column; gap:0.25rem; }
.fids-obs-display {
  font-size: 0.875rem;
  line-height: 1.35;
  color: var(--ink-2);
  cursor: text;
  border-radius: var(--fc-radius);
}
.fids-obs-secao--processo .fids-obs-display {
  border: var(--bs-border-width) solid transparent;
  padding:0 0.25rem;
}
.fids-obs-secao--processo .fids-obs-display:hover { border-color: var(--line-3); background: var(--surf-2); }
.fids-obs--vazio { color: var(--ink-3); }
.fids-obs--placeholder { color: var(--ink-3); font-style: italic; }
.fids-obs-edit { display: flex; flex-direction: column; gap:0.25rem; }
/* .form-control-sm + só a largura mínima que a célula da grade exige. */
.fids-obs-textarea { min-width: 11.25rem; resize: vertical; }
.fids-obs-actions { display: flex; gap:0.25rem; }

.fids-obs-status { font-size: 0.875rem; color: var(--fc-urgent-fg); }

/* ── Loading / skeleton / empty / error ────────────────────── */
/* .fids-loading/.fids-skeleton removidos — loading unificado (overlay Bootstrap). */

.fids-empty { display: flex; flex-direction: column; align-items: center; gap:0.5rem; padding:3rem 0; text-align: center; }
.fids-empty-icon { font-size: 2rem; color: var(--ink-4); }
.fids-empty-title { font-size: 1rem; font-weight: 600; color: var(--ink-2); }
.fids-empty-sub, .fids-empty-ts { font-size: 0.875rem; color: var(--ink-3); }
.fids-empty-ts { color: var(--ink-4); }

.fids-error { display: flex; flex-direction: column; align-items: center; gap:0.5rem; padding:3rem 0; text-align: center; }
.fids-error-icon { font-size: 2rem; color: var(--fc-urgent-fg); }
.fids-error-msg { font-size: 1rem; font-weight: 600; color: var(--ink); }
.fids-error-hint { font-size: 0.875rem; color: var(--ink-3); }

/* ── KPI: banda apertada + cartão de containers por família ── */
/* A lista é a tela (ver o bloco de altura no topo): cada rem que a banda gasta
   é uma linha a menos no board, então o cartão perde respiro de propósito. */
.page[data-pagina="forecast_comex"] #fids-stats .card-body { padding:0.5rem 0.75rem; }
/* O board é o último bloco da página: o respiro de baixo já vem do padding da
   própria página, o do cartão só empurrava a lista para cima. */
.page[data-pagina="forecast_comex"] > .grid.mt-2 > .card { padding-bottom:0.5rem; }

/* Quebra por família do cartão "Containers no mês" — chips de texto, sem
   moldura: são 4 a 6 famílias e uma borda em cada viraria ruído. */
.fids-familias { display: flex; flex-wrap: wrap; align-items: baseline; gap:0 0.625rem; line-height: 1.35; }
.fids-familias-mes { font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--ink-4); }
.fids-familia { display: inline-flex; align-items: baseline; gap:0.25rem; }
.fids-familia-nome { color: var(--ink-3); }
.fids-familia-qtd { font-family: var(--bi-font-mono); font-weight: 600; color: var(--ink-2); }
.fids-familias-vazio { color: var(--ink-4); font-style: italic; }

/* ── Legenda ───────────────────────────────────────────────── */

/* ══════════════════════════════════════════════════════════
   MODAIS — overlay único compartilhado, shell = .modal do Bootstrap
   (dialog/content/header/body/footer/btn-close). Só sobra aqui o que
   é conteúdo próprio deste modal.
   ══════════════════════════════════════════════════════════ */
.fids-modal-codigo { font-family: var(--bi-font-mono); font-weight: 600; color: var(--ink-2); }
.fids-modal-loading { display: flex; align-items: center; gap:0.5rem; color: var(--ink-3); font-size: 0.875rem; }
.fids-modal-status { font-size: 0.875rem; color: var(--ink-3); }
.fids-modal-marcar-todos { display: flex; align-items: center; gap:0.5rem; flex-wrap: wrap; padding-bottom:0.5rem; border-bottom: var(--bs-border-width) solid var(--fc-border); }
.fids-modal-container-list { display: flex; flex-direction: column; gap:0.25rem; max-height: 20rem; overflow: auto; }
.fids-modal-container-row { display: flex; align-items: center; justify-content: space-between; gap:0.5rem; }
.fids-modal-container-num { font-family: var(--bi-font-mono); font-size: 0.875rem; color: var(--ink); }

/* ══════════════════════════════════════════════════════════
   ETL DRAWER — .offcanvas do Bootstrap (backdrop/ESC/scroll nativos)
   ══════════════════════════════════════════════════════════ */
#fids-etl-drawer { --bs-offcanvas-width: min(560px, 94vw); }
.fids-etl-drawer-title { display: flex; align-items: center; gap:0.5rem; }

.fids-etl-log {
  flex: 1; margin:0; overflow: auto;
  padding:1rem 1rem;
  font-family: var(--bi-font-mono); font-size: 0.875rem; line-height: 1.55;
  color: var(--ink-2); background: var(--surf-2);
  white-space: pre-wrap; word-break: break-word;
}

/* ── Responsivo: rola a grade horizontalmente em telas estreitas ── */
@media (max-width:991.98px) {
  .fids-col-headers, .fids-row { min-width: 41.5rem; }
  .card:has(#fids-table-body) { overflow-x: auto; }
}

/* ===== MERGED FROM static/css/obs-produtos-comex.css (P5 — page-local dissolve) ===== */
/* ══════════════════════════════════════════════════════════
   OBS-PRODUTOS-COMEX — Gerenciamento de Observações de Produto
   Surface/cards/header come from FCDS (.card, .card-hd, .lab,
   .grid). Only page-specific form/table/inline-edit rules live here.
   ══════════════════════════════════════════════════════════ */

.obs-page {
  padding:1.5rem;
}

/* ── Nova observação (form lives inside an FCDS .card) ── */
.obs-nova-form {
  display: flex;
  gap:0.5rem;
  align-items: flex-end;
  flex-wrap: wrap;
}
.obs-nova-field {
  display: flex;
  flex-direction: column;
  gap:0.25rem;
}
.obs-nova-field--obs {
  flex: 1;
  min-width: 12.5rem;
}
.obs-nova-label {
  font-size: 0.875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--ink-3);
}
/* .form-control-sm cobre borda/altura/foco; residual = largura fixa + mono (código de produto). */
.obs-nova-input {
  width: 10rem;
  font-family: var(--mono);
}
.obs-nova-textarea {
  width: 100%;
  font-size: 0.875rem;
  border: var(--bs-border-width) solid var(--line-3);
  border-radius: var(--bs-border-radius-sm);
  padding:0.25rem 0.5rem;
  resize: vertical;
  min-height: 3.25rem;
  outline: none;
  font-family: inherit;
  line-height: 1.4;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.obs-nova-textarea:focus {
  border-color: var(--acc);
  box-shadow: var(--ring);
}
.obs-nova-actions {
  display: flex;
  align-items: center;
  gap:0.5rem;
  padding-bottom:0;
}

.obs-nova-status {
  font-size: 0.875rem;
  font-family: var(--mono);
  color: var(--negative-text);
}
.obs-nova-status--ok {
  color: var(--positive-text);
}

/* ── Table ── */
/* .table + .table-hover do Bootstrap; aqui só o que é desta tela. */
table.obs-table { font-size: 0.875rem; }
table.obs-table thead th {
  background: var(--surf-2);
  border-bottom: 2px solid var(--line);
  padding:0.5rem 1rem;
  font-weight: 600;
  color: var(--ink-2);
  font-size: 0.875rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  white-space: nowrap;
}
table.obs-table td { padding:0.5rem 1rem; color: var(--ink); }
.obs-col-obs {
  width: 50%;
}

/* ── Cell content ── */
.obs-codigo {
  font-family: var(--mono);
  font-weight: 600;
  font-size: 0.875rem;
  color: var(--acc);
  white-space: nowrap;
}
.obs-meta {
  font-size: 0.875rem;
  color: var(--ink-3);
  white-space: nowrap;
}

/* ── Inline edit ── */
.obs-display {
  cursor: pointer;
  padding:0.25rem 0.25rem;
  border-radius: var(--bs-border-radius-sm);
  border: var(--bs-border-width) solid transparent;
  min-height: 1.6rem;
  word-break: break-word;
  line-height: 1.45;
  transition: border-color 0.15s, background 0.15s;
  position: relative;
}
.obs-display:hover {
  border-color: var(--line-3);
  background: var(--surf-2);
}
.obs-display:hover::after {
  content: '\f303';
  font-family: 'Font Awesome 6 Free';
  font-weight: 900;
  font-size: 0.875rem;
  color: var(--ink-4);
  position: absolute;
  top: 0.25rem;
  right: 0.3rem;
}
.obs-display--vazio {
  color: var(--ink-3);
  font-style: italic;
}
.obs-edit {
  display: none;
}
.obs-textarea {
  width: 100%;
  font-size: 0.875rem;
  border: var(--bs-border-width) solid var(--acc);
  border-radius: var(--bs-border-radius-sm);
  padding:0.25rem 0.5rem;
  resize: vertical;
  min-height: 3.25rem;
  outline: none;
  box-shadow: var(--ring);
  font-family: inherit;
  line-height: 1.4;
}
.obs-actions {
  display: flex;
  gap:0.25rem;
  margin-top:0.25rem;
}

.obs-status {
  font-size: 0.875rem;
  color: var(--negative-text);
  min-height: 0.9rem;
  font-family: var(--mono);
  margin-top:0.25rem;
}

/* ── Delete button ── */

/* ── States ── */
.obs-empty {
  padding:3rem 1.5rem;
  text-align: center;
  color: var(--ink-4);
  font-size: 0.875rem;
}
.obs-empty-icon {
  font-size: 1.5rem;
  display: block;
  margin-bottom:0.5rem;
}

/* Loading: shimmer skeleton bars (FCDS skeleton tokens) in place of a
   spinner, matching the project-wide .skeleton standard. */
/* .obs-loading / .obs-skeleton / shimmer removidos — obs-produtos usa o overlay
   Bootstrap unificado (carregando('obs-table-wrap')). */

/* ── Mobile (≤768px) ── */
@media (max-width: 768px) {
  .obs-page {
    padding:0;
  }
  table.obs-table {
    min-width: 35rem;
  }
  .obs-col-obs {
    width: auto;
    min-width: 12.5rem;
  }
  
}

/* ===== MERGED FROM static/css/processos-comex.css (P5 — page-local dissolve) ===== */
/* ============================================================
   Processos Comex — Listagem paginada via Conexos direto
   Page-local presentation. Tokens come from custom.css.
   ============================================================ */

.processos-page {
  color: var(--ink);
  /* Preenche a altura da viewport: sem faixa de espaço vazio sob o card. O
     corpo da tabela rola dentro do card (.pcx-table-wrapper), não a página. */
  display: flex;
  flex-direction: column;
  /* altura FIXA (não min-height): trava o card na viewport p/ o corpo da tabela
     rolar dentro dele. 68px = chrome acima (topbar+crumb); 28px = padding-bottom
     do .content. Abaixo de 560px de viewport vira auto (mobile/paisagem curta). */
  height: calc(100vh - 96px);
}
@media (max-height: 560px) { .processos-page { height: auto; } }
.processos-page > .grid { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.processos-page .pcx-card { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.processos-page .pcx-card > .pcx-table-wrapper { flex: 1 1 auto; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
/* Só o corpo da tabela (.datatable-scroll = 'rt') rola; toolbar (topo) e
   bottom (info+paginação) ficam fixos, sempre visíveis. */
.processos-page .pcx-table-wrapper .dataTables_wrapper { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
/* max-height:none anula o teto global `--bi-dt-scroll-cap` (min(560px,82dvh)),
   pensado p/ tabelas inline. Aqui o layout é full-height (height:calc(100vh-96px))
   e o corpo cresce por flex; sem isto o teto trava o scroll em ~434px e sobra uma
   faixa branca de ~40% da viewport abaixo da paginação. */
.processos-page .pcx-table-wrapper .datatable-scroll { flex: 1 1 auto; min-height: 0; overflow: auto; max-height: none; }

/* ── Página cuja LISTA é a tela ────────────────────────────────────────────
   A lista ocupa a janela inteira menos a topbar, rola POR DENTRO, e cabeçalho +
   linha de filtros ficam parados no topo dela.

   `height` (não `min-height`) é o ponto todo. O `.main` do app declara
   min-height:calc(100vh - 52px); com apenas um mínimo, um filho `flex:1;
   min-height:0` não tem altura definida contra a qual se dimensionar — ele cresce
   até o conteúdo, o scroller interno deixa de existir e o `position:sticky` do
   cabeçalho passa a se ancorar numa caixa que sobe junto com a página. Foi essa a
   causa do cabeçalho "não grudar". Com altura definida a cadeia fecha, o
   .datatable-scroll volta a ser o elemento que rola, e o th gruda nele — parado.

   Ativada por `{% block content_class %}content--altura-cheia{% endblock %}`. */
.main:has(> .content--altura-cheia) {
  height: calc(100dvh - 52px);   /* 52px = .topbar (3.25rem), fixa no topo */
  min-height: 0;
  overflow: hidden;              /* quem rola é a lista, não a página */
  display: flex;
  flex-direction: column;
}
.content--altura-cheia { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.content--altura-cheia > .page { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.content--altura-cheia .fcds-filters-host { flex: 0 0 auto; }
/* Tela de altura cheia não tem "moldura de página": o recuo do shell (16px em
   cima, 20px nas laterais, 24px embaixo do .page) empurrava o conteúdo para
   dentro e roubava 40px de altura — a barra de decisão terminava a 24px do
   fim da janela. Quem dá respiro aqui é o próprio conteúdo, que já tem os
   seus paddings (capa, corpo, rodapé). */
.content--altura-cheia { padding: 0; }
/* Horizontal reposto (18/08/2026): com `padding:0` nos quatro lados, a primeira
   coluna nascia em x=48 — 15px ATRÁS da barra lateral, que vai até x=64 (medido
   em /romaneio/ e descrito no antigo remendo da inadimplência). O eixo vertical
   segue zerado, que é o que devolve altura à tela; o horizontal usa o mesmo
   recuo do resto do app (`--content-pad-x`), então a coluna começa em x=68 aqui
   e nas telas normais. */
.content--altura-cheia > .page { padding: 0 var(--content-pad-x); }
/* Exceção: o FUNIL não tem capa nem rodapé próprios para dar o recuo — quem
   segura a margem lá é a página. A tela do negócio fica colada porque cada
   faixa dela (capa, corpo, rodapé) já traz o seu. */
.content--altura-cheia > .page[data-pagina="crm"] {
  padding: 1rem var(--crm-respiro-x, 1.25rem) 0 !important; }
/* A promessa do comentário acima, cumprida: a tela do NEGÓCIO fica colada.
   A exceção só existia para o funil, e a capa e o rodapé do negócio paravam
   20px antes da borda (defeito relatado pelo dono, 25/08/2026) — cada faixa
   já traz o próprio recuo (`padding-inline` com centragem), então o da
   página só afastava a pele da janela. */
.content--altura-cheia > .page[data-pagina="crm-deal"] { padding: 0 !important; }
.content--altura-cheia > .page > .grid { flex: 1 1 auto; min-height: 0; display: grid; }
.content--altura-cheia .grid > .card { min-height: 0; display: flex; flex-direction: column; }

/* O card cede o PADDING, não a superfície. Tirar `background` dele jogava as
   linhas direto no canvas (--surface-app #edf0f4) e a hairline de separação
   (--line #e6e8ec) sumia contra ele: a tabela ficava sem grade e sem contraste,
   e o campo Buscar deixava de parecer um campo. O contorno e o fundo ficam; some
   só o recuo interno, que é o que de fato devolve espaço aos dados. */
.content--altura-cheia .grid > .card { padding: 0; }
/* Com o card sem padding, quem afasta o conteúdo da borda é cada faixa. */
.content--altura-cheia .card-hd,
.content--altura-cheia .datatable-toolbar,
.content--altura-cheia .datatable-bottom { padding-inline: var(--bi-space-md); }
.content--altura-cheia .card-hd { padding-block: var(--bi-space-sm); }

/* Separação de linha um passo mais firme que a hairline padrão: são 13 colunas
   numéricas lidas na diagonal, e `--line-2` desaparece nessa densidade. */
.content--altura-cheia .tbl tbody td { border-bottom: 1px solid var(--line); }
/* Zebra por linha, com a paridade reiniciando a cada bloco de cliente (classe posta
   no draw, ver acompanhamento-inadimplencia.js — `nth-child` do CSS não serve porque
   os cabeçalhos de bloco entram na paridade e o cinza escorrega).
   A faixa usa o MESMO overlay do hover (`--bs-table-accent-bg`), um degrau abaixo
   dele: .035 aqui, .075 no hover. Enquanto era `background: var(--surf-2)` — hex
   opaco idêntico ao `--bi-bg-hover` do hover — o hover pintava a mesma cor que já
   estava lá e sumia em cima da faixa. Duas escalas separadas colidem; uma só, não.
   `:not(:hover)` é o que devolve a linha ao hover: esta regra tem `.content--altura-cheia`
   a mais e venceria a regra genérica de hover na especificidade. Fora de hover a faixa
   pinta; sob o cursor ela para de casar e o overlay .075 assume. */
.content--altura-cheia .tbl tbody tr.linha-alternada:not(:hover) > td { --bs-table-accent-bg: rgba(0, 0, 0, .035); }

/* Grade vertical. Mais clara (--line-2) que o separador de linha (--line) de
   propósito: a horizontal carrega a identidade da linha, a vertical é guia de
   coluna. No mesmo peso as duas competem e a tabela lê como gaiola.
   `:not(:last-child)` evita filete dobrado contra a borda do card — o DataTables
   tira do DOM as colunas ocultas, então o último visível é o último de fato.
   Só a 1ª linha do thead (os rótulos) leva grade: a 2ª é a dos filtros, onde cada
   controle já tem borda própria e o filete só somava traço em cima de traço. */
.content--altura-cheia .tbl thead tr:first-child th:not(:last-child),
.content--altura-cheia .tbl tbody td:not(:last-child) {
  border-right: 1px solid var(--line-2);
}
/* O cabeçalho de grupo atravessa a tabela inteira (colspan): filete vertical ali
   cortaria o nome do cliente ao meio. */
.content--altura-cheia .tbl tbody tr.dtrg-group th { border-right: 0 !important; }

/* Dinheiro e atraso são as duas colunas que decidem a ligação: alinhadas,
   tabulares e com peso. O resto da linha fica em tom secundário. */
.content--altura-cheia .tbl tbody td.tbl__numeric {
  font-variant-numeric: tabular-nums;
  font-weight: var(--bi-fw-semibold);
  color: var(--ink);
}

.content--altura-cheia .tbl-wrapper { flex: 1 1 auto; min-height: 0; overflow: hidden; display: flex; flex-direction: column; }
/* Só o corpo rola; toolbar (topo) e info+paginação (base) ficam sempre à vista. */
.content--altura-cheia .dataTables_wrapper { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.content--altura-cheia .datatable-scroll {
  flex: 1 1 auto; min-height: 0; max-height: none; overflow: auto;
}
/* Âncora do sticky volta a ser o .datatable-scroll (parado): topo zerado. */
.content--altura-cheia .datatable-scroll thead tr:first-child th { top: 0 !important; }
.content--altura-cheia .datatable-scroll thead tr:nth-child(2) th {
  top: var(--thead-linha1-altura, 0px) !important;
}

/* Tela baixa: volta a fluir, senão a lista não cabe junto da barra de filtros. */
@media (max-height: 560px) {
  .main:has(> .content--altura-cheia) { height: auto; overflow: visible; display: block; }
  .content--altura-cheia { display: block; }
  .content--altura-cheia .datatable-scroll { max-height: var(--bi-dt-scroll-cap); }
}

.pcx-summary { font-size: 0.875rem; white-space: nowrap; }

/* ── Table ── */
/* A tabela é a grade da casa (.grade-tabela, static/js/grade.js): base/freeze
   de coluna vêm de lá (congelarColunas monta .stickcols sozinho). Aqui só os
   cosméticos específicos do Processos Comex. */
.pcx-col-num { text-align: right; font-family: var(--bi-font-mono); }

.pcx-cell-detail {
  text-align: center;
  width: 2rem;
  color: var(--ink-3);
}
.pcx-cell-processo {
  font-family: var(--bi-font-mono);
  font-weight: 600;
  color: var(--acc);
}

.pcx-table-wrapper { position: relative; }

/* ── Detail Modal content ── */
.pcx-detail-section {
  margin-bottom:1.5rem;
}
.pcx-detail-section-title {
  font-family: var(--bi-font-display);
  font-weight: 600;
  font-size: 1rem;
  margin-bottom:0.5rem;
  color: var(--acc);
  border-bottom: var(--bs-border-width) solid var(--line);
  padding-bottom:0.25rem;
}
.pcx-detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13.75rem, 1fr));
  gap:0.5rem 1rem;
}
.pcx-detail-field-label {
  font-family: var(--bi-font-mono);
  font-size: 0.875rem;
  color: var(--ink-3);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.pcx-detail-field-value {
  font-size: 1rem;
  color: var(--ink);
}
/* .table.table-sm do Bootstrap dá largura, colapso, padding e borda de linha. */
.pcx-detail-table { font-size: 0.875rem; }
.pcx-detail-table th, .pcx-detail-table td { text-align: left; }
.pcx-detail-table th {
  background: var(--surf-2);
  font-weight: 600;
  font-family: var(--bi-font-display);
}
.pcx-hist-lista { max-height: 16.25rem; overflow-y: auto; }
.pcx-hist__item { padding:0.5rem 0; border-bottom: var(--bs-border-width) solid var(--line); }
.pcx-hist__item:last-child { border-bottom: 0; }
.pcx-hist__cab { font-size: 0.875rem; margin-bottom:0.25rem; }
.pcx-hist__item--falha .pcx-hist__cab strong { color: var(--negative-text); }

/* ===== MERGED FROM static/css/tracking-comex.css (P5 — page-local dissolve) ===== */
/* =====================================================
   VARIÁVEIS CSS DINÂMICAS - Responsive ao sidebar
   ===================================================== */

:root {
    --sidebar-width: 14.0625rem;
    --sidebar-margin:0.5rem;
    --header-height: 3.5rem;
    --tracking-header-height: 4.375rem;

    /* =====================================================
       CANONICAL COLOR SOURCE (Stage 1 foundation)
       Single source of truth for category/status color on this page.
       Resolved in JS via getTrackingColor() (static/js/tracking-comex.js).
       NEVER hardcode hex in JS or templates — read these tokens instead.
       ===================================================== */

    /* Product-group identity → FCDS categorical tokens (--cat-*).
       13 group names collapse onto their original color families; each
       family gets ONE distinct, legible cat token (the label carries the
       finer identity). De-duplicates the colliding raw hex (was #E28702 ×3,
       #B42727 ×6). Stable map — reuse in markers, dots, badges (stages 2-5). */
    /* Cor por SEGMENTO do catálogo do admin. Os 13 "grupos" antigos já apontavam
       para 5 cores (todo o aço era --cat-8): a paleta sempre foi por segmento, só o
       código é que fingia treze. O sub-segmento é o texto do badge, não a cor.
       Este mapa vale SÓ para o tracking (dots/badges do mapa) — em gráfico,
       categorizar é a rampa do azul (decisão do dono 2026-08-06, DESIGN.md §2). */
    --tcx-segmento-steel:       var(--cat-8);  /* STEEL — cordoalha, arames, fixadores… */
    --tcx-segmento-agro:        var(--cat-3);  /* AGRO */
    --tcx-segmento-nutritional: var(--cat-1);  /* NUTRITIONAL */
    --tcx-segmento-resin:       var(--cat-2);  /* RESIN */
    --tcx-segmento-wine:        var(--cat-2);  /* WINE */
    --tcx-segmento-trading:     var(--cat-2);  /* TRADING */
    --tcx-segmento-medical:     var(--cat-4);  /* MEDICAL */
    --tcx-segmento-outros:      var(--cat-6);  /* OUTROS */
    --tcx-segmento-fallback:    var(--ink-3);  /* segmento desconhecido → tinta neutra */

    /* Status identity → NEUTRAL (One-Command Rule: status counts/tiles stay
       neutral; identity is carried by the LABEL + optional small dot, not a
       per-status hue). All point at neutral ink here; a later stage may
       repoint a specific status to a --positive/--negative/--warning token
       ONLY if a real good/bad direction is declared. Replaces the rainbow
       palette (was #dc3545/#ffc107/#17a2b8/#28a745/#fd7e14/#20c997/#6f42c1/
       #e83e8c/#198754/#6c757d). */
    --tcx-status:               var(--ink-3);

    /* Map markers & route — meaning-carrying color (the map keeps semantic hue:
       line color = progress, markers/dots = unidade de negócio). Tokenized,
       never hardcoded hex. Buttons/status tiles stay neutral; only the map
       carries this color. */
    --tcx-marker-vessel:    var(--cat-1);    /* vessel bubble + traveled route = blue (progress "percorrido") */
    --tcx-route-pending:    var(--ink-4);    /* restante (gray dashed) */
    --tcx-marker-dest:      var(--cat-3);    /* arrival = green */
    --tcx-transship-passed: var(--negative); /* passed waypoint = red */
}

body.sb-sidenav-toggled {
    --sidebar-width: 0;
}

/* =====================================================
   FOCUS MODE - Destaque de elemento selecionado no mapa
   ===================================================== */

/* Focus mode is scoped under `#map.map-focus-mode` (id + class = high
   specificity), so dim/focus rules win the cascade WITHOUT a wall of
   !important. Leaflet does not set inline opacity/filter on markers, and for
   SVG paths an inline `stroke-opacity` style beats the presentation attribute —
   so those properties win on specificity alone. Only z-index / stroke-width,
   which Leaflet writes inline for positioning/rendering, retain !important. */

/* Elementos desabilitados no focus mode (dim every status tile while a
   process is focused on the map). Scoped under .tracking-comex-page so it
   wins on cascade without !important. */
.tracking-comex-page .tracking-badge.tracking-badge-disabled {
    opacity: 0.55;            /* keep dimmed badge text ≥3:1 (was 0.4, too faint) */
    filter: grayscale(100%);
    pointer-events: none;
    cursor: not-allowed;
}

/* =====================================================
   Marcadores e Polylines - Focus/Disabled (scoped, low-!important)
   ===================================================== */

/* Marcadores de navio - SEM transições (evita flicker) */
#map.map-focus-mode .leaflet-marker-icon.vessel-marker,
#map.map-focus-mode .leaflet-marker-icon[class*="vessel"] {
    transition: none;
    will-change: opacity;
}

/* Elementos desabilitados - com transição SUAVE para outros elementos */
#map.map-focus-mode .leaflet-marker-disabled:not(.vessel-marker):not([class*="vessel"]) {
    opacity: 0.3;
    filter: grayscale(60%);
    transition: opacity 0.2s ease, filter 0.2s ease;
}

/* Marcadores de navio desabilitados - SEM transição */
#map.map-focus-mode .leaflet-marker-disabled.vessel-marker,
#map.map-focus-mode .leaflet-marker-disabled[class*="vessel"] {
    opacity: 0.3;
    filter: grayscale(60%);
    transition: none;
}

#map.map-focus-mode .leaflet-polyline-disabled {
    opacity: 0.25;
    stroke-opacity: 0.25;
    transition: opacity 0.2s ease, stroke-opacity 0.2s ease;
}

#map.map-focus-mode .leaflet-popup-disabled {
    opacity: 0.4;
    pointer-events: none;
}

/* Elementos focados - aparecem INSTANTANEAMENTE, com anel de destaque ESTÁTICO
   (independente do pulso, então legível p/ reduced-motion). */
#map.map-focus-mode .leaflet-marker-focused {
    opacity: 1;
    filter: drop-shadow(0 0 0 2px var(--acc));
    z-index: 1000 !important;   /* Leaflet writes z-index inline → needs !important */
    transition: none;
}

/* Forçar visibilidade de marcadores focados */
#map.map-focus-mode .leaflet-marker-focused,
#map.map-focus-mode .leaflet-marker-focused .custom-div-icon,
#map.map-focus-mode .leaflet-marker-focused .vessel-marker-wrapper {
    display: block;
    visibility: visible;
}

#map.map-focus-mode .leaflet-polyline-focused {
    opacity: 1;
    stroke-opacity: 1;
    stroke-width: 4 !important;  /* Leaflet writes stroke-width inline → needs !important */
    z-index: 999 !important;
    transition: none;
}

/* Wrapper do marcador de navio - otimização de performance */
.vessel-marker-wrapper {
    will-change: opacity, transform;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}

/* =====================================================
   Select2 e Modais
   ===================================================== */

.tracking-comex-page .select2-container { z-index: 1150 !important; }
.tracking-comex-page .select2-dropdown { z-index: 1151 !important; }

/* Acima do overlay de estado do mapa (.tcx-map-state 1200) e dos status-cards (1100),
   ainda muito abaixo do backdrop dos modais Comex (11900). Sem empate por ordem de DOM. */
body:has(.tracking-comex-page) #topbar { z-index: 1250; }

.tracking-modal {
    --bs-modal-zindex: 12000 !important;
    z-index: 12000 !important;
}

.tracking-modal .modal-dialog {
    position: fixed !important;
    left: calc(var(--sidebar-width) + var(--sidebar-margin) + 12px) !important;
    top: calc(var(--header-height) + var(--tracking-header-height) + 80px) !important;
    transform: none !important;
    margin:0 !important;
    max-width: 35rem !important;
    width: calc(100% - var(--sidebar-width) - calc(var(--sidebar-margin) * 2) - 24px) !important;
    max-height: calc(100vh - var(--header-height) - var(--tracking-header-height) - 100px) !important;
    transition: left 0.15s ease-in-out, width 0.15s ease-in-out, top 0.15s ease-in-out;
}

@media (min-width: 992px) {
    .tracking-modal .modal-dialog {
        left: calc(var(--sidebar-width) + var(--sidebar-margin) + 12px) !important;
        max-width: 35rem !important;
        top: calc(var(--header-height) + var(--tracking-header-height) + 80px) !important;
    }
}

.tracking-modal.fade .modal-dialog {
    transition: transform 0.3s ease-out, opacity 0.3s ease-out !important;
    transform: translateX(-100%) !important;
    opacity: 0;
}

.tracking-modal.show .modal-dialog {
    transform: translateX(0) !important;
    opacity: 1;
}

@media (max-width:991.98px) {
    .tracking-modal .modal-dialog {
        left: calc(var(--sidebar-width) + var(--sidebar-margin) + 12px) !important;
        max-width: 32.5rem !important;
        top: calc(var(--header-height) + var(--tracking-header-height) + 75px) !important;
    }
}

@media (max-width: 768px) {
    .tracking-modal .modal-dialog {
        left: calc(var(--sidebar-width) + 8px) !important;
        width: calc(100% - var(--sidebar-width) - 16px) !important;
        max-width: 30rem !important;
        top: calc(var(--header-height) + var(--tracking-header-height) + 70px) !important;
    }
    
    .tracking-comex-page .tracking-modal .modal-body { 
        max-height: calc(100vh - var(--header-height) - var(--tracking-header-height) - 140px);
    }
}

@media (max-width: 576px) {
    .tracking-modal .modal-dialog {
        left: 12px !important;
        width: calc(100% - 24px) !important;
        max-width: none !important;
        max-height: calc(100vh - var(--header-height) - 55px - 20px) !important;
        top: calc(var(--header-height) + 55px + 60px) !important;
    }
    
    .tracking-comex-page .tracking-modal .modal-body { 
        max-height: calc(100vh - var(--header-height) - 55px - 140px);
    }
}

/* =====================================================
   Produtos e Summary
   ===================================================== */

.process-products {
    display: grid;
    gap:0.25rem;
    margin-top:0.5rem;
}

/* Bordo/bg/radius/padding-base (+ layout em coluna) vêm de .card.card-body
   (Bootstrap), aplicado junto no JS — sem residual próprio. */

.process-product-name {
    font-weight: 600;
    color: var(--ink);
    font-size: 1rem;
}

/* Bordo/bg/radius/padding-base vêm de .card.card-body (Bootstrap), aplicado
   junto no JS; aqui só o residual: linha flex com quebra (labels+valores lado
   a lado, várias colunas) que o .card (coluna) não dá. */
.process-summary {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    gap:0.5rem 1rem;
    margin-bottom:0.5rem;
}

.process-summary-item {
    min-width: 8.75rem;
}

.process-summary-label {
    font-size: 0.875rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ink-3);
}

.process-summary-value {
    font-weight: 600;
    color: var(--ink);
    font-size: 1rem;
}

/* Numeric summary value (FOB / Total / Itens / counts / USD / qty): Roboto
   (official numeral font, --mono) tabular, right-aligned so figures
   align and compare (Tabular Rule). The
   text labels (Encomendante/Exportador/Status…) keep the proportional value. */
.process-summary-value.is-num {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    text-align: right;
    letter-spacing: -0.01em;
}

/* Status-dot chip: small direction/neutral dot + neutral ink label, legible
   without hue (colorblind-safe). Dot hue supplied inline via --tcx-status-dot
   (defaults to neutral ink). */
.tcx-status-chip {
    display: inline-flex;
    align-items: center;
    gap:0.25rem;
    font-weight: 600;
    color: var(--ink);
    font-size: 1rem;
}
.tcx-status-chip::before {
    content: "";
    width: 0.4375rem;
    height: 0.4375rem;
    border-radius: 50%;
    background: var(--tcx-status-dot, var(--ink-3));
    flex: 0 0 auto;
}

/* FCDS inline warning note (replaces Bootstrap alert-warning). Subtle amber
   tint fill, AA-safe deep-amber text (via --color-indicator-warning-text, hoje
   apontando para --chart-alerta-text — mesma laranja do sistema de gráficos),
   single --line hairline, no left stripe, real FontAwesome glyph. */
.tcx-warn-note {
    display: flex;
    align-items: flex-start;
    gap:0.5rem;
    padding:0.5rem 0.5rem;
    margin-bottom:1rem;
    background: var(--warning-subtle);
    border: var(--bs-border-width) solid var(--line);
    border-radius: var(--r-sm);
    color: var(--color-indicator-warning-text);
    font-size: 0.875rem;
    line-height: 1.4;
}
.tcx-warn-note .tcx-warn-icon {
    color: var(--color-indicator-warning-text);
    margin-top:0;
    flex: 0 0 auto;
}

/* =====================================================
   Timeline / Progress bar do Navio (modal de detalhes)
   ===================================================== */
.process-timeline { margin-bottom:0.5rem; }
.process-timeline-top { font-size: 1rem; color: var(--ink-2); }
.process-timeline .timeline-origin,
.process-timeline .timeline-dest { max-width: 46%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Progress = MAGNITUDE → slate only (--acc); never group-hued. Track is a
   neutral --line rail. Width/left transitions are gated behind
   prefers-reduced-motion: no-preference so reduced-motion users get the final
   position instantly (no animated decoration). */
.timeline-track { position: relative; height: 1.25rem; }
.timeline-line { position: absolute; left: 0; top: 50%; height: 0.125rem; transform: translateY(-50%); border-radius: var(--bs-border-radius-sm); background: var(--line); width: 100%; }
.timeline-progress { position: absolute; left: 0; top: 50%; height: 0.125rem; transform: translateY(-50%); border-radius: var(--bs-border-radius-sm); background: var(--acc); }
.timeline-ship { position: absolute; top: 50%; transform: translate(-50%,-50%); z-index: 5; }
@media (prefers-reduced-motion: no-preference) {
    .timeline-progress { transition: width 200ms cubic-bezier(.2,.8,.2,1); }
    .timeline-ship { transition: left 200ms cubic-bezier(.2,.8,.2,1); }
}
.ship-icon { width: 1.375rem; height: 1.375rem; display: inline-flex; align-items: center; justify-content: center; background: var(--surf); border-radius: 50%; box-shadow: var(--sh1); border: var(--bs-border-width) solid var(--line); font-size: 0.875rem; color: var(--acc); }
.process-timeline-meta { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap:0.5rem; font-size: 0.875rem; color: var(--ink-3); }
.process-timeline-meta .timeline-meta-left,
.process-timeline-meta .timeline-meta-right { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 0.875rem; color: var(--ink-3); font-family: var(--mono); font-variant-numeric: tabular-nums; }
.process-timeline-meta .timeline-meta-center { text-align: center; font-weight: 600; color: var(--ink); }
.process-timeline .progress-percent { font-weight: 600; color: var(--ink); font-family: var(--mono); font-variant-numeric: tabular-nums; }
@media (max-width: 576px) {
    .process-timeline-meta { grid-template-columns: 1fr auto 1fr; gap:0.25rem; }
    .process-timeline-meta .timeline-meta-center { font-size: 1rem; }
}
@media (max-width: 576px) {
    .process-timeline .timeline-origin, .process-timeline .timeline-dest { max-width: 40%; }
}

/* =====================================================
   Modal Backdrop
   ===================================================== */

/* Backdrop: o do Bootstrap, sem override. O que morava aqui era
   `background-color: rgba(0,0,0,.25) !important`, que combinado com o
   `opacity:.5` do `.show` dava .125 efetivo — clareamento global, com
   `!important`, sem nenhum token do FCDS por trás. */

/* A elevação p/ z-11900 é SÓ da tracking-comex (backdrop acima do topbar-1200 e
   do mapa Leaflet). Escopada via body:has(.tracking-comex-page) p/ não vazar e
   soterrar os modais Bootstrap padrão (z-1055) nas demais telas. Só mexe no
   z-index — a regra .tracking-comex-modal-open .modal-backdrop (transparência)
   continua vencendo por não haver conflito de propriedade. */
body:has(.tracking-comex-page) .modal-backdrop {
    --bs-backdrop-zindex: 11900 !important;
    z-index: 11900 !important;
}

.tracking-comex-modal-open .modal-backdrop {
    background-color: transparent !important;
    opacity: 0 !important;
}

.tracking-comex-page .modal.show ~ .select2-container--open .select2-dropdown {
    z-index: 12500 !important;
}

/* =====================================================
   Header / toolbar (FCDS tokens, sem !important)
   ===================================================== */

/* ── Topbar actions do tracking (.tb-btn): variante sólida p/ ação primária
   (Atualizar) + estados disabled/active token-driven que o .tb-btn base não
   traz. Escopados por id/classe pois vivem no topbar FCDS (fora de
   .tracking-comex-page). ── */
#tcx-refresh-btn, #btn-reset-map,
#tracking-export-json, #tracking-export-csv { cursor: pointer; }
.tb-btn:active { background: var(--surf-3); border-color: var(--line-3); }
/* disabled token-driven (export até cache popular) */
.tb-btn:disabled, .tb-btn[disabled], .tb-btn[aria-disabled="true"] {
    opacity: .55; cursor: not-allowed;
    background: var(--surf-2); border-color: var(--line); color: var(--ink-4);
}
.tb-btn:disabled svg, .tb-btn[disabled] svg, .tb-btn[aria-disabled="true"] svg { color: var(--ink-4); }
/* variante sólida — ação primária da página (B2: brand-blue) */
.tb-btn--solid { background: var(--brand); border-color: var(--brand); color: var(--bi-text-on-accent); }
.tb-btn--solid svg { color: var(--bi-text-on-accent); }
.tb-btn--solid:hover, .tb-btn--solid.open { background: var(--brand-strong); border-color: var(--brand-strong); }
.tb-btn--solid:active { background: var(--brand-strong); border-color: var(--brand-strong); }
.tb-btn--solid:disabled, .tb-btn--solid[disabled], .tb-btn--solid[aria-disabled="true"] {
    background: var(--brand); border-color: var(--brand); color: var(--bi-text-on-accent);
}
.tb-btn--solid:disabled svg, .tb-btn--solid[disabled] svg, .tb-btn--solid[aria-disabled="true"] svg { color: var(--bi-text-on-accent); }
/* spinner do Atualizar durante reload */
@media (prefers-reduced-motion: no-preference) {
    .tb-btn.is-loading .tcx-refresh-icon { animation: tcx-spin .8s linear infinite; transform-origin: 50% 50%; }
}
@keyframes tcx-spin { to { transform: rotate(360deg); } }

.tracking-comex-page .tracking-header {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap:0.5rem;
    padding:0.5rem 1rem;
    margin:0;
    background: var(--surf);
    border-bottom: var(--bs-border-width) solid var(--line);
}
/* barra fina do corpo: só a busca Select2, ocupando a largura disponível */
.tracking-comex-page .tracking-header .process-search-wrapper {
    flex: 1 1 auto;
    max-width: 35rem;
}

/* ── Filtros no popover do topbar (fora de .tracking-comex-page → sem escopo de
   página; este CSS só carrega no tracking, então é seguro) ──
   Escopo/Via usam o vocabulário FCDS .optrow (.lab + .ck + .nm); "Com posição
   AIS" usa o .form-switch nativo do Bootstrap. Os <select> de Escopo/Via ficam
   escondidos (.tcx-state-select) como modelo de estado lido por
   _fetchTrackingData; o switch é o próprio input visível. */
.tcx-state-select, .tcx-state-check {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%);
    white-space: nowrap; border: 0; padding:0; margin:-0;
}
.tcx-filter-group { margin-bottom:0.25rem; }
.tcx-filter-lab { padding:0.25rem 0.5rem 0; }
/* .optrow é botão (single-select por grupo); marca de seleção via aria-checked */
#tcx-filtros-pop .optrow[aria-checked="true"] .ck { background: var(--acc); border-color: var(--acc); }
#tcx-filtros-pop .optrow[aria-checked="true"] .ck svg { opacity: 1; }
#tcx-filtros-pop .popftog { display: flex; align-items: center; }
/* .form-switch nativo espalhado na linha: label à esquerda, switch à direita
   (neutraliza o padding-left/margin-left do .form-switch p/ layout space-between). */
#tcx-filtros-pop .popftog .form-check { width: 100%; display: flex; align-items: center; justify-content: space-between; padding-left: 0; margin: 0; }
#tcx-filtros-pop .popftog .form-check-input { margin: 0; float: none; }
#tcx-filtros-pop .popftog .form-check-label { margin: 0; }

/* (header__title / header-controls / header__check removidos — controles foram
   p/ o topbar na reskin Fase 2e; só a busca Select2 permanece em .tracking-header) */

/* Select da busca no toolbar — alinhar à altura dos tb-btn */
.tracking-comex-page .tracking-header .form-select-sm {
    width: auto;
    min-width: 8.125rem;
    height: 2.125rem;
}

/* Wrapper do search */
.tracking-comex-page .tracking-header .process-search-wrapper {
    display: flex;
    align-items: center;
    width: 30rem;
    min-width: 25rem;
    flex-shrink: 0;
}

/* Select2 dentro do toolbar */
.tracking-comex-page .tracking-header .select2-container {
    min-height: 2.125rem;
    display: block;
    width: 100% !important;
}

.tracking-comex-page .tracking-header .select2-selection,
.tracking-comex-page .tracking-header .select2-selection--single {
    height: 2.125rem;
    padding:0.25rem 0.5rem;
    display: flex;
    align-items: center;
    font-size: 0.875rem;
    line-height: 1.4;
    background-color: var(--surf-2);
    border: var(--bs-border-width) solid var(--line);
    border-radius: var(--r-sm);
    color: var(--ink-2);
}

.tracking-comex-page .tracking-header .select2-container--default .select2-selection--single .select2-selection__arrow {
    height: 100%;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
}

.tracking-comex-page .tracking-header .select2-container--default .select2-selection--single .select2-selection__rendered {
    line-height: 1.4;
    padding:0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--ink-2);
}

/* Dropdown do Select2 */
.tracking-comex-page .select2-dropdown .select2-search--dropdown .select2-search__field {
    width: 100%;
    padding:0.5rem 0.5rem;
    box-sizing: border-box;
    font-size: 1rem;
    border: var(--bs-border-width) solid var(--line);
    border-radius: var(--r-sm);
}

.tracking-comex-page .select2-results__option {
    padding:0.5rem 0.5rem;
    font-size: 0.875rem;
    transition: background-color 160ms ease, color 160ms ease;
}

.tracking-comex-page .select2-results__option--highlighted,
.tracking-comex-page .select2-results__option:hover {
    background-color: var(--acc-soft);
    color: var(--acc);
}

.tracking-comex-page .select2-container--open .select2-selection--single,
.tracking-comex-page .select2-container--focus .select2-selection--single {
    border-color: var(--acc);
    box-shadow: var(--ring);
    transition: box-shadow 180ms ease, border-color 180ms ease;
}

@media (prefers-reduced-motion: reduce) {
    .tracking-comex-page .select2-container--open .select2-selection--single,
    .tracking-comex-page .select2-container--focus .select2-selection--single { transition: none; }
}

/* Placeholder lê em contraste de corpo (--ink-3 ~4.7:1); o valor selecionado
   permanece em --ink-2 mais escuro (regra acima). */
.tracking-comex-page .select2-selection__placeholder {
    color: var(--ink-3);
}

/* Estado loading/disabled do search enquanto processosData resolve. A classe é
   posta no wrapper por tracking-comex.js; mostra um skeleton sobre o controle e
   bloqueia interação até os dados chegarem. */
/* .process-search is-loading skeleton removido — loading unificado (overlay Bootstrap). */

.tracking-comex-page .select2-dropdown {
    border: var(--bs-border-width) solid var(--line);
    border-radius: var(--bs-border-radius-lg);
    box-shadow: var(--sh-glass);
}

/* Responsive - Header */
@media (max-width: 576px) {
    .tracking-comex-page .tracking-header {
        flex-direction: column;
        align-items: stretch;
    }

    .tracking-comex-page .tracking-header .process-search-wrapper {
        width: 100%;
        min-width: 0;
        max-width: none;
        order: 3;
        margin-top:0.5rem;
    }
}

/* =====================================================
   Layout e Mapa
   ===================================================== */

.tracking-comex-page {
    height: calc(100vh - 56px) !important;
    display: flex;
    flex-direction: column;
}

.tracking-comex-page .d-flex.flex-column.h-100 > .tracking-row {
    flex: 1 1 auto;
    min-height: 0;
    /* Trap the map's stacking context: Leaflet panes (z-index up to ~700) and
       the .tcx-map-state overlay (z-index 1200) would otherwise bubble to the
       root and paint OVER the shell sidebar (z-index 30/60) and topbar. isolate
       contains them so the shell chrome always wins. */
    isolation: isolate;
}

/* (#layoutSidenav_content.tracking-comex-active removido — esse elemento/classe
   eram da shell SB-Admin antiga e nunca existem no FCDS; regras eram mortas.) */

.tracking-comex-page #map {
    width: 100%;
    height: 100%;
    border-radius: 0;
    box-shadow: none;
    /* Join the FCDS surface ladder: a 1px --line hairline separates the canvas
       from the worksheet/topbar instead of bleeding edge-to-edge. */
    border-top: var(--bs-border-width) solid var(--line);
}

/* Reskin Leaflet's default control chrome to FCDS tokens (was white boxes /
   #ccc borders / blue focus). */
.tracking-comex-page .leaflet-control-zoom a,
.tracking-comex-page .leaflet-control-attribution {
    background: var(--surf);
    border: var(--bs-border-width) solid var(--line);
    color: var(--ink-2);
}

.tracking-comex-page .leaflet-control-zoom a {
    border-radius: var(--r-sm);
    transition: background-color 0.16s ease, color 0.16s ease, border-color 0.16s ease;
}

.tracking-comex-page .leaflet-control-zoom a:hover {
    background: var(--acc-soft);
    border-color: var(--acc-line);
    color: var(--acc);
}

.tracking-comex-page .leaflet-control-zoom a:focus-visible {
    outline: none;
    box-shadow: var(--ring);
}

.tracking-comex-page .leaflet-control-attribution {
    border-radius: var(--r-xs);
}

.tracking-comex-page .leaflet-control-attribution a {
    color: var(--ink-2);
}

@media (prefers-reduced-motion: reduce) {
    .tracking-comex-page .leaflet-control-zoom a { transition: none; }
}

/* country-flag pin — chrome moved off inline styles to the surface ladder:
   --surf fill, 1px --surf hairline, one soft low-alpha lift (no heavy shadow). */
.tracking-comex-page .country-flag-marker {
    background: var(--surf);
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    border: var(--bs-border-width) solid var(--line);
    box-shadow: 0 1px 3px rgba(25, 28, 34, 0.18);
    cursor: pointer;
}

/* =====================================================
   Cards Overlay
   ===================================================== */

.tracking-comex-page #status-cards-container {
    position: absolute;
    top: 12px;
    left: calc(var(--sidebar-width) + var(--sidebar-margin));
    z-index: 1100;
    pointer-events: auto;
    transition: left 0.15s ease-in-out;
}

@media (max-width:767.98px) {
    .tracking-comex-page #status-cards-container {
        left: 8px !important;
        right: 8px;
        flex-wrap: wrap;
    }
}

/* Stage 1: #group-cards / #group-cards-container rules removed (dead code —
   renderGroupCards deleted; #group-cards never existed in the template). */
.tracking-comex-page #status-cards {
    display: flex;
    gap:0.5rem;
    align-items: stretch;
    background: var(--surf);
    border: var(--bs-border-width) solid var(--line);
    padding:0.25rem;
    border-radius: var(--r-xs);
    box-shadow: none;
    max-height: 60vh;
    overflow-x: auto;
    white-space: nowrap;
    pointer-events: auto;
}

.tracking-comex-page #status-cards > div {
    flex: 0 0 auto;
}

@media (max-width:767.98px) {
    .tracking-comex-page #status-cards { gap:0.25rem; padding:0.25rem; }
}

/* Skeleton dos status-cards enquanto _fetchTrackingData resolve. Reserva a
   mesma altura/box da faixa real (#status-cards) para não causar CLS quando os
   cards reais aparecem. */
/* .tcx-cards-skeleton / .tcx-skb-pill removidos — loading unificado (overlay Bootstrap). */

/* =====================================================
   Estados de página sobre o mapa (loading / vazio / erro)
   -----------------------------------------------------
   Nunca deixa o mapa silenciosamente em branco: distingue carregando, sem
   processos, e falha de fetch/parse. data-state alterna qual bloco é exibido.
   ===================================================== */
.tracking-comex-page .tcx-map-state {
    position: absolute;
    inset: 0;
    z-index: 1200;
    display: grid;
    place-items: center;
    padding:1rem;
    pointer-events: none;
}
/* Some quando há dados plotados (data-state="ready"). */
.tracking-comex-page .tcx-map-state[data-state="ready"] { display: none; }
.tracking-comex-page .tcx-map-state__card {
    pointer-events: auto;
    min-width: 15rem;
    max-width: 22.5rem;
    padding:1.5rem 1.5rem;
    gap:0.5rem;
    background: var(--surf);
    border: var(--bs-border-width) solid var(--line);
    border-radius: var(--r-sm);
    box-shadow: var(--sh2);
    text-align: center;
    color: var(--ink-2);
}
.tracking-comex-page .tcx-map-state__icon {
    width: 1.875rem;
    height: 1.875rem;
    color: var(--ink-3);
    margin-bottom:0.25rem;
}
.tracking-comex-page .tcx-map-state__msg {
    margin:0;
    font-size: 0.875rem;
    line-height: 1.45;
    color: var(--ink-2);
}
/* alterna blocos conforme data-state */
.tracking-comex-page .tcx-map-state__loading,
.tracking-comex-page .tcx-map-state__empty,
.tracking-comex-page .tcx-map-state__error { display: none; flex-direction: column; align-items: center; gap:0.5rem; }
.tracking-comex-page .tcx-map-state[data-state="loading"] .tcx-map-state__loading { display: flex; }
.tracking-comex-page .tcx-map-state[data-state="empty"]   .tcx-map-state__empty   { display: flex; }
.tracking-comex-page .tcx-map-state[data-state="error"]   .tcx-map-state__error   { display: flex; }
.tracking-comex-page .tcx-map-state__loading .tcx-map-state__msg { margin-top:0.25rem; color: var(--ink-3); }

/* =====================================================
   Marcadores e Tooltips
   ===================================================== */

.tracking-comex-page .custom-div-icon { background: transparent !important; border: none !important; }

.tracking-comex-page .leaflet-tooltip.custom-tooltip {
    background-color: var(--ink);
    color: var(--surf);
    border: none;
    border-radius: var(--bs-border-radius-sm);
    padding:0.25rem 0.5rem;
    font-size: 0.875rem;
    font-weight: 500;
    box-shadow: var(--sh2);
    min-width: 10rem;
    max-width: 22.5rem;
    white-space: normal;
    word-break: break-word;
    line-height: 1.2;
}

.tracking-comex-page .leaflet-tooltip.custom-tooltip::before { border-top-color: var(--ink); }

/* marker utilities consolidated (moved from inline templates).
   Depth = a 1px --surf hairline ring + ONE soft low-alpha lift. App-wide
   --sh1/--sh2 are `none` for worksheet cards, but a marker floats over the
   raster basemap and needs minimal separation from the tiles; --tcx-marker-sh
   centralizes that soft shadow (replaces the legacy `border:3px solid white` +
   `box-shadow:0 3px 10px rgba(0,0,0,.5)` heavy-shadow tell). */
:root { --tcx-marker-sh: 0 1px 3px rgba(25, 28, 34, 0.18); }
.pulse { animation: pulse 2s infinite; }
@keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.15); } }
@media (prefers-reduced-motion: reduce) {
    .pulse { animation: none; }
}

/* shared 32px round map bubble (origin/destination/vessel/consolidated) */
.custom-div-icon .consolidated-marker,
.consolidated-marker,
.custom-div-icon .destination-marker,
.destination-marker,
.custom-div-icon .vessel-marker,
.vessel-marker,
.port-marker {
    width: 2rem; height: 2rem; border-radius:50%;
    display:flex; align-items:center; justify-content:center;
    border:var(--bs-border-width) solid var(--surf);
    box-shadow:var(--tcx-marker-sh);
    cursor:pointer;
}

/* arrival = green (destination); origin = unidade de negócio (group color,
   supplied inline via --tcx-marker, fallback slate) */
.destination-marker,
.port-marker--destination { background: var(--tcx-marker-dest); }
.port-marker--origin { background: var(--tcx-marker, var(--acc)); }

.consolidated-count-badge { position:absolute; top:-8px; right:-8px; background:var(--acc); width: 1.5rem; height: 1.5rem; border-radius:50%; border:var(--bs-border-width) solid var(--surf); display:flex; align-items:center; justify-content:center; box-shadow:var(--tcx-marker-sh); }
/* count is magnitude → mono tabular ink-on-surf, never red (Tabular + One-Command) */
.consolidated-count-text { color:var(--surf); font-family:var(--mono); font-variant-numeric:tabular-nums; font-weight:700; font-size:0.875rem; }

/* per-process group identity dots over the vessel (categorical → cat token fill,
   supplied inline; chrome is a neutral --surf ring) */
.vessel-group-dot {
    width: 0.5rem; height: 0.5rem; border-radius:50%;
    border:var(--bs-border-width) solid var(--surf);
    box-shadow:var(--tcx-marker-sh);
}

/* transshipment dot: passed = solid red, pending = hollow gray ring.
   Differentiated by FILL (solid vs ring) AND hue — colorblind-safe + colorful. */
.transshipment-dot {
    width: 0.75rem; height: 0.75rem; border-radius:50%;
    box-shadow:var(--tcx-marker-sh);
}
.transshipment-dot.is-passed {
    background: var(--negative);
    border:var(--bs-border-width) solid var(--surf);
}
.transshipment-dot.is-pending {
    background: var(--surf);
    border:2px solid var(--ink-4);
}

/* =====================================================
   Badges
   ===================================================== */

/* FCDS number-first tile (status filter). Magnitude (count) is MONO ink and
   never hued; the status name is an --ink-3 label that carries identity.
   Background is the neutral surface ladder — no per-status hue. */
.tracking-badge {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-start;
    gap:0;
    padding:0.25rem 0.5rem;
    border-radius: var(--r-xs);
    background: var(--surf);
    border: var(--bs-border-width) solid var(--line);
    cursor: pointer;
    transition: background-color 0.16s ease, border-color 0.16s ease;
    white-space: nowrap;
    margin:0;
}

.tracking-badge:hover {
    background: var(--acc-soft);
    border-color: var(--acc-line);
}

.tracking-badge:focus-visible {
    outline: none;
    box-shadow: var(--ring);
}

.tracking-badge:active {
    background: var(--surf-2);
}

.tracking-badge .badge-count {
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    font-size: 1rem;
    line-height: 1.05;
    color: var(--ink);
    letter-spacing: -0.01em;
}

.tracking-badge .badge-label {
    font-size: 0.875rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--ink-3);
}

/* Real zero-count disabled state: dimmed + non-interactive. The 0 stays in
   strong --ink so it remains legible through the .55 opacity; only the label
   recedes to --ink-4. */
.tracking-badge.is-disabled {
    background: var(--surf-2);
    border-color: var(--line-2);
    opacity: 0.55;
    pointer-events: none;
    cursor: default;
}

.tracking-badge.is-disabled .badge-label {
    color: var(--ink-4);
}

@media (prefers-reduced-motion: reduce) {
    .tracking-badge { transition: none; }
}

.tracking-badges-container {
    display: flex;
    flex-wrap: wrap;
    padding:0 0;
    gap:0;
    background: transparent;
}

/* =====================================================
   Controles e Botões do Modal
   ===================================================== */

.tracking-comex-page .tracking-modal .modal-content .btn {
    font-size: 0.875rem;
    font-weight: 400 !important;
    padding:0.25rem 0.5rem !important;
}

/* "Detalhes" → FCDS slate ghost button (not Bootstrap primary blue). Full
   state set: default / hover / focus-visible / active. */
.tracking-comex-page .tracking-modal .process-details-btn {
    background: var(--surf);
    border: var(--bs-border-width) solid var(--acc-line);
    color: var(--acc-ink);
    border-radius: var(--r-sm);
    transition: background-color 0.16s ease, border-color 0.16s ease, color 0.16s ease;
}
.tracking-comex-page .tracking-modal .process-details-btn:hover {
    background: var(--acc-soft);
    border-color: var(--acc);
    color: var(--acc-ink);
}
.tracking-comex-page .tracking-modal .process-details-btn:focus-visible {
    outline: none;
    box-shadow: var(--ring);
    border-color: var(--acc);
}
.tracking-comex-page .tracking-modal .process-details-btn:active {
    background: var(--surf-2);
}
@media (prefers-reduced-motion: reduce) {
    .tracking-comex-page .tracking-modal .process-details-btn { transition: none; }
}

/* Hairline-separated process rows (replaces Bootstrap .list-group boxed cards):
   no per-item box, just a single --line bottom hairline. */
.tracking-comex-page .tracking-modal .process-row {
    padding:0.5rem 0;
    border-bottom: var(--bs-border-width) solid var(--line);
}
.tracking-comex-page .tracking-modal .process-row:first-child { padding-top:0; }
.tracking-comex-page .tracking-modal .process-row:last-child { border-bottom: none; padding-bottom:0; }
.tracking-comex-page .tracking-modal .process-row h6 { margin-bottom:0.25rem; }

/* =====================================================
   Popups Customizados
   ===================================================== */

/* =====================================================
   Modal Styles
   ===================================================== */

/* Depth = opaque --surf fill + flat --sh2 popover shadow + a single --line
   hairline. No backdrop-filter blur, no hard !important border (the
   .tracking-modal id+class scope wins on specificity). */
.tracking-comex-page .tracking-modal .modal-content {
    border-radius: var(--bs-border-radius-lg);
    box-shadow: var(--sh2);
    border: var(--bs-border-width) solid var(--line);
    background-color: var(--surf);
}

.tracking-comex-page .tracking-modal .modal-header {
    border-top-left-radius: 10px !important;
    border-top-right-radius: 10px !important;
    background: linear-gradient(135deg, var(--surf-2) 0%, var(--surf) 100%);
    border-bottom: var(--bs-border-width) solid var(--line);
    padding:1rem 1rem;
}

.tracking-comex-page .tracking-modal .modal-title {
    font-size: 1rem;
    font-weight: 600;
    color: var(--ink);
}

.tracking-comex-page .tracking-modal .btn-close {
    padding:0.5rem;
    opacity: 0.6;
}

.tracking-comex-page .tracking-modal .btn-close:hover {
    opacity: 1;
}

.tracking-comex-page .tracking-modal .modal-footer {
    border-bottom-left-radius: 10px !important;
    border-bottom-right-radius: 10px !important;
    background-color: var(--surf-2);
    padding:0.5rem 1rem;
    border-top: var(--bs-border-width) solid var(--line);
}

.tracking-comex-page .tracking-modal .modal-body {
    max-height: calc(100vh - var(--header-height) - var(--tracking-header-height) - 160px);
    overflow-y: auto;
    overflow-x: hidden;
    padding:1rem 1rem;
}

.tracking-comex-page .tracking-modal .modal-body::-webkit-scrollbar {
    width: 0.5rem;
}

.tracking-comex-page .tracking-modal .modal-body::-webkit-scrollbar-track {
    background: var(--surf-2);
    border-radius: var(--bs-border-radius-sm);
}

.tracking-comex-page .tracking-modal .modal-body::-webkit-scrollbar-thumb {
    background: var(--line-3);
    border-radius: var(--bs-border-radius-sm);
}

.tracking-comex-page .tracking-modal .modal-body::-webkit-scrollbar-thumb:hover {
    background: var(--ink-4);
}

/* FCDS tab treatment — clean cascade, no !important. Bootstrap's .nav-tabs
   borders are neutralised once via `border:0;background:none`, then we draw a
   single transparent bottom border that becomes --acc on the active tab
   (active underline). Specificity (.tracking-comex-page .tracking-modal
   .nav-tabs .nav-link) wins against Bootstrap's .nav-tabs .nav-link without
   forcing. */
.tracking-comex-page .tracking-modal .nav-tabs {
    border-bottom: var(--bs-border-width) solid var(--line);
    margin-bottom:1rem;
}

.tracking-comex-page .tracking-modal .nav-tabs .nav-link {
    background: none;
    border: 0;
    border-bottom: 2px solid transparent;
    margin-bottom:-0;
    color: var(--ink-3);
    padding:0.5rem 0.5rem;
    font-weight: 500;
    font-size: 1rem;
    transition: color 0.16s ease, border-color 0.16s ease;
}

.tracking-comex-page .tracking-modal .nav-tabs .nav-link:hover {
    color: var(--ink-2);
    border-bottom-color: var(--line-3);
}

.tracking-comex-page .tracking-modal .nav-tabs .nav-link:focus-visible {
    outline: none;
    box-shadow: var(--ring);
    border-radius: var(--r-xs);
}

.tracking-comex-page .tracking-modal .nav-tabs .nav-link.active {
    color: var(--acc);
    border-bottom-color: var(--acc);
    font-weight: 600;
}

@media (prefers-reduced-motion: reduce) {
    .tracking-comex-page .tracking-modal .nav-tabs .nav-link { transition: none; }
}

.tracking-comex-page #countryProcessModal .nav-tabs {
    display: flex;
    flex-wrap: nowrap;
    gap:0.25rem;
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom:0.25rem;
    scrollbar-width: thin;
}

.tracking-comex-page #countryProcessModal .nav-tabs .nav-item {
    flex: 0 0 auto;
}

.tracking-comex-page #countryProcessModal .nav-tabs .nav-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap:0.25rem;
    width: auto;
    padding:0.25rem 0.5rem;
    font-size: 0.875rem;
    white-space: nowrap;
    text-align: center;
}

/* FCDS mono count pill on tabs (replaces Bootstrap badge bg-secondary). Neutral
   --acc-soft fill, mono tabular count in slate ink — never grey Bootstrap. */
.tracking-comex-page .tracking-modal .nav-tabs .tcx-tab-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.25rem;
    padding:0 0.5rem;
    margin-left:0.5rem;
    border-radius: var(--raio-chip);
    background: var(--acc-soft);
    color: var(--acc-ink);
    font-family: var(--mono);
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    font-size: 0.875rem;
    line-height: 1.5;
}

.tracking-comex-page #countryProcessModal .modal-dialog {
    max-width: 32.5rem !important;
}

/* Bordo/bg/radius/padding-base vêm de .card.card-body (Bootstrap), aplicado
   junto no JS. cursor:pointer + hover elevado do bloco antigo foram removidos:
   este item é só informativo dentro do modal consolidado, sem handler de
   clique (afordância morta). Resta o espaçamento entre itens da lista. */
.tracking-comex-page .consolidated-process-item {
    margin-bottom:0.5rem;
}

.tracking-comex-page .consolidated-process-item:last-child {
    margin-bottom:0;
}

.tracking-comex-page .consolidated-process-item strong {
    font-size: 1rem;
}

.tracking-comex-page .consolidated-process-item div {
    font-size: 1rem;
    line-height: 1.5;
}

/* ===== MERGED FROM bi/static/bi/css/despesas_comex.css (P5) ===== */
/* ============================================================================
   Despesas Comex — pilot reference page (FCDS reference-quality refactor)

   Pilot-scoped ONLY. Every rule is namespaced under
   .page[data-pagina="despesas_comex"] so nothing here leaks to other pages
   or to the shared main.css / fcds/*.css layers. Loaded in {% block styles %}
   (after main.css, before statement-theme.css) — selectors carry the
   [data-pagina] attribute so they outrank statement-theme's lower-specificity
   rules without !important wherever possible.

   Goal: resolve the incoherences the audit found on this page —
     · the .content (gradient) vs .page (flat panel) surface seam,
     · KPI numbers not monospace (FCDS rule 3),
     · the 5-colour KPI "rainbow" (FCDS rule 1: one accent; rule 2: colour=meaning),
     · sub-12px filter labels,
     · filter strip / tab skin coherence.
   References: docs/planos/pilot-visual-audit-B.md, pilot-datatables-audit-C.md,
   pilot-color-audit-D.md.
   ========================================================================== */

/* ── 1. Surface seam ───────────────────────────────────────────────────────
   .content (shell) shows the body's 4-stop gradient over #edf0f4; .page
   painted a flat opaque #edf0f4 panel on top, masking the gradient inside the
   page while it stayed visible in the shell margins. Make the page transparent
   so the single body gradient is the one canvas under everything (system.md §9
   "one quiet gradient under everything"). Page-scoped; global .page untouched. */
.page[data-pagina="despesas_comex"] {
  background-color: transparent;
}

/* ── 1b. Linha em foco (clique numa notificação do balão) ──────────────────
   `?titulo=fil-tip-doc-tit` na URL faz `despesas_comex.js` abrir a aba, paginar
   até a linha e acender esta classe. Âmbar e não o acento da casa: é um "olhe
   aqui" temporário, não um estado da linha — mesmo precedente de `.dre-focada`.
   O gradiente do fundo pede `background` na CÉLULA (o <tr> não pinta em tabela
   com colunas sticky). Escopo de página; nada aqui vaza. */
.page[data-pagina="despesas_comex"] tr.df-focada > td {
  animation: df-piscar 1.6s ease-out;
}
@keyframes df-piscar {
  0%, 30% { background: var(--warning-subtle); }
  100%    { background: transparent; }
}
@media (prefers-reduced-motion: reduce) {
  /* Sem pulso, mas o destaque tem de sobrar: quem desligou animação continua
     precisando achar a linha. */
  .page[data-pagina="despesas_comex"] tr.df-focada > td {
    animation: none;
    background: var(--warning-subtle);
  }
}

/* ── 2. Topbar timestamp ────────────────────────────────────────────────────
   Was inline style="font-size:0.875rem"; now a class on the same element.
   (KPI-band, filter-strip e length-select responsivo desta página foram
   canonizados: .kpi-band__secondary tabular-nums vive no componente global; os
   filtros migraram para os widgets colfilter canônicos; o length-select em mobile
   é tratado no componente .datatable compartilhado.) */
.df-timestamp {
  font-size: var(--bi-fs-caption, 0.875rem);
  font-variant-numeric: tabular-nums;
}

/* ===== DIAGNOSTICO (dp-*) ===== */
/* Diagnóstico de preenchimento — só o que NÃO é da permanência.
   Card, raias, KPIs e modais reusam custom.css (classes pp-*). */

.dp__escopo { color: var(--ink-2); }

/* A lista de processos preenche a altura restante do shell (.pp é flex column,
   altura fixa = 100vh - topbar) e ROLA sozinha. Antes o container herdava
   .pp__kanban, que é flex horizontal com overflow-y:hidden — feito para as raias
   rolarem lado a lado — e decepava a tabela alta por volta da 13ª linha: as 86
   linhas existiam no DOM mas só ~13 apareciam. overflow-x cobre telas estreitas. */
.dp__lista {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: auto;
}

/* Chip de sugestão do e-mail: `.card.border-start.border-success.border-3`
   (montarSugestao em diagnostico-preenchimento.js). Verde = resolvível, em
   contraste com o âmbar/vermelho da anomalia que o card responde; a faixa
   esquerda + `.card-body` bastam, sem CSS autoral. */

/* Tabela de processos. Cores do semáforo = as mesmas da permanência
   (custom.css), para que a régua de dias seja uma só na cabeça de
   quem lê as duas telas. */
.dp-tabela { font-size: 0.875rem; }
.dp-tabela th {
  font-size: 0.875rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--ink-3);
  font-weight: 600;
}
.dp-tabela tbody tr { cursor: pointer; }

.dp-modal__bl {
  padding:0.5rem 0;
  border-top: var(--bs-border-width) solid var(--line);
}
.dp-modal__bl-titulo { font-weight: 600; }
.dp-modal__bl-meta { font-size: 0.875rem; color: var(--ink-3); }
.dp-modal__anomalia {
  padding:0.5rem 0;
  border-top: var(--bs-border-width) solid var(--line);
}
.dp-modal__anomalia-detalhe { margin-top:0.25rem; color: var(--ink-2); }
.dp-modal__anomalia-bls { margin-top:0; font-size: 0.875rem; color: var(--ink-3); }
.dp-modal__evidencia { margin-top:0.25rem; }

/* ==========================================================================
   ESTOQUES — ícone de detalhe da grade
   Migrado do <style> inline de bi/templates/bi/estoques.html (regra dura: CSS
   autorado vive só aqui e em styles.css). As regras do antigo child-row de
   lotes (.estoque-lotes-scroll / .estoque-lotes) foram descartadas junto com o
   drill inline — o detalhe agora abre em modal.
   ========================================================================== */

.lote-caret {
  color: var(--ink-2);
  user-select: none;
  cursor: pointer;
}

/* ── Histórico de Preços — busca de produto ──────────────────────────────────
   A lista de sugestões é ancorada NO campo (overlay), não um bloco no fluxo:
   solta, ela aparecia descolada do input e empurrava a página a cada tecla. */
.hp-busca__lista {
    position: absolute;
    /* Colada no campo: o `+2px` daqui era o "espacinho" que fazia a lista parecer
       solta do input. Sem folga, campo e lista leem como UM controle. */
    top: 100%;
    left: 0;
    right: 0;
    /* ABAIXO da sidebar (`.side`, z-index 30) — a lista é conteúdo de página e não
       pode passar por cima do chrome do app quando a sidebar expande no hover.
       Acima do conteúdo comum da página, que não tem z-index. */
    z-index: 20;
    max-height: 20rem;
    overflow-y: auto;
    box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
    border: var(--bs-border-width) solid var(--line);
    background: var(--surf);
}
.hp-busca__lista .list-group-item.is-focused {
    background: var(--surf-2);
}

/* ── Histórico de Preços — pickers de mês (De/Até) ───────────────────────────
   Os dois campos são flatpickr com altInput: o input visível é criado pelo
   plugin e NÃO herda o width que ficava inline no <input type="month">. Largura
   travada aqui para o par De/Até não comer a linha do campo Produto. */
.hp-mes-input {
    width: 7rem;
    background-color: var(--surf);     /* readonly não pode parecer desabilitado */
    cursor: pointer;
}

/* ── Acompanhamento de Produção — pickers de mês (De/Até) ────────────────────
   Mesmo problema do par acima: `style="width:150px"` estava no <input> que o
   flatpickr ESCONDE (`altInput` cria o campo visível, sem herdar o width
   inline). Largura repassada via `classeAltInput` (montarCampoMes). */
.ap-mes-input {
    width: 150px;
    background-color: var(--surf);
    cursor: pointer;
}

/* ── Histórico de Preços — Buscar único (nível do produto) ───────────────────
   O gatilho de consulta desta tela é o botão ao lado do campo de produto. O
   Buscar do topbar (e o trigger mobile) ficam ocultos: mudar o período não pode
   fazer aparecer um segundo Buscar. O botão do campo pulsa quando há janela nova
   a aplicar (novo produto escolhido, ou período alterado). */
body.hp-buscar-unico #fcds-buscar,
body.hp-buscar-unico .btn-buscar-trigger { display: none !important; }

/* Topbar enxuta: só o período. O chip de Empresa (multi-empresa) fica oculto —
   remove o item do topbar sem mexer no ESCOPO: a empresa segue vindo do RBAC/URL,
   só some o controle. Segmento/Sub-seg já saem por `sem_segmentos` no include. */
body.hp-buscar-unico #fcds-empresa-wrap { display: none !important; }

/* Sem o aviso "Data alterada — clique em Buscar…" do shell: nesta tela quem sinaliza
   consulta pendente é o próprio botão do campo, que passa de `btn-outline-primary` a
   `btn-primary` (Bootstrap puro, sem CSS autoral — o pulso animado que morava aqui
   foi removido). O banner do topbar (que aparece com `body.fcds-pending`) seria um
   segundo aviso, apontando para o Buscar oculto. */
body.hp-buscar-unico #fcds-stale { display: none !important; }

/* ── Histórico de Preços — a lista de NFs rola DENTRO do card ────────────────
   `.grade .datatable-scroll { max-height:none }` (global, "a grade é a tela")
   é para a página cuja lista É a tela (Pedidos, Notas…): sem ancestral de
   altura fixa, o flex vira sizing por conteúdo e a lista — aqui até 2 mil
   linhas — esticava a PÁGINA a 77 mil px em vez de rolar por dentro. Esta tela
   não é `content--altura-cheia`: tem o card de filtros e o gráfico acima, e a
   lista sempre foi um card comum, com o mesmo teto de qualquer DataTables
   inline. Restaura esse teto só aqui — sobrescrever o token global mudaria
   toda tela migrada para a grade. */
[data-pagina="historico_precos"] #hp-card-tabela .grade .datatable-scroll {
  max-height: var(--bi-dt-scroll-cap);
}

/* ============================================================================
   Importar OF (Conexos → NF rascunho no Senior homolog) — tela oculta, F440GNE.
   O Romaneio dividia esta casca (o seletor carregava os dois prefixos) até ser
   recriado em 17/08/2026 com layout próprio de altura cheia: as regras dele
   moram na seção `romaneio` mais abaixo, e daqui só sobrou o que é da /importar-of/.
   Tokens FCDS.
   ============================================================================ */

/* A tela entrou na bancada em 18/08/2026: a casca (colunas, rolagem, régua) é
   `.bnc*`; daqui para baixo é só o conteúdo da NF. `.iof-panel`,
   `.iof-searchrow`, `.iof-list` e `.iof-actionbar` morreram com os cards e com
   a barra de ação do corpo — a ação vive na régua. */
.iof-barra{display:flex;align-items:center;gap:0.75rem;
  padding:0.75rem 1rem;border-bottom:var(--bs-border-width) solid var(--line)}
.iof-deprow{display:flex;align-items:center;gap:0.5rem;margin:0;
  font-size:0.875rem;color:var(--ink-3)}
.iof-deprow input{width: 4.375rem}

.iof-empty{padding:3rem 1rem;text-align:center;color:var(--ink-3)}
.iof-empty--err{color:var(--negative-text)}

.iof-doc__t{font-weight:600}
.iof-doc__sub{color:var(--ink-3);font-size:0.875rem;margin-top:0.25rem}
.iof-muted{color:var(--ink-3)}

.iof-sec{padding:1rem 1rem;border-top:var(--bs-border-width) solid var(--line)}
.iof-sec>h3{font-size:0.875rem;text-transform:uppercase;letter-spacing:.06em;
  color:var(--ink-3);font-weight:600;margin:0 0 0.5rem}
.iof-sec--muted>h3{color:var(--ink-4,var(--ink-3))}
.iof-fields{display:grid;
  grid-template-columns:repeat(auto-fill,minmax(11.25rem,1fr));gap:1rem 1rem}
.iof-f{display:flex;flex-direction:column;gap:0.25rem;min-width:0}
.iof-f__k{font-size:0.875rem;color:var(--ink-3);display:flex;align-items:center;gap:0.25rem}
.iof-f__v{font-weight:600;color:var(--ink);word-break:break-word}

/* itens: Bootstrap .table .table-sm (larg./bordas/padding). Só o cabeçalho
   uppercase-pequeno e o sub-texto de alíquota ficam custom (sem primitiva). */
.iof-items{font-size:0.875rem}
.iof-items th{font-size:0.875rem;text-transform:uppercase;
  letter-spacing:.04em;color:var(--ink-3)}
.iof-sub{color:var(--ink-3);font-size:0.875rem}

.iof-lote{display:flex;gap:1rem;align-items:flex-start;
  padding:1rem;border-radius:var(--r-sm);background:var(--surf-2);border:var(--bs-border-width) dashed var(--line-3);
  color:var(--ink-3)}
.iof-lote__ic{width: 1.875rem;height: 1.875rem;border-radius:var(--bs-border-radius-lg);background:var(--surf);
  border:var(--bs-border-width) solid var(--line-3);display:grid;place-items:center;flex:none;color:var(--ink-3)}
.iof-lote b{color:var(--ink-2)}

.iof-note{padding:1rem;border-top:var(--bs-border-width) solid var(--line);
  font-size:0.875rem;color:var(--ink-3)}
.iof-note b{color:var(--ink-2)}

.iof-result{display:flex;align-items:center;gap:0.5rem;
  padding:1rem 1rem;border-top:var(--bs-border-width) solid var(--line);font-size:0.875rem;color:var(--ink-2)}
.iof-result__ic{width: 1.875rem;height: 1.875rem;border-radius:50%;flex:none;
  display:grid;place-items:center;color:var(--bi-text-on-accent);font-weight:700}
.iof-result--loading{color:var(--ink-3)}
.iof-result--ok{background:var(--positive-subtle)}
.iof-result--ok .iof-result__ic{background:var(--positive)}
.iof-result--ok b{color:var(--positive-text)}
.iof-result--err{background:var(--negative-subtle)}
.iof-result--err .iof-result__ic{background:var(--negative)}
.iof-result--err b{color:var(--negative-text)}

/* O JSON do payload — hoje na prancheta, antes num modal. `.iof-modal-sub`
   morreu junto: a prancheta usa `.iof-note` para a linha de contexto. */
.iof-json{margin:0;font-family:var(--mono);font-size:var(--bnc-fs-rotulo);line-height:1.6;
  font-variant-numeric:tabular-nums;white-space:pre;overflow-x:auto;color:var(--ink-2)}
.iof-json .iof-jk{color:var(--brand-ink)}
.iof-json .iof-js{color:var(--positive-text)}
.iof-json .iof-jn{color:var(--cat-4)}
.iof-json .iof-jp{color:var(--ink-3)}
.iof-dup-list{margin:0.25rem 0 0.5rem;padding-left:1rem}
.iof-dup-list li{margin:0 0}

/* Situação intermediária (sobra/falta) ganha o terceiro tom (--warn), ao lado
   de --ok/--err acima. */
.iof-result--warn{background:var(--warning-subtle)}
.iof-result--warn .iof-result__ic{background:var(--warning)}
.iof-result--warn b{color:var(--warning-text)}

/* ── Histórico de Preços — controles compactos (produto + período no card) ───
   Produto e os dois campos de mês (De/Até) vivem no MESMO card, numa linha só.
   O produto cresce; os campos de mês têm largura fixa; Buscar alinha ao fim. */

/* ── Separação: a superfície aberta NÃO é um cartão ──────────────────────────
   Pedido do dono, 27/08/2026: "não precisa ser dentro de card nenhum". Aberta,
   a superfície JÁ é a tela — ela tem altura fixa, fundo próprio e cada painel
   rola por dentro. A moldura em volta (borda, raio e o recuo do `.content`)
   desenhava um cartão flutuando sobre um fundo que ninguém vê, e cobrava
   40 px de largura e 52 px de altura por isso. Medido ao vivo: 1512x796 vira
   1552x848, e a lista de lotes passa de 10 para 11 peças à vista.

   Zera os TOKENS, não o `padding`: a altura da `.wsurface` é
   `calc(100dvh - 52px - var(--content-pad-y) - var(--content-pad-b))`, então
   mexer no token corrige o recuo e a altura de uma vez. Zerar só o `padding`
   deixaria a superfície 52 px mais curta que a janela.

   `:has()` em vez de uma classe no `<body>` porque a MESMA página serve os dois
   estados: a fila é um cartão de verdade, sobre o fundo do app, e continua com
   o recuo do resto do BI. Quem manda é o que está na tela agora, e o seletor lê
   exatamente isso.

   O RECUO LATERAL É ASSIMÉTRICO, e isso não é desleixo — é o que a geometria
   do shell pede. `aside.side` é `position:fixed` com 64 px, mas `main` tem
   `margin-left:48px`: a barra cobre os primeiros 16 px de `main` em TODA página
   do app, e é o recuo do `.content` que sempre escondeu isso. Sem recuo nenhum
   a capa perdia a primeira letra de cada rótulo ("EDIDO", "TENS DO PEDIDO"),
   visto ao vivo. Então à ESQUERDA os 16 px são obrigatórios — e invisíveis,
   porque a barra ocupa exatamente eles.

   À DIREITA não há barra nenhuma para desviar, e um recuo igual ao da esquerda
   só desenhava uma tira do fundo do app colada na janela — que é o que parece
   espaço reservado para uma rolagem que não existe (nenhum ancestral aqui tem
   `overflow-y:scroll` nem `scrollbar-gutter`). Zerado, a superfície branca
   encosta na janela e a tabela ganha os 16 px. O respiro entre a tabela e a
   borda continua existindo: é o `padding` do próprio `.wsurface__main`.

   Consertar o desencontro na raiz é `main{margin-left:64px}` — mexe no shell
   das ~28 páginas e não cabe neste commit. */
.content:has(#sep-superficie:not([hidden])){
  --content-pad-y:0px;--content-pad-b:0px;padding:0 0 0 16px}
.content:has(#sep-superficie:not([hidden])) #sep-superficie{border:0;border-radius:0}

/* ── Separação e faturamento ─────────────────────────────────────────────────
   A linha da tabela de itens é o alvo que troca o produto da etapa de lotes.
   Só o cursor entra aqui: a marcação da linha aberta é `.table-active` do
   Bootstrap e o anel de foco é o `:focus-visible` do Bootstrap — nada de
   destaque ou de foco autoral nesta tela. */
.sep-item-linha{cursor:pointer}
/* O cartão do item é TRÊS LINHAS CURTAS (descrição, código, estado) e vivia
   com o respiro de parágrafo do shell: 89 px por item, com 24 px de altura de
   linha para textos de 13 px. Apertado ao que ele é — entrelinha de leitura de
   rótulo, não de prosa — cai para 77 px, e o trilho ganha um item inteiro a
   cada seis. Escopado à `.sep-item-linha`, nunca à `.wsurface__item` do FCDS,
   que outras bancadas usam com conteúdo mais longo. */
.sep-item-linha{padding:.5rem .75rem;line-height:1.35}

/* ── O estado de cada item no trilho, e o progresso do pedido ─────────────
   Três estados servidos pelo backend (`/resumo-itens/`): pendente, marcado e
   não gravado, gravado. Antes o cartão só sabia dizer "Já com lote", e um item
   com sete lotes marcados era visualmente idêntico a um intocado — foi assim
   que a marcação evaporou sem ninguém ver (pedido 20878).
   Cor só onde ela significa: o marcado é o único que pede ação e leva o acento;
   o gravado é história e fica em positivo discreto; o pendente é texto morno. */
.sep-item-estado{margin-top:.125rem;font-weight:600;color:var(--ink-3)}
.sep-item-estado[data-estado="marcado"]{color:var(--acc)}
.sep-item-estado[data-estado="gravado"]{color:var(--positive-text)}
.sep-progresso{font-weight:600;color:var(--ink-2);text-transform:none;letter-spacing:0}
/* O pedido inteiro ao lado da ação, no rodapé. Só aparece com mais de um item
   marcado — o texto vem pronto do backend. */
.sep-consolidado{font-weight:600;color:var(--ink-2);white-space:nowrap}
/* A lista de itens dentro da confirmação: o que exatamente vai ser gravado,
   um por linha, antes de uma escrita sem desfazer. */
.sep-confirma-itens{margin:.5rem 0 0;padding-left:1.1rem}
.sep-confirma-itens li{margin-bottom:.15rem}
/* O efeito no pedido (cresce / encolhe) dentro da linha da revisão. Ele morava
   no diálogo do item, que deixou de existir quando a revisão virou uma só, do
   pedido inteiro: aqui é a última coisa que se lê antes de autorizar a escrita,
   então destaca do resto da linha sem virar alarme. */
.sep-confirma-efeito{font-weight:600;color:var(--ink-2)}
/* A marca da linha aberta é a classe `.table-active` do Bootstrap, mas a
   pintura dela mora em `.table > :not(caption) > * > *` — e a tabela desta
   tela é `.tbl`, não `.table`, então a classe entrava no DOM e não pintava
   nada (conferido ao vivo: background rgba(0,0,0,0) na linha marcada).
   Só se repete o seletor; a cor continua sendo a do Bootstrap — o token
   `--bs-table-active-bg` também só é declarado em `.table`, daí o fallback
   com o mesmo valor que o Bootstrap 5.2.3 lhe dá. */
.tbl > tbody > tr.table-active > td{background:var(--bs-table-active-bg,rgba(0,0,0,.1))}

/* ── Fila de pedidos da separação (escolher em QUAL pedido trabalhar) ─────────
   Onze colunas em 1.560 px, e a coluna da AÇÃO tem de ser uma delas. Medido
   antes: `Criado` saía cortada na borda direita e o botão Separar ficava FORA da
   tela — a fila oferecia trabalho que ninguém alcançava sem rolar de lado.
   `.cell-clip` genérico dá 22 rem, largo demais quando quatro colunas o usam
   (cliente, produto, comentário, vendedor). O truncamento em si é no JS, com o
   texto inteiro no `title`.

   E o cabeçalho no mesmo tom do resto da tela: caixa normal, miúdo, tinta fraca
   — o versalete espaçado do padrão FCDS empatava em peso com os badges de
   situação e urgência, que são o que a pessoa varre. Escopado à página; nenhuma
   outra tela muda. A superfície de trabalho é irmã deste bloco no template, não
   descendente, então não é alcançada por este seletor: quem a veste é `.pickbox`. */
/* AS COLUNAS SE AJUSTAM AO CONTEÚDO. O teto de 10rem foi calibrado quando a
   fila tinha ONZE colunas e quatro delas eram texto largo (cliente, produto,
   comentário, vendedor). Sobraram oito, e três daquelas quatro saíram — o teto
   fixo agora só serve para cortar nome de cliente numa tabela que tem espaço de
   sobra. `table-layout:auto` (já herdado) distribui pelo conteúdo; o
   truncamento continua existindo para o caso extremo, mas com um teto que
   respira e sem largura mínima que empurre as outras. */
/* LARGURA POR PAPEL, não uma trava só para todas. O teto único de 10rem
   cortava tudo igual — nome de cliente, produto e observação — num layout que
   já tinha espaço. Agora cada coluna de texto tem o teto do que ela precisa:

   - observação: é INSTRUÇÃO de quem vendeu ("ENTREGAR SÓ PELA MANHÃ",
     "FATURAR SOMENTE EM SETEMBRO"), lida antes de escolher o pedido — ganha o
     maior teto e quebra em até três linhas;
   - cliente: identifica, não instrui. Razão social de 50 caracteres não precisa
     caber inteira; o `title` guarda o resto;
   - financeiro: o motivo cabe em duas linhas curtas.

   `table-layout:auto` (herdado) distribui o resto pelo conteúdo. */
[data-pagina="separacao_faturamento"] .cell-clip{max-width:none}
/* Na grade da casa (15/09/2026) as larguras vão por CLASSE da coluna, não pela
   posição: o `nth-child` prendia a regra na coluna errada toda vez que a ordem
   mudava. O invólucro `.grade-celula` corta em uma linha; as duas colunas que
   se LEEM (Financeiro e Observação) voltam a quebrar em duas. */
[data-pagina="separacao_faturamento"] .grade .grade-tabela :is(th, td){padding-left:.4rem;padding-right:.4rem}
[data-pagina="separacao_faturamento"] .grade .sep-col-cliente{max-width:8rem}
[data-pagina="separacao_faturamento"] .grade .sep-col-financeiro{min-width:7.5rem;max-width:11rem}
[data-pagina="separacao_faturamento"] .grade .sep-col-observacao{max-width:8rem}
[data-pagina="separacao_faturamento"] .grade .grade-tabela :is(.sep-col-financeiro, .sep-col-observacao) .grade-celula{
  white-space:normal}
/* A observação sai da célula já cortada pelo JS (`.text-truncate`, uma linha):
   aqui ela volta a quebrar em DUAS, que é o que se lê antes de escolher. */
[data-pagina="separacao_faturamento"] .grade .sep-col-observacao .cell-clip{
  max-width:none;white-space:normal;display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;overflow:hidden}
/* O motivo do bloqueio para em DUAS linhas: em tela estreita ele ia a quatro e
   dobrava a altura da linha bloqueada, numa lista que se lê pela regularidade. */
[data-pagina="separacao_faturamento"] .sep-motivo{display:-webkit-box;
  -webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
/* Em tela larga a sobra vai para quem tem texto: as colunas curtas ficam do
   tamanho do conteúdo (`width:1%` em layout auto) e Cliente e Observação ganham
   teto maior. Abaixo de 1600px os tetos baixos é que evitam rolagem lateral. */
@media (min-width:1600px){
  [data-pagina="separacao_faturamento"] .grade .sep-col-curta{width:1%}
}
@media (min-width:1800px){
  [data-pagina="separacao_faturamento"] .grade .sep-col-cliente{max-width:14rem}
  [data-pagina="separacao_faturamento"] .grade .sep-col-observacao{max-width:22rem}
}

/* ── .detrow — LINHA DE DETALHE DE UMA TABELA (componente) ────────────────────
   O conteúdo que a linha truncada esconde, aberto embaixo dela. O corpo é
   desenhado por quem chama; aqui está a fita de rótulos, a célula do controle e
   o botão que gira. Casado com `row().child()` do DataTables — é a tabela que
   fecha a filha ao reordenar, filtrar e paginar. */
/* O controle é `.drill-plus`, a afordância canônica de abrir detalhe (mais ↔
   menos, glifo no `::before` do componente). A seta que girava aqui era
   invenção local: um segundo vocabulário de "abre isto" na mesma app. */
.detrow__cel{width:1%;padding-right:0}
/* A LINHA-FILHA não é uma linha de dados: não se lista, não reage ao mouse e não
   tem moldura. O DataTables cria o <tr> da filha sem classe, então ela caía nas
   regras de listra e de hover das outras linhas — e como o painel cinza tem
   fundo próprio, quem mudava de cor era só o PADDING da <td> em volta dele: uma
   moldura de 8 px que acendia e apagava conforme o cursor passava. Padding zero
   faz o painel preencher a célula, e o `box-shadow:none` desliga a listra e o
   realce (é por `box-shadow` inset que o Bootstrap pinta os dois).
   O `!important` do padding não é preferência: `.tbl.dataTable tbody td`
   já declara o dele com `!important`, e sem isto o zero é ignorado —
   medido no navegador, a moldura continuava lá. */
.tbl tbody tr.detrow__filha > td,
.tbl tbody tr.detrow__filha:hover > td{padding:0 !important;box-shadow:none;background:none}
/* Fundo BRANCO, como as linhas de dados: o painel é a continuação do pedido que
   está logo acima, não um bloco estranho encaixado na lista. O cinza que estava
   aqui competia com a listra da tabela e criava uma terceira cor de fundo. */
.detrow{display:grid;grid-template-columns:repeat(auto-fit,minmax(16rem,1fr));
  gap:.625rem 1.5rem;margin:0;padding:.75rem 1rem;background:var(--surf)}
.detrow__campo{min-width:0}
.detrow__campo dt{margin:0;font-size: var(--bi-fs-micro);font-weight:600;color:var(--ink-3)}
.detrow__campo dd{margin:.125rem 0 0;font-size: var(--bi-fs-compact);color:var(--ink)}
/* A faixa de medidas do topo separa-se da barra da tabela. */
/* A faixa de medidas é CONTEÚDO do cartão e precisa do recuo lateral que a
   regra global de coerência de página tira de toda `.page > section`
   (`padding-left/right:0 !important`, para a tabela poder encostar nas bordas).
   Sem isto a primeira medida nascia colada na borda esquerda e a última na
   direita — medido: a medida começava em x=69 num cartão que começa em x=68. A
   tabela SEGUE encostada, que é o que aquela regra existe para permitir. */
/* As medidas MORAM na barra da tabela (o JS as move para
   `.datatable-toolbar__left`, ao lado de Copiar e Colunas). Como faixa própria
   elas gastavam 56px de altura para dizer dois números, enquanto a barra ao
   lado tinha metade da largura vazia — duas faixas para uma leitura só. Aqui
   elas perdem a moldura de cartão e viram par rótulo/valor em linha: o mesmo
   texto, na altura que a barra já ocupava. */
[data-pagina="separacao_faturamento"] #sep-resumo{margin:0;gap:.25rem}
[data-pagina="separacao_faturamento"] #sep-resumo .measure{min-width:0;
  display:flex;align-items:baseline;gap:.375rem;padding:.125rem .5rem;
  background:none;border-color:transparent}
[data-pagina="separacao_faturamento"] #sep-resumo .measure dd{margin:0;font-size:.875rem}
/* A que pede atenção (bloqueados > 0) mantém o fundo de alerta — é a única que
   precisa saltar, e sem ela a barra ficaria com dois números iguais. */
[data-pagina="separacao_faturamento"] #sep-resumo .measure--alerta{
  background:var(--warning-subtle);border-color:var(--warning-border)}
/* "Bloqueados" é ATALHO (liga o filtro do Financeiro): botão de verdade, com a
   mão e o foco, e o estado ligado no mesmo retângulo cheio dos chips da grade. */
[data-pagina="separacao_faturamento"] #sep-resumo button.measure--atalho{
  font:inherit;color:inherit;cursor:pointer;text-align:left}
[data-pagina="separacao_faturamento"] #sep-resumo button.measure--atalho:hover{filter:brightness(.97)}
[data-pagina="separacao_faturamento"] #sep-resumo button.measure--atalho:focus-visible{
  outline:2px solid var(--grade-tinta, #212529);outline-offset:1px}
[data-pagina="separacao_faturamento"] #sep-resumo button.measure--atalho[aria-pressed="true"]{
  background:var(--grade-tinta, #212529);border-color:var(--grade-tinta, #212529)}
[data-pagina="separacao_faturamento"] #sep-resumo button.measure--atalho[aria-pressed="true"] :is(dt, dd){
  color:#fff}

/* QUANTIDADE EM UMA LINHA — estado à esquerda, número flush à direita. */
/* INLINE, não flex: num container flex o navegador descarta o nó de texto entre
   os dois spans, e o botão Copiar da barra levava "Não separado30.000 KG" para
   a área de transferência. Alinhamento pela direita e um recuo no rótulo dão o
   mesmo desenho preservando o espaço. */
[data-pagina="separacao_faturamento"] .sep-qtd{text-align:right;white-space:nowrap}
[data-pagina="separacao_faturamento"] .sep-qtd--separado{color:var(--ink-3)}
[data-pagina="separacao_faturamento"] .sep-qtd .sep-legenda{margin-right:.25rem}
/* TELA ESTREITA PAGA COM RECUO, NÃO COM ALTURA. Abaixo de 1400px a régua de dez
   colunas não fecha (medido: pedia 1.326px num vão de 1.276) e a saída óbvia
   seria deixar Entrega e Quantidade quebrarem de novo — mas isso devolve 12px
   de altura a TODAS as 72 linhas para acomodar duas. Apertar o recuo lateral
   das células devolve 8px por coluna, 80px na linha inteira, e não custa
   nenhuma altura: a tabela volta a caber e a densidade vale em toda largura. */
@media (max-width:1399px){
  [data-pagina="separacao_faturamento"] .tbl.dataTable td,
  [data-pagina="separacao_faturamento"] .tbl.dataTable th{
    padding-inline:.25rem !important}
}
[data-pagina="separacao_faturamento"] .sep-qtd .sep-legenda{font-size: var(--bi-fs-micro);letter-spacing:.03em}
/* Os dois botões da linha ficam com o recuo de um botão de GRADE, não de
   formulário: 159px para "Detalhes Separar" era largura de coluna de dados. O
   alvo de toque continua acima do mínimo (31px de altura, inalterado). */
[data-pagina="separacao_faturamento"] .tbl.dataTable td:nth-child(1) .btn{
  padding-inline:.5rem}

/* O RODAPÉ DA TABELA É UMA LINHA, não uma faixa. "1–72 de 72" mais um paginador
   de uma página só ocupavam 59px — mais que uma linha de pedido. O texto e os
   controles ficam (o contador é o que avisa quando um filtro escondeu gente);
   some o recuo que os cercava. */
[data-pagina="separacao_faturamento"] .datatable-bottom{padding-block:.25rem}
[data-pagina="separacao_faturamento"] .datatable-bottom .page-link{
  padding:.125rem .5rem;font-size: var(--bi-fs-compact)}
[data-pagina="separacao_faturamento"] .tbl thead th{text-transform:none;
  letter-spacing:0;font-size: var(--bi-fs-compact)}
/* A coluna da AÇÃO fica grudada na borda direita (componente `.stickcols` +
   `stick-r--1`, o mesmo das telas de matriz): são doze colunas num cartão de
   1.512 px, a tabela rola de lado, e o que saía de vista era justamente o botão
   — a pessoa via o pedido e não alcançava o trabalho dele sem rolar.
   Aqui só a largura: o resto (opacidade, listra, divisor, escada de z) já é do
   componente. Tentei antes um `position:sticky` local com `box-shadow` de
   divisor e caí exatamente na armadilha que o comentário do componente
   documenta: a listra do `.table-striped` é pintada com `box-shadow inset
   9999px`, que atropela o divisor e deixa a célula transparente em metade das
   linhas (medido: `background-color: rgba(0,0,0,0)` nas linhas `.odd`, com a
   data da coluna de trás aparecendo através do botão). */
[data-pagina="separacao_faturamento"] .tbl td.stick-r--1,
[data-pagina="separacao_faturamento"] .tbl th.stick-r--1{white-space:nowrap}

/* Alvo de toque do checkbox de lote. A caixa desenhada tem 14x14 px — metade
   do mínimo da WCAG 2.2 e impossível de acertar de luva num tablet do galpão.
   O <label> em volta alterna a caixa nativamente, então basta dimensioná-lo:
   44x44 px de área clicável com a caixa centrada e um pouco maior. */
.sep-alvo-toque{display:flex;align-items:center;justify-content:center;
  min-width:44px;min-height:44px;margin:0;cursor:pointer}
.sep-alvo-toque .form-check-input{width:1.5rem;height:1.5rem;margin:0;flex:none}

/* Barra de progresso da fila (separado × saldo). Fina de propósito: informa a
   proporção de relance sem competir com o número, que é o dado exato. O
   percentual vem pronto do backend (`progresso_pct`). */
.sep-progresso{height:.35rem;margin-top:.25rem}

/* Rodapé fixo do modal do pedido. Medido antes: um produto com 204 lotes dá
   `scrollHeight` 8.247 px numa janela de 779 px — dez telas de checkbox até o
   botão, que ficava DEPOIS da lista. Sticky dentro do `.modal-body` rolável põe
   a decisão sempre à mão. As margens negativas sangram o padding do corpo para
   a faixa ir de borda a borda, como um rodapé de modal de verdade. */
.sep-rodape{position:sticky;bottom:0;z-index:2;
  display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap;
  margin:1rem -1rem -1rem;padding:.75rem 1rem;
  background:var(--surf);border-top:var(--bs-border-width) solid var(--line)}

/* Régua de peso — a peça de assinatura da tela e a única coisa dela que muda de
   cor. O pedido pede um número redondo (6.000 KG), o mundo entrega números
   tortos (1.748 + 1.579 + 1.702), e a pergunta que a pessoa faz o tempo todo é
   "o que marquei já cobre o pedido, e quanto passou?". Sem animação nenhuma:
   galpão, tablet, luva — a cor é o sinal inteiro, e por não se mover ela já
   respeita `prefers-reduced-motion`. A classificação (falta/coberto/passa) vem
   decidida do Python; aqui só se escolhe a cor de cada uma. */
.sep-regua{display:flex;align-items:baseline;gap:.5rem;flex-wrap:wrap;
  font-variant-numeric:tabular-nums}
.sep-regua__estado{font-weight:600;padding:.125rem .5rem;border-radius:var(--r-xs)}
.sep-regua--falta   .sep-regua__estado{background:var(--surf-3);color:var(--ink-2)}
.sep-regua--coberto .sep-regua__estado{background:var(--positive-subtle);color:var(--positive-text)}
.sep-regua--passa   .sep-regua__estado{background:var(--warning-subtle);color:var(--warning-text)}

/* ── .wsurface — SUPERFÍCIE DE TRABALHO (componente, não página) ─────────────
   Modo-tarefa em tela cheia: a lista de onde se veio some, e a tela inteira
   passa a ser a tarefa. Nasceu para a separação de pedidos, mas nada aqui sabe
   o que é um lote — serve qualquer fluxo em que a pessoa entra num registro,
   trabalha nele e sai (conferência, importação, fechamento).

   Por que não um modal: o modal é uma caixa por cima de uma lista, com duas
   barras de rolagem e um corpo que encolhe conforme o conteúdo cresce. Numa
   tarefa de galpão com 200 lotes isso é uma janelinha rolando dentro de outra.
   A superfície ocupa a altura útil e distribui: capa em cima, trilho de
   contexto à esquerda, trabalho no centro, decisão grudada embaixo. Cada painel
   rola por si; a página nunca rola.

   Estrutura:
     .wsurface > .wsurface__cap  (capa: quem é o registro)
               > .wsurface__body > .wsurface__rail  (contexto/navegação interna)
                                 > .wsurface__main  (o trabalho)
               > .wsurface__foot (medida + ação, sempre à vista) */
.wsurface{display:flex;flex-direction:column;gap:0;
  /* Altura FIXA, não mínima: é ela que faz o rodapé com a medida e a ação ficar
     sempre à vista. Com `min-height` a superfície crescia com a lista de lotes
     (11 lotes já passavam da dobra) e a decisão ia junto para o fim da página —
     exatamente o que o rodapé grudado existe para evitar. Quem rola é o painel
     de dentro. 52px = a topbar fixa (`.topbar`, 3.25rem), o mesmo literal que a
     coluna de conteúdo já desconta na linha 6677; não existe token de altura de
     topbar em `:root` e inventar um aqui criaria uma segunda verdade. */
  height:calc(100dvh - 52px);   /* o padding do `.content` já foi anulado acima */
  background:var(--surf);border:var(--bs-border-width) solid var(--line);
  border-radius:var(--r);overflow:hidden}
/* A CAPA É UMA GRADE, não uma fila de blocos. Em flex, cada bloco aninhado
   media a própria largura e o que sobrava na linha ficava em branco: a linha do
   cliente acabava a 540px numa capa de 1.660 e as outras informações esperavam
   embaixo. Colunas de largura dinâmica (`auto-fill` + `minmax`) e cada
   informação como célula fazem a linha fechar sozinha, com a hierarquia dada
   pelo quanto cada uma ocupa: o cliente vale duas colunas, a data de entrega
   (que tem controle) duas, cada campo uma, e a advertência toma a sobra. */
/* A CAPA É UMA CAIXA DE FATOS ADENSADA.
   O formato continua o mesmo — rótulo miúdo em cima, valor embaixo —, o que
   muda é o quanto cada fato ocupa e como eles se arrumam. Antes: entrelinha de
   texto corrido, recuos de 1rem, colunas fixas e fileiras conforme sobrasse —
   uma ficha gastava 40px de altura para dizer "Carga · Carreta ou truque", e a
   capa ia a 364px.
   Agora a ficha tem 28px (rótulo em 11px/1.1, valor em 13px/1.2), o fluxo é por
   COLUNA sobre duas trilhas fixas — os fatos descem, viram a coluna e descem de
   novo, então quem se ajusta ao volume é o número de colunas, não a altura — e
   o cliente ocupa duas colunas de UMA fileira, não as duas: comendo as duas ele
   deixava um vão do tamanho dele embaixo do nome. */
.wsurface__cap{display:grid;
  /* 8 e 4 na régua de 12 do Bootstrap: os fatos com dois terços, a advertência
     com um. O voltar é trilha `auto` — tem largura de botão, não de coluna. */
  /* As fichas tomam a largura que PRECISAM e a advertência fica com o resto —
     não uma fatia fixa. Com 8fr/4fr as colunas de fato eram todas do mesmo
     tamanho, então "Cidade · JOINVILLE · SC" reservava tanto quanto "Frete ·
     CIF — frete por nossa conta" e sobrava um vão depois de cada valor curto,
     mais um vão maior antes da advertência. */
  /* 50/50: fichas e advertência com metade cada. Sem observação a regra abaixo
     colapsa para uma coluna só e as fichas tomam a capa inteira. */
  /* A ADVERTÊNCIA MEDE O QUE ELA DIZ. Com metade da capa reservada, uma
     observação de uma linha ficava com 654px de caixa para 426px de texto —
     228px de amarelo vazio — e as fichas espremidas na metade restante, com
     vão depois de cada valor curto (marcado na captura do dono, 13/08/2026).
     `fit-content` dá à advertência o tamanho do texto dela, até um teto de
     30rem para o recado longo não comer a capa; o que sobra vai para as
     fichas, que se espalham por ele. */
  /* O TETO DA ADVERTÊNCIA É UMA FRAÇÃO DA CAPA. `max-content` + `max-width:
     30rem` no item eram 480px numa capa de 1.830 (1920px): fichas com meia
     fileira vazia e o recado cortado a três linhas — "travado de um jeito
     pequeno" (dono, 18/08/2026). `fit-content(42%)` mede o texto (recado curto
     continua do tamanho dele) até 42% da capa; o resto é das fichas — mesma
     proporção em qualquer largura. Percentual no `max-width` do item não serve:
     resolve contra a própria trilha e volta a 30rem. */
  grid-template-columns:minmax(0,1fr) fit-content(42%);
  /* E ela também não estica em ALTURA: `stretch` pintava 79px de amarelo para
     16px de frase. Quem manda na altura da capa são as fichas. */
  align-items:start;gap:.375rem .875rem;
  padding:.5rem .875rem;border-bottom:var(--bs-border-width) solid var(--line);
  background:var(--surf-2)}
/* Sem observação não há segunda coluna: os fatos tomam a capa inteira. */
.wsurface__cap:has(> .wsurface__cap-obs:empty){grid-template-columns:minmax(0,1fr)}
/* AS FICHAS SE EMPACOTAM, NÃO SE ALINHAM EM COLUNAS. Numa grade de colunas, a
   coluna tem a largura da ficha MAIS LARGA dela: "Cliente · ALYA CONSTRUTORA
   S/A" esticava a coluna e deixava rastro branco depois de "Pedido · 20318",
   que está em cima. E `max-content` em todas as colunas estourava a capa em tela
   estreita — a advertência caía para o mínimo e era cortada.
   Empacotadas (flex com quebra), cada ficha mede o que o valor dela mede, elas
   enchem a linha até o fim e a seguinte recomeça. Não sobra rastro porque não
   há coluna a respeitar. */
/* AS FICHAS COMEÇAM NA ESQUERDA, COM ESPAÇAMENTO IGUAL. Com
   `space-between` a folga da fileira era repartida ENTRE as fichas, e cada
   fileira repartia de um jeito: "Carga" caía embaixo de "Cliente", "Valor do
   pedido" embaixo de "Cidade" e nada se alinhava com nada — a grade parecia
   torta (marcado pelo dono, 13/08/2026). O `space-between` existia para matar o
   rastro branco antes da advertência, e esse rastro deixou de existir quando a
   advertência passou a medir o próprio texto. Grade de trilhas iguais foi
   tentada e custou uma fileira a mais (10 fichas de larguras muito desiguais em
   colunas de 156px: 3 fileiras, 145px de capa) — empacotar continua sendo o que
   cabe em duas. */
.wsurface__cap-esq{display:flex;flex-wrap:wrap;align-content:flex-start;
  align-items:flex-start;justify-content:flex-start;
  gap:.25rem 1.5rem;min-width:0}
/* A `<dl>` some como caixa para que cada ficha entre no empacotamento. Sem isto
   a fita inteira é UM item e não há o que empacotar. */
.wsurface__cap-esq > .wsurface__cap-campos{display:contents}
/* O cliente é ficha como as outras — mesmo rótulo miúdo, mesmo corpo de valor —
   só que com o dobro de LARGURA: a razão social tem 25 caracteres e numa coluna
   só ela quebraria em três linhas, esticando a fileira inteira. */

/* AS FICHAS SE ESPALHAM ATÉ AS DUAS BORDAS. Empacotadas só pelo tamanho do
   conteúdo, a última de cada fileira parava onde o texto dela acabava e o resto
   ficava em branco até a advertência — a faixa que estava circulada. Deixá-las
   CRESCER não resolve: a folga entra dentro da última ficha e o branco continua
   no mesmo lugar, só que dentro de uma caixa maior. Espalhando (`space-between`)
   a folga vira distância ENTRE as fichas, a primeira encosta na esquerda e a
   última na direita — não existe mais ponta livre. */
.wsurface__cap-campo{min-width:0}
/* Cliente e vendedor são razões sociais de 25 a 50 caracteres: numa célula só
   quebrariam em três linhas e esticariam a fileira inteira. Duas células. */
.wsurface__cap-campo.sep-cliente{grid-column:span 2}
.wsurface__cap-campo dt{font-size: var(--bi-fs-micro);line-height:1.1;text-transform:uppercase;
  letter-spacing:.02em;color:var(--ink-3);font-weight:600;margin:0}
.wsurface__cap-campo dd{margin:.0625rem 0 0;font-size: var(--bi-fs-compact);line-height:1.2;
  color:var(--ink);font-weight:500}
/* A entrega tem campo e botão; os dois cabem na largura de uma ficha. Ela nasceu
   em corpo de número (1,25rem) para sair do tamanho de filtro — numa grade em
   que cada fato vale uma célula, esse corpo obrigava a coluna a ser o dobro das
   vizinhas. */
/* A entrega tem campo e botão na MESMA linha do valor — empilhados, a ficha
   ficava mais alta que as vizinhas e a sobra virava faixa vazia sob elas. O
   botão virou ícone (o rótulo "Alterar" custava 55px numa fita onde cada ficha
   mede pouco mais de 100). */
.wsurface__cap-campo.sep-entrega dd{display:flex;align-items:center;gap:.25rem}
.wsurface__cap .sep-entrega__data{font-size: var(--bi-fs-compact);width:7rem;min-width:0;
  padding:.0625rem .25rem;height:auto;font-weight:600}
/* O `.ms-1` do botão vem do markup (herança do tempo em que ele ficava AO LADO
   do campo); empilhado, esse recuo o desalinhava do campo acima. */
.wsurface__cap .sep-entrega .btn{padding:.0625rem .375rem;font-size: var(--bi-fs-compact);
  margin-left:0 !important}
.wsurface__body{display:grid;grid-template-columns:minmax(15rem,20rem) minmax(0,1fr);
  flex:1;min-height:0}
.wsurface__rail{border-right:var(--bs-border-width) solid var(--line);
  overflow-y:auto;padding:.75rem}
/* Sem trilho, o trabalho toma a largura inteira. Sem esta regra a primeira
   trilha da grade continuaria reservada e sobraria uma coluna vazia de 15rem. */
.wsurface__body:has(> .wsurface__rail[hidden]){grid-template-columns:minmax(0,1fr)}
.wsurface__main{overflow-y:auto;padding:.75rem 1rem;min-width:0}
.wsurface__foot{position:sticky;bottom:0;z-index:2;
  display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap;
  padding:.75rem 1rem;background:var(--surf);
  border-top:var(--bs-border-width) solid var(--line)}
/* O painel de confirmação EMPILHA: texto e previsão em cima, botões embaixo à
   direita. Como linha de rodapé, a previsão de 8 linhas crescia e os botões
   flutuavam no meio da lateral — era a "tela estranha" da foto do usuário. Com
   teto e rolagem própria, um pedido de 24 linhas não empurra a decisão para
   fora da tela. */
#sep-confirmacao{flex-direction:column;align-items:stretch;flex-wrap:nowrap;
  max-height:70vh;overflow:auto}
#sep-confirmacao > .d-flex{justify-content:flex-end}
/* Num tablet em pé o trilho vira uma faixa em cima do trabalho, não some:
   é ele que diz de qual item são as linhas do centro. */
@media (max-width:991.98px){
  .wsurface__body{grid-template-columns:minmax(0,1fr)}
  .wsurface__rail{border-right:0;border-bottom:var(--bs-border-width) solid var(--line);
    max-height:14rem}
}

/* Item selecionável do trilho — a versão em bloco da linha de tabela marcada.
   `aria-current` é quem manda: o estado visual segue o atributo que o leitor de
   tela já anuncia, em vez de uma classe paralela que pode divergir dele. */
.wsurface__item{display:block;width:100%;text-align:left;cursor:pointer;
  padding:.5rem .625rem;border:var(--bs-border-width) solid transparent;
  border-radius:var(--r-sm);background:none;color:inherit;margin-bottom:.25rem}
.wsurface__item:hover{background:var(--surf-2)}
.wsurface__item[aria-current="true"]{background:var(--acc-soft);
  border-color:var(--acc-line)}
/* As medidas dentro do cartão do item: mesmo componente, escala do trilho. A
   coluna tem ~300 px e a ficha padrão (7rem de largura mínima) só deixava duas
   por linha com folga nenhuma. Aqui elas encolhem para caber as três, e a
   margem de baixo sai porque quem separa os cartões é a margem do próprio
   cartão. */
.wsurface__item .measures{margin:0;gap:.25rem}
.wsurface__item .measure{min-width:0;flex:1 1 4.5rem;padding:.25rem .5rem}
.wsurface__item .measure__v{font-size: var(--bi-fs-compact)}
.wsurface__item[aria-current="true"] .measure{background:var(--surf)}
.wsurface__item[aria-current="true"] .measure--dest{background:var(--acc-soft)}

/* ── .fillbar — BARRA SEGMENTADA RUMO A UM ALVO (componente) ─────────────────
   Uma barra de progresso responde "quanto por cento". Esta responde "de que
   PARTES o total é feito": um segmento por parcela, cada um com a largura da
   sua contribuição. Na separação, cada segmento é uma bobina — e é assim que se
   enxerga que 20 t são treze bobinas e não um número. Serve igual para meta
   composta por vendedor, carteira por faixa, orçamento por rubrica.

   As larguras (`pct`), o traço do alvo (`alvo_pct`) e quem é excesso chegam
   calculados do backend. A escala é o maior entre alvo e total, então quando a
   seleção passa do alvo o traço cai antes do fim e o excesso aparece hachurado
   em vez de estourar o contêiner.

   Sem transição: galpão, tablet, luva — e por não se mover já respeita
   `prefers-reduced-motion` sem uma media query. */
/* Fina e em pílula, como no desenho aprovado: 20 px de altura davam a uma medida
   auxiliar o peso visual de um gráfico, competindo com o número exato que está
   logo abaixo dela. A barra responde "de quantas partes"; quem responde "quanto"
   é a legenda. */
.fillbar{position:relative;display:flex;height:.625rem;overflow:visible;
  background:var(--surf-3);border-radius:var(--r-full)}
.fillbar__seg{min-width:1px;background:var(--acc);
  border-right:1px solid var(--surf)}
.fillbar__seg:first-child{border-start-start-radius:var(--r-full);
  border-end-start-radius:var(--r-full)}
.fillbar__seg:last-child{border-right:0;
  border-start-end-radius:var(--r-full);border-end-end-radius:var(--r-full)}
.fillbar__seg--over{background:repeating-linear-gradient(45deg,
  var(--warning-text) 0 4px,var(--warning-subtle) 4px 8px)}
/* Traço do alvo: onde o pedido termina. Fica por cima dos segmentos e sobra 3 px
   para cada lado — numa barra de 10 px, um traço contido nela desaparece. */
.fillbar__mark{position:absolute;top:-3px;bottom:-3px;width:2px;margin-left:-1px;
  background:var(--ink);pointer-events:none}
.fillbar__mark::after{content:attr(data-rotulo);position:absolute;top:100%;
  left:0;transform:translateX(-50%);white-space:nowrap;
  font-size: var(--bi-fs-micro);color:var(--ink-3)}
/* Legenda da barra: números tabulares e o estado em pílula. A classificação
   (falta/coberto/passa) vem decidida do backend; aqui só se pinta cada uma. */
.fillbar-leg{display:flex;align-items:baseline;gap:.5rem;flex-wrap:wrap;
  font-variant-numeric:tabular-nums}
.fillbar-leg__estado{font-weight:600;padding:.125rem .5rem;border-radius:var(--r-xs)}
.fillbar-leg--falta   .fillbar-leg__estado{background:var(--surf-3);color:var(--ink-2)}
.fillbar-leg--coberto .fillbar-leg__estado{background:var(--positive-subtle);color:var(--positive-text)}
.fillbar-leg--passa   .fillbar-leg__estado{background:var(--warning-subtle);color:var(--warning-text)}

/* ── .stepbar — FAIXA DE PASSOS QUE INSTRUI (componente) ─────────────────────
   Não é um "stepper" decorativo com bolinhas numeradas: o TEXTO de cada passo
   muda com o estado, então a faixa responde "o que eu faço agora, e o que isto
   vai causar no registro" em vez de enumerar etapas. Numa tela que grava de
   forma irreversível num ERP, é ela que carrega a consequência em português
   antes de a pessoa clicar — o número sozinho não avisa nada.

   Serve qualquer fluxo de poucos passos onde a consequência importa mais que a
   contagem (separação, importação, fechamento). Nada aqui sabe o que é um lote.

   `data-ativo` / `data-feito` são atributos, não classes: quem escreve a faixa
   decide o estado num lugar só e o CSS lê exatamente o mesmo dado.

   As divisórias saem de `gap` sobre um fundo da cor da linha, não de
   `border-right` no passo: com `auto-fit` os passos podem quebrar em duas
   fileiras, e a borda lateral deixaria a fileira de baixo sem separador em cima
   (e o último da primeira fileira com uma borda sobrando). */
/* OS PASSOS PESAM IGUAL. O passo zero ("Voltar à fila") é um botão de largura
   própria; 1, 2 e 3 dividem em partes iguais o que sobra, cada um com título e
   frase. O passo ativo se distingue pela cor e pelo numeral, não por roubar
   largura dos vizinhos — uma faixa que muda de geometria a cada marcação faz o
   olho reprocessar a instrução inteira. */
.stepbar{display:flex;flex-wrap:wrap;
  gap:var(--bs-border-width);background:var(--line);
  border-bottom:var(--bs-border-width) solid var(--line)}
.stepbar__passo{display:flex;align-items:center;gap:.625rem;flex:1 1 0;
  min-width:0;padding:.5rem 1rem;background:var(--surf-2)}
.stepbar__voltar{flex:0 1 auto}
.stepbar__num{flex:none;display:flex;align-items:center;justify-content:center;
  width:1.375rem;height:1.375rem;border-radius:var(--r-full);
  background:var(--surf-3);color:var(--ink-3);
  font-size: var(--bi-fs-compact);font-weight:600;line-height:1}
/* UMA LINHA POR PASSO. Título em cima e descrição embaixo davam 80px de faixa
   permanente — duas linhas de instrução para três passos, dos quais só um está
   acontecendo. Título e descrição na MESMA linha, e o que não couber na fatia
   do passo é cortado com reticências (o texto inteiro fica no `title`). A faixa
   cai para 40px e os 40 que sobram vão para a lista de lotes, que é onde o
   trabalho acontece. */
.stepbar__txt{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.stepbar__txt b{font-size: var(--bi-fs-compact);font-weight:600;color:var(--ink)}
.stepbar__txt span{font-size: var(--bi-fs-compact);color:var(--ink-2);line-height:1.45}
.stepbar__txt span::before{content:" — "}
/* O passo ZERO: mesmo desenho dos outros, mas é botão. `.stepbar__voltar` não
   tem numeral — tem a seta —, e é o único da faixa que reage ao ponteiro. */
.stepbar__voltar{border:0;font:inherit;text-align:left;color:var(--acc);cursor:pointer}
.stepbar__voltar .stepbar__num{background:var(--acc-soft);color:var(--acc)}
.stepbar__voltar .stepbar__txt b{color:var(--acc)}
.stepbar__voltar:hover{background:var(--acc-soft)}
.stepbar__passo[data-ativo="1"]{background:var(--surf)}
.stepbar__passo[data-ativo="1"] .stepbar__num{background:var(--acc);color:#fff}
.stepbar__passo[data-feito="1"] .stepbar__num{background:var(--positive-text);color:#fff}
/* Passo que ainda não chegou: só o título recua de tinta, para o passo ativo
   ser o que salta sem que os outros virem texto ilegível. */
.stepbar__passo[data-ativo="0"][data-feito="0"] .stepbar__txt b{color:var(--ink-3)}

/* ── .pickbox — BLOCO DE ESCOLHA (componente) ────────────────────────────────
   O par "o que eu já escolhi" × "o que ainda há para escolher", cada um num
   bloco com cabeçalho e contagem próprios. Uma lista só, com as marcações
   espalhadas entre 200 linhas, obriga a reler a lista inteira para conferir a
   escolha; partida em dois, a conferência é o bloco de cima e nada mais.

   Nada aqui sabe o que é bobina: serve qualquer seleção dentro de um catálogo
   longo (notas de um lote, títulos de uma remessa, linhas de uma conferência). */
/* O par de blocos lado a lado numa tela larga, empilhado no tablet em pé.
   Empilhados sempre, uma escolha de 34 itens ocupa a tela e a lista de onde se
   escolhe nasce fora da dobra (medido: 700 px de profundidade). Lado a lado, o
   item sai de uma coluna e entra na outra à vista. */
.pickbox-par{display:grid;gap:1rem;grid-template-columns:minmax(0,1fr)}
@media (min-width:1200px){.pickbox-par{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}}
.pickbox{margin-bottom:1rem}
.pickbox__cab{display:flex;align-items:baseline;gap:.75rem;flex-wrap:wrap;
  margin-bottom:.375rem}
.pickbox__cont{font-size: var(--bi-fs-compact);color:var(--ink-3);font-variant-numeric:tabular-nums}
/* A dica de ordenação encosta na direita: é ajuda de uso, não título. */
.pickbox__dica{margin-left:auto;font-size: var(--bi-fs-compact);color:var(--ink-3)}
/* Vazio INSTRUTIVO — diz o que fazer, não só que está vazio. Tracejado para não
   se confundir com uma tabela de verdade que por acaso não tem linhas. */
.pickbox__vazio{border:var(--bs-border-width) dashed var(--line-3);
  border-radius:var(--r-sm);padding:.875rem;text-align:center;
  font-size:.875rem;color:var(--ink-3)}
/* O bloco dos escolhidos leva o fundo do acento nas linhas: é o que distingue
   "escolhido" de "livre" com a lista rolada. */
.pickbox--escolhidos tbody > tr > td{background:var(--acc-soft)}
/* Cada bloco rola por si, com altura limitada — é o que faz os dois caberem na
   mesma tela. Sem isto, uma escolha de 34 itens empurra a lista do que ainda há
   para escolher a 2.101 px de profundidade (medido), e o trabalho seguinte fica a
   duas telas de distância. O bloco dos escolhidos é mais baixo: ele existe para
   conferir a escolha, não para navegar nela. */
.pickbox__rolo{max-height:22rem;overflow:auto}
/* AS LISTAS ESTICAM ATÉ O RODAPÉ. O teto de 22rem acima é o fallback das telas
   baixas e do empilhado; lado a lado (≥1200px), a altura vem da corrente de
   flex que desce do painel: o que sobrar entre o cabeçalho do produto e o
   rodapé é das listas — era a faixa morta que sobrava embaixo delas. Cada elo
   com `min-height:0`, senão o flex recusa encolher e a rolagem interna morre. */
/* O anúncio da fila alinha com o CONTEÚDO da tabela, não com a borda do
   cartão: a toolbar tem 16px de recuo interno, e o balão colado na borda
   parecia sangrar dos dois lados (queixa do usuário, duas vezes). */
#sep-anuncio .alert{margin-inline:1rem}
/* A margem do resultado só existe quando há resultado: o `mt-3` do Bootstrap
   (que é !important) contava 16px de faixa morta mesmo com o nó vazio. */
#sep-resultado:not(:empty){margin:1rem 0}
/* O resultado da data (aviso/erro/sucesso do salvar) nasce num <span> dentro da
   célula da capa: sem virar bloco com respiro próprio, o alert encosta no campo
   e na borda da célula. */
#sep-data-resultado:not(:empty){display:block;margin-top:.375rem}
/* O CÁLCULO NO BACKEND TEM CARA: enquanto a releitura do estoque corre, régua e
   passos apagam meio tom (o número visível é o ANTERIOR) e um girador aparece
   na ponta da régua. Some sozinho quando a resposta chega e tudo é reescrito. */
.sep-aguarda{opacity:.55;transition:opacity .15s}
#sep-medida.sep-aguarda::after{content:"";display:inline-block;
  width:.875rem;height:.875rem;margin-left:.5rem;vertical-align:-.125rem;
  border:2px solid var(--acc);border-right-color:transparent;
  border-radius:var(--r-full);animation:bi-spin .6s linear infinite}
@media (prefers-reduced-motion:reduce){
  #sep-medida.sep-aguarda::after{animation:none;border-right-color:var(--acc-soft)}
}
@media (min-width:1200px){
  .wsurface__main{display:flex;flex-direction:column}
  .wsurface__main #sep-lotes{display:flex;flex-direction:column;flex:1;min-height:0}
  .wsurface__main #sep-lotes-listas{flex:1;min-height:0}
  .wsurface__main .pickbox-par{height:100%;grid-template-rows:minmax(0,1fr)}
  .wsurface__main .pickbox{display:flex;flex-direction:column;min-height:0}
  .wsurface__main .pickbox__rolo{flex:1;min-height:0;max-height:none}
}
/* Cabeçalho que acompanha a rolagem do próprio bloco. Numa lista de 166 itens ele
   é mais que rótulo de coluna: é o único controle de ordenação, e rolar embora o
   tornava inalcançável sem voltar ao topo.
   `border-collapse:separate` é REQUISITO, não estética: com o `collapse` do `.tbl`
   o Chromium simplesmente ignora `sticky` em `th` (medido — o cabeçalho rolou
   junto, a 634 px acima do topo do painel). */
.pickbox .grade-tabela{border-collapse:separate;border-spacing:0}
/* A coluna da CAIXINHA vem primeiro e é a mais estreita possível: é o controle
   de inclusão, e a pessoa varre a lista por ela. A segunda coluna (o código do
   lote) é a identidade do item e absorve toda a folga da tabela — sem isto
   (medido) a coluna do peso ficava com 522 px e o número nadava a 300 px do seu
   próprio cabeçalho. */
.pickbox thead th:first-child,.pickbox tbody td:first-child{width:1%;
  padding-right:0;white-space:nowrap}
.pickbox thead th:nth-child(2),.pickbox tbody td:nth-child(2){width:100%}
/* A caixinha alinhada ao centro da sua célula, sem esticar a linha rasa. */
.pickbox__marca{text-align:center;vertical-align:middle}
.pickbox__marca .form-check-input{margin:0;cursor:pointer}
/* A linha inteira responde à marcação — o fundo já distingue os dois blocos, mas
   dentro do bloco de escolhidas a caixinha marcada é o que confirma "esta entra". */
.pickbox tbody tr:has(.form-check-input:checked){background:var(--acc-soft)}
/* O campo numérico é `display:block` com largura fixa (Bootstrap), e `text-align`
   não move caixa de bloco — `margin-left:auto` é o que o encosta no fim da coluna,
   embaixo do cabeçalho dela. Escopado ao `.pickbox`: o mesmo `.inp-qty` é usado
   dentro de linhas flex noutros lugares, onde `auto` empurraria para o lado errado. */
.pickbox td > .inp-qty{margin-left:auto}
/* Densidade e tom de instrumento, portados do mockup aprovado. Duas diferenças
   deliberadas do `.tbl` padrão do app, e só dentro do `.pickbox`:
   - cabeçalho em caixa NORMAL, sem letter-spacing, miúdo e em tinta fraca. O
     versalete espaçado do padrão grita numa tabela de 200 linhas onde o
     cabeçalho é permanente (é `sticky`) e o que importa são os números.
   - linhas mais rasas. A 32 px por linha caberiam 6 bobinas na área do bloco; a
     26 px cabem 8, e é lista de escolher, não de ler.
   Fora do `.pickbox` o padrão do FCDS segue intacto — nenhuma outra tela muda. */
.pickbox .grade-tabela{font-size:.8125rem}
/* DENSIDADE DA MESA DE SEPARAÇÃO (27/08/2026, pedido do dono: "deixar o
   conteúdo mais compacto"). Feito na folha, não com `zoom` num container: o
   `zoom` é o Ctrl+- de verdade, mas o painel `position:fixed` dos filtros de
   coluna é posicionado por JS com `getBoundingClientRect`, e sob zoom ele abre
   130 px fora do gatilho (medido a 0.9 e a 0.8, em `body`, `main` e no bloco).
   Encolher os valores de projeto não tem esse efeito colateral.

   O ALVO DE TOQUE é o piso da altura da linha, não a fonte: os 44x44 da caixa
   de marcar sozinhos faziam a linha de 53 px. A 36 px a linha cai para 43 e
   cabem 10 lotes na tela em vez de 8 — e 36 continua muito acima do mínimo de
   24 px da WCAG 2.2, que é o que protege quem separa de luva. Abaixo disso
   (32 px, 11 lotes) o ganho é UM lote por tela e o alvo começa a encostar no
   piso: não vale. */
.pickbox .sep-alvo-toque{min-width:36px;min-height:36px}
.pickbox .sep-alvo-toque .form-check-input{width:1.25rem;height:1.25rem}
/* QUEM CEDE LARGURA É O CABEÇALHO, NUNCA O DADO (27/08/2026). Duas medidas
   que só funcionam juntas:
   - Respiro lateral de .375rem, não .625rem: são NOVE colunas, e a folga larga
     custava 180 px de padding puro num bloco de ~570 px — quase um terço da
     largura visível gasto em branco, com o "Levar" atrás do rolo horizontal.
   - Título livre para quebrar em duas linhas. Sem isso o cabeçalho é o PISO da
     coluna mesmo sendo maior que o dado: "Em estoque (KG)" reservava 128 px
     para "3.128 KG", que ocupa 65. A altura cresce uma linha, uma vez, no topo
     do bloco — contra 60 px ganhos em toda linha da tabela.
   Medido ao vivo (pedido 20953): a tabela de disponíveis cai de 830 px para
   668 px. */
.pickbox .grade-tabela tbody td{padding:.1875rem .375rem}
/* O DADO NUNCA QUEBRA. Com o título livre, a coluna pode ficar mais estreita
   que o valor — e "3.128 KG" virou "3.128" / "KG" em duas linhas, dobrando a
   altura de TODA linha para economizar 6 px de largura. Aqui cada célula é um
   átomo curto (código do lote, nome do depósito, um dígito, uma data), e
   nenhum deles se lê partido: o código "COR3075/22H-MO110225-150768 A"
   quebrado desalinha a linha inteira, e truncá-lo é pior que rolar — é ele que
   a pessoa confere contra a etiqueta da bobina. Quando não couber, o bloco
   rola de lado (`.pickbox__rolo` já é `overflow:auto`). */
.pickbox .grade-tabela tbody td{white-space:nowrap}
/* Campo dentro de linha rasa: o `form-control-sm` do Bootstrap ainda tem 31 px de
   altura e esticava a linha da bobina escolhida em 8 px sobre as demais. */
.pickbox .inp-qty{padding-block:.125rem;height:auto}
/* O ENDEREÇO NÃO PAGA CROMO DE FILTRO (27/08/2026). Rua, Posição e Nível
   guardam um caractere cada, mas quem fixava a largura das três colunas era o
   GATILHO do filtro — funil + a palavra "Todos" + a seta, `nowrap`, ~95 px por
   coluna: ~285 px de cabeçalho para três traços, e o "Levar" empurrado para
   trás do rolo horizontal. Sem recorte o gatilho fica só o funil; quem nomeia
   a coluna é o `th` logo acima. Assim que há recorte o valor volta, porque aí
   o texto é o ESTADO da coluna e não enfeite — a mesma régua do `rotulo()` em
   utils.js, que só acende `--ativo` quando o filtro realmente corta.
   Escopado ao bloco de disponíveis: o gatilho do FCDS segue inteiro em toda
   coluna larga do resto do BI, onde o texto cabe e ajuda. */
/* As tabelas de lotes vestem a grade da casa (15/09/2026): cabeçalho em uma
   linha, seta cheia, filtro que diz o estado ("Todas") em vez de um funil mudo,
   e sem caixa em volta. A grade aqui não estica a tela: o bloco rola por dentro. */
.pickbox .grade--lotes{flex:1;min-height:0}
.pickbox .grade--lotes .grade-tabela thead tr:first-child th{padding:.35rem .375rem}
.pickbox .grade--lotes .grade-tabela thead tr.grade-filtros-col th{padding:.2rem .375rem .35rem}
.pickbox .grade--lotes .th-ord{cursor:pointer}
.pickbox .grade--lotes .th-ord sup{margin-left:.15rem}

/* ── .sep-estado — O PEDIDO COMO ESTÁ HOJE, na coluna de contexto ────────────
   A tabela vive numa coluna de ~300 px e é de LEITURA, não de trabalho: nada
   nela pode ser cortado, ou ela deixa de responder à única pergunta que existe
   para fazer ("como está o pedido?"). `table-layout:fixed` + `width:100%` fazem
   as duas colunas dividirem a largura disponível em vez de exigirem a largura do
   conteúdo — medido: sem isto a coluna da quantidade saía da caixa e mostrava
   "1", "28", "250" no lugar de "1.771 KG". */
.sep-estado .tbl{table-layout:fixed;width:100%;font-size: var(--bi-fs-compact)}
.sep-estado .tbl th,.sep-estado .tbl td{padding:.375rem .5rem}
.sep-estado .tbl thead th{text-transform:none;letter-spacing:0;font-size: var(--bi-fs-micro)}
/* O código da bobina é longo e aqui pode quebrar: nesta coluna ele é referência
   de leitura, não o campo que se confere contra a etiqueta (esse está na lista
   de escolha, onde não quebra). */
.sep-estado .tbl td{white-space:normal;overflow-wrap:anywhere}
.sep-estado .badge{margin-top:.125rem}

/* ── .sep-entrega / .sep-obs — O QUE A CAPA NÃO DIZ E O GALPÃO PRECISA ───────
   A data de entrega decide a ordem do trabalho e estava do tamanho de um filtro,
   ao lado de um botão escrito "Salvar". A observação do pedido é INSTRUÇÃO de
   quem vendeu para quem carrega ("ENTREGAR SÓ PELA MANHÃ", o cronograma inteiro)
   e estava em `small` cinza no pé da coluna. As duas sobem de patamar: a data em
   corpo de número, a observação em corpo de leitura. */
.sep-entrega__data{font-size:1.25rem;font-weight:600;font-variant-numeric:tabular-nums;
  padding:.25rem .5rem;height:auto;width:auto}
.sep-obs p:last-child{margin-bottom:0}
.sep-obs{font-size:.875rem}

/* ── .measures — AS MEDIDAS DE UM REGISTRO, EM FICHAS (componente) ───────────
   Os números que decidem o trabalho, um por ficha, com a ficha do ALVO em
   acento. Era uma fita de `<dt>/<dd>` do mesmo tamanho para tudo: pedido,
   separado e saldo pesavam igual, e o saldo — o único número que a pessoa
   precisa cobrir com bobinas — não se destacava de nada.
   `--dest` marca a medida que é o alvo do trabalho, nunca "a mais importante do
   ponto de vista do negócio": quem escolhe é quem monta a tela. */
.measures{display:flex;gap:.5rem;flex-wrap:wrap;margin:0 0 .75rem}
.measure{min-width:7rem;padding:.375rem .75rem;background:var(--surf-2);
  border:var(--bs-border-width) solid var(--line);border-radius:var(--r-sm)}
.measure dt,.measure__k{margin:0;font-size: var(--bi-fs-micro);font-weight:600;color:var(--ink-3)}
.measure dd,.measure__v{margin:.0625rem 0 0;font-size:1rem;font-weight:600;
  color:var(--ink);font-variant-numeric:tabular-nums}
.measure--dest{background:var(--acc-soft);border-color:var(--acc-line)}
.measure--dest dd,.measure--dest .measure__v{color:var(--acc-ink)}
/* `--alerta` é a medida que PEDE ATENÇÃO quando não é zero (pedidos atrasados,
   pedidos bloqueados). Distinta de `--dest`, que é o alvo do trabalho: uma diz
   "é isto que você tem de cobrir", a outra "olhe para isto". */
.measure--alerta{background:var(--warning-subtle);
  border-color:color-mix(in srgb,var(--warning) 34%,transparent)}
.measure--alerta dd,.measure--alerta .measure__v{color:var(--warning-text)}

/* ── .nota — RECADO QUE EXPLICA (componente) ─────────────────────────────────
   O `.alert` do Bootstrap é feito para interromper: fundo saturado, tinta da
   própria cor, peso de anúncio. Isto é para EXPLICAR uma regra de negócio no
   lugar onde ela morde — tinta normal (legível em bloco de 3 linhas), fundo
   discreto, e a cor só na borda e no título. Numa tela que grava sem volta, a
   pessoa tem de LER o recado; um `.alert` amarelo de quatro linhas é o que se
   aprende a pular. */
.nota{padding:.625rem .8125rem;margin-bottom:.875rem;
  border:var(--bs-border-width) solid var(--line);border-radius:var(--r-sm);
  background:var(--surf-2);font-size:.875rem;line-height:1.6;color:var(--ink)}
.nota__t{display:block;font-weight:600;margin-bottom:.125rem}
.nota--info{background:var(--acc-soft);border-color:var(--acc-line)}
.nota--info .nota__t{color:var(--acc-ink)}
.nota--aviso{background:var(--warning-subtle);
  border-color:color-mix(in srgb,var(--warning) 34%,transparent)}
.nota--aviso .nota__t{color:var(--warning-text)}
.nota--risco{background:var(--negative-subtle);
  border-color:color-mix(in srgb,var(--negative) 34%,transparent)}
.nota--risco .nota__t{color:var(--negative-text)}

/* ── .chglist — O QUE VAI MUDAR NO REGISTRO (componente) ─────────────────────
   Uma linha por alteração, tingida pelo tipo dela, e o total antes → depois no
   pé. Substitui duas tabelas lado a lado ("como está" × "como fica"): medido, um
   pedido de 35 rolos gerava 40 linhas de tabela em duas colunas — 700 px de
   conferência antes de a pessoa chegar ao trabalho. A informação é a mesma,
   porque cada linha do depois já vem classificada em nova/alterada/intacta pelo
   backend: a cor diz o que a segunda tabela dizia por comparação. */
.chglist{display:flex;flex-direction:column;gap:.125rem}
.chg{display:grid;grid-template-columns:2.5rem minmax(0,1fr) auto;gap:.5rem;
  align-items:baseline;padding:.3125rem .625rem;border-radius:var(--r-sm);
  font-size:.875rem;background:var(--surf-2)}
.chg__seq{font-size: var(--bi-fs-compact);color:var(--ink-3);font-variant-numeric:tabular-nums}
.chg__lote{color:var(--ink-2);font-size: var(--bi-fs-compact);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chg__kg{font-weight:600;font-variant-numeric:tabular-nums;text-align:right}
.chg__et{display:block;font-size: var(--bi-fs-micro);font-weight:600;color:var(--ink-3);
  text-transform:uppercase;letter-spacing:.03em}
/* "sem lote" é rótulo de estado, como as etiquetas — mesma caixa alta. */
.chg--nova .chg__lote{text-transform:uppercase;font-size: var(--bi-fs-compact)}
.chg--nova{background:var(--positive-subtle)}
.chg--nova .chg__et{color:var(--positive-text)}
.chg--alterada{background:var(--acc-soft)}
.chg--alterada .chg__et{color:var(--acc-ink)}
/* A linha que a separação cancela. Tachada porque cancelar é só de ida: o
   Senior não desfaz, e a quantidade riscada diz isso sem precisar de legenda. */
.chg--cancelada{background:var(--negative-subtle)}
.chg--cancelada .chg__et{color:var(--negative-text)}
.chg--cancelada .chg__lote,.chg--cancelada .chg__kg{text-decoration:line-through}
.chg__tot{display:flex;justify-content:space-between;gap:.625rem;
  margin-top:.625rem;padding-top:.625rem;
  border-top:var(--bs-border-width) solid var(--line);
  font-size:.875rem;color:var(--ink-2)}
.chg__tot strong{color:var(--ink);font-variant-numeric:tabular-nums}
.pickbox thead th{position:sticky;top:0;z-index:1;
  background:var(--surf-2);box-shadow:inset 0 -1px 0 var(--line-3)}

/* ── .th-ord — CABEÇALHO QUE ORDENA A COLUNA (componente) ────────────────────
   Clique troca o critério, invertendo o sentido se já era ele; shift+clique
   acrescenta um segundo critério como desempate, e aí cada seta ganha o número
   da sua prioridade. `aria-sort` é o que o leitor de tela anuncia — e é o mesmo
   atributo que o CSS lê para pintar, então áudio e tela não podem divergir.

   Para tabelas montadas à mão (`.tbl`). Quem usa DataTables já ganha o
   ordenador do plugin e não precisa disto. */
.th-ord{cursor:pointer;user-select:none}
.th-ord:hover{background:var(--surf-2)}
.th-ord[aria-sort]:not([aria-sort="none"]){color:var(--acc-ink)}
.th-ord__seta{margin-left:.25rem;font-size: var(--bi-fs-compact);opacity:.45}
.th-ord__seta--on{opacity:1}
.th-ord__seta sup{font-size:.65em;margin-left:.0625rem}

/* O utilitário `.rail--danger|warning|positive` (filete de cor na borda esquerda
   da linha) FOI REMOVIDO por pedido do usuário. Ele existia para dar à fila de
   pedidos um sinal de urgência legível de longe, mas repetia em cor o que a
   coluna Urgência diz em palavra — e com 119 dos 121 pedidos atrasados a lista
   inteira ficava vermelha: uma marca que vale para todos não distingue ninguém.
   A fila tinha o único consumidor; sem ele o CSS ficaria morto. Se um dia
   alguma tela precisar do padrão, o histórico do git tem a implementação (e o
   porquê de ser `::before` posicionado e não `box-shadow: inset`, que o zebrado
   do Bootstrap 5.2 apagava nas linhas pares). */

/* ── .cell-clip — CÉLULA QUE NÃO DEIXA A TABELA CRESCER (utilitário) ─────────
   Um texto longo numa célula (uma observação de pedido com 300 caracteres)
   empurra as colunas seguintes para fora da tela. Com `text-truncate` do
   Bootstrap junto, a célula mostra o começo e o resto vive no `title`. */
.cell-clip{max-width:22rem}

/* ── .inp-qty — CAMPO NUMÉRICO DENTRO DE CÉLULA (utilitário) ─────────────────
   Quantidade editável numa tabela: estreito, alinhado à direita, tabular, e sem
   as setas do `number` (que roubam 1rem da largura e disparam com a rolagem do
   dedo). O `inputmode` é o que traz o teclado numérico no tablet. */
.inp-qty{width:7.5rem;text-align:right;font-variant-numeric:tabular-nums}
.inp-qty::-webkit-outer-spin-button,
.inp-qty::-webkit-inner-spin-button{appearance:none;margin:0}
.inp-qty[type=number]{appearance:textfield;-moz-appearance:textfield}

/* ── Skip link do shell ──────────────────────────────────────────────────────
   Primeiro focável do documento. Fora do foco fica acima da borda da janela
   (nunca `display:none`, que o tiraria da ordem de tabulação e o mataria);
   ao receber foco de teclado desce para o canto e vira um botão comum.
   Medido antes dele: 86 Tabs até o primeiro elemento do conteúdo. */
.skip{position:fixed;top:-4rem;left:.75rem;z-index:2000;
  padding:.5rem .875rem;border-radius:.5rem;
  background:var(--brand);color:#fff;text-decoration:none;font-weight:600}
.skip:focus-visible{top:.75rem}
/* O contêiner de conteúdo só é focável para receber o salto — sem anel. */
.content:focus{outline:none}

/* ── Separação · a linha do tempo do produto no pedido ───────────────────────
   Só LEITURA. Era uma lista de rádios para escolher em qual parte se trabalha,
   e ela morreu junto com o recorte por linha: o pool de separação é o produto,
   e no pedido 19880 essa lista tinha 24 rádios para escolher um. O que sobra é
   o que ela sempre respondeu bem — "o que tem neste produto": o que falta
   separar, o que já está com lote, o que virou nota, o que foi cancelado.

   Uma coluna só: o painel tem 400px. Viva em tinta cheia, histórico em tinta
   fraca; a quantidade à direita, alinhada, porque é ela que distingue uma parte
   da outra quando duas têm o mesmo estado. */
.sep-item-cab{display:flex;align-items:center;justify-content:space-between;
  gap:.5rem 1rem;flex-wrap:wrap}
.sep-item-cab .min-w-0{min-width:0}
/* Nome, código e entrega na MESMA linha de base; os controles da lista
   (filtro, depósito, histórico) fecham a faixa à direita. */
.sep-item-cab__id{display:flex;align-items:baseline;gap:.5rem;flex-wrap:wrap}
.sep-item-cab__acoes{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;
  margin-left:auto}
/* A FAIXA DO ITEM CABE EM UMA LINHA. Ela nasceu para ser uma só (título à
   esquerda, controles à direita) e quebrava em duas por 67px: título 512 +
   controles 553 contra 998 de painel. Quebrada, o lado direito do título fica
   vazio de ponta a ponta e a lista de lotes desce 31px — foi o vão marcado na
   captura do dono (13/08/2026). O filtro não precisa de 180px para caber
   "COR3232/26D" e o seletor mostra o nome do depósito com folga em 12rem. */
.sep-item-cab #sep-filtro-lote{max-width:7.25rem}
.sep-item-cab #sep-deposito{max-width:12rem}
.sep-partes{margin-top:.5rem;background:var(--surf-2);border-radius:var(--radius);
  padding:.5rem .625rem}
.sep-partes__cab{font-size: var(--bi-fs-micro);text-transform:uppercase;letter-spacing:.05em;
  color:var(--ink-2);font-weight:600;margin:0 0 .25rem}
.sep-partes__lista{list-style:none;margin:0 0 1rem;padding:0;
  display:grid;grid-template-columns:1fr;gap:.125rem}
.sep-parte{display:flex;align-items:baseline;justify-content:space-between;
  gap:.75rem;padding:.0625rem 0;min-width:0}
.sep-parte__txt{font-size: var(--bi-fs-compact);min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.sep-parte__q{font-size: var(--bi-fs-compact);color:var(--ink-2);flex:none}
.sep-parte--atual .sep-parte__txt{font-weight:600;color:var(--ink)}
.sep-parte--historico .sep-parte__txt,
.sep-parte--historico .sep-parte__q{color:var(--ink-3)}
/* A célula "Levar" da bobina: campo + botão "Fracionar" lado a lado. O campo
   tem largura própria porque dentro do flex o form-control (width:100%)
   colapsava a uma lasca quando o botão entrou ao lado. */
.sep-levar-par{display:flex;align-items:center;justify-content:flex-end;gap:.25rem}
.sep-levar-par .sep-levar{width:6.5rem;flex:0 0 auto}
/* O botão guarda a própria largura: enquanto a consulta corre o rótulo
   "Fracionar" dá lugar ao girador, e sem piso a célula encolheria e a tabela
   inteira pularia embaixo do cursor no meio do gesto. */
.sep-fracionar{min-width:5.5rem}
.sep-hist__t{font-size: var(--bi-fs-micro);text-transform:uppercase;letter-spacing:.05em;
  color:var(--ink-2);font-weight:600;margin:0 0 .25rem}
/* A linha do tempo do pedido: data | evento | quantidade, um evento por linha,
   em ordem cronológica. O fio à esquerda liga os eventos — é o que diz "isto é
   uma sequência" sem escrever a palavra. O "hoje" fecha em acento. */
.sep-tempo{list-style:none;margin:0 0 1.25rem;padding:0}
.sep-tempo__ev{display:flex;align-items:baseline;gap:.625rem;
  padding:.375rem 0 .375rem .875rem;position:relative;
  border-left:2px solid var(--line)}
.sep-tempo__ev::before{content:"";position:absolute;left:-5px;top:.8em;
  width:8px;height:8px;border-radius:var(--r-full);
  background:var(--surf);border:2px solid var(--ink-3)}
.sep-tempo__ev[data-tipo="nota"]::before{background:var(--positive-text);
  border-color:var(--positive-text)}
.sep-tempo__ev[data-tipo="hoje"]{border-left-color:transparent}
.sep-tempo__ev[data-tipo="hoje"]::before{background:var(--acc);border-color:var(--acc)}
.sep-tempo__data{flex:none;width:5.25rem;font-size: var(--bi-fs-compact);color:var(--ink-3)}
.sep-tempo__meio{min-width:0;flex:1 1 auto;display:flex;flex-direction:column}
.sep-tempo__t{font-size: var(--bi-fs-compact);font-weight:600;color:var(--ink)}
.sep-tempo__ev[data-tipo="hoje"] .sep-tempo__t{color:var(--acc)}
.sep-tempo__d{font-size: var(--bi-fs-compact);color:var(--ink-2)}
.sep-tempo__q{flex:none;font-size: var(--bi-fs-compact);font-weight:600;color:var(--ink)}

/* Separação · a observação do pedido na capa, em balão.
   Ela é INSTRUÇÃO de quem vendeu para quem carrega ("ENTREGAR SÓ PELA MANHÃ",
   "PEDIDO REFERENTE A NF QUE FOI ESTORNADA"). Em fita de dt/dd lia como mais um
   campo; o balão devolve o destaque que ela tinha. */
/* UM PARÁGRAFO NÃO É UM CAMPO. Em `flex:1 1 22rem;max-width:34rem` ela entrava
   na fita como mais um item — 544px de largura por 189 de altura — e esticava a
   LINHA INTEIRA para 266px, deixando um vão embaixo de todos os pares curtos: a
   capa ia a 364px, 43% da superfície, para um cabeçalho. Com `flex-basis:100%`
   ela cai na própria linha, ocupa a largura toda e o mesmo texto cabe em duas
   linhas em vez de cinco. */
/* A observação ocupa a SOBRA da fita, não uma fileira própria. Ela nasceu com
   `max-width:34rem`: 544px num vão de 1.478, o que a empurrava para cinco linhas
   e esticava a fita inteira para 266px. Depois foi para `flex-basis:100%` — uma
   fileira só dela, três linhas, com o lado direito da fita de campos vazio. Sem
   teto de largura ela fica NA MESMA fileira dos campos, consome o espaço que
   sobrava à direita deles e a capa cabe na altura de um bloco só.
   `flex-start` no alinhamento porque a fita alinha por `baseline`, e um bloco de
   várias linhas ao lado de pares de uma linha empurrava todos para baixo.
   Entrelinha de leitura, não de aviso curto: o `line-height:1.6` de `.nota` é
   feito para UMA frase. Vai nesta regra, não na `.sep-obs` solta — aquela vem
   ANTES de `.nota` no arquivo e, com a mesma especificidade, perdia calada. */
/* A advertência ocupa a faixa que sobrava à DIREITA DO CLIENTE, na primeira
   linha da capa; a fita de campos desce para a segunda, inteira. Medido no
   20318 a 1713px: com o balão dentro da fita, a fita ficava larga demais para
   caber ao lado do nome, descia junto e a primeira linha ia vazia de ponta a
   ponta — capa de 211px. Com o balão como irmão, capa de 164px.
   Entrelinha de leitura, não de aviso curto: o `line-height:1.6` de `.nota` é
   feito para UMA frase. Vai nesta regra, não na `.sep-obs` solta — aquela vem
   ANTES de `.nota` no arquivo e, com a mesma especificidade, perdia calada. */
/* A ADVERTÊNCIA MANDA NA ALTURA. Ela leva 2/5 da largura e o texto dela decide
   quantas linhas a capa tem; os campos se acomodam nos 3/5 restantes, em
   quantas fileiras couberem. Tentei antes fazê-la absorver a sobra de uma
   fileira (`grid-column:auto/-1`, depois `span 8`): com um lado auto a grade dá
   span 1 e o balão virava uma coluna magra de 40 linhas na ponta (capa de
   712px); com span fixo, a capa oscilava entre 205 e 270px conforme a janela,
   porque o span não sabe quantas colunas sobraram. */
/* O teto da advertência mora no ITEM, não na trilha: `fit-content()` na trilha
   colapsou a coluna para 66px e quebrou o recado em uma palavra por linha
   (medido). Com trilha `auto` a coluna mede o texto, e este teto impede que um
   recado longo coma a capa inteira. */
/* O teto mora na TRILHA (`fit-content(42%)` em `.wsurface__cap`), não aqui:
   ver o comentário lá. */
.wsurface__cap-obs{min-width:0}
.wsurface__cap-obs:empty{display:none}
/* A ADVERTÊNCIA ROLA DENTRO DA ALTURA QUE A CAPA TEM. Quem manda na altura são
   as duas fileiras de campos; o parágrafo se encaixa nelas e o excedente vem
   pelo arrastar. `position:absolute` é o que tira a altura dele da conta da
   grade — com `max-height` em rem o número seria chute, e sobraria faixa vazia
   quando o texto fosse curto ou corte quando a capa fosse alta. O piso existe
   para o balão não virar uma tarja de duas linhas num pedido de poucos campos. */
/* NA MESMA ALTURA DA CAPA: quem manda são os campos — o balão acompanha a
   fileira deles, nem um pixel a mais, e o texto excedente rola por dentro. O
   piso de 5.5rem que existia aqui era o que deixava o balão MAIS ALTO que os
   fatos ao lado, com a borda dele caindo abaixo da última fileira. */
/* O BALÃO VOLTOU PARA O FLUXO. Absoluto ele não tinha tamanho nenhum para a
   grade, então a coluna dele só podia ser uma FATIA FIXA da capa (metade) —
   era isso que pintava 654px de amarelo para 426px de frase, e espremia as
   fichas na metade restante. Em fluxo ele mede o texto (trilha `max-content`,
   teto de 30rem), e o teto de altura evita o efeito que o absoluto resolvia:
   um recado de dez linhas esticando a capa. */
/* 5.5rem cortava a terceira linha ao meio numa capa de duas fileiras (1400px):
   o recado é INSTRUÇÃO de quem vendeu, e um corte no meio da frase esconde
   justamente o final ("…não é permitida a entrada de pessoas com bermuda"). 8rem
   dão quatro linhas inteiras; recado maior que isso rola por dentro. */
.wsurface__cap-obs .sep-obs{max-height:8rem;overflow:auto}
.wsurface__cap-obs:empty{display:none}
.wsurface__cap-obs .sep-obs{margin:0;line-height:1.45}
.wsurface__cap-campos .sep-obs p{margin-bottom:.125rem}
.wsurface__cap-campo.sep-entrega dd{display:flex;align-items:center;gap:.25rem;flex-wrap:wrap}
/* A data cabe numa célula da capa. Ela nasceu em corpo de número (1,25rem) para
   sair do tamanho de filtro; numa grade de doze onde cada campo vale uma célula,
   esse corpo obrigava a coluna a ser o dobro das vizinhas. Corpo de valor, como
   os outros campos, com o peso mantendo o destaque. */
.wsurface__cap .sep-entrega__data{font-size:.875rem;max-width:100%;min-width:0;
  padding-inline:.25rem}
.wsurface__cap .sep-entrega .btn{padding-inline:.375rem}
.wsurface__cap .sep-entrega dd{gap:.25rem .375rem}

/* Separação · a legenda da coluna "Não separado".
   Caixa alta com tracking: é rótulo do número acima, não frase — a mesma
   gramática dos rótulos de medida do topo. Sem isso ela competia em peso com o
   valor que deveria explicar. */
.sep-legenda{font-size: var(--bi-fs-micro);text-transform:uppercase;letter-spacing:.05em;
  color:var(--ink-2);line-height:1.3}

/* ═══════════════════════════════════════════════════════════════════════════
   DISTRIBUIÇÃO DO FATURAMENTO  (/distribuicao-faturamento/)
   Barra empilhada por cliente + matriz cliente × mês.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Altura fixa e generosa: é ela que compra faixa visível para os clientes do
   meio do ranking. Medido — com 20 nomeados numa área de ~430px a menor faixa
   fica em 1,79px; abaixo disso deixa de ser clicável. */

/* A legenda é o que transforma "um tom de azul" em "o cliente X": com 20 blocos
   a rampa de um tom só não distingue vizinhos, e a identidade passa a vir daqui,
   do hover e do clique. Grid de colunas fluidas para caber 20 nomes sem virar
   parede de texto. */
.df-legenda{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(250px, 1fr));
  gap:2px 14px; margin-top:.75rem; padding-top:.75rem;
  border-top:1px solid var(--line); max-height:190px; overflow-y:auto;
}
.df-legenda__item{
  display:flex; align-items:center; gap:.45rem; width:100%; text-align:left;
  font-size: var(--bi-fs-compact); color:var(--ink-2); background:none; border:0;
  padding:.2rem .25rem; border-radius:var(--r-sm); cursor:pointer;
}
.df-legenda__item:hover:not(:disabled){ background:var(--surf-2); color:var(--ink); }
.df-legenda__item:disabled{ cursor:default; }
.df-legenda__item:focus-visible{ outline:2px solid var(--chart-azul); outline-offset:1px; }
.df-legenda__item[aria-pressed="true"]{
  background:color-mix(in srgb, var(--chart-azul) 12%, var(--surf));
  color:var(--ink); font-weight:600;
}
.df-legenda__cor{ flex:none; width:13px; height:11px; border-radius:2px; }
.df-legenda__cor--outros{
  background:color-mix(in srgb, var(--chart-azul) 11%, var(--surf));
  border:1px solid color-mix(in srgb, var(--chart-azul) 28%, var(--surf));
}
.df-legenda__nome{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.df-legenda__pct{ flex:none; margin-left:auto; color:var(--ink-3); font-variant-numeric:tabular-nums; }

/* Drill-down do mês: a pizza e sua legenda, e nada mais. O ranking completo já
   está na matriz da página; repeti-lo aqui era a mesma tabela duas vezes. */
.df-drill{ display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.15fr); gap:22px;
  align-items:center; }
@media (max-width:720px){ .df-drill{ grid-template-columns:minmax(0,1fr); } }
.df-drill__pizza{ position:relative; height:300px; }
.df-drill__legenda{ list-style:none; margin:0; padding:0; display:grid; gap:1px; }
.df-drill__legenda li{ display:grid; grid-template-columns:auto minmax(0,1fr) auto auto;
  align-items:center; gap:.5rem; padding:.3rem .35rem; border-radius:var(--r-sm);
  font-size: var(--bi-fs-compact); }
.df-drill__legenda li:nth-child(odd){ background:var(--surf-2); }
.df-drill__cor{ width:11px; height:11px; border-radius:2px; flex:none; }
.df-drill__nome{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:var(--ink-2); }
/* Valor e % nunca quebram: "R$ 1,858M" partido no meio deixa de ser número. */
.df-drill__valor{ white-space:nowrap; font-weight:600; }
.df-drill__pct{ white-space:nowrap; color:var(--ink-3); min-width:3.2rem; text-align:right; }

/* Mês clicável: o cabeçalho é a porta do drill, e precisa parecer uma. */
.df-mes{ cursor:pointer; }
.df-mes:hover{ color:var(--chart-azul); text-decoration:underline; }
.df-mes:focus-visible{ outline:2px solid var(--chart-azul); outline-offset:-2px; }

/* Cabeçalho de família marcável (colfilterMulti `grupoMarcavel`): pesa mais que o
   item e recua os filhos, para a hierarquia família ▸ produto ser lida de relance. */
.colfilter-multi__grupo{ font-weight:600; text-transform:uppercase; font-size: var(--bi-fs-micro);
  letter-spacing:.04em; margin-top:.35rem; }
.colfilter-multi__filho{ padding-left:1.5rem; }

/* Coluna de identificação congelada enquanto os meses rolam na horizontal.
   Sem isso, rolar até dez/26 deixa a linha órfã: números sem dono. */
.tbl-scroll--freeze-col .tbl-freeze{
  position:sticky; left:0; z-index:3; background:var(--surf);
  border-right:1px solid var(--line);
  min-width:230px; max-width:230px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.tbl-scroll--freeze-col thead .tbl-freeze,
.tbl-scroll--freeze-col tfoot .tbl-freeze{ z-index:4; background:var(--surf-2); }
.tbl-scroll--freeze-col tbody tr:hover .tbl-freeze{ background:var(--surf-2); }
.tbl-scroll--freeze-col tbody tr.table-active .tbl-freeze{ font-weight:600; }
.tbl-scroll--freeze-col tfoot td{ position:sticky; bottom:0; background:var(--surf-2); }
.tbl-scroll--freeze-col tbody tr{ cursor:pointer; }
.tbl-scroll--freeze-col tbody tr:focus-visible{ outline:2px solid var(--chart-azul); outline-offset:-2px; }

/* ============================================================
   CRM — DOCUMENTO DA PROPOSTA (impressão / PDF WeasyPrint)
   Réplica do layout da proposta comercial do Ploomes (gabarito:
   proposta 16.900-0, docs/planos/crm.md). Renderizado por
   bi/templates/bi/crm_proposta_pdf.html; mesmo HTML no preview
   e no PDF (weasyprint.CSS deste arquivo). Prefixo .prop-.
   ============================================================ */
@page {
  size: A4;
  margin: 30mm 12mm 40mm 12mm;
  @top-left { content: element(prop-cab); }
  @bottom-center { content: element(prop-rodape); }
}
.prop-doc{ font-family:'DejaVu Sans', Arial, sans-serif; font-size:8.5pt;
  color:#212529; line-height:1.32; }
.prop-cab{ position:running(prop-cab); display:flex;
  justify-content:space-between; align-items:flex-end; width:186mm; }
/* A logo do documento original ocupa quase um terço da faixa; 40mm a
   deixavam do tamanho de um selo. A arte tem 4626px de largura, então
   ampliar não perde nitidez. */
.prop-logo-img{ width:58mm; }
.prop-emp{ font-size:8pt; text-align:right; line-height:1.5; }
.prop-emp b{ font-size:8.5pt; }
.prop-faixa{ display:flex; justify-content:space-between; background:#4a4a4c;
  color:#fff; font-weight:700; font-size:9.5pt; padding:1.5mm 3mm; margin-bottom:2mm; }
/* Explicação do painel de condições quando ele abre sozinho. Fundo do acento
   em vez de cinza: cinza é a cor de quem não quer ser lido, e esta frase
   existe justamente para ser lida. */
[data-pagina="crm-deal"] .crm-aviso-suave{
  background: var(--crm-acento-fundo); border: 1px solid #d3e2d9;
  border-radius: 8px; padding: .7rem .9rem; margin: 0 0 1rem;
  font-size: var(--bi-fs-compact); color: var(--crm-tinta-2); line-height: 1.5; }

/* ---------------------------------------------------------------------------
   Vocabulário do CRM que o Bootstrap não cobre. Existe porque estilo inline
   NÃO se usa aqui (regra do dono) e porque inline vence a folha: a regra que
   eu escrevi para o bloco de embalagem no telefone foi ignorada por um
   `justify-content` inline que estava no elemento. O que o Bootstrap cobre
   exatamente (mt-1, d-block, ms-auto, align-items-end…) usa o Bootstrap; o
   que não cobre está aqui, com nome.
   --------------------------------------------------------------------------- */
/* Larguras de campo dos formulários de cadastro. São medidas do CONTEÚDO
   (UF tem 2 letras, CEP tem 8 dígitos), por isso nome do campo e não número. */
[data-pagina^="crm"] .crm-campo-uf { flex: 0 0 4rem; }
[data-pagina^="crm"] .crm-campo-numero { flex: 0 0 5rem; }
[data-pagina^="crm"] .crm-campo-cep { flex: 0 0 7.5rem; }
[data-pagina^="crm"] .crm-campo-9 { flex: 0 1 9rem; }
[data-pagina^="crm"] .crm-campo-10 { flex: 0 0 10rem; }
[data-pagina^="crm"] .crm-campo-11 { flex: 0 1 11rem; }
/* Lupa escondida (cliente pessoa física, que não tem consulta pública) deixa
   o campo como último da linha — e o Bootstrap só arredonda a ponta direita do
   que é `:last-child`. Com `display:none` o botão continua sendo o último
   filho, então o canto ficava quadrado, encostado em nada. */
[data-pagina^="crm"] .input-group > .form-control:has(+ .crm-oculto) {
  border-top-right-radius: var(--bs-border-radius);
  border-bottom-right-radius: var(--bs-border-radius); }
[data-pagina^="crm"] .crm-campo-12 { flex: 0 1 12rem; }
[data-pagina^="crm"] .crm-campo-13 { flex: 0 1 13rem; }
[data-pagina^="crm"] .crm-largura-10 { max-width: 10rem; }
[data-pagina^="crm"] .crm-largura-16 { max-width: 16rem; }
[data-pagina^="crm"] .crm-largura-20 { max-width: 20rem; }
/* Pílula que é botão (o chip da embalagem reabre o bloco): mesma aparência de
   pílula, comportamento de botão. */
.crm-pilula-botao { border: 0; cursor: pointer; }
/* Lista de escolhas de um campo que aceita VÁRIAS (os trianguladores padrão do
   cadastro, 01/09/2026). Cada escolha é uma `.crm-pilula` com um ✕ dentro — o
   ✕ é o botão, a pílula não. */
[data-pagina^="crm"] .crm-fichas { display: flex; flex-wrap: wrap; gap: .35rem; }
/* O ✕ é o botão; a pílula não. Tamanho MÍNIMO real, não área invisível: a
   primeira tentativa estendia o alvo com um `::after` de 44px, e ele avançava
   sobre a ficha vizinha — clicar no começo da segunda podia tirar a primeira.
   Alvo fantasma que cobre o vizinho é pior que alvo pequeno. */
[data-pagina^="crm"] .crm-ficha-tirar { display: inline-flex; align-items: center;
  justify-content: center; min-width: 1.5rem; min-height: 1.5rem; border: 0;
  background: transparent; color: inherit; cursor: pointer; padding: 0;
  margin-left: .1rem; line-height: 1; opacity: .65; }
/* No TOQUE o alvo vai a 44px e a ficha cresce junto — é o certo: dedo não
   acerta 12px, e uma pílula mais alta no telefone não atrapalha nada. */
@media (pointer: coarse) {
  [data-pagina^="crm"] .crm-ficha-tirar { min-width: 2.75rem; min-height: 2.75rem; }
}
[data-pagina^="crm"] .crm-ficha-tirar:hover,
[data-pagina^="crm"] .crm-ficha-tirar:focus-visible { opacity: 1; }
/* Foco visível: o ✕ é operável por teclado e sem isto o anel do navegador
   sumia atrás da pílula. */
[data-pagina^="crm"] .crm-ficha-tirar:focus-visible { outline: 2px solid var(--acc-line);
  outline-offset: 2px; border-radius: 2px; }
/* Botão dentro de linha de tabela ou de cabeçalho de painel: aperta o padding
   sem virar outro componente. */
.crm-btn-compacto { padding: .25rem .5rem; }
/* Total do rodapé — o número que se lê de longe. */
[data-pagina="crm-deal"] .crm-numero-grande { font-size: 1.25rem; font-weight: 700; }
[data-pagina^="crm"] .crm-separador { margin: 1.5rem 0 1rem; }
[data-pagina^="crm"] .crm-recuo { margin: .25rem 0 0 1rem; }
[data-pagina^="crm"] .crm-linha-lista { padding: .5rem 0;
  border-top: 1px solid var(--crm-borda); }
.min-w-0 { min-width: 0; }
/* Largura dos painéis laterais, por peso do conteúdo. */
.crm-oc--estreita { --bs-offcanvas-width: 22rem; }
.crm-oc--media { --bs-offcanvas-width: 26rem; }
.crm-oc--larga { --bs-offcanvas-width: 30rem; }
/* O painel de cadastro usa o MESMO canvas da ficha (`#crm-modal-ficha`,
   abaixo): é o mesmo formulário de 34 campos, e em 30rem ele não cabe em
   disposição nenhuma — medido em 09/09/2026, 2.111px de conteúdo para 654 de
   dobra. `crm-oc--larga` continua no elemento para as telas que ainda o
   herdam; esta regra, mais específica, é quem manda. */
#crm-modal-novo { --bs-offcanvas-width: min(88rem, 96vw); }
/* Campo obrigatório. O asterisco é do RÓTULO, não do campo: quem lê a tela
   procura na etiqueta, e leitor de tela anuncia o `aria-required` do input
   sem tropeçar num caractere solto. A régua é a do SERVIDOR — só recebe
   estrela o que ele de fato recusa vazio. */
/* `campo-obrigatorio` é o nome de TODO o app (compras e BI usam o mesmo); o
   `crm-obrigatorio` continua valendo por já estar espalhado no CRM. */
.crm-obrigatorio::after,
.campo-obrigatorio::after { content: " *"; color: var(--crm-erro, #b3261e);
  font-weight: 700; }
/* Obrigatório do ERP: acende só quando o cadastro vai ao Senior (a classe do
   container é do JS, que lê `cliente.prospect` do servidor). No lead o servidor
   não recusa esses campos — asterisco ali seria estrela mentirosa. */
.crm-form-cliente--erp .crm-obrigatorio-erp::after {
  content: " *"; color: var(--crm-erro, #b3261e); font-weight: 700; }

/* Revisar mostra o documento inteiro: largura de papel, não de formulário. */
.crm-oc--documento { --bs-offcanvas-width: min(52rem, 96vw); }
[data-pagina="crm-deal"] .crm-oc-documento { padding: 0; display: flex; }
[data-pagina="crm-deal"] .crm-documento-previa { flex: 1; width: 100%;
  border: 0; background: #e9ecef; }
/* Espera do documento: ocupa o lugar do papel enquanto ele é gerado. Fundo
   igual ao do quadro para a troca não piscar de cor. */
[data-pagina="crm-deal"] .crm-documento-espera { flex: 1; display: flex;
  flex-direction: column; align-items: center; justify-content: center;
  gap: .75rem; background: #e9ecef; color: var(--crm-tinta-2, #6c757d);
  font-size: .875rem; }
[data-pagina="crm-deal"] .crm-documento-espera.crm-oculto { display: none; }

/* Roteiro da proposta: os passos, acionáveis. Diferente do trilho de etapas
   (indicador, não se clica), aqui cada passo LEVA ao lugar onde se resolve o
   que falta. O que está pronto fica discreto; o passo da vez é o único com
   peso — a tela responde "e agora?" sem ninguém perguntar.

   O respiro é do PRÓPRIO bloco (padding), não margem, e só EM CIMA: embaixo
   quem separa é o padding do corpo, que já vale 1,25rem. Somar os dois dava
   1px acima contra 36px abaixo — o roteiro nascia colado no trilho de etapas
   e solto do trabalho. */
[data-pagina="crm-deal"] .crm-roteiro{ display: flex; flex-wrap: wrap;
  gap: .4rem; margin: 0; padding-block: 1.25rem 0; flex: 0 0 auto; }
[data-pagina="crm-deal"] .crm-roteiro__passo{ display: flex; align-items: center;
  gap: .5rem; flex: 1 1 12rem; text-align: left; cursor: pointer;
  background: var(--crm-superficie); border: 1px solid var(--crm-borda);
  border-radius: 8px; padding: .5rem .7rem; color: var(--crm-tinta-2);
  font-size: .8125rem; transition: border-color .15s ease, background .15s ease; }
[data-pagina="crm-deal"] .crm-roteiro__passo:hover{ border-color: var(--crm-acento); }
[data-pagina="crm-deal"] .crm-roteiro__n{ display: inline-flex;
  align-items: center; justify-content: center; flex: 0 0 1.4rem; height: 1.4rem;
  border-radius: 50%; background: #eaeeec; color: var(--crm-tinta-2);
  font-size: .75rem; font-weight: 700; }
[data-pagina="crm-deal"] .crm-roteiro__rot{ display: block; font-weight: 600;
  color: var(--crm-tinta); }
[data-pagina="crm-deal"] .crm-roteiro__falta{ display: block; font-size: .75rem;
  color: var(--crm-tinta-2); }
[data-pagina="crm-deal"] .crm-roteiro__passo--ok .crm-roteiro__n{
  background: var(--crm-acento); color: #fff; }
[data-pagina="crm-deal"] .crm-roteiro__passo--agora{
  border-color: var(--crm-acento); background: var(--crm-acento-fundo); }
[data-pagina="crm-deal"] .crm-roteiro__passo--agora .crm-roteiro__n{
  background: var(--crm-acento); color: #fff; }

/* Título do negócio: a primeira coisa depois da faixa preta, centralizado.
   É a linha que diz de QUE cotação se trata, e o cliente costuma ter mais de
   uma na mesa. Um ponto acima do corpo — chama sem gritar. */
.prop-obra{ font-size:9.5pt; font-weight:700; text-align:center;
  margin:0 0 2.5mm; }
.prop-vend{ font-size:8pt; margin-bottom:2.5mm; line-height:1.55; }
/* Quatro linhas empilhadas, como no documento real — em fita elas viravam
   uma linha só e o nome do empreendimento colava no telefone. */
.prop-vend > div{ display:block; }
.prop-tabela{ width:100%; border-collapse:collapse; font-size:8.5pt;
  /* fixed: sem isto as larguras abaixo são só sugestão e o navegador dá à
     coluna Produto o que sobra dos cabeçalhos longos ("Disponibilidade"),
     quebrando a descrição em três linhas. */
  table-layout:fixed; }
.prop-tabela th{ background:#e3e3e5; text-align:center; font-size:7.2pt;
  /* Respiro lateral curto: sao ate nove colunas em 186mm, e cada milimetro
     aqui decide se "Conteudo" cabe numa linha ou parte no meio. */
  font-weight:700; padding:2mm .8mm; border:.5pt solid #b9b9be;
  /* Cabeçalho de PALAVRA ÚNICA numa coluna estreita não quebra sozinho: ele
     transborda por cima da coluna vizinha, e foi assim que "Embalagem" saiu
     colado em "Conteúdo" na proposta da Sandra. Com isto ele parte. */
  /* `break-word` e NAO `anywhere`: o segundo parte dentro da palavra mesmo
     quando ela caberia inteira na linha seguinte, e escrevia "Valor por
     bobi-na". Este so parte quando a palavra sozinha nao cabe. */
  overflow-wrap:break-word; }
/* Larguras por CLASSE (não por nth-child: a coluna de previsão é condicional
   e os índices dançariam). Sem elas o código rouba espaço da descrição e
   "FOUR CORDOALHA CP 190 RB 9,5MM" quebra em duas linhas.
   São 186mm úteis (A4 menos 12mm de margem de cada lado); o que sobra depois
   destas nove vai para Produto, a única que precisa crescer. Cada número aqui
   foi medido contra um valor real, não estimado — em 24mm "R$ 125.000,00"
   quebrava entre o "R$" e o valor, e em 18mm a palavra "Quantidade" partia no
   meio ("Quantidad / e").
   Os dois totais (sem e com IPI) cabem porque o "R$" saiu das células e foi
   para o cabeçalho: cada coluna de dinheiro devolveu ~5mm, e são quatro.
   Sem o "R$" o valor virou uma palavra SEM ESPAÇO onde quebrar: em 18mm
   "2.600.646,40" (proposta da AGIS, 31/08/2026) não quebrava — transbordava
   4,5mm por cima da coluna vizinha, e o papel saía com os três valores
   embolados. Medido com o próprio WeasyPrint (DejaVu Sans 8,5pt): esse valor
   ocupa 20,0mm de texto, então a coluna de dinheiro precisa de 23mm (texto +
   2,4mm de respiro + a borda). Os 15mm vieram da descrição do produto (39mm
   → 26mm, autorizado pelo dono) e de código/conteúdo, que sobravam. Isso
   cobre até "9.999.999,99"; acima disso o valor volta a transbordar.
   CUIDADO ao editar este bloco: a barra em "s/ IPI" fechava o comentário no
   meio da frase, e o resto virava seletor — a regra `.c-item` logo abaixo era
   engolida pelo parser, a coluna `#` ficava sem largura e, com
   `table-layout:fixed`, herdava o espaço que era para ser da descrição do
   produto. Escreva "sem IPI" por extenso. */
.prop-tabela .c-item{ width:7mm; }
.prop-tabela .c-cod{ width:19mm; }
.prop-tabela .c-disp{ width:19mm; }
.prop-tabela .c-emb{ width:16mm; }
.prop-tabela .c-cont{ width:16mm; }
.prop-tabela .c-qtd{ width:19mm; }
.prop-tabela .c-preco{ width:14mm; }
.prop-tabela .c-vol{ width:23mm; }
/* O cento é dinheiro CURTO — "8,66" na caixa de 3.000, "259,71" na cotação
   cheia —, nunca o total de uma proposta. Por isso ele não herda os 23mm da
   coluna de volume: 16mm comportam "9.999,99" a 8,5pt e devolvem 7mm para a
   descrição do produto, que é a única coluna que cresce. */
.prop-tabela .c-cento{ width:16mm; }
.prop-tabela .c-total{ width:23mm; }
/* Com a coluna de previsão são ONZE colunas em 186mm, e aí não existe
   milímetro para tirar de vizinho: apertar a de dinheiro quebra o valor,
   apertar a do produto empilha a descrição em oito linhas. A tabela inteira
   encolhe um ponto — o papel continua legível e todas as colunas respiram de
   novo. Antes eu trocava uma quebra por outra a cada ajuste. */
.prop-tabela--densa{ font-size:7.8pt; }
.prop-tabela--densa th{ font-size:6.6pt; padding:1.6mm .6mm; }
.prop-tabela--densa td{ padding:1.2mm 1.4mm; }
/* Medido no papel, não estimado: em 14mm o código de 8 dígitos partia em duas
   linhas ("300300 / 02") e em 12mm o cabeçalho "Volumes" virava "Volume / s".
   O que sobra depois destas dez vai para Produto, a única que cresce.
   Aqui o dinheiro precisa de 22mm (a 7,8pt "2.600.646,40" mede 18,4mm), e com
   onze colunas o milímetro sai de onde existe folga: previsão (texto livre,
   que já quebrava a data) e produto. */
.prop-tabela--densa .c-item{ width:6mm; }
.prop-tabela--densa .c-cod{ width:18mm; }
.prop-tabela--densa .c-disp{ width:14mm; }
.prop-tabela--densa .c-emb{ width:15mm; }
.prop-tabela--densa .c-cont{ width:15mm; }
.prop-tabela--densa .c-qtd{ width:17mm; }
.prop-tabela--densa .c-preco{ width:13mm; }
.prop-tabela--densa .c-vol{ width:22mm; }
.prop-tabela--densa .c-cento{ width:15mm; }
.prop-tabela--densa .c-total{ width:22mm; }
/* Preco de 4 casas (so acontece com frete diluido, onde o preco e o resultado
   de uma divisao e nao o que alguem digitou). Medido com a regua deste bloco
   em 02/09/2026: "1.297,0931" ocupa 17,2mm a 8,5pt e a celula precisa de
   20,0mm com o respiro e a borda; a 7,8pt sao 15,8mm e 18,6mm. Cobre ate
   "9.999,9999", que mede o mesmo (o separador de milhar entra e um digito
   sai).
   De onde vem: 3mm do valor por volume, a UNICA coluna com folga medida
   (23mm para "999.999,99", que pede 20,0mm), e 3mm da descricao do produto
   (26->23mm). Nenhuma outra tem de onde tirar — codigo, quantidade e os
   totais estao todos com menos de 1mm de sobra, e conteudo ja estoura.
   Por isso a classe e CONDICIONAL e nao a largura padrao: 2.9% dos precos da
   casa passam de duas casas, e apertar a descricao do produto — o que o
   cliente confere — nas outras 97% pagaria por um problema que elas nao tem.
   Quem decide e o servico (`tem_preco_longo`), nao o template. */
.prop-tabela--preco-longo .c-preco{ width:20mm; }
.prop-tabela--preco-longo .c-vol{ width:20mm; }
.prop-tabela--preco-longo.prop-tabela--densa .c-preco{ width:19mm; }
.prop-tabela--preco-longo.prop-tabela--densa .c-vol{ width:19mm; }
/* Célula de número e de código respiram menos nas laterais que a de texto —
   é onde cada milímetro decide se o valor cabe numa linha só. */
.prop-tabela td.num, .prop-tabela td.ctr{
  padding-left:1.2mm; padding-right:1.2mm; }
/* Quebra SÓ na disponibilidade, que é texto livre de até 40 caracteres
   ("logo após o carnaval") e transbordava por cima da descrição do produto.
   Nas outras células centradas o mesmo `break-word` partia o código do
   produto ("300300 / 02") e a data ("20/09/202 / 6"): ali o conteúdo tem
   tamanho conhecido e a coluna é dimensionada para ele. */
.prop-tabela td.c-disp{ overflow-wrap:break-word; }
/* O código é uma palavra só, sem espaço onde quebrar: com 14 caracteres ele
   transbordava POR CIMA da coluna vizinha (na proposta 10 ele invadia a linha
   da previsão). `anywhere` e não `break-word` porque aqui não existe "próxima
   linha melhor" — ou parte no meio, ou vaza. */
.prop-tabela td.c-cod{ overflow-wrap:anywhere; }
/* Grade fechada: linha entre TODOS os campos, não só entre as linhas. Com
   sete colunas de número, a borda vertical é o que separa "3.000" de
   "15.000" sem o leitor precisar mirar o cabeçalho. */
.prop-tabela td{ padding:1.4mm 2mm; border:.5pt solid #cfcfd2;
  vertical-align:top; }
/* Numero NAO leva nowrap: com 4.200.000 PC ou R$ 1.260.000,00 o nowrap nao
   aperta nada, ele TRANSBORDA por cima da coluna vizinha. Sem ele a celula
   quebra no unico espaco que existe ("R$" numa linha, o valor na outra), que
   e feio uma vez a cada mil propostas e legivel sempre. */
.prop-tabela .num{ text-align:right; font-variant-numeric:tabular-nums; }
.prop-tabela .ctr{ text-align:center; }
.prop-totais{ width:100%; border-collapse:collapse; font-size:8.5pt;
  margin-bottom:3mm; }
.prop-totais td{ padding:1.2mm 2mm; border:.5pt solid #d8d8dc; }
.prop-totais tr:nth-child(odd) td{ background:#ececee; }
.prop-totais .rot{ text-align:right; font-weight:700; }
.prop-totais .num{ text-align:right; font-variant-numeric:tabular-nums;
  width:30mm; }
/* A frase que explica o frete destacado: abre as Observações (reporte #4,
   15/09/2026), e sai em negrito porque diz quem cobra de quem — o cliente
   que a pular acha que a Four lhe fatura o frete. */
.prop-frete-aviso{ font-size:7.5pt; font-weight:700; line-height:1.35;
  margin:1mm 0; }
.prop-sec{ font-size:8.5pt; font-weight:700; border-bottom:1.5pt solid #9b1c2e;
  padding-bottom:.8mm; margin:2.5mm 0 1.5mm; }
.prop-grade{ width:100%; border-collapse:collapse; font-size:8.5pt; }
/* A ficha de faturamento ganha só a linha horizontal: fechar a grade aqui
   transformaria oito pares rótulo/valor num formulário de imposto. */
.prop-grade td{ padding:1.1mm 2mm; vertical-align:top;
  border-bottom:.5pt solid #e4e4e8; }
.prop-grade .rot{ font-weight:700; white-space:nowrap; width:34mm; }
/* Observação escrita PELO VENDEDOR: fundo amarelo, como quem passa marca-texto
   no papel. É a única linha do documento que não é padrão — nasce da conversa
   daquele negócio ("consulte nossas condições especiais para…") — e em itálico
   preto ela se perdia entre a EC 87 e as condições gerais, que o cliente já
   nem lê. O amarelo é o que faz o olho parar ali. */
.prop-obs-destaque{ font-style:italic; font-weight:700; font-size:8.5pt;
  margin:1mm 0; background:#fff3a3; padding:1.5mm 2mm;
  white-space:pre-wrap; }
.prop-obs{ font-size:6.8pt; color:#343a40; line-height:1.35;
  white-space:pre-wrap; }
.prop-cond{ font-size:7.5pt; line-height:1.4; }
/* O rodapé sangra 6mm de cada lado da caixa de texto: são sete fotos de
   produto com legenda, e em 186mm as legendas ficavam ilegíveis. A arte tem
   2048px de largura — aguenta a ampliação. */
.prop-rodape{ position:running(prop-rodape); width:198mm; margin-left:-6mm; }
.prop-rodape img{ width:198mm; height:auto; }
/* Marca d'água da revisão superada. `position:fixed` no WeasyPrint repete em
   TODAS as páginas — é o mecanismo de marca d'água, não um bug. Fica atrás do
   conteúdo (z-index negativo) para não atrapalhar a leitura dos números. */
.prop-marca{ position:fixed; top:45%; left:0; right:0; z-index:-1;
  text-align:center; transform:rotate(-24deg); pointer-events:none;
  color:rgba(155,28,46,.16); }
.prop-marca__tit{ display:block; font-size:30pt; font-weight:700;
  letter-spacing:.06em; line-height:1; white-space:nowrap; }
.prop-marca__sub{ display:block; font-size:13pt; font-weight:700;
  letter-spacing:.12em; margin-top:3mm; }

/* ============================================================
   OCUPADO — sinal global de ação em andamento (biUtils.ocupado)
   Barra fina no topo enquanto uma escrita está no ar. Diferente do
   esqueleto de carregamento: o conteúdo continua à vista, só não
   aceita clique — assim ninguém dispara a mesma ação duas vezes.
   ============================================================ */
.bi-ocupado {
  position: fixed; top: 0; left: 0; right: 0; height: 3px;
  z-index: 2000; pointer-events: none;
  background: linear-gradient(90deg,
    transparent 0%, var(--crm-acento, #1d4d38) 45%,
    var(--crm-acento, #1d4d38) 55%, transparent 100%);
  background-size: 240% 100%;
  animation: bi-ocupado-desliza 1.1s ease-in-out infinite;
}
@keyframes bi-ocupado-desliza {
  from { background-position: 120% 0; }
  to   { background-position: -20% 0; }
}
/* enquanto trabalha, a página não aceita novo clique (o cursor conta por quê) */
body.bi-ocupado-ativo { cursor: progress; }
body.bi-ocupado-ativo main, body.bi-ocupado-ativo .offcanvas {
  pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
  .bi-ocupado { animation: none; background: var(--crm-acento, #1d4d38); }
}

/* ============================================================
   CRM — DO ZERO (v3): A RAMPA DO FUNIL
   Telas /crm/ e /crm/deal/. Sistema próprio, sem chrome nem
   utilitários Bootstrap (a mecânica do offcanvas fica; o vestido é
   daqui). Tema claro. Assinatura: UM verde em QUATRO profundidades,
   uma por etapa — a cor codifica o avanço do deal (Prospecção clara
   → Fechamento profundo). Cabeçalho de estação é bloco sólido no
   tom da etapa; o stepper do deal usa a mesma rampa; dinheiro e CTA
   ficam no verde profundo. Tudo escopado por
   [data-pagina="crm"|"crm-deal"].
   ============================================================ */
/* A fila de cobrança (/acompanhamento-inadimplencia) adota esta MESMA
   linguagem, por decisão do dono do produto: uma paleta só, definida uma
   vez. Reuso do bloco de tokens, não cópia dos valores — se o verde mudar
   aqui, muda nas duas telas. A Agenda (`crm-agenda`) entra na mesma lista
   pelo mesmo motivo: casamento por IGUALDADE, nunca por prefixo
   (`[data-pagina^="crm"]`) — ver o incidente documentado em
   `bi/templates/bi/crm_produtividade.html` (o token some em silêncio e a
   borda do campo renderiza quase preta). */
[data-pagina="crm"], [data-pagina="crm-deal"], [data-pagina="crm-agenda"],
[data-pagina="crm-tabelas-preco"], [data-pagina="crm-clientes"],
[data-pagina="crm-representantes"], [data-pagina="crm-usuarios"],
[data-pagina="crm-classificacao"],
/* `.topbar` na lista porque ela é IRMÃ da `div[data-pagina]`, não filha: sem
   isto o `.crm-btn` da barra fica sem `--crm-acento` — texto branco em barra
   branca. Só classes `.crm-*` leem estes tokens; as outras telas não mudam. */
[data-pagina="acompanhamento_inadimplencia"], .topbar {
  --crm-fundo: #f4f6f5;
  --crm-superficie: #ffffff;
  --crm-tinta: #171a18;
  --crm-tinta-2: #4e544f;
  --crm-tinta-3: #6d746f;
  --crm-borda: #e2e6e3;
  --crm-borda-forte: #cfd5d1;
  /* rampa do funil: um verde, quatro profundidades (todas ≥4.5:1 com branco) */
  --crm-tom-1: #4f7a67;
  --crm-tom-2: #3f6b57;
  --crm-tom-3: #2e5c47;
  --crm-tom-4: #1d4d38;
  /* Perdido fica FORA da rampa: o verde codifica avanço, e a raia dos negócios
     perdidos pintada com ele diria que perder é o fim bom do funil. Grafite:
     registro fechado, não alarme (perder faz parte de vender; o vermelho
     gritaria a cada card). */
  --crm-tom-perdido: #5a615c;
  --crm-acento: var(--crm-tom-4);
  --crm-acento-fundo: #e9f2ec;
  /* Semântica: ALIAS do global, não valor próprio. Medido, a duplicata produzia
     divergência exatamente onde importa e nenhuma onde não importa: o vermelho
     saía #b42318 aqui e #ca2a26 em /inadimplencia/ — telas irmãs, uma o
     detalhamento da outra, dois prints discordando do que é "ruim"; o verde
     divergia em 1 de G e 1 de B, imperceptível. Um token duplicado que não
     produzia nem a diferença que justificaria duplicá-lo. A rampa autoral do
     funil (--crm-tom-1..4) segue própria: ela codifica a etapa, que é o dado. */
  --crm-ok: var(--positive-text);  --crm-ok-fundo: var(--positive-subtle);
  --crm-avi: var(--warning-text);  --crm-avi-fundo: var(--warning-subtle);
  --crm-mal: var(--negative-text); --crm-mal-fundo: var(--negative-subtle);
  /* Contêiner: nem tudo melhora esticando. Acima disto a linha de comando
     abria 1.400px de vão entre a busca e as medidas, e a tabela de itens
     dava 665px só para a descrição do produto. */
  --crm-largura-max: 110rem;
  /* Teto da coluna do funil. 272px é o piso do Trello (menor largura que
     ainda cabe título + valor + dois metadados) e ~352px é onde o card ainda
     lê como card. Nenhum kanban do mercado estica card além disso. */
  --crm-coluna-max: 22rem;
  --crm-raio: 10px;
  --crm-sombra: 0 1px 2px rgba(23, 26, 24, .05);
  --crm-sombra-2: 0 6px 20px rgba(23, 26, 24, .09);
  background: var(--crm-fundo);
  color: var(--crm-tinta);
  /* A altura vem do shell (`content--altura-cheia`): a tela ocupa a janela e
     quem rola é a coluna / o corpo do negócio, nunca a página. */
  min-height: 0;
}
/* cada raia do funil e cada etapa do stepper carregam o próprio tom */
[data-pagina="crm"] .crm-raia { --tom: var(--crm-tom-4); }
[data-pagina="crm"] .crm-raia[data-raia="prospeccao"] { --tom: var(--crm-tom-1); }
[data-pagina="crm"] .crm-raia[data-raia="negociacao"] { --tom: var(--crm-tom-2); }
[data-pagina="crm"] .crm-raia[data-raia="reserva"]    { --tom: var(--crm-tom-3); }
/* Adiado é estacionamento, não avanço: o tom CLAREIA depois da reserva (o
   tom-1 ficou livre quando a Prospecção saiu) para a raia não ler como um
   passo a mais rumo ao ganho. */
[data-pagina="crm"] .crm-raia[data-raia="adiado"]     { --tom: var(--crm-tom-1); }
/* A fila do Ploomes (08/09/2026) não é etapa de venda — é fila de
   redistribuição, e o tom NEUTRO diz isso antes de qualquer texto: nenhum dos
   quatro tons do funil, que marcam avanço rumo ao ganho. Cinza é o que sobra
   quando a coluna não afirma progresso nenhum. */
[data-pagina="crm"] .crm-raia[data-raia="importado"]  { --tom: #adb5bd; }
/* Arrastar card entre as raias abertas (02/09/2026). Só o card que o backend
   marcou (`destinos`) tem `draggable`; a raia que aceita o drop acende com o
   próprio tom. Sem transição no card arrastado: o fantasma do navegador já é
   o feedback, e opacidade na origem diz "isto está saindo daqui". */
[data-pagina="crm"] .crm-cartao[draggable="true"] { cursor: grab; }
[data-pagina="crm"] .crm-cartao--arrastando { opacity: .45; }
[data-pagina="crm"] .crm-raia--alvo .crm-raia__corpo {
  outline: 2px dashed var(--tom); outline-offset: -4px;
  background: color-mix(in srgb, var(--tom) 8%, transparent); }
[data-pagina="crm"] .crm-raia[data-raia="ganho"]      { --tom: var(--crm-tom-4); }
/* sem esta regra a raia dos perdidos herdaria o default de `.crm-raia` — o
   mesmo verde escuro dos ganhos */
[data-pagina="crm"] .crm-raia[data-raia="perdido"]    { --tom: var(--crm-tom-perdido); }

/* --- primitivas de layout (o que os utilitários do Bootstrap faziam) ---
   `crm-clientes` entrou em 26/08/2026, quando a lista ganhou a ficha como
   canvas por cima: sem ele, `.crm-oculto` não escondia (balões de erro
   vazios pintados na tela) e `.crm-linha` não era flex (espaçamento do
   formulário quebrado). Igualdade, nunca prefixo — ver o comentário do
   bloco de tokens. */
[data-pagina="crm"] .crm-linha, [data-pagina="crm-deal"] .crm-linha,
[data-pagina="crm-agenda"] .crm-linha, [data-pagina="crm-clientes"] .crm-linha {
  display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; }
[data-pagina="crm"] .crm-cresce, [data-pagina="crm-deal"] .crm-cresce,
[data-pagina="crm-agenda"] .crm-cresce,
[data-pagina="crm-clientes"] .crm-cresce { flex: 1 1 auto; }
[data-pagina="crm"] .crm-oculto, [data-pagina="crm-deal"] .crm-oculto,
[data-pagina="crm-agenda"] .crm-oculto,
[data-pagina="crm-clientes"] .crm-oculto { display: none !important; }

/* Grupo dobrável do formulário de cliente ("Dados do CRM"): summary sem o
   marcador do navegador — o `.drill-plus` é o único sinal de abrir. */
.crm-form-grupo > summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: .5rem; }
.crm-form-grupo > summary::-webkit-details-marker { display: none; }

/* ═══ CRM · CADASTRO DO CLIENTE EM COLUNAS ════════════════════════════════
   Os 34 campos de uma vez, sem acordeão e sem rolagem (dono, 09/09/2026).
   Antes: 2.111px de formulário para 654 de dobra, 23 campos atrás de dois
   `<details>` fechados, e o CNPJ — que sozinho preenche outros dez — a
   898px do topo.

   `columns` e não `grid`: `column-fill: balance` é o padrão, então o
   navegador iguala as alturas sozinho. Com grid seria preciso uma tabela de
   distribuição em JS, que teria de ser refeita a cada grupo novo.

   O nome é `crm-form-bloco`, e não `crm-form-grupo`: esse já existe, como
   etiqueta de seção do painel do negócio (`negocio.js`) e com borda e recuo
   próprios em `[data-pagina="crm-deal"]` — que é uma das duas páginas que
   incluem este formulário. Reaproveitar traria a borda de lá para cá.
   ============================================================ */
/* 13,5rem e não os 17 do mockup: com o bloco das pessoas dentro do
   formulário (pedido do dono, 09/09/2026) o conteúdo cresceu, e trilho mais
   estreito é mais trilho. Medido nos dez monitores: 17rem dava QUATRO colunas
   em todos e sobrava campo fora da dobra em quatro deles; 13,5 dá CINCO de
   1280 para cima. É o MESMO valor da faixa estreita — um número só para a
   tela inteira, em vez de dois para manter em dia. */
.crm-form-colunas { columns: 13.5rem; column-gap: 1.15rem; }
.crm-form-bloco { margin-bottom: .65rem; break-inside: avoid; }
.crm-form-bloco__nome {
  font-size: .7rem; text-transform: uppercase; letter-spacing: .06em;
  color: var(--crm-tinta-3); font-weight: 700; line-height: 1.3;
  padding-bottom: .25rem; margin-bottom: .45rem;
  border-bottom: 1px solid var(--crm-borda);
}
.crm-form-campo { margin-bottom: .35rem; }

/* "Trabalha com": sete opções curtas. Em caixa de seleção empilhada eram sete
   linhas num trilho de 272px; em PASTILHA cabem em duas ou três, e o que está
   marcado se lê de longe (dono, 09/09/2026).

   Por baixo continua `<input type="checkbox">` — teclado e leitor de tela
   inteiros, de graça. O input some da vista mas NÃO do foco: `opacity:0` com
   tamanho zero, e não `display:none`, que o tiraria da ordem de tabulação. */
.crm-form-chips { display: flex; flex-wrap: wrap; gap: .25rem; }
.crm-form-chip__marca {
  position: absolute; opacity: 0; width: 0; height: 0; margin: 0;
}
.crm-form-chip {
  border: 1px solid var(--crm-borda-forte); border-radius: var(--raio-chip);
  padding: .1rem .55rem; font-size: .72rem; line-height: 1.5;
  color: var(--crm-tinta-2); cursor: pointer; user-select: none;
}
.crm-form-chip:hover { border-color: var(--crm-acento); color: var(--crm-acento); }
.crm-form-chip__marca:checked + .crm-form-chip {
  background: var(--crm-acento); border-color: var(--crm-acento);
  color: #fff; font-weight: 600;
}
/* O foco tem de aparecer no RÓTULO: o input que o recebe é invisível. */
.crm-form-chip__marca:focus-visible + .crm-form-chip {
  outline: 2px solid var(--crm-acento); outline-offset: 2px;
}
.crm-form-colunas .form-label {
  display: flex; align-items: baseline; gap: .4rem;
  font-size: .75rem; line-height: 1.3; margin-bottom: .08rem;
  color: var(--crm-tinta-2);
}
/* A lupa do CNPJ vive num input-group: sem a mesma altura do campo, ela fica
   com os 38px padrão do Bootstrap ao lado de um campo de 34 e o par
   desalinha. */
.crm-form-colunas .form-control,
.crm-form-colunas .form-select,
.crm-form-colunas .input-group > .btn { height: 34px; padding: .2rem .55rem; font-size: .82rem; }
.crm-form-colunas textarea.form-control { height: auto; }
.crm-form-colunas .form-text { font-size: .7rem; line-height: 1.3; margin-top: .1rem; }
.crm-form-colunas .crm-linha { gap: .45rem; margin-bottom: .35rem; }

/* O CNPJ é o motor do formulário: dez dos 34 campos saem da consulta dele.
   Destaque de POSIÇÃO (primeiro da primeira coluna) e de moldura, uma vez só
   na tela — dois destaques e nenhum destaca. */
.crm-form-motor {
  background: var(--crm-acento-fundo); border: 1px solid #c5ded0;
  border-radius: 8px; padding: .5rem .65rem .55rem; margin-bottom: .6rem;
  break-inside: avoid;
}
.crm-form-motor .form-control,
.crm-form-motor .form-select { border-color: var(--crm-acento); border-width: 2px; }
.crm-form-motor__nota {
  font-size: .69rem; line-height: 1.35; color: var(--crm-acento);
  margin-top: .35rem; font-weight: 600;
}

/* O botão mora NO RÓTULO do campo de origem: é dali que a cópia sai, e a
   pessoa lê "E-mail do contato → usar este nos três" numa varredura só.

   LINK, não pastilha (pedido do dono, 09/09/2026): a pastilha de fundo verde
   encostava na caixa do campo e virava um bloco a mais na coluna. Texto de
   acento sublinhado carrega a mesma promessa de "isto é clicável" sem ocupar
   área — e cinza sem sublinhado, que era o `crm-btn-3`, lia como legenda do
   campo, porque cinza nesta casa é a cor de desabilitado. */
.crm-form-colunas .crm-form-replicar,
.crm-form-colunas .crm-form-redistribuir {
  color: var(--crm-acento); background: none; border: 0; border-radius: 0;
  text-decoration: underline; text-underline-offset: .15em;
  font-weight: 600;
}
.crm-form-colunas .crm-form-replicar:hover,
.crm-form-colunas .crm-form-replicar:focus-visible,
.crm-form-colunas .crm-form-redistribuir:hover,
.crm-form-colunas .crm-form-redistribuir:focus-visible {
  color: var(--crm-tinta); background: none; text-decoration-thickness: 2px;
}
.crm-form-colunas .crm-form-replicar {
  margin-left: auto; font-size: .7rem; padding: 0;
}

/* Nasce onde o problema está e some quando ele acaba. Sem `margin-left:auto`:
   ele pertence ao campo de cima, não ao canto do cartão. */
.crm-form-colunas .crm-form-redistribuir {
  font-size: .7rem; padding: 0; margin-top: .2rem; align-self: flex-start;
}

/* As PESSOAS de contato: bloco do PAINEL, fora do formulário do cadastro
   (10/09/2026). Dentro dele — onde estiveram por um dia — o bloco herdava a
   invisibilidade do `#nd-prospect`, que só abre em "Cadastrar cliente novo":
   quem escolhia um cliente existente via o negócio ser recusado por falta de
   contato sem ter onde digitá-lo.

   As classes ficam as do formulário de propósito: é a mesma ESCALA de campo e
   rótulo do cadastro logo acima. Sem isto a pessoa herdava o tamanho solto do
   Bootstrap e lia como outra tela colada no painel. */
.crm-form-bloco--pessoas {
  border-top: 2px solid var(--crm-borda-forte); padding-top: .5rem;
  margin-top: .35rem;
}
.crm-form-pessoa__linha { position: relative; }
.crm-form-pessoa__linha + .crm-form-pessoa__linha {
  border-top: 1px dashed var(--crm-borda); padding-top: .4rem; margin-top: .4rem;
}
/* O ✕ só existe da linha 1 em diante — não dá para o formulário ficar com
   zero pessoas. Fora da grade, encostado à direita, para não roubar coluna de
   campo nenhum. */
.crm-form-pessoa__tirar { position: absolute; top: .1rem; right: 0; }
.crm-form-pessoa__linha + .crm-form-pessoa__linha .crm-form-contato__campos {
  padding-right: 1.6rem;
}

/* A pessoa usa a MESMA escala do cadastro acima. Sem isto ela herdava o
   tamanho solto do Bootstrap — campo de 38px contra 32, rótulo de 14 contra
   12 — e lia como outra tela colada no fim desta. O gancho é o bloco, que só
   existe no painel de cadastro: no painel do negócio (30rem) o MESMO
   componente continua como estava. */
.crm-form-bloco--pessoas .form-label {
  font-size: .75rem; line-height: 1.3; margin-bottom: .08rem;
  color: var(--crm-tinta-2);
}
.crm-form-bloco--pessoas .form-control,
.crm-form-bloco--pessoas .form-select,
.crm-form-bloco--pessoas .input-group > .btn { height: 34px; padding: .2rem .55rem; font-size: .82rem; }
.crm-form-bloco--pessoas .form-text { font-size: .7rem; line-height: 1.3; margin-top: .1rem; }

/* Os cinco campos numa linha só, com largura por PESO do conteúdo: nome e
   e-mail são longos, cargo é uma lista curta, telefone tem tamanho fixo e
   aniversário é uma data. Antes eram duas linhas de flex e o nome esticava
   por 1.065px — um campo enorme e vazio para caber "Maria Silva". */
/* Um campo por linha: o bloco vive num trilho de 216 a 272px. `auto-fit`
   e não `1fr` fixo porque o mesmo componente também é montado no painel do
   negócio, mais largo — lá ele volta a caber lado a lado sozinho. */
.crm-form-bloco--pessoas .crm-form-contato__campos {
  display: grid; gap: .1rem .55rem; align-items: end;
  /* 7rem: num trilho de 272px cabem DOIS campos por linha, e a pessoa deixa
     de custar cinco linhas inteiras. Abaixo disso o rótulo quebra. */
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
}
@media (max-width: 1200px), (max-height: 820px) {
  .crm-form-bloco--pessoas .form-control,
  .crm-form-bloco--pessoas .form-select,
  .crm-form-bloco--pessoas .input-group > .btn { height: 32px; }
  .crm-form-pessoa { padding-top: .6rem; margin-top: .7rem; }
}

/* O botão de copiar o e-mail da capa: mesma família de acento do "Usar este
   nos três" lá em cima. Cinza sem borda, nesta casa, é a cor de desabilitado. */
.crm-form-bloco--pessoas .input-group > .btn {
  color: var(--crm-acento); background: var(--crm-acento-fundo);
  border-color: #c5ded0;
}
.crm-form-bloco--pessoas .input-group > .btn:hover,
.crm-form-bloco--pessoas .input-group > .btn:focus-visible {
  background: #dcebe2; color: var(--crm-acento);
}


/* Canvas estreito (1152 e 1024) é o caso mais duro: com trilhos de 17rem
   cabem TRÊS, e três colunas não seguram 34 campos em 654px de dobra — medido,
   712 contra 654. A saída é mais trilhos, mais estreitos, com os pares
   desfeitos: dois campos lado a lado não cabem num trilho estreito, um cabe.
   Desempilhar custa altura, mas a coluna a mais paga com folga.

   13,5rem foi medido, não escolhido: com 15rem o trilho mede 258px e 983
   ainda dá TRÊS — desempilhava os pares e pagava a altura sem ganhar a
   coluna. Com 13,5rem (234px) dá quatro em 1024 e em 1152.

   O gatilho é 1200 e não 1120 porque a media query lê a JANELA e o formulário
   mora no canvas, que é 96vw: em 1152×864 a janela passava dos 1120 e a
   altura passava dos 820, então nenhuma das duas faixas pegava — o canvas de
   1106 ficava com trilhos de 17rem e ritmo largo, e três campos caíam fora
   (medido: 809 de bloco para 750 de dobra). */
@media (max-width: 1200px) {
  .crm-form-colunas { columns: 10.5rem; }
  .crm-form-colunas .crm-linha { display: block; }
  .crm-form-colunas .crm-linha > * + * { margin-top: .2rem; }
  /* O par tipo-pessoa + CNPJ do motor continua LADO A LADO: são dois campos
     curtos, e é o bloco que abre a tela. */
  .crm-form-motor .crm-linha { display: flex; }
  .crm-form-motor .crm-linha > * + * { margin-top: 0; }
}

/* Dois gatilhos para o MESMO aperto do RITMO, ambos medidos: canvas estreito
   e janela baixa. O teto de altura é 820 e não a altura da janela porque a
   dobra não é a janela: em 1366×768 a janela tem 768 e a dobra tem 654 — o
   cabeçalho, o rodapé e o preâmbulo do painel comem 114. Aperta o respiro,
   nunca esconde campo: o defeito que esta reforma corrige é campo escondido. */
@media (max-width: 1200px), (max-height: 820px) {
  /* Na faixa apertada o BLOCO pode ser partido entre duas colunas, e é essa a
     mudança que mais rende: seis pedaços indivisíveis (cinco blocos mais o
     motor do CNPJ) em quatro colunas desperdiçam ~250px de equilíbrio, porque
     o navegador tem de fechar a coluna quando o próximo pedaço não cabe
     inteiro. Partir custa continuidade de leitura; não partir custava campo
     fora da dobra, que é o defeito que esta reforma existe para corrigir.

     O que NUNCA parte: o campo do seu rótulo (`crm-form-campo`, `crm-linha`),
     o rótulo do bloco do primeiro campo dele (`break-after: avoid`) e o motor
     do CNPJ, que é um bloco de destaque de quatro linhas. */
  /* Partir custa continuidade — o bloco pode fechar uma coluna e continuar na
     seguinte sem repetir o cabeçalho. Medi as duas saídas: proibindo partir,
     seis pedaços indivisíveis em quatro colunas desperdiçam ~250px de
     equilíbrio e voltam a sobrar campos fora da dobra (613 de bloco para 654
     em 1366, quatro campos fora em 1280×720). Partindo, sobra folga em todos.
     Entre continuação sem cabeçalho e campo escondido, a regra do dono decide:
     campo escondido é campo esquecido, e o rótulo de cada campo já diz o que
     ele é ("Endereço", "Bairro", "Cidade" não precisam do título do grupo). */
  .crm-form-bloco { break-inside: auto; }
  .crm-form-bloco__nome { break-after: avoid; }
  .crm-form-campo, .crm-form-colunas .crm-linha { break-inside: avoid; }
  .crm-form-bloco { margin-bottom: .3rem; }
  .crm-form-bloco__nome { padding-bottom: .15rem; margin-bottom: .3rem; }
  .crm-form-campo { margin-bottom: .15rem; }
  .crm-form-colunas .form-text { font-size: .68rem; line-height: 1.25; }
  /* O grupo de caixas de seleção respira menos que os campos: são rótulos
     curtos numa linha só, e o respiro deles era o mesmo de um campo com
     rótulo em cima. */
  .crm-form-colunas .form-check { margin-bottom: 0; min-height: 1.25rem; }
  .crm-form-motor__nota { line-height: 1.25; }
  .crm-form-colunas .crm-linha { margin-bottom: .2rem; }
  .crm-form-colunas .form-label { line-height: 1.25; }
  /* 32px é o `form-control-sm` do Bootstrap, não altura inventada. */
  .crm-form-colunas .form-control,
  .crm-form-colunas .form-select,
  .crm-form-colunas .input-group > .btn { height: 32px; }
  .crm-form-motor { padding: .45rem .6rem .5rem; margin-bottom: .45rem; }
  .crm-form-colunas textarea.form-control { height: auto; }
}

/* --- tipografia --- */
.crm-rotulo { font-size: var(--bi-fs-micro); font-weight: 400; color: var(--crm-tinta-3);
  letter-spacing: .01em; }
/* Nota que PRECISA ser lida (referências da condição de pagamento que
   divergem, enquadramento fora do herdado). O `text-warning` do Bootstrap
   (#ffc107) é o pior amarelo do fundo branco em corpo miúdo; o token da casa
   já é a tinta de aviso legível. */
.crm-rotulo--avi { color: var(--crm-avi); }
.crm-numero { font-variant-numeric: tabular-nums lining-nums;
  font-weight: 600; letter-spacing: -.015em; }
/* Campo de PERCENTUAL (comissão, IPI): o sinal fica dentro do campo, à
   direita. O número sozinho não dizia a unidade — o vendedor digitava "3" ou
   "3%" sem saber qual a tela esperava (relato do dono, 25/08/2026). O sinal é
   só leitura: a máscara decimal já descarta o "%" que alguém digite, e o que
   viaja ao servidor continua sendo o número. Não usa `input-group` porque a
   coluna tem 80px e a borda extra do addon comeria o campo. */
.crm-pct { position: relative; display: block; }
.crm-pct > .form-control { padding-right: 1.3rem; }
.crm-pct::after { content: '%'; position: absolute; right: .4rem; top: 50%;
  transform: translateY(-50%); pointer-events: none;
  font-size: var(--bi-fs-micro); color: var(--crm-tinta-3); }
/* TÍTULO DE SEÇÃO — caixa alta. Toda a interface já rotula em caixa alta
   (etapa, coluna de tabela, campo da capa); o título do painel era o único
   em caixa mista, o que fazia ele parecer conteúdo em vez de estrutura.
   Caixa alta pede tracking positivo e peso maior para não fechar. */
.crm-titulo { font-size: var(--bi-fs-compact); font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--crm-tinta); }
/* PERGUNTA — a faixa de confirmação faz uma pergunta em frase inteira, e
   frase inteira em caixa alta lê-se pior (e grita). Fica em caixa mista. */
.crm-pergunta { font-size: 1rem; font-weight: 600; letter-spacing: -.01em;
  color: var(--crm-tinta); }
.crm-etiqueta { font-size: var(--bi-fs-micro); font-weight: 600; color: var(--crm-tinta-3);
  text-transform: uppercase; letter-spacing: .1em; }
/* Etiqueta usada como rótulo de campo é sempre bloco com respiro embaixo —
   isso estava repetido em 14 `style=` inline nos dois formulários. */
[data-pagina="crm"] label.crm-etiqueta,
[data-pagina="crm-deal"] label.crm-etiqueta { display: block; margin-bottom: .3rem; }
.crm-forte { font-weight: 600; letter-spacing: -.01em; }

/* --- superfícies --- */
/* UMA superfície de card no CRM. `.crm-painel` é o mesmo cartão com recuo
   interno — eram duas declarações idênticas que já divergiam por descuido. */
.crm-cartao, .crm-painel { background: var(--crm-superficie);
  border: 1px solid var(--crm-borda); border-radius: var(--crm-raio);
  box-shadow: var(--crm-sombra); }
.crm-painel { padding: 1rem 1.15rem; }

/* --- selos de estado (cantos 6px: selo, não cápsula) --- */
.crm-pilula { display: inline-flex; align-items: center; gap: .3rem;
  padding: .1rem .45rem; border-radius: 6px; font-size: var(--bi-fs-micro);
  font-weight: 500; white-space: nowrap; }
.crm-pilula--ok     { background: var(--crm-ok-fundo);     color: var(--crm-ok); }
.crm-pilula--aviso  { background: var(--crm-avi-fundo);    color: var(--crm-avi); }
.crm-pilula--erro   { background: var(--crm-mal-fundo);    color: var(--crm-mal); }
.crm-pilula--acento { background: var(--crm-acento-fundo); color: var(--crm-acento); }
.crm-pilula--neutra { background: #eaeeec; color: var(--crm-tinta-2); }
/* A borda entra PARA DENTRO: sem descontar o 1px, a única pílula com traço
   ficava 2px mais alta que as vizinhas e o alinhamento da linha dançava. */
.crm-pilula--tracejada { background: transparent;
  border: 1px dashed var(--crm-borda-forte); color: var(--crm-tinta-2);
  padding: calc(.1rem - 1px) calc(.45rem - 1px); }
/* Espera de um fato que ainda vem do servidor (o saldo de estoque do item
   recém-escolhido). O pulso é o que separa "estou consultando" de um rótulo
   parado — sem ele, a pílula tracejada parecia mais um estado final. */
.crm-pilula--pulsa { animation: crm-doc-pulsa 1.4s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
  .crm-pilula--pulsa { animation: none; }
}

/* CRM · selo de prospect (cliente sem código no Senior) */
.crm-selo--prospect { background: #fff3cd; color: #664d03; border: 1px solid #ffe69c;
  border-radius: .25rem; font-size: .7rem; padding: 0 .35rem; margin-left: .35rem; }

/* --- controles --- */
[data-pagina="crm"] .form-control, [data-pagina="crm"] .form-select,
[data-pagina="crm-deal"] .form-control, [data-pagina="crm-deal"] .form-select {
  background-color: var(--crm-superficie); border: 1px solid var(--crm-borda);
  border-radius: 8px; color: var(--crm-tinta); font-size: 0.875rem;
  transition: border-color .15s ease, box-shadow .15s ease; }
[data-pagina="crm"] .form-control::placeholder,
[data-pagina="crm-deal"] .form-control::placeholder { color: var(--crm-tinta-3); }
[data-pagina="crm"] .form-control:focus, [data-pagina="crm"] .form-select:focus,
[data-pagina="crm-deal"] .form-control:focus, [data-pagina="crm-deal"] .form-select:focus {
  border-color: var(--crm-tinta); box-shadow: 0 0 0 3px rgba(26, 26, 30, .08); }
[data-pagina="crm"] .form-select, [data-pagina="crm-deal"] .form-select {
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%2374747d' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round' d='M2.5 4.5 6 8l3.5-3.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .7rem center;
  background-size: 12px; }
[data-pagina="crm"] .form-check-input:checked,
[data-pagina="crm-deal"] .form-check-input:checked {
  background-color: var(--crm-tinta); border-color: var(--crm-tinta); }
[data-pagina="crm"] .form-check-input:focus,
[data-pagina="crm-deal"] .form-check-input:focus {
  border-color: var(--crm-tinta); box-shadow: 0 0 0 3px rgba(26, 26, 30, .08); }
[data-pagina="crm"] .form-label, [data-pagina="crm-deal"] .form-label {
  font-size: var(--bi-fs-compact); font-weight: 500; margin-bottom: .3rem; }
[data-pagina="crm"] .form-text, [data-pagina="crm-deal"] .form-text {
  font-size: var(--bi-fs-compact); color: var(--crm-tinta-3); }

/* busca com lupa dentro do campo */
/* A busca do funil ENCOLHE, não cresce, e cabe em 16rem. Ela carregava
   `.crm-cresce` + `.crm-largura-20` e ficava com 320px ao lado de uma fita de
   medidas de 660px: a barra somava 1424px em 1352 disponíveis e "Novo
   negócio" caía numa segunda linha. A folga era ZERO — bastaram dez pixels a
   mais no rótulo de um botão para a linha estourar. 16rem (256px) sobra para
   o placeholder, que mede 208px. */
[data-pagina="crm"] .crm-comando > .crm-busca { flex: 0 1 16rem; max-width: 16rem; }
/* As duas ações andam juntas e ficam à direita mesmo quando a linha quebra —
   `margin-left:auto` vale por LINHA no flex, então na segunda ela continua
   encostada na direita em vez de nascer à esquerda. */
[data-pagina="crm"] .crm-comando__acoes { display: flex; align-items: center;
  gap: var(--crm-e2); margin-left: auto; }
/* PREFIXO, não igualdade: os canvas de histórico e de documentos (com as
   buscas deles) são incluídos também pela lista de clientes, que é
   `data-pagina="crm-clientes"`. Com `="crm"` as três regras não casavam lá, o
   `.crm-busca` deixava de ser contexto de posicionamento e a lupa voltava ao
   fluxo — renderizava como bloco ACIMA do campo, que perdia o recuo. Medido
   em 03/09/2026 nas duas buscas da tela Clientes. `^=` é o mesmo casamento
   que este arquivo já usa em outros 54 lugares. */
[data-pagina^="crm"] .crm-busca { position: relative; }
[data-pagina^="crm"] .crm-busca > i { position: absolute; left: .8rem; top: 50%;
  transform: translateY(-50%); color: var(--crm-tinta-3); font-size: var(--bi-fs-compact);
  pointer-events: none; }
[data-pagina^="crm"] .crm-busca > .form-control { padding-left: 2.1rem; }

/* --- botões --- */
/* text-decoration explícito: "Ligar" é um <a href="tel:"> com cara de botão,
   e sem isto herdava o sublinhado de link. */
.crm-btn { display: inline-flex; align-items: center; justify-content: center;
  gap: .4rem; background: var(--crm-acento); color: #fff;
  border: 1px solid var(--crm-acento); border-radius: 8px;
  padding: .3rem .7rem; font-size: var(--bi-fs-compact); font-weight: 500; text-decoration: none;
  transition: opacity .15s ease; cursor: pointer; }
.crm-btn:hover { opacity: .84; color: #fff; text-decoration: none; }
.crm-btn:focus-visible { outline: 2px solid var(--crm-acento); outline-offset: 2px; }
.crm-btn:disabled { opacity: .45; cursor: default; }
/* Ação secundária na COR DA MARCA. Era texto cinza com borda cinza-clara —
   a mesma receita de um botão desativado —, e os vendedores relataram não
   enxergar que era clicável. Verde no texto e na borda põe na mesma família
   do primário sem acrescentar mais um bloco sólido à tela; "Cancelar" e
   companhia foram para o `.crm-btn-3`, que é o peso que um cancelar merece. */
.crm-btn-2 { display: inline-flex; align-items: center; justify-content: center;
  gap: .4rem; background: var(--crm-superficie); color: var(--crm-acento);
  border: 1px solid var(--crm-acento); border-radius: 8px;
  padding: .3rem .7rem; font-size: var(--bi-fs-compact); font-weight: 600; text-decoration: none;
  transition: background .15s ease, color .15s ease; cursor: pointer; }
.crm-btn-2:hover { background: var(--crm-acento-fundo); color: var(--crm-acento);
  text-decoration: none; }
.crm-btn-2:focus-visible { outline: 2px solid var(--crm-acento); outline-offset: 2px; }
.crm-btn-2:disabled { opacity: .45; cursor: default; }
/* Mesmo botão, cor de desfazer. "Remover embalagem" era texto fantasma ao
   lado do contorno verde de "Salvar embalagem": duas ações do mesmo bloco
   com dois pesos diferentes, e a de desfazer parecendo legenda. Mesmo
   contorno, vermelho — par legível, e o vermelho já diz que ela apaga. */
.crm-btn-2--perigo { color: var(--crm-mal); border-color: var(--crm-mal); }
.crm-btn-2--perigo:hover { background: var(--crm-mal-fundo); color: var(--crm-mal); }
/* Especificidade alta de propósito: o anel de foco genérico do deal é
   `[data-pagina]`-qualificado e ganharia de um seletor de classe só. */
[data-pagina="crm-deal"] .crm-btn-2--perigo:focus-visible,
[data-pagina="crm"] .crm-btn-2--perigo:focus-visible {
  outline: 2px solid var(--crm-mal); outline-offset: 2px; }
/* min-height 24px = WCAG 2.2 SC 2.5.8 (AA). Media 23px antes — abaixo do
   mínimo, e são ações reais (trocar produto, editar embalagem, remover). */
.crm-btn-3 { display: inline-flex; align-items: center; gap: .3rem;
  min-height: 24px;
  background: none; border: 0; padding: .15rem .3rem; border-radius: 6px;
  font-size: var(--bi-fs-compact); font-weight: 500; color: var(--crm-tinta-2);
  cursor: pointer; transition: color .15s ease, background .15s ease; }
.crm-btn-3:hover { color: var(--crm-tinta); background: #eaeeec; }
/* Ganhar e Perder são o MESMO botão com outra cor: herdam a base do .crm-btn
   e só trocam o que os distingue. As diferenças de 0,02rem de fonte e 0,15rem
   de padding que existiam aqui eram acidente, não decisão. */
.crm-btn-ganhar, .crm-btn-perder { display: inline-flex; align-items: center;
  justify-content: center; gap: .4rem; border-radius: 8px;
  padding: .3rem .7rem; font-size: var(--bi-fs-compact); font-weight: 500;
  transition: opacity .15s ease, background .15s ease; cursor: pointer; }
.crm-btn-ganhar { background: var(--crm-ok); color: #fff;
  border: 1px solid var(--crm-ok); font-weight: 600; }
.crm-btn-ganhar:hover { opacity: .85; color: #fff; }
.crm-btn-perder { background: transparent; color: var(--crm-mal);
  border: 1px solid transparent; }
.crm-btn-perder:hover { background: var(--crm-mal-fundo); color: var(--crm-mal); }
.crm-btn-ganhar:disabled, .crm-btn-perder:disabled { opacity: .45; cursor: default; }

/* Foco visível em TODA ação — antes só quatro seletores tinham, e Ganhar,
   Perder e Enviar proposta (as irreversíveis) estavam entre os que não. */
[data-pagina="crm"] .crm-btn-2:focus-visible,
[data-pagina="crm"] .crm-btn-3:focus-visible,
[data-pagina="crm"] .crm-cartao__acao:focus-visible,
[data-pagina="crm"] .crm-raia__cabo:focus-visible,
[data-pagina="crm"] .crm-lista__item:focus-visible,
[data-pagina="crm-deal"] .crm-btn-2:focus-visible,
[data-pagina="crm-deal"] .crm-btn-3:focus-visible,
[data-pagina="crm-deal"] .crm-btn-ganhar:focus-visible,
[data-pagina="crm-deal"] .crm-btn-perder:focus-visible,
[data-pagina="crm-deal"] .crm-lista__item:focus-visible {
  outline: 2px solid var(--crm-acento); outline-offset: 2px; }

/* Anel de foco dos campos: 8% de preto era invisível na prática. */
[data-pagina="crm"] .form-control:focus, [data-pagina="crm"] .form-select:focus,
[data-pagina="crm-deal"] .form-control:focus, [data-pagina="crm-deal"] .form-select:focus {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--crm-acento) 28%, transparent); }

/* --- medidas (painel de instrumento na linha de comando) --- */
.crm-medidas { display: flex; flex-wrap: wrap; margin: 0; }
.crm-medidas .crm-medida { display: flex; flex-direction: column; gap: .06rem;
  padding: 0 1.35rem; border-left: 1px solid var(--crm-borda); }
.crm-medidas .crm-medida:first-child { border-left: 0; padding-left: 0; }
.crm-medidas .crm-medida dt { font-size: var(--bi-fs-micro); font-weight: 600;
  color: var(--crm-tinta-3); text-transform: uppercase; letter-spacing: .1em; }
.crm-medidas .crm-medida dd { margin: 0; font-size: 1.12rem; line-height: 1.15;
  font-variant-numeric: tabular-nums; font-weight: 700; letter-spacing: -.02em; }
@media (max-width: 991.98px) {
  [data-pagina="crm"] .crm-medidas { display: none; }
}

/* ------------------------------------------------------------
   FUNIL — board em grid, estações com TRILHO DE SEGMENTOS
   ------------------------------------------------------------ */
/* O board tem QUATRO etapas fixas — não dá para usar largura sobrando criando
   coluna nova. E card largo não é card melhor: em 2560px cada um passava de
   580px para três linhas de texto, virando caixa esticada com metade vazia.
   A coluna ganha um teto e a sobra vira margem; acima de 1600px a sobra vira
   o painel de follow-ups à direita, que antes empurrava o board para baixo. */
/* CINCO colunas desde 02/09/2026 — Adiados saiu de dentro da Reserva (ver
   `ETAPAS` em crm/services/crm.py). Foram quatro desde 23/08 (Finalizado
   virou Ganhos + Perdidos) e três entre 08/08 e 23/08, quando a Prospecção
   saiu. O número acompanha `ETAPAS`: mudou lá, muda aqui. O `minmax(0, …)`
   é o que deixa as cinco colunas encolherem abaixo do teto numa janela
   estreita, em vez de estourarem a largura da tela. */
[data-pagina="crm"] .crm-board { display: grid; gap: 1rem;
  /* Seis desde 08/09/2026: a fila do Ploomes entrou na frente das cinco. */
  grid-template-columns: repeat(6, minmax(0, var(--crm-coluna-max)));
  /* O contêiner já tem a largura exata das colunas, então alinhar ao início
     mantém board e barra de comando na mesma vertical. */
  /* `align-content` PRECISA esticar: com `start` a linha da grade empacota no
     topo e a coluna nunca ganha altura — logo, nunca rola. Era metade da causa
     do board de 226px numa tela de 929px (a outra metade é o `align-items` da
     .crm-tela, logo abaixo). */
  justify-content: start; align-content: stretch; min-height: 0; }
@media (max-width: 1199.98px) {
  /* O teto vale aqui também: em duas colunas a 1199px o card chegava a
     528px — pior que no layout de quatro. */
  [data-pagina="crm"] .crm-board {
    grid-template-columns: repeat(2, minmax(0, var(--crm-coluna-max))); }
}
@media (max-width: 767.98px) {
  [data-pagina="crm"] .crm-board { grid-template-columns: minmax(0, 1fr); gap: .65rem; }
}


/* A tela do funil: board + follow-ups. Até 1599px eles se empilham (o painel
   só existe quando há compromisso, então não rouba espaço à toa); daí para
   cima o painel vira a coluna da direita, ocupando a sobra que o board não
   usa. */
/* Contêiner das duas telas — a linha de comando e o board dividem o mesmo
   limite, senão as medidas fogem para o canto e o board fica sozinho no meio. */
/* O funil não usa o contêiner geral: ele tem a largura NATURAL das cinco
   colunas (5 × 22rem + 4 gaps). Assim a barra de comando e o board terminam
   no mesmo lugar — board centrado com a barra esticada ficava torto. */
[data-pagina="crm"] .crm-comando,
[data-pagina="crm"] .crm-tela {
  max-width: calc(5 * var(--crm-coluna-max) + 4rem);
  margin-inline: auto; width: 100%; }
/* O feed de ações era a coluna fixa da direita (com faixa RESERVADA para o
   board não mudar de tamanho a cada tecla da busca). Virou o drawer
   #crm-modal-fups (pedido do dono, 25/08/2026) — o board tem a largura toda
   e a tela volta a uma coluna só. */
[data-pagina="crm"] .crm-tela { display: grid; gap: 1rem;
  grid-template-columns: minmax(0, 1fr); align-items: stretch; }

/* laje contida com os cards: leve tintura do tom da etapa */
[data-pagina="crm"] .crm-coluna {
  background: color-mix(in srgb, var(--tom) 7%, #fff); border-radius: 12px;
  padding: .6rem; display: flex; flex-direction: column; gap: .6rem;
  min-height: 13rem; }
/* Painel sem nada a listar: para de esticar até o rodapé. */
[data-pagina="crm"] .crm-painel--hug { align-self: start; }

/* Busca sem nenhum resultado: uma faixa no lugar do board inteiro. Ocupa as
   quatro trilhas para não deslocar a grade, e não estica: o vazio não merece
   a altura da tela. */
[data-pagina="crm"] .crm-board__vazio { grid-column: 1 / -1; align-self: start;
  background: var(--crm-superficie); border: 1px dashed var(--crm-borda);
  border-radius: 12px; padding: 2rem 1rem; text-align: center;
  color: var(--crm-tinta-2); font-size: 0.875rem; }
/* A frase começa ONDE O CONTEÚDO COMEÇARIA, não no meio da coluna: centrada
   verticalmente num vão de 724px ela flutuava longe do cabeçalho que explica,
   e o olho tinha de descer meia tela para achar a resposta. `flex:1` mantinha
   a caixa esticada até o fim da raia só para centralizar. */
/* Explicativo da coluna vazia, um degrau menor (passe de compacidade,
   28/08/2026): é rodapé de raia sem negócio, não corpo de texto. */
[data-pagina="crm"] .crm-coluna__vazio { color: var(--crm-tinta-3);
  font-size: var(--bi-fs-micro); padding: var(--crm-e2) var(--crm-e3) 0;
  line-height: 1.4; text-wrap: pretty; }

/* card do deal — passe de compacidade (28/08/2026, aprovado): padding e
   margens ~30% mais curtos em toda a pilha do cartão. */
[data-pagina="crm"] .crm-coluna .crm-cartao { overflow: hidden;
  transition: border-color .15s ease, box-shadow .15s ease, transform .15s ease; }
[data-pagina="crm"] .crm-coluna .crm-cartao:hover {
  border-color: var(--crm-borda-forte); box-shadow: var(--crm-sombra-2);
  transform: translateY(-1px); }
[data-pagina="crm"] .crm-cartao__corpo { display: block; padding: .55rem .7rem;
  color: inherit; text-decoration: none; }
[data-pagina="crm"] .crm-cartao__corpo:hover { color: inherit; }
[data-pagina="crm"] .crm-cartao__corpo:focus-visible {
  outline: 2px solid var(--crm-acento); outline-offset: -2px; }
[data-pagina="crm"] .crm-cartao__nome { font-size: .85rem; font-weight: 600;
  letter-spacing: -.01em; line-height: 1.2; display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* `min-width:0` nos selos: um único selo mais largo que o cartão (nome de
   etapa comprido) travava a fileira no tamanho do conteúdo e vazava por
   cima da borda mesmo com `flex-wrap`, medido 262px de conteúdo em 235px de
   cartão. Com ele o selo quebra em vez de estourar. */
[data-pagina="crm"] .crm-cartao__selos { display: flex; flex-wrap: wrap;
  gap: .2rem; margin-top: .2rem; min-width: 0; }
[data-pagina="crm"] .crm-cartao__selos > * { min-width: 0; }
/* `min-width:0` sozinho não bastava: o selo LONGO ("Pedido 20974 · Não
   fechado no Senior · HML2") é quem estoura, não a fileira — `.crm-pilula`
   herda `white-space:nowrap` do global. Texto que TEM que ser lido por
   inteiro (número do pedido + estado) quebra em duas linhas em vez de
   vazar; não trunca (28/08/2026, medido 255>241). Mesma causa no delta de
   preço da tabela de itens — consertada junto. */
[data-pagina="crm"] .crm-cartao__selos .crm-pilula,
[data-pagina="crm-deal"] .crm-tabela .crm-pilula {
  white-space: normal; min-width: 0; }
[data-pagina="crm"] .crm-cartao__valor { font-size: .9rem; font-weight: 700;
  font-variant-numeric: tabular-nums; letter-spacing: -.02em; margin-top: .3rem;
  color: var(--tom); }
[data-pagina="crm"] .crm-cartao__rodape { display: flex; align-items: center;
  gap: .4rem; border-top: 1px solid var(--crm-borda); padding: .25rem .7rem; }
/* Link, não botão: "Marcar previsão" pesava como uma banda própria (peso de
   botão, fundo no hover) numa fileira que já é o rodapé compacto — a MESMA
   fileira do avatar. Sublinhado e sem fundo lê como ação secundária, do
   tamanho da linha em que já mora. */
[data-pagina="crm"] .crm-cartao__acao { margin-left: auto; border: 0;
  background: none; color: var(--crm-acento); font-size: var(--bi-fs-micro);
  font-weight: 500; text-decoration: underline; text-underline-offset: 2px;
  cursor: pointer; padding: .1rem .15rem; }
[data-pagina="crm"] .crm-cartao__acao:hover { opacity: .8; }
.crm-avatar { width: 1.45rem; height: 1.45rem; border-radius: 50%; flex: none;
  background: #e2e2e6; color: var(--crm-tinta-2); display: inline-flex;
  align-items: center; justify-content: center; font-size: var(--bi-fs-micro);
  font-weight: 600; letter-spacing: .02em; }

/* UM cabeçalho por raia — o bloco sólido no tom da etapa. Era declarado duas
   vezes com os MESMOS três dados: `.crm-estacao` da tabuleta larga e
   `.crm-raia__cabo` do telefone. Agora é o mesmo elemento: no telefone ele
   também colapsa a raia (daí ser <button>), na tabuleta é só o rótulo. */
[data-pagina="crm"] .crm-raia__cabo { display: flex; align-items: center;
  gap: .5rem; width: 100%; appearance: none; text-align: left;
  background: var(--tom); color: #fff; border: 0; border-radius: 8px;
  padding: .5rem .75rem; margin-bottom: .55rem; cursor: default; }
[data-pagina="crm"] .crm-raia__nome { font-size: var(--bi-fs-micro); font-weight: 700;
  color: #fff; text-transform: uppercase; letter-spacing: .1em; }
[data-pagina="crm"] .crm-raia__conta { font-size: var(--bi-fs-micro); font-weight: 600;
  color: #fff; font-variant-numeric: tabular-nums;
  border: 1px solid rgba(255, 255, 255, .55); border-radius: var(--raio-chip);
  padding: 0 .38rem; line-height: 1.4; }
/* Ganho e perdido no cabeçalho da raia terminal: é a composição do número ao
   lado, não uma segunda medida — por isso texto de apoio, no branco da faixa
   com opacidade, e não outra pílula competindo com a contagem. */
[data-pagina="crm"] .crm-raia__detalhe { font-size: var(--bi-fs-micro);
  font-weight: 600; color: #fff; opacity: .85; }
/* "e mais 1916": o resto que o teto da fila não desceu. Discreto de
   propósito — é ressalva do cabeçalho, não um segundo número competindo com a
   contagem. */
[data-pagina="crm"] .crm-raia__ocultos { font-size: .72rem; color: #6c757d;
  white-space: nowrap; }
[data-pagina="crm"] .crm-raia__soma { margin-left: auto; font-size: var(--bi-fs-compact);
  font-weight: 700; color: #fff;
  font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
/* o marcador (`.drill-plus`, + ↔ −) é do colapso, que só existe no telefone;
   branco porque o cabo da raia é escuro. Estado pelo aria-expanded do cabo. */
[data-pagina="crm"] .crm-raia__cabo .drill-plus { display: none; }
@media (max-width: 767.98px) {
  [data-pagina="crm"] .crm-raia__cabo { cursor: pointer; margin-bottom: 0; }
  [data-pagina="crm"] .crm-raia__cabo .drill-plus {
    display: inline-flex; margin-left: .5rem; color: #fff; }
  /* Quem empurra o marcador para a direita é a soma (`margin-left: auto`).
     Perdidos não tem soma — de propósito —, e sem isto o "+" daquela raia
     ficaria colado na contagem, no meio da faixa. */
  [data-pagina="crm"] .crm-raia__cabo:not(:has(.crm-raia__soma)) .drill-plus {
    margin-left: auto; }
  [data-pagina="crm"] .crm-raia__corpo { display: none; }
  [data-pagina="crm"] .crm-raia--aberta .crm-raia__corpo { display: block;
    margin-top: .55rem; }
}

/* --- follow-ups --- */
[data-pagina="crm"] .crm-fups li { display: flex; flex-wrap: wrap;
  align-items: center; gap: .5rem; padding: .45rem 0; }
[data-pagina="crm"] .crm-fups li + li { border-top: 1px solid var(--crm-borda); }
/* Botão flutuante das próximas ações: o compromisso do dia à vista em
   qualquer rolagem. Herda a pele do .crm-btn (verde cheio); aqui só a
   flutuação e o destaque. Abaixo do offcanvas do Bootstrap (1045), acima de
   todo o resto da página. */
[data-pagina="crm"] .crm-fab { position: fixed;
  right: var(--crm-respiro-x, 1.5rem); bottom: 1.5rem; z-index: 1030;
  border-radius: var(--raio-chip); padding: .7rem 1.15rem;
  box-shadow: 0 6px 20px rgba(23, 26, 24, .28); }
[data-pagina="crm"] .crm-fab:hover { transform: translateY(-1px); }
/* A contagem no verde: texto claro; a pílula de atraso continua vermelha. */
[data-pagina="crm"] .crm-fab #crm-fups-n { gap: .4rem; }
[data-pagina="crm"] .crm-fab #crm-fups-n > span:not([class*="pilula"]) {
  opacity: .85; }

/* ------------------------------------------------------------
   DEAL — página própria: capa, trilho, corpo (rail + main),
   rodapé de decisão grudado. Sem wsurface.
   ------------------------------------------------------------ */
[data-pagina="crm-deal"] .crm-pagina { display: flex; flex-direction: column;
  gap: 0; min-height: 0; flex: 1 1 auto; }
/* A capa é a grade de 12 do Bootstrap (row/col, montada no JS). Nenhuma regra
   de layout aqui: as larguras são das colunas, e o CSS cuida só do que o
   Bootstrap não tem — a pele da faixa, o nome do cliente e o resumo. */
[data-pagina="crm-deal"] .crm-capa { background: var(--crm-superficie);
  border-bottom: 1px solid var(--crm-borda); padding-block: .5rem .45rem; }
[data-pagina="crm-deal"] .crm-capa .crm-etiqueta { display: block;
  margin-bottom: .2rem; }
/* Campo com botão colado (contato + Ligar): o select cede, o botão não —
   sem `nowrap` o select tomava a coluna inteira e o Ligar caía para a linha
   de baixo, esticando a capa em 40px. */
[data-pagina="crm-deal"] .crm-capa .crm-linha { flex-wrap: nowrap; }
[data-pagina="crm-deal"] .crm-capa .crm-linha > .form-select { min-width: 0; }
[data-pagina="crm-deal"] .crm-capa .crm-linha > .crm-btn-2 { white-space: nowrap; }
/* Resumo do que está guardado no painel de detalhes: leitura, não campo. Em
   três linhas e não duas — nomear cada valor (Task 4) engordou a fita o
   bastante para cortar a validade em 142 das 220 condições do catálogo com
   frete destacado. */
[data-pagina="crm-deal"] .crm-resumo { font-size: .875rem;
  color: var(--crm-tinta-2); display: -webkit-box; -webkit-line-clamp: 3;
  -webkit-box-orient: vertical; overflow: hidden; }
/* Prévia da assinatura no painel de envio: papel, não campo — fundo branco,
   contorno leve e a arte encolhida para caber nos 30rem do painel. */
[data-pagina="crm-deal"] .crm-assinatura-previa { background: #fff;
  border: 1px solid var(--crm-borda); border-radius: 8px;
  padding: .7rem .8rem; overflow-x: auto; }
[data-pagina="crm-deal"] .crm-assinatura-previa img { max-width: 100%;
  height: auto; }
[data-pagina="crm-deal"] .crm-assinatura-previa p { margin: 0 0 .5rem; }
/* Formulário do painel lateral: uma coluna, campos empilhados. Em duas
   colunas num painel de 26rem nenhum campo caberia inteiro. */
[data-pagina="crm-deal"] .crm-form-lista { display: grid; gap: .85rem;
  margin: 0; }
[data-pagina="crm-deal"] .crm-form-lista dt { font-size: var(--bi-fs-micro);
  font-weight: 600; color: var(--crm-tinta-3); text-transform: uppercase;
  letter-spacing: .1em; }
[data-pagina="crm-deal"] .crm-form-lista dd { margin: .25rem 0 0; }
/* Título de bloco dentro do painel: separa o que vai para o pedido do que
   sai impresso. Linha em cima, e nenhuma no primeiro. */
[data-pagina="crm-deal"] .crm-form-grupo { padding-top: .85rem;
  border-top: 1px solid var(--crm-borda); }
[data-pagina="crm-deal"] .crm-form-grupo:first-child { padding-top: 0;
  border-top: 0; }
[data-pagina="crm-deal"] .crm-form-lista .form-control,
[data-pagina="crm-deal"] .crm-form-lista .form-select,
[data-pagina="crm-deal"] .crm-form-lista .crm-combo { width: 100%; }
[data-pagina="crm-deal"] .crm-form-lista textarea.form-control {
  min-height: 5.5rem; resize: vertical; }
/* Bloco de frete: os seis campos numa LINHA SÓ, colunas iguais (pedido do
   dono, 25/08/2026 — simetria acima de tudo). Rótulo curto cabe na coluna;
   a explicação mora na nota embaixo. O rótulo reserva duas linhas para o
   caso de quebra no notebook denso — os controles nascem alinhados. */
[data-pagina="crm-deal"] .crm-form-lista--frete {
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 1.1rem 1.25rem; align-items: start; }
[data-pagina="crm-deal"] .crm-form-lista--frete dt {
  min-height: 2.4em; display: flex; align-items: flex-end; }
[data-pagina="crm-deal"] .crm-form-lista--frete .crm-campo-un { display: flex; }
[data-pagina="crm-deal"] .crm-form-lista--frete .crm-campo-un .form-control {
  flex: 1; }
@media (max-width: 1100px) {
  [data-pagina="crm-deal"] .crm-form-lista--frete {
    grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 600px) {
  [data-pagina="crm-deal"] .crm-form-lista--frete {
    grid-template-columns: minmax(0, 1fr); }
  [data-pagina="crm-deal"] .crm-form-lista--frete dt { min-height: 0; }
}
[data-pagina="crm-deal"] .crm-conta-nome { font-size: 1.25rem; font-weight: 700;
  letter-spacing: -.02em; }
/* O nome virou link para a ficha do cliente, mas continua sendo a IDENTIDADE
   da página, não uma ação — herda a cor do texto normal, sem sublinhado; o
   sublinhado só aparece no hover, para ainda avisar que é clicável. */
[data-pagina="crm-deal"] a.crm-conta-nome { color: inherit; text-decoration: none; }
[data-pagina="crm-deal"] a.crm-conta-nome:hover,
[data-pagina="crm-deal"] a.crm-conta-nome:focus-visible { text-decoration: underline; }
[data-pagina="crm-deal"] .crm-capa-obs:empty { display: none; }
[data-pagina="crm-deal"] .crm-capa-obs { margin-top: .6rem; }
/* Recado do cadastro do cliente: `pre-line` porque o vendedor escreveu em
   linhas ("SCORE 810" embaixo de "SEM RESTRIÇÕES") e emendar tudo numa
   frase só perde a leitura que ele montou. */
[data-pagina="crm-deal"] .crm-obs-cliente { white-space: pre-line; }
/* Recado comprido não pode empurrar o formulário de proposta/produtos para
   fora da tela (dropdown de busca de produto abria fora da viewport,
   28/08/2026). Mesmo mecanismo do `.wsurface__cap`/`.wsurface__cap-obs` da
   separação (canônico, custom.css ~8100/~8749): a fatia da observação
   MEDE O TEXTO (`fit-content`) até um teto, os campos ficam com o resto da
   linha, e sem observação a coluna some — CRM-prefixado porque `#dl-campos`
   é grade Bootstrap própria, não o `.wsurface__cap-esq` empacotado. */
[data-pagina="crm-deal"] .crm-capa-linha { display: grid;
  grid-template-columns: minmax(0,1fr) fit-content(42%);
  align-items: start; gap: .375rem .875rem; }
[data-pagina="crm-deal"] .crm-capa-linha:has(> .crm-cap-obs-cliente:empty) {
  grid-template-columns: minmax(0,1fr); }
[data-pagina="crm-deal"] .crm-cap-obs-cliente:empty { display: none; }
/* A caixa MANDA na própria altura, não na da linha: teto de 8rem (mesmo da
   separação) com rolagem interna para o excedente — sem isso um recado
   comprido esticaria a capa inteira. Dois blocos (pedido/nota) empilham
   dentro dela, sem clamp individual: quem rola é a caixa toda. Compacta:
   nota lateral, não hero. */
[data-pagina="crm-deal"] .crm-cap-obs-cliente { min-width: 0; max-height: 8rem;
  overflow: auto; padding: .5rem .7rem; border-radius: 8px;
  border: 1px solid #f0d9a7; background: var(--crm-avi-fundo);
  font-size: .8125rem; line-height: 1.3; }
[data-pagina="crm-deal"] .crm-cap-obs-cliente b { display: block; font-size: .75rem; }
[data-pagina="crm-deal"] .crm-cap-obs-cliente .crm-rotulo { font-size: .7rem; }

/* O stepper de etapas (`.crm-etapas`/`.crm-etapa`) foi removido em 10/08/2026
   junto com o markup: 56px de altura repetindo a faixa de estado. Ver o
   comentário em `crm/templates/crm/negocio.html`. As ~40 linhas de regra que
   moravam aqui saíram com ele — CSS sem markup é peso que ninguém cobra. */

/* corpo: trilho de contexto + trabalho */
/* O trilho era 17rem fixo enquanto a tabela ia a 2.100px — a descrição do
   produto sozinha ficava com 665px. Agora o trilho acompanha um pouco e o
   corpo respeita o contêiner. */
/* O acompanhamento deixou de ser contexto e virou a NEGOCIAÇÃO inteira
   (rodadas + conversas na mesma linha), então ganhou largura: 20rem apertava
   uma rodada com valor e ação em três linhas. A tabela de itens continua no
   centro porque é campo de trabalho — é nela que se digita. */
[data-pagina="crm-deal"] .crm-corpo { display: grid;
  grid-template-columns: minmax(20rem, 25rem) minmax(0, 1fr); gap: 1.25rem;
  /* Respiro lateral em variável (era 1.25rem fixo): a barra de rolagem do
     corpo mora colada na borda direita e o sidebar na esquerda — canto
     arredondado de card a 13px deles parecia grudado. Capa/roteiro/rodapé
     usam a MESMA variável para o conteúdo seguir alinhado. */
  padding: 1.25rem var(--crm-respiro-x, 2rem); align-items: start; flex: 1;
  max-width: var(--crm-largura-max); margin-inline: auto; width: 100%; }
/* A faixa (fundo branco, borda) continua atravessando a tela — é ela que
   separa as camadas —, mas o CONTEÚDO respeita o mesmo contêiner do corpo.
   Sem isto, em 2560px o seletor de representante ficava com 1.000px e o
   "Pedido no Senior" ia parar a um palmo da borda, longe do resto. */
[data-pagina="crm-deal"] .crm-capa,
[data-pagina="crm-deal"] .crm-roteiro,
[data-pagina="crm-deal"] .crm-rodape {
  padding-inline: max(var(--crm-respiro-x, 2rem),
                      calc((100% - var(--crm-largura-max)) / 2)); }
/* O respiro cresce com a tela: canto de 10px precisa de chão para não
   parecer grudado no sidebar e na barra de rolagem. A régua vale para o
   corpo E para capa/roteiro/rodapé — um número só, sempre alinhados. O modo
   denso de notebook (≤1600) aperta, mas não gruda; celular volta ao .8rem. */
[data-pagina^="crm"] { --crm-respiro-x: 3rem; }
@media (max-width: 1600px) {
  [data-pagina^="crm"] { --crm-respiro-x: 1.5rem; }
}
@media (max-width: 991.98px) {
  [data-pagina^="crm"] { --crm-respiro-x: .8rem; }
}
/* A régua vale para TODO o CRM (pedido do dono, 25/08/2026): o recuo do
   .content sai da frente e cada página CRM respira pela variável. O funil
   e o negócio têm regra própria (abaixo, na seção de altura cheia). */
.content:has(> .page[data-pagina^="crm"]) { padding-inline: 0; }
.content > .page[data-pagina^="crm"] {
  padding-inline: var(--crm-respiro-x, var(--content-pad-x)); }
/* Montando a proposta, o acompanhamento sai: a tabela de itens é a superfície
   de trabalho e ganha a tela inteira. A conversa com o cliente volta a
   importar antes (prospecção) e depois (proposta pronta) — durante, ela só
   estreita a coluna em que se digita. */
[data-pagina="crm-deal"] .crm-corpo--montando { grid-template-columns: minmax(0, 1fr); }
[data-pagina="crm-deal"] .crm-corpo--montando .crm-trilho { display: none; }
@media (max-width: 991.98px) {
  [data-pagina="crm-deal"] .crm-corpo { grid-template-columns: minmax(0, 1fr);
    padding: .8rem; gap: .8rem; }
}
/* Acompanhamento: superfície própria, cabeçalho que não rola e a lista
   rolando por dentro. Antes era texto solto sobre o canvas, ao lado de cards —
   parecia sobra de layout, e a lista empurrava a página inteira. */
[data-pagina="crm-deal"] .crm-trilho { position: sticky; top: 0;
  align-self: stretch; min-height: 0; max-height: 100%;
  display: flex; flex-direction: column;
  background: var(--crm-superficie); border: 1px solid var(--crm-borda);
  border-radius: var(--crm-raio); box-shadow: var(--crm-sombra);
  /* MESMO recuo do `.crm-painel` ao lado. Eram .9rem/1rem contra 1rem/1.15rem:
     dois cartões vizinhos com o texto em alturas e recuos diferentes, o que
     fazia a borda esquerda passear ao descer a tela (medido: 5 valores
     distintos no celular, entre 13px e 30px). */
  padding: 1rem 1.15rem; }
[data-pagina="crm-deal"] .crm-trilho > .crm-linha { flex: 0 0 auto; }
[data-pagina="crm-deal"] .crm-tempo { flex: 1 1 auto; min-height: 0;
  overflow-y: auto; padding-right: .2rem; }
/* Ações da proposta em linha, dentro do card dela. Quebra em duas linhas
   quando não couber. (A fita de revisões morreu: as rodadas vivem na linha
   do tempo, junto das conversas que as provocaram.) */
/* ESCALA DE ESPAÇO DO CRM. Medido em 08/08/2026 na tela do negócio: 12 valores
   distintos de `gap`, e os quatro mais usados eram 6,4px / 4,8px / 11,2px /
   9,6px — decimais de rem escolhidos um a um. Onze deles cabiam na faixa de
   1,6 a 12px, onde a diferença não é perceptível: o espaço deixava de dizer o
   que está junto e o que está separado. Base 4pt; regra nova ou tocada usa
   estes tokens, e a diferença entre dois passos é sempre visível. */
[data-pagina^="crm"] {
  --crm-e1: 4px;    /* dentro de um grupo: botões irmãos, rótulo e valor */
  --crm-e2: 8px;
  --crm-e3: 12px;
  --crm-e4: 16px;   /* entre blocos de um mesmo painel */
  --crm-e5: 24px;   /* entre GRUPOS de intenção diferente */
  --crm-e6: 32px;
}

/* A barra da proposta são dois grupos, e a separação entre eles é a
   informação: o que se faz COM o papel (ler, baixar, mandar) e o que MEXE
   nele. Apertado dentro, generoso entre — 4px contra 24px. Antes eram cinco
   ações a 6,4px umas das outras, uma fileira que no squint virava mancha. */
/* `flex-end` para a fileira que QUEBRA continuar encostada à direita: sem
   isto o segundo grupo caía na linha de baixo alinhado à esquerda, e os dois
   blocos de ação deixavam de se ler como um bloco só. */
[data-pagina="crm-deal"] .crm-proposta-acoes { flex-wrap: wrap;
  justify-content: flex-end; gap: var(--crm-e3) var(--crm-e5); }
[data-pagina="crm-deal"] .crm-acoes-grupo { display: inline-flex;
  align-items: center; flex-wrap: wrap; gap: var(--crm-e1); }
/* Grupo cujos botões estão todos escondidos (a sessão de edição esconde as
   ações do documento) não deixa um vão de 24px para trás. */
[data-pagina="crm-deal"] .crm-acoes-grupo:not(:has(> :not(.crm-oculto))) {
  display: none; }
@media (max-width: 991.98px) {
  [data-pagina="crm-deal"] .crm-trilho { position: static; }
}

/* ações da proposta no trilho: lista quieta */
/* próximo passo: a única superfície tingida */
[data-pagina="crm-deal"] .crm-passo { background: var(--crm-acento-fundo);
  border: 1px solid #d3e2d9; border-radius: var(--crm-raio);
  padding: .55rem .9rem; display: flex; flex-wrap: wrap; align-items: center;
  gap: .35rem 1rem; margin-bottom: 1rem; }
[data-pagina="crm-deal"] .crm-passo__etiqueta { font-size: var(--bi-fs-micro);
  font-weight: 700; color: var(--crm-acento); text-transform: uppercase;
  letter-spacing: .08em; flex: none; }
[data-pagina="crm-deal"] .crm-passo__texto { flex: 1 1 14rem; font-size: 0.875rem;
  color: var(--crm-tinta); }
/* Silêncio que passou do limiar: a faixa troca de tom. Verde é "está tudo no
   trilho"; aqui não está — a proposta está parada na mão do cliente. */
[data-pagina="crm-deal"] .crm-passo[data-cobrando] { background: var(--crm-mal-fundo);
  border-color: color-mix(in srgb, var(--crm-mal) 25%, #fff); }

/* A rodada da negociação tem PESO na linha do tempo: é o marco que passa a
   bola. Conversa é texto corrido; rodada é linha com valor e PDF. */
[data-pagina="crm-deal"] .crm-tempo__rodada { display: flex; align-items: center;
  flex-wrap: wrap; gap: .3rem .6rem; margin: .1rem 0 .2rem; }
[data-pagina="crm-deal"] .crm-tempo--rodada .crm-tempo__no {
  background: var(--crm-acento); box-shadow: 0 0 0 3px var(--crm-acento-fundo); }

/* tabela de itens */
.crm-tabela { width: 100%; border-collapse: collapse; }
.crm-tabela th { font-size: var(--bi-fs-micro); font-weight: 600; color: var(--crm-tinta-3);
  text-transform: uppercase; letter-spacing: .1em; text-align: left;
  padding: .5rem .75rem; border-bottom: 1px solid var(--crm-borda); }
.crm-tabela td { padding: .7rem .75rem; border-bottom: 1px solid var(--crm-borda);
  vertical-align: top; font-size: 0.875rem; }
.crm-tabela tbody tr:last-child td { border-bottom: 0; }
.crm-tabela .num { text-align: right; font-variant-numeric: tabular-nums; }
/* Colunas NUMÉRICAS não precisam do mesmo respiro horizontal do texto
   (passe de compacidade, 28/08/2026) — "1,5%" e "R$ 7,49" não têm com o que
   colidir de perto. Menos padding aqui é o que sobra para a tabela caber em
   1366px sem rolagem interna. */
[data-pagina="crm-deal"] .crm-tabela .num { padding-inline: .4rem; }
.crm-tabela .num .form-control, .crm-tabela .num .form-select {
  max-width: 7.5rem; margin-left: auto; }
/* O select de tabela não tem mais largura própria (decisão do dono, 10/08):
   vale a mesma dos outros campos da linha, os 7,5rem da regra acima. A opção
   fechada foi encurtada para caber nela — "0421 · R$ 7,49" em vez do rótulo
   inteiro do backend, que vive no `title` e na lista aberta. */
.crm-tabela tfoot td { border-top: 1px solid var(--crm-borda-forte);
  border-bottom: 0; font-variant-numeric: tabular-nums; }
/* A EMBALAGEM É COLUNA, como qualquer outro dado do item. Foi, nesta ordem:
   um balão tingido sobre a tabela (campos sem cabeçalho, era preciso
   reaprender o que era cada um), uma segunda <tr> alinhada coluna a coluna,
   e uma célula única entre Preço e Total — três formas de esconder três
   campos atrás de um gesto. Em 10/08 o dono decidiu o fim do gesto: três
   colunas fixas depois do Preço, vazias quando o item não se embala. Sem
   fundo tingido e sem borda própria: a coluna já é o que separa, e o
   cabeçalho já é o que nomeia. */

/* timeline com fio: o fio nasce no marcador e vai até o próximo, e a última
   entrada não puxa fio para o vazio. */
.crm-tempo { list-style: none; margin: 0; padding: 0; }
/* RITMO DA LINHA DO TEMPO. Toda entrada tinha o mesmo padding e o mesmo nó: no
   teste de squint a coluna era uma escada uniforme, e "Rodada 1 · R$ 22.198,75
   · entregue ao cliente" pesava exatamente o mesmo que "Descarga: vazio → Não
   se aplica". Medido no negócio 27: 12 de 12 entradas automáticas, sete delas
   no MESMO segundo (um Salvar do painel de detalhes). O que aconteceu de
   verdade ganha ar e nó cheio; o diff de campo encolhe e clareia. */
.crm-tempo > li { display: grid; grid-template-columns: .55rem 1fr;
  gap: var(--crm-e2); padding-bottom: var(--crm-e4); position: relative; }
.crm-tempo > li.crm-tempo--auto { padding-bottom: var(--crm-e2); }
.crm-tempo > li.crm-tempo--auto .crm-tempo__texto { color: var(--crm-tinta-2); }
.crm-tempo > li.crm-tempo--auto .crm-tempo__no { width: .35rem; height: .35rem;
  margin-top: .5rem; border-width: 1px; }
/* O ar entra ANTES do que interrompe a sequência de automáticos: é ali que a
   história volta a ser de gente. */
.crm-tempo > li.crm-tempo--auto + li:not(.crm-tempo--auto) {
  padding-top: var(--crm-e3); }
/* O resumo do gesto: a linha diz quantos campos mudaram e o diff abre por
   baixo. `<details>` nativo — não há estado a guardar nem JS a escrever. */
/* padding-block: 21px de altura ficava abaixo do piso de 24px do WCAG 2.5.8
   (AA) — o único alvo da tela fora da régua. */
[data-pagina="crm-deal"] .crm-tempo__detalhe > summary { font-size: 0.875rem; cursor: pointer;
  color: var(--crm-tinta-2); list-style: none; padding-block: 2px;
  display: flex; align-items: center; gap: .35rem; }
/* O marcador do navegador ficava pendurado para fora, cortado pela linha do
   tempo; o `.drill-plus` canônico entra no fluxo da frase. */
.crm-tempo__detalhe > summary::-webkit-details-marker { display: none; }
.crm-tempo__detalhe > summary:hover { color: var(--crm-tinta); }
.crm-tempo__detalhe > summary:focus-visible { outline: 2px solid var(--crm-acento);
  outline-offset: 2px; border-radius: 3px; }
.crm-tempo__detalhe > ul { margin: var(--crm-e1) 0 0; padding-left: var(--crm-e4);
  font-size: var(--bi-fs-compact); color: var(--crm-tinta-2); }
.crm-tempo__detalhe > ul > li { margin-top: 2px; }
.crm-tempo > li:not(:last-child)::before { content: ''; position: absolute;
  left: calc(.275rem - .5px); top: 1.05rem; bottom: -.05rem; width: 1px;
  background: var(--crm-borda); }
.crm-tempo > li.crm-tempo--solto { display: block; }
.crm-tempo > li.crm-tempo--solto::before { display: none; }
.crm-tempo .crm-tempo__no { width: .55rem; height: .55rem; border-radius: 50%;
  background: var(--crm-superficie); border: 2px solid var(--crm-borda-forte);
  margin-top: .42rem; box-sizing: border-box; }
/* Compromisso futuro é o único cheio: ele é o que ainda pede ação. */
.crm-tempo > li.crm-tempo--futuro .crm-tempo__no { background: var(--crm-acento);
  border-color: var(--crm-acento); }
.crm-tempo .crm-tempo__quando { font-size: var(--bi-fs-micro); font-weight: 500;
  color: var(--crm-tinta-3); }
.crm-tempo .crm-tempo__texto { font-size: 0.875rem; margin-top: .05rem; }
.crm-tempo .crm-tempo__quem { font-size: var(--bi-fs-micro); color: var(--crm-tinta-3);
  margin-top: .1rem; }

/* Lista de leads: o rodapé do "mostrar mais" e o selo da fonte. A visão de
   leads pagina no servidor desde 31/08/2026 (os 40 mil leads do Ploomes
   entraram nela), então ela tem rodapé próprio no lugar do do DataTables. */
.cl-mais { display: flex; justify-content: center; align-items: center;
  gap: .5rem; padding: .75rem 0 .25rem; }
.cl-mais:empty { display: none; }
.crm-selo--acervo { background: var(--crm-superficie-2, #f1f3f5);
  color: var(--crm-tinta-2); border: 1px solid var(--crm-borda); }

/* Anexos da conversa (registrar contato). Duas telas os desenham — a linha do
   tempo do negócio e o histórico do cliente — com o mesmo HTML, por isso a
   regra não é escopada por página. O tocador de áudio fica estreito de
   propósito: é um anexo dentro de uma linha, não o assunto dela. */
.crm-tempo__anexos { display: flex; flex-wrap: wrap; align-items: center;
  gap: .35rem .5rem; margin-top: .35rem; }
.crm-anexo { display: inline-flex; align-items: center; gap: .35rem;
  max-width: 100%; padding: .18rem .5rem; border: 1px solid var(--crm-borda);
  border-radius: var(--raio-chip); background: var(--crm-superficie-2, #f8f9fa);
  font-size: var(--bi-fs-micro); color: var(--crm-tinta-2);
  text-decoration: none; }
.crm-anexo:hover { border-color: var(--crm-acento); color: var(--crm-tinta); }
/* O nome corta com reticências; o title completo fica no atributo. Sem isto um
   arquivo de 184 caracteres (existem, vieram do Ploomes) empurra a linha. */
.crm-anexo__nome { max-width: 16rem; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; }
.crm-anexo-audio { max-width: 20rem; width: 100%; height: 2rem; }

/* rodapé de decisão grudado */
[data-pagina="crm-deal"] .crm-rodape { position: sticky; bottom: 0; z-index: 20;
  background: var(--crm-superficie); border-top: 1px solid var(--crm-borda);
  padding-block: .7rem; display: flex; flex-wrap: wrap; align-items: center;
  gap: .6rem 1rem; }
[data-pagina="crm-deal"] .crm-rodape__acoes { margin-left: auto; display: flex;
  flex-wrap: wrap; align-items: center; gap: .5rem; }
/* avisos moram no rodapé, na linha acima dos botões; vazio não ocupa linha */
[data-pagina="crm-deal"] .crm-rodape__avisos { flex: 1 1 100%; }
[data-pagina="crm-deal"] .crm-rodape__avisos:empty { display: none; }
[data-pagina="crm-deal"] .crm-rodape__avisos .crm-aviso { margin-bottom: .35rem; }

/* A barra é a ÚNICA superfície de ação da tela desde 11/08 — dez botões onde
   antes havia quatro grupos espalhados por quatro bordas. Sem menu "mais":
   decisão do dono, tudo à mostra. Para caber numa fileira a 1366 (a resolução
   real da frota) os botões daqui encolhem: 12px (o piso da escala), padding
   curto e SEM ícone. O ícone valia ~20px por botão e não dizia nada que o
   rótulo já não diga — um lápis ao lado de "Editar proposta" é decoração com
   custo de largura. Ícone SEM rótulo seria o anti-referente nº 1 do produto
   (ERP legado); não é o caso aqui, os rótulos ficam. */
[data-pagina="crm-deal"] .crm-rodape__acoes .crm-btn,
[data-pagina="crm-deal"] .crm-rodape__acoes .crm-btn-2,
[data-pagina="crm-deal"] .crm-rodape__acoes .crm-btn-3,
[data-pagina="crm-deal"] .crm-rodape__acoes .crm-btn-ganhar,
[data-pagina="crm-deal"] .crm-rodape__acoes .crm-btn-perder {
  font-size: 12px; padding: .3rem .5rem; min-height: 28px;
  /* borda transparente nos fantasmas: sem ela os contornados ficam 2px mais
     altos e a fileira desalinha em degraus de 1px */
  border: 1px solid transparent; }
[data-pagina="crm-deal"] .crm-rodape__acoes .fa-solid,
[data-pagina="crm-deal"] .crm-rodape__acoes .fa-regular { display: none; }

/* A barra é grudada, então ela COBRE o fim da página — o acompanhamento
   ficava debaixo dela numa tela de 768px de altura, e tabular até lá levava o
   foco para fora de vista. O respiro é do tamanho dela. */
[data-pagina="crm-deal"] .crm-corpo { padding-bottom: 3.5rem; }

/* No toque o dedo volta a mandar: abaixo de 992px a tela já vira cartão, e
   alvo de 26px ali seria mira, não botão. */
@media (max-width: 991.98px) {
  [data-pagina="crm-deal"] .crm-rodape__acoes .crm-btn,
  [data-pagina="crm-deal"] .crm-rodape__acoes .crm-btn-2,
  [data-pagina="crm-deal"] .crm-rodape__acoes .crm-btn-3,
  [data-pagina="crm-deal"] .crm-rodape__acoes .crm-btn-ganhar,
  [data-pagina="crm-deal"] .crm-rodape__acoes .crm-btn-perder {
    font-size: 13px; padding: .45rem .7rem; min-height: 38px; }
}

/* --- avisos --- */
.crm-aviso { background: var(--crm-superficie); border: 1px solid var(--crm-borda);
  border-radius: 8px; padding: .65rem .9rem; font-size: 0.875rem;
  display: flex; gap: .6rem; align-items: flex-start; margin-bottom: .75rem; }
.crm-aviso--ok   { border-color: #b7e2c5; background: var(--crm-ok-fundo); }
.crm-aviso--avi  { border-color: #f0d9a7; background: var(--crm-avi-fundo); }
.crm-aviso--erro { border-color: #f2c6c0; background: var(--crm-mal-fundo); }

/* --- estados vazios --- */
.crm-vazio { color: var(--crm-tinta-3); font-size: var(--bi-fs-compact); padding: 1.2rem .5rem; }

/* --- listas de sugestão (autocomplete) --- */
[data-pagina="crm"] .crm-lista, [data-pagina="crm-deal"] .crm-lista {
  background: var(--crm-superficie); border: 1px solid var(--crm-borda);
  border-radius: 10px; box-shadow: var(--crm-sombra-2); overflow: hidden;
  overflow-y: auto; }
[data-pagina="crm"] .crm-lista__item, [data-pagina="crm-deal"] .crm-lista__item {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  border-bottom: 1px solid var(--crm-borda); padding: .6rem .85rem;
  font-size: 0.875rem; color: var(--crm-tinta); cursor: pointer; }
[data-pagina="crm"] .crm-lista__item:last-child,
[data-pagina="crm-deal"] .crm-lista__item:last-child { border-bottom: 0; }
[data-pagina="crm"] .crm-lista__item:hover,
[data-pagina="crm"] .crm-lista__item:focus,
[data-pagina="crm-deal"] .crm-lista__item:hover,
[data-pagina="crm-deal"] .crm-lista__item:focus { background: var(--crm-fundo); }
[data-pagina="crm"] .crm-lista--flutua, [data-pagina="crm-deal"] .crm-lista--flutua {
  position: absolute; left: 0; right: 0; z-index: 1060; max-height: 16rem; }

/* --- offcanvas: painel do sistema ---
   `crm-clientes` entra na lista em 01/09/2026: a lista de clientes/leads
   inclui os MESMOS canvas (ficha, histórico, documentos, negócios) desde
   26/08, e sem esta linha eles caíam no padding padrão do Bootstrap — a mesma
   ficha tinha margem diferente conforme a tela de onde era aberta. Por
   IGUALDADE e nunca por prefixo, como o resto do skin do CRM (ver o incidente
   em `bi/templates/bi/crm_produtividade.html`). */
[data-pagina="crm"] .offcanvas, [data-pagina="crm-deal"] .offcanvas,
[data-pagina="crm-clientes"] .offcanvas {
  border-left: 0; box-shadow: -12px 0 48px rgba(26, 26, 30, .16); }
[data-pagina="crm"] .offcanvas-header, [data-pagina="crm-deal"] .offcanvas-header,
[data-pagina="crm-clientes"] .offcanvas-header {
  padding: 1rem 1.25rem; }
[data-pagina="crm"] .offcanvas-body, [data-pagina="crm-deal"] .offcanvas-body,
[data-pagina="crm-clientes"] .offcanvas-body {
  padding: 1rem 1.25rem; }
[data-pagina="crm"] .crm-oc-rodape, [data-pagina="crm-deal"] .crm-oc-rodape,
[data-pagina="crm-clientes"] .crm-oc-rodape {
  display: flex; gap: .6rem; padding: .9rem 1.25rem;
  border-top: 1px solid var(--crm-borda); }
[data-pagina="crm"] .crm-oc-rodape > *, [data-pagina="crm-deal"] .crm-oc-rodape > *,
[data-pagina="crm-clientes"] .crm-oc-rodape > * {
  flex: 1 1 0; }
[data-pagina="crm"] .btn-close, [data-pagina="crm-deal"] .btn-close,
[data-pagina="crm-clientes"] .btn-close {
  opacity: .55; transition: opacity .15s ease; }
[data-pagina="crm"] .btn-close:hover, [data-pagina="crm-deal"] .btn-close:hover,
[data-pagina="crm-clientes"] .btn-close:hover {
  opacity: 1; }
[data-pagina="crm"] .btn-close:focus, [data-pagina="crm-deal"] .btn-close:focus,
[data-pagina="crm-clientes"] .btn-close:focus {
  box-shadow: 0 0 0 3px rgba(26, 26, 30, .12); opacity: 1; }

/* --- toque e movimento --- */
@media (pointer: coarse) {
  [data-pagina="crm"] .crm-btn, [data-pagina="crm"] .crm-btn-2,
  [data-pagina="crm"] .form-control, [data-pagina="crm"] .form-select,
  [data-pagina="crm-deal"] .crm-btn, [data-pagina="crm-deal"] .crm-btn-2,
  [data-pagina="crm-deal"] .crm-btn-ganhar, [data-pagina="crm-deal"] .crm-btn-perder,
  [data-pagina="crm-deal"] .form-control, [data-pagina="crm-deal"] .form-select {
    min-height: 2.75rem; }
  /* O `.crm-btn-3` estava aqui numa lista de seletores terminada em VÍRGULA
     seguida do `}` — o parser descartava a regra inteira, e o comentário
     prometia um alvo de toque que nunca existiu (verificado no browser: o
     bloco ficava com uma regra só). Quem cobre esses botões hoje é a regra de
     44px lá embaixo, que é mais alta que os 2,75rem prometidos aqui. */
}
@media (prefers-reduced-motion: reduce) {
  [data-pagina="crm"] *, [data-pagina="crm-deal"] * { transition: none !important; }
}

/* colunas de apoio da tabela: somem em telas menores */
@media (max-width: 767.98px) {
  [data-pagina="crm-deal"] .crm-col-md { display: none; }
}
@media (max-width: 991.98px) {
  [data-pagina="crm-deal"] .crm-col-lg { display: none; }
}
/* As três colunas de embalagem somem quando NENHUM item da proposta tem
   embalagem preenchida (decisão do dono, 11/08/2026) — 685 dos 740 produtos
   do catálogo não se embalam, e a maioria das propostas oferecia três
   colunas em branco. Quem decide o fato é o backend
   (`tem_item_com_embalagem`, `crm.py` `_serializar_proposta`); a classe
   `.crm-sem-embalagem` na tabela é aplicada por `renderItens` (itens.js),
   já combinada com o estado de EDIÇÃO — em edição ela nunca entra, porque
   escondê-las ali impediria preencher a embalagem pela primeira vez. Sem
   `@media` aqui de propósito: a regra vale em qualquer largura, inclusive
   no cartão do celular — três classes (id + duas classes) para vencer o
   `#dl-itens td { display: flex }` genérico do cartão (uma classe a menos:
   já aconteceu nesta tela uma regra mais fraca perder por engano). */
[data-pagina="crm-deal"] #dl-itens.crm-sem-embalagem .crm-col-embalagem { display: none; }
[data-pagina="crm-deal"] .crm-tabela .num .form-control { text-align: right; }
/* Sem `min-width` aqui, `table-layout:auto` (herdado) redistribui a coluna
   pelo que sobra: fechada a embalagem ela cabe folgada, mas assim que o
   bloco abre (nova coluna ao lado pedindo espaço) o navegador reduz esta
   coluna e "Tabela 0002 · 5,30" volta a cortar em "5…" — medido ao vivo, o
   max-width do select (acima) não segura sozinho quando outra coluna
   disputa a MESMA largura total da tabela. */
/* A coluna acompanha o campo (11/08/2026): com o seletor em 19ch, os 13rem de
   antes deixavam ~60px de sobra à direita do campo, e a coluna larga com o
   campo estreito dentro é o mesmo desalinho que os 13rem tinham vindo
   corrigir, invertido. 10,5rem = o campo mais o respiro da célula. */
[data-pagina="crm-deal"] .crm-tabela .crm-col-lg { min-width: 10.5rem; }
/* O seletor cabe o par que IDENTIFICA a tabela — código e preço —, não o
   rótulo inteiro (decisão do dono, 11/08/2026, revendo o "ocupa a coluna
   inteira" de 10/08). Medido: com o nome dentro, o campo abria 447px e a
   coluna crescia atrás dele. Os 19ch somam "0002 · R$ 7,49" mais a seta.
   O nome não se perde: a lista ABERTA se dimensiona pelo conteúdo, e cada
   opção leva `title` com a frase inteira. */
[data-pagina="crm-deal"] .crm-tabela .num .crm-tabela-item { max-width: 19ch; }
/* Alinhar o que NÃO é campo com o texto de quem é. Duas tentativas:
   `vertical-align: middle` na célula centrava tudo — e aí a célula que
   ganha um comentário embaixo (o delta do preço base, a conversão da
   embalagem) fica mais alta, o meio dela sobe, e o campo daquela coluna
   descola dos vizinhos. O comentário é EVENTUAL; o desalinho que ele
   causava, não.
   Então: célula alinhada pelo TOPO (o comentário cresce para baixo, sem
   mexer em nada) e o valor desce os 7px que põem sua linha de texto na
   mesma altura do texto dentro do campo — 35px de campo centram o texto
   em 17,5px; 21px de pílula centram em 10,5px; a diferença é a margem.
   Só em edição: os `data-previa-*` não existem fora dela, e sem campo ao
   lado não há com o que alinhar. */
[data-pagina="crm-deal"] #dl-itens tbody [data-previa-estoque],
[data-pagina="crm-deal"] #dl-itens tbody [data-previa-total],
[data-pagina="crm-deal"] #dl-itens tbody [data-remover] { margin-top: .45rem; }
[data-pagina="crm-deal"] #dl-itens tbody [data-previa-estoque],
[data-pagina="crm-deal"] #dl-itens tbody [data-previa-total] {
  display: inline-block; }

/* ------------------------------------------------------------
   TELEFONE — densidade: sem altura mínima fantasma no funil,
   capa do deal em grade compacta, stepper enxuto, trilho da
   proposta DEPOIS do trabalho principal.
   ------------------------------------------------------------ */
@media (max-width: 767.98px) {
  /* funil: a laje encolhe até o conteúdo — nada de ar fantasma */
  [data-pagina="crm"] .crm-coluna { min-height: 0; }
  [data-pagina="crm"] .crm-raia__cabo { padding: .55rem .6rem; }

  /* capa do deal: as colunas do Bootstrap já empilham (col-12); aqui só a
     densidade — e os dois botões de editar dividem a linha em vez de sair
     pela borda. */
  [data-pagina="crm-deal"] .crm-capa { padding: .7rem .8rem .6rem; }
  [data-pagina="crm-deal"] .crm-capa .row > .col-auto:last-child { flex: 1 1 100%; }
  [data-pagina="crm-deal"] .crm-capa .row > .col-auto:last-child > .crm-btn {
    flex: 1 1 0; justify-content: center; }
  [data-pagina="crm-deal"] .crm-conta-nome { font-size: 1rem; }

  /* O roteiro tinha ficado de fora: seguia com o recuo de desktop (20px)
     enquanto capa, etapas, corpo e rodapé encolhiam para 12,8px — era ele o
     degrau que sobrava na borda esquerda ao rolar a tela. */
  [data-pagina="crm-deal"] .crm-roteiro { padding-inline: .8rem; }

  /* corpo: trabalho primeiro, trilho da proposta depois */
  [data-pagina="crm-deal"] .crm-corpo { padding: .8rem; gap: .8rem; }
  [data-pagina="crm-deal"] .crm-trilho { order: 2; padding: .85rem .8rem; }
  [data-pagina="crm-deal"] .crm-painel { padding: .85rem .8rem; }
  [data-pagina="crm-deal"] .crm-rodape { padding: .6rem .8rem; }

  /* iOS: input com fonte < 16px dispara ZOOM automático ao focar — o
     zoom desloca o rodapé sticky pro meio da tela e o conteúdo vaza
     por trás. 1rem = 16px mata o zoom na raiz. */
  [data-pagina="crm"] .form-control, [data-pagina="crm"] .form-select,
  [data-pagina="crm-deal"] .form-control, [data-pagina="crm-deal"] .form-select {
    font-size: 1rem; }

  /* tabela de itens: células e inputs mais enxutos pro TOTAL caber */
  [data-pagina="crm-deal"] .crm-tabela th { padding: .45rem .3rem; }
  [data-pagina="crm-deal"] .crm-tabela td { padding: .55rem .3rem;
    font-size: var(--bi-fs-compact); }
  [data-pagina="crm-deal"] .crm-tabela td:empty { padding: 0; }
  [data-pagina="crm-deal"] .crm-tabela .num .form-control,
  [data-pagina="crm-deal"] .crm-tabela .num .form-select { max-width: 5.4rem; }
  /* descrição do produto não vira parágrafo: 2 linhas e reticências */
  [data-pagina="crm-deal"] .crm-tabela td .crm-rotulo { display: -webkit-box;
    -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }

  /* teclado aberto (edição de item) esconde o rodapé de decisão —
     classe posta pelo JS no focusin/focusout da tabela */
  [data-pagina="crm-deal"] .crm-rodape--editando { display: none; }

  /* Rodapé de decisão no telefone: FIXO, não sticky. O sticky depende da
     altura do container, e no Safari do iPhone essa altura muda quando a
     barra de URL recolhe — o banner "descolava" e ficava no meio da rolagem.
     Fixo + safe-area encosta na borda de baixo sempre; a página ganha um
     colchão do mesmo tamanho pra última linha não ficar por baixo dele. */
  [data-pagina="crm-deal"] .crm-rodape {
    position: fixed; left: 0; right: 0; bottom: 0;
    padding-bottom: calc(.6rem + env(safe-area-inset-bottom, 0px));
    box-shadow: 0 -1px 12px rgba(23, 26, 24, .1); }
  [data-pagina="crm-deal"] .crm-pagina {
    padding-bottom: calc(7rem + env(safe-area-inset-bottom, 0px)); }
  /* a faixa de confirmação toma o lugar do rodapé — mesma âncora */
  [data-pagina="crm-deal"] #dl-confirmacao { align-items: flex-start; }
  [data-pagina="crm-deal"] #dl-confirmacao .crm-rodape__acoes { width: 100%; }
  [data-pagina="crm-deal"] #dl-confirmacao .crm-rodape__acoes > * { flex: 1 1 0; }

  /* no telefone o painel é folha de tela cheia */
  [data-pagina="crm"] .offcanvas, [data-pagina="crm-deal"] .offcanvas {
    --bs-offcanvas-width: 100%; }
}

/* OFFCANVAS FECHADO NÃO PODE FICAR ESTACIONADO FORA DA TELA (toque).
   O Bootstrap guarda o painel com `translateX(100%)`: um box da largura
   da tela parado logo à direita dela. O Safari do iPhone/iPad conta esse
   box na largura do conteúdo ao calcular a escala INICIAL — a página abre
   com zoom-out e aceita arrastar de lado. (No Chromium o `overflow-x:
   clip` do html mascara o sintoma, por isso não aparecia nas medições.)
   Até 1199px o painel não usa transform: aparece e some por opacidade.
   No desktop (≥1200px, sem escala automática) o slide lateral fica. */
@media (max-width: 1199.98px) {
  [data-pagina="crm"] .offcanvas, [data-pagina="crm-deal"] .offcanvas {
    transform: none !important;
    transition: opacity .2s ease; opacity: 1; }
  [data-pagina="crm"] .offcanvas:not(.show):not(.showing),
  [data-pagina="crm-deal"] .offcanvas:not(.show):not(.showing) { opacity: 0; }
}

/* deal frio: parado na etapa acima do limiar (classificado no backend) —
   o card inteiro esquenta pro âmbar, escaneável descendo a raia */
[data-pagina="crm"] .crm-cartao--frio { border-color: #ecc94b66;
  background: #fffdf4; }
[data-pagina="crm"] .crm-cartao--frio .crm-cartao__rodape {
  border-top-color: #f0e6c0; }

/* ------------------------------------------------------------
   NOTEBOOK DE 1366×768 — a tela real do comercial.
   Medido em 10/08/2026 no negócio 27, nessa viewport: 462px de altura
   consumidos ANTES da primeira linha de item (60% da tela) e a tabela
   vazando 327px pela direita, com "Total" e "Ações" fora da janela. Dois
   itens visíveis em leitura, 1,4 em edição — e a linha de item medindo
   166px, das quais a maior parte era texto quebrando em coluna estreita.

   O que se resolve aqui é ALTURA e LARGURA ao mesmo tempo, e por deleção
   antes de encolhimento: a faixa de etapas saiu (template), os rótulos da
   capa saíram (JS) e o trilho de acompanhamento desce em vez de disputar a
   largura. O que sobra é densidade — um passo, não uma tela em miniatura.
   ------------------------------------------------------------ */

/* --- 1. O trilho DESCE, não some (≤ 1600px) ---
   Em leitura o acompanhamento ocupava 400px de largura à esquerda: exatamente
   o que a tabela vazava pela direita. Ele é CONTEXTO e a proposta é o
   trabalho, então abaixo do desktop largo ele vai para depois — o mesmo
   movimento que o telefone já fazia (`order: 2`), agora começando onde a
   disputa começa. Nada é escondido: rolar o corpo continua chegando nele. */
@media (max-width: 1600px) {
  [data-pagina="crm-deal"] .crm-corpo { grid-template-columns: minmax(0, 1fr); }
  [data-pagina="crm-deal"] .crm-trilho { order: 2; position: static;
    max-height: 32rem;
    /* `stretch` (herdado do modo lado a lado) numa linha de grade só dele:
       a linha media o trilho pelo mínimo da lista (`min-height: 0` +
       overflow), e o acompanhamento nascia com 31px e rolagem interna —
       uma entrada visível (medido no negócio 27 a 1600px). `start` deixa o
       trilho medir o conteúdo até os 32rem. */
    align-self: start; }
}

/* --- 2. Densidade: um passo, dentro do CRM só ---
   `[data-pagina^="crm"]` cobre funil e negócio e nada mais: `custom.css` é
   lido por ~28 páginas, e mexer em token global vazaria no app inteiro. */
@media (max-width: 1600px) {
  [data-pagina^="crm"] .crm-capa { padding-block: .55rem; }
  [data-pagina^="crm"] .crm-painel { padding: .8rem .9rem; }
  /* Denso na VERTICAL; na horizontal vale a régua de respiro (o fallback
     .8rem cobre o funil, que não declara a variável). */
  [data-pagina^="crm"] .crm-corpo {
    padding: .8rem var(--crm-respiro-x, .8rem); gap: .8rem; }
  [data-pagina^="crm"] .crm-rodape { padding-block: .5rem; }
  /* Controles um degrau mais baixos. 38px era altura de toque; no notebook o
     ponteiro é fino, e `pointer: coarse` (acima) continua devolvendo os 44px
     a quem usa touch — a regra de toque não é revogada por esta. */
  [data-pagina^="crm"] .form-control, [data-pagina^="crm"] .form-select {
    padding-block: .3rem; min-height: 2rem; }
  [data-pagina^="crm"] .crm-btn, [data-pagina^="crm"] .crm-btn-2,
  [data-pagina^="crm"] .crm-btn-3 { padding-block: .35rem; }
}

/* --- 3. A tabela de itens tem largura DECLARADA ---
   Mesma disciplina do documento em PDF (`.prop-tabela`), pelo mesmo motivo:
   com `layout: auto` a pílula de estoque ("591.834,215 KG") e o seletor de
   tabela puxavam a largura, e sobravam 95px para o nome do produto — que é o
   que se lê. Cada número abaixo foi conferido contra conteúdo real na tela,
   não estimado.

   REFEITO em 21/08/2026, com a coluna da COMISSÃO: as larguras são declaradas
   por POSIÇÃO, então a coluna nova empurrou todas as seguintes uma casa e o
   TOTAL — a última com largura declarada — ficou sem nenhuma e colapsou para
   zero em 1366×768. Medido: a tabela pedia 1.263px numa faixa de 1.236px. Os
   6rem da comissão foram tirados de onde havia gordura, e o Produto encolheu
   por decisão do dono (o nome longo agora corta com reticências, e a frase
   inteira fica no `title`). Somam 76,25rem = 1.220px — e a
   régua é a CASCA que rola (1.222px), não a tabela: 1.228px cabiam na tabela
   e ainda assim acendiam a barra de rolagem do contêiner por 6px. */
/* REFEITO em 28/08/2026: as três colunas de embalagem (posições 8-10)
   viraram UMA (posição 8) — o TOTAL e as AÇÕES sobem uma casa cada (9 e
   10/last). Mesma disciplina de sempre: largura por POSIÇÃO, então quem
   mexe na ordem tem que refazer a soma. Embalagem ganha mais espaço que a
   antiga coluna "Tipo" sozinha (agora carrega a frase inteira ou os três
   controles agrupados), e o TOTAL ganha largura DECLARADA pela primeira vez
   — antes ela contava com a sobra, e foi exatamente isso que a fez colapsar
   em 21/08 quando a Comissão entrou. Soma: 73,75rem = 1.180px, contra os
   ~83rem (Total incluso) da versão de 12 colunas — folga de sobra para
   1366px. */
@media (min-width: 992px) and (max-width: 1600px) {
  [data-pagina="crm-deal"] #dl-itens { table-layout: fixed; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(1) { width: 11rem; }
  [data-pagina="crm-deal"] #dl-itens th.crm-col-md { width: 6rem; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(3) { width: 8rem; }
  [data-pagina="crm-deal"] #dl-itens th.crm-col-lg { width: 10.5rem;
    min-width: 0; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(5) { width: 7.5rem; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(6) { width: 6rem; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(7) { width: 6rem; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(8) { width: 9rem; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(9) { width: 7rem; }
  [data-pagina="crm-deal"] #dl-itens th:last-child { width: 2.75rem; }
  [data-pagina="crm-deal"] .crm-tabela th { padding: .4rem .5rem; }
  [data-pagina="crm-deal"] .crm-tabela td { padding: .45rem .5rem; }
  /* "EMBALAGENS" é UMA palavra de 10 letras: a 12px com 1,2px de espaçamento
     ela pede 98px, e a coluna tem 80. Palavra não quebra — ela vazava por
     cima da vizinha ("EMBALAGENSEMBALAGEM" na medição de 1366×768). Menos
     corpo e menos espaçamento SÓ nesta faixa: o cabeçalho continua em caixa
     alta, e passa a caber. */
  [data-pagina="crm-deal"] .crm-tabela th { font-size: 11px; letter-spacing: .04em; }

  /* `layout: fixed` NÃO recorta: conteúdo maior que a coluna declarada vaza
     POR CIMA da vizinha em vez de alargá-la, e foi o que aconteceu na
     primeira medição — o "KG" ao lado da quantidade caía dentro do seletor de
     tabela, e o do volume por cima do total. Com `auto` esse mesmo excesso
     roubava a largura do nome do produto; o vazamento é o preço de declarar
     largura, e quem o paga é esta regra. Cada filho da célula fica preso à
     célula, e o campo ENCOLHE em vez de empurrar o sufixo para fora. */
  [data-pagina="crm-deal"] #dl-itens td > * { max-width: 100%; }
  [data-pagina="crm-deal"] #dl-itens .crm-campo-un { max-width: 100%; }
  /* `min-width: 0` é o que permite encolher: sem ele o `flex` respeita a
     largura mínima do conteúdo do input e o encolhimento não acontece. */
  [data-pagina="crm-deal"] #dl-itens .crm-campo-un > .form-control {
    width: auto; flex: 1 1 auto; min-width: 0; }
  /* A UNIDADE não encolhe: quem cede espaço é o campo. Deixada com o
     `flex-shrink` padrão ela virava "K" em vez de "KG" — e uma unidade pela
     metade ao lado de "3.000" é pior que o vazamento que a regra acima
     consertou: dá para ler 3.000 K como outra coisa. */
  [data-pagina="crm-deal"] #dl-itens .crm-campo-un > .crm-rotulo {
    flex: 0 0 auto; }
  [data-pagina="crm-deal"] #dl-itens [data-previa-conversao],
  [data-pagina="crm-deal"] #dl-itens [data-previa-delta] { max-width: 100%; }
}

/* --- 3-b. ACIMA de 1600px a mesma disciplina, em PROPORÇÃO ---
   O bloco acima parava em 1600px, e daí para cima a tabela voltava ao
   `layout: auto` SEM largura declarada: bastava uma frase longa numa célula —
   a conversão da embalagem, "5.000 KG = 1 bobina × 5.000 KG · R$ 27.500,00 por
   bobina" — para ela pedir mais que o contêiner e acender barra de rolagem
   horizontal num monitor grande, com a coluna TOTAL cortada (defeito relatado
   pelo dono, 25/08/2026).
   Aqui a largura é PERCENTUAL, não rem: o espaço extra do monitor se reparte
   entre as colunas em vez de sobrar para uma frase esticar. As proporções são
   as mesmas que os rem do bloco anterior produzem a 1366 (medidas na tela,
   somam 100%). Abaixo de 1601px nada muda: lá o problema é caber, e caber
   pede número absoluto.
   REFEITO em 28/08/2026 junto com o bloco de cima: posições 8-10 (as três
   colunas de embalagem) viraram a posição 8 só, com mais % que a antiga
   "Tipo" sozinha; Total e Ações sobem para 9 e 10/last, com Total ganhando
   % DECLARADA (não sobra) pela mesma razão do bloco anterior. Soma
   continua 100%. */
@media (min-width: 1601px) {
  [data-pagina="crm-deal"] #dl-itens { table-layout: fixed; width: 100%; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(1) { width: 13%; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(2) { width: 7%; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(3) { width: 9.5%; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(4) { width: 12.5%; min-width: 0; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(5) { width: 9%; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(6) { width: 7%; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(7) { width: 7%; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(8) { width: 20%; }
  [data-pagina="crm-deal"] #dl-itens th:nth-child(9) { width: 11%; }
  [data-pagina="crm-deal"] #dl-itens th:last-child { width: 4%; }
}

/* As regras de CONTENÇÃO valem de 992px para cima, nas duas faixas: é
   `table-layout: fixed` que as exige (conteúdo maior que a coluna vaza por
   cima da vizinha em vez de alargá-la), e agora as duas faixas o usam. Estavam
   presas ao bloco de 992–1600 e, acima de 1600, a frase da conversão saía sem
   freio. */
@media (min-width: 992px) {
  /* A coluna de AÇÕES não se esconde atrás da rolagem: na faixa de rem
     (992–1600) a tabela em edição estoura o contêiner (23px a 1366, 189px a
     1200 — foi assim que o zoom negativo da Letícia sumiu com o X de
     remover) e a última coluna ia junto. Sticky na borda direita: visível
     em qualquer largura efetiva, com ou sem rolagem. */
  [data-pagina="crm-deal"] #dl-itens th:last-child,
  [data-pagina="crm-deal"] #dl-itens td:last-child {
    position: sticky; right: 0; background: #fff; }
  [data-pagina="crm-deal"] #dl-itens td > * { max-width: 100%; }
  [data-pagina="crm-deal"] #dl-itens .crm-campo-un { max-width: 100%; }
  [data-pagina="crm-deal"] #dl-itens .crm-campo-un > .form-control {
    width: auto; flex: 1 1 auto; min-width: 0; }
  [data-pagina="crm-deal"] #dl-itens .crm-campo-un > .crm-rotulo {
    flex: 0 0 auto; }
  [data-pagina="crm-deal"] #dl-itens [data-previa-conversao],
  [data-pagina="crm-deal"] #dl-itens [data-previa-delta] { max-width: 100%; }
}

/* --- 4. A LINHA de item: 166px eram três textos quebrando ---
   Nome do produto em 4 linhas, o gatilho da previsão em 3 e a frase de
   conversão em 5. Nenhum deles precisa de mais de uma ou duas linhas: o que
   não couber vai para o `title`, que é onde texto longo pertence numa
   tabela. Vale em toda largura — o desperdício não era do notebook. */
[data-pagina="crm-deal"] #dl-itens td .crm-rotulo { display: -webkit-box;
  -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* A SEGUNDA LINHA IMAGINÁRIA (pedido do dono, 25/08/2026). As legendas sob os
   campos — referência da tabela, aviso de piso, variação do preço, IPI do
   cadastro, conversão da embalagem — nasciam cada uma colada no próprio
   campo, e como cada célula tem altura própria elas ficavam em alturas
   diferentes: "preço tabela, variação, ipi alinhados no topo, embalagem no
   fundo". Aqui todas viram camadas absolutas ancoradas na MESMA altura
   (`--crm-linha2`), formando uma linha de comentários com as mesmas
   propriedades sob a linha de campos; o `padding-bottom` do td reserva a
   banda que o absoluto não reserva.
   Só na linha EM EDIÇÃO (`tr:has(.form-control)`) e só em tela de tabela:
   em leitura as células são texto de uma linha, e no telefone a linha é um
   cartão empilhado. */
@media (min-width: 992px) {
  [data-pagina="crm-deal"] #dl-itens tbody { --crm-linha2: 3.2rem; }
  /* :not(:last-child): a célula de AÇÕES fica de fora — ela é sticky (regra
     acima) e `position: relative` aqui a soltava da borda, escondendo o X
     de remover atrás da rolagem. Legenda nunca mora nela. */
  [data-pagina="crm-deal"] #dl-itens tbody tr:has(.form-control) > td:not(:last-child) {
    position: relative; padding-bottom: 2.9rem; }
  /* Cada legenda pelo SEU seletor, nunca um `td > .crm-rotulo` genérico: o
     nome do produto também é `.crm-rotulo` filho de td, e o genérico o
     arrancava para a linha de baixo. O `!important` do margin vence o
     `.mt-1` do wrapper da variação, que também é !important. */
  [data-pagina="crm-deal"] #dl-itens tbody tr:has(.form-control) [data-previa-ipi-item] > .crm-rotulo,
  [data-pagina="crm-deal"] #dl-itens tbody tr:has(.form-control) [data-previa-comissao] > .crm-rotulo,
  [data-pagina="crm-deal"] #dl-itens tbody tr:has(.form-control) > td > [data-previa-delta],
  [data-pagina="crm-deal"] #dl-itens tbody tr:has(.form-control) > td > [data-previa-aviso],
  [data-pagina="crm-deal"] #dl-itens tbody tr:has(.form-control) [data-previa-tabela] > .crm-rotulo {
    position: absolute; top: var(--crm-linha2); left: .5rem; right: .5rem;
    margin-top: 0 !important; }
  /* A conversão da embalagem CORRIA sob as colunas vizinhas ("Qtd", "Total")
     de propósito (`max-width: 34rem`, sem `right`) — pré-28/08/2026, quando
     elas só tinham conteúdo na primeira linha e a folga era inofensiva. Não
     é mais: a coluna Total ganhou o selo do frete diluído na SEGUNDA linha
     (`itens.js` `badgeComFrete`), e a legenda passava por cima dele (achado
     ao vivo, deal 73, 1500px — 164px de vazamento medidos: legenda indo até
     1443, a própria célula da Embalagem terminando em 1279). `right: .5rem`
     tranca a legenda na SUA célula, como as outras desta banda; o texto que
     não couber corta em reticências (`overflow`/`text-overflow` abaixo). */
  [data-pagina="crm-deal"] #dl-itens [data-previa-conversao] {
    position: absolute; top: var(--crm-linha2); left: .5rem; right: .5rem;
    margin-top: 0; display: block; -webkit-line-clamp: unset;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; z-index: 1; }
}
@media (min-width: 992px) and (max-width: 1600px) {
  /* Os controles são um degrau mais baixos nesta faixa (min-height 2rem):
     a linha imaginária sobe junto. */
  [data-pagina="crm-deal"] #dl-itens tbody { --crm-linha2: 2.9rem; }
}
/* A LEGENDA DA COLUNA DE EMBALAGEM VOLTA AO FLUXO (01/09/2026).
   A "segunda linha imaginária" acima é `position:absolute`, e para as outras
   colunas ela está certa: elas têm UM controle, e a faixa de baixo está
   livre. Esta coluna não: a embalagem tem três controles e o cento tem dois,
   e em 149px (medidos ao vivo no deal 73 a 1366px) eles não cabem lado a
   lado — quebram, ocupam a segunda faixa, e a legenda absoluta era desenhada
   POR CIMA do segundo campo. Medido: campo em y 495..528, legenda em
   502..520. Estava assim na embalagem antes deste passe ("5.000 KG = 10
   bobinas…" escrito sobre o campo de volumes) e o cento herdaria o mesmo.
   Nenhum teste via — o DOM estava correto; quem mostrou foi a foto.
   Em fluxo normal a legenda desce para depois dos campos. Ela deixa de
   alinhar com as das colunas vizinhas, e é o preço certo a pagar: legenda
   desalinhada se lê, legenda por cima de um campo não.
   E ela QUEBRA em vez de cortar (pedido do dono, 01/09): "5.000 KG = 10
   bobinas × 500 KG · R$ 250.000,0…" com reticências escondia justamente o
   número que a legenda existe para dar. */
[data-pagina="crm-deal"] #dl-itens .crm-col-embalagem [data-previa-conversao] {
  position: static; margin-top: .25rem; white-space: normal;
  overflow: visible; text-overflow: clip; -webkit-line-clamp: unset; }
/* O seletor de tabela carrega o NOME dela (10/08/2026), e o texto é mais longo
   que a coluna de propósito: quem identifica é o código e o preço, que vêm
   antes, e o nome corta com reticências.
   Fechado, o campo cabe só o par que identifica — "0002 · R$ 7,49" são 15
   caracteres, e os 19ch abaixo somam a seta do `<select>` (decisão do dono,
   11/08/2026: o botão não precisa da largura do nome). O nome inteiro
   continua alcançável de dois jeitos, sem custo de espaço: a lista ABERTA o
   mostra (o popup nativo se dimensiona pelo conteúdo, não pelo campo) e o
   `title` de cada opção entrega a frase inteira ao passar o mouse.
   Tentou-se trocar estas três declarações pelo `.text-truncate` do Bootstrap
   (11/08/2026). Não serve: na legenda existe um `-webkit-line-clamp: 2` logo
   abaixo, e o utility do BS forçaria UMA linha, mudando o que a célula mostra;
   no `<select>` ele não muda nada, porque o widget nativo já elide sozinho. A
   MEDIDA, essa, o BS não tem como expressar — `w-auto` devolve a largura do
   conteúdo, que é exatamente o que se quer evitar aqui. */
[data-pagina="crm-deal"] .crm-tabela-item,
[data-pagina="crm-deal"] .crm-tabela-legenda { max-width: 19ch;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* A COLUNA DA COMISSÃO NÃO PRECISA DOS 7,5rem dos outros campos da linha: ela
   mostra "1,5%" ou "Outro", nunca uma frase. Medido a 1366×768 com a coluna
   nova (21/08/2026): a tabela somava 1.263px em 1.236px disponíveis, e quem
   colapsava era o TOTAL — 27px de excesso apagavam da tela o número que fecha
   a linha. Estreitar aqui devolve mais do que os 27. */
[data-pagina="crm-deal"] .crm-tabela .num .crm-comissao-item { max-width: 6rem; }

/* E o TOTAL nunca é quem some. Ele não tem largura própria (a tabela reparte o
   que sobra), então qualquer coluna que cresça o espreme primeiro — foi o que
   aconteceu acima. Piso + `nowrap`: se faltar espaço, a tabela rola e as
   colunas de embalagem é que saem da vista, não o valor da linha. */
[data-pagina="crm-deal"] .crm-tabela .crm-col-total { min-width: 7rem; white-space: nowrap; }

/* Selo "R$ X c/ frete" no TOTAL: o `nowrap` que segura o número da linha
   (regra acima) valia por herança para o selo também, e `.crm-pilula` (a
   família toda) já é `nowrap` por padrão. Um valor grande ("R$
   1.291.625,00 c/ frete") é mais largo que os 7rem da coluna declarada, e
   sem quebra o excesso VAZAVA por cima da coluna vizinha (Embalagem, à
   esquerda — `.num` alinha à direita, e o texto que sobra escapa pela
   esquerda da célula). Achado ao vivo no deal 73, 1500px, frete diluído.
   Só este selo quebra linha; as pílulas curtas do resto da tabela (delta,
   estoque) continuam numa linha só. */
[data-pagina="crm-deal"] #dl-itens .crm-pilula--frete { white-space: normal; }

/* O NOME DO PRODUTO QUEBRA EM LINHAS (decisão do dono, 01/09/2026 — reverte a
   de 21/08, que o punha em UMA linha com reticências).
   O motivo de então era altura: "CORDOALHA ENGRAXADA 12,7MM CP-190 RB" em duas
   linhas dobrava a linha inteira da tabela. O que mudou é que o corte passou a
   esconder o que distingue um item do outro — os seis fixadores só se
   diferenciam no fim da descrição ("TCP1 ... (CX C 3000PC)" contra "TCP4 ...
   (CX C 100PC)"), e cortados em 183px medidos a 1366px eles viram a mesma
   linha na tela. Reticências que escondem a diferença entre dois produtos
   custam mais que a altura que economizam. */
[data-pagina="crm-deal"] #dl-itens td .crm-produto-nome {
  display: block; -webkit-line-clamp: none; white-space: normal;
  overflow: visible; text-overflow: clip; overflow-wrap: anywhere; }

/* A LINHA DE ADICIONAR PRODUTO não é um formulário — é um convite. Ela ocupava
   a largura inteira da tabela com um campo de 33px de altura, e pesava mais na
   tela do que qualquer item já incluído. Campo miúdo e curto (decisão do dono,
   21/08): o texto do placeholder cabe, e a linha para de competir com o que a
   tabela tem para mostrar. */
[data-pagina="crm-deal"] #dl-itens td > #dl-add-busca { max-width: 34rem; }

/* O gatilho da previsão alinha com o CÓDIGO do produto, não com o centro da
   célula: em duas linhas, centralizado, ele parecia legenda do item em vez de
   ação. Recuo lateral zerado pelo mesmo motivo. */
[data-pagina="crm-deal"] .crm-btn-previsao { text-align: left; padding-inline: 0; }

/* --- 5. Funil: a barra de comando cabe em UMA linha, e o card encolhe ---
   Medido a 1366×768: a barra somava mais que os 1.278px disponíveis e
   quebrava em duas — a fileira de botões caía sozinha embaixo, e o primeiro
   card começava só aos 230px. O comentário do template já previa a conta
   ("somam 1369 numa linha de 1352"); aqui ela fecha, encolhendo o campo de
   busca, que é o único elemento da barra cuja largura era arbitrária.
   O card ia a 174–200px para cinco fatos: o que come a altura é o recuo, a
   entrelinha do título e a faixa do rodapé, não o conteúdo. */
@media (max-width: 1600px) {
  [data-pagina="crm"] .crm-comando { margin-bottom: .75rem !important; }
  /* A busca ficou com a largura de origem: encolhê-la foi tentativa de fazer
     a barra caber ANTES de descobrir que o que não cabia eram duas medidas
     repetindo o board. Cortado o excesso, não há por que apertar o campo. */
  /* Medido: as quatro medidas somavam 708px dos 1.278 disponíveis, e eram
     ELAS que empurravam a fileira de botões para a segunda linha. Quem
     ocupava a largura era o RÓTULO ("Negócios abertos" em 14px), não o
     número — e rótulo de indicador é legenda, não dado. Em micro eles somam
     ~470px e a barra fecha numa linha só, sem tocar no valor, que continua
     no corpo de leitura. */
  [data-pagina="crm"] .crm-medidas { gap: .65rem; }
  /* O rótulo é CAIXA ALTA com 1,2px de espaçamento entre letras: são as duas
     coisas que fazem "NEGÓCIOS ABERTOS" medir 133px. Reduzir o corpo sozinho
     não moveu nada (medido: 708 → 691px) — o espaçamento é que carrega a
     largura, e num rótulo de indicador ele é decoração. */
  [data-pagina="crm"] .crm-medida { padding-right: .3rem; }
  [data-pagina="crm"] .crm-medida dt { font-size: 11px; letter-spacing: .4px; }
  [data-pagina="crm"] .crm-medida dd { font-size: .95rem; }
  /* O card do funil: 217px para cinco fatos. O conteúdo mede 118px — o resto
     era respiro entre linhas que não separam grupo nenhum (nome, cidade,
     selo, proposta e valor são a MESMA coisa: a identidade do negócio). */
  [data-pagina="crm"] .crm-cartao { padding: .55rem .65rem; }
  /* `gap` não existe aqui: `.crm-cartao__corpo` é `display: block` (medido —
     a regra anterior de gap não fazia nada). Quem separa são as margens dos
     filhos, e são elas que encolhem. */
  [data-pagina="crm"] .crm-cartao__nome { line-height: 1.2; }
  [data-pagina="crm"] .crm-cartao__selos { margin-top: .15rem; }
  [data-pagina="crm"] .crm-cartao__valor { margin-top: .25rem; }
  [data-pagina="crm"] .crm-cartao__rodape { padding-block: .35rem; }
  [data-pagina="crm"] .crm-raia__cabo { padding: .45rem .6rem; }
}

/* Onde + o quê, numa linha só. Trava em UMA linha em qualquer largura: o
   subtítulo vai de "FBS CONSTRUCAO" a "proposta P-2026-0027 · rev. 1 ·
   entregue", e sem a trava o card voltaria a ter duas linhas exatamente nos
   negócios que já têm proposta — os que mais aparecem no board. */
[data-pagina="crm"] .crm-cartao__onde { white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }

/* --- 6. Rótulos da capa em MICRO, não ausentes ---
   Tirá-los devolveu 20px e custou reconhecimento: campo preenchido sem rótulo
   não diz o que é. Eles chegaram a ficar em 10px para o ganho de altura ser
   quase inteiro — e 10px é texto fora da escala do sistema, cujo piso é 12px
   e não tem exceção para "só um pouquinho menor". Voltaram para o degrau
   Label (12px); a entrelinha 1 e os 2px de respiro seguram a altura. */
[data-pagina="crm-deal"] .crm-capa-campos .crm-etiqueta {
  font-size: var(--bi-fs-micro); line-height: 1; letter-spacing: .04em;
  margin-bottom: 2px; }

/* --- 7. O resumo das condições, na capa, é UMA linha ---
   Cinco partes ("Pagamento 21/28/35 · Frete CIF · …") quebravam em três
   linhas e faziam sozinhas a segunda faixa da capa ter 73px. A frase inteira
   fica no `title`; o que a capa responde é se há algo combinado. */
/* A linha QUEBRA, não trunca. Ela cortava em "Frete destacado R$ 1…" com o
   valor só no `title` — inalcançável no toque, e o comercial que está na
   ligação não lê o frete que ele mesmo negociou. Número que a tela mostra tem
   que ser legível NA tela: esconder dinheiro atrás de hover contraria a regra
   de auditoria da casa, e as duas linhas que isso custa cabem. */
[data-pagina="crm-deal"] .crm-resumo__linha { display: block;
  white-space: normal; overflow: visible; }

/* ------------------------------------------------------------
   A TELA CABE NA JANELA (ambas as páginas do CRM).
   O shell dá a altura (`content--altura-cheia`: .main com height fixa e
   overflow hidden). Aqui só se diz QUEM rola: no funil, cada coluna do
   kanban; no negócio, o corpo. A página em si nunca rola — perder a barra
   de comando e o rodapé de decisão ao rolar era o custo de deixar rolar.
   ------------------------------------------------------------ */
[data-pagina="crm"] .crm-tela { flex: 1 1 auto; min-height: 0; }
[data-pagina="crm"] .crm-comando { flex: 0 0 auto; }

/* Só a partir de md o board é grade de colunas — abaixo disso as raias
   são um acordeão e quem rola é a tela inteira. */
@media (min-width: 768px) {
  [data-pagina="crm"] .crm-board { min-height: 0; align-items: stretch; }
  [data-pagina="crm"] .crm-raia { display: flex; flex-direction: column;
    min-height: 0; }
  [data-pagina="crm"] .crm-raia__corpo { display: flex; flex-direction: column;
    min-height: 0; flex: 1 1 auto; }
  [data-pagina="crm"] .crm-coluna { flex: 1 1 auto; min-height: 0;
    overflow-y: auto; }
  /* Card NÃO encolhe. Sem isto a coluna flex espreme os cards para caber na
     altura disponível e o `overflow-y: auto` nunca dispara: 13 cards ficavam
     nos mesmos 885px, cada um mais fino, e a rolagem simplesmente não existia. */
  [data-pagina="crm"] .crm-coluna > .crm-cartao { flex: 0 0 auto; }
  [data-pagina="crm"] .crm-tela { overflow: hidden; }
  /* O painel de follow-ups é a segunda coluna: rola sozinho também. */
  [data-pagina="crm"] .crm-tela > .crm-painel { min-height: 0; overflow-y: auto; }
}
@media (max-width: 767.98px) {
  [data-pagina="crm"] .crm-tela { overflow-y: auto; }
}

/* Negócio: capa e rodapé ficam parados; o corpo rola. */
[data-pagina="crm-deal"] .crm-capa,
[data-pagina="crm-deal"] .crm-rodape { flex: 0 0 auto; }
[data-pagina="crm-deal"] .crm-corpo { flex: 1 1 auto; min-height: 0;
  overflow-y: auto; }

/* Campo buscável (crm-combo.js): a lista flutua ancorada no campo. */
[data-pagina="crm"] .crm-combo,
[data-pagina="crm-deal"] .crm-combo { position: relative; display: block; }

/* Prévia do rascunho em voo: os números derivados esmaecem no instante da
   digitação e voltam quando o servidor responde — sem isto o total da conta
   ANTERIOR parecia ser o da digitação atual. */
[data-pagina="crm-deal"] .crm-previa-pendente [data-previa-total],
[data-pagina="crm-deal"] .crm-previa-pendente [data-previa-frete-total],
[data-pagina="crm-deal"] .crm-previa-pendente [data-previa-qtd],
[data-pagina="crm-deal"] .crm-previa-pendente [data-previa-tabela],
[data-pagina="crm-deal"] .crm-previa-pendente [data-previa-delta],
[data-pagina="crm-deal"] .crm-previa-pendente .crm-conversao__txt,
[data-pagina="crm-deal"] .crm-previa-pendente tfoot {
  opacity: .35;
  transition: opacity .15s ease;
}
/* A gangorra é conta do SERVIDOR: mexer na quantidade, no nº de volumes ou
   no conteúdo manda a linha inteira para lá e espera. Esmaecer o número
   velho diz "isto não vale mais"; o giro ao lado da conversão diz "estou
   contando" — sem ele, a espera se parecia com tela travada. Fica na
   legenda porque é ali que se lê o resultado da gangorra. */
[data-pagina="crm-deal"] .crm-previa-pendente [data-previa-conversao]::after {
  content: ''; display: inline-block; vertical-align: -1px;
  width: .7rem; height: .7rem; margin-left: .45rem;
  border: 2px solid var(--crm-acento); border-right-color: transparent;
  border-radius: 50%; animation: crm-girando .6s linear infinite; }
@keyframes crm-girando { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  [data-pagina="crm-deal"] .crm-previa-pendente [data-previa-conversao]::after {
    animation: none; border-right-color: var(--crm-borda); }
}

/* Montar a proposta é a própria tabela: a última linha procura o produto e os
   achados entram como linhas logo abaixo (lista flutuante era cortada pelo
   contêiner que rola). */
/* Recuo miúdo (21/08): a linha era um convite com peso de formulário. */
[data-pagina="crm-deal"] .crm-linha-nova > td { padding-block: .35rem; }
[data-pagina="crm-deal"] .crm-linha-achado { cursor: pointer; }
[data-pagina="crm-deal"] .crm-linha-achado > td { padding-left: 1.5rem; }
[data-pagina="crm-deal"] .crm-linha-achado:hover > td,
[data-pagina="crm-deal"] .crm-linha-achado:focus > td {
  background: var(--crm-acento-fraco, rgba(23, 26, 24, .05));
}

/* Unidade colada no número (KG ao lado do campo, não embaixo dele): abaixo
   do campo ela era lida como legenda de outra coisa. */
[data-pagina="crm-deal"] .crm-campo-un { display: inline-flex; align-items: center;
  gap: .4rem; justify-content: flex-end; }
[data-pagina="crm-deal"] .crm-campo-un > .form-control { width: 7.5rem; text-align: right; }

/* Lista de escolha com marca à direita (contatos do cliente no "Novo
   negócio"): o item continua sendo `.crm-lista__item`, mas com duas colunas —
   a ficha à esquerda, o sinal de escolhida à direita. Em bloco, a marca caía
   numa linha própria e parecia mais um dado da pessoa. */
[data-pagina="crm"] .crm-lista--escolha .crm-lista__item {
  display: flex; align-items: center; gap: .6rem;
}
[data-pagina="crm"] .crm-lista--escolha [aria-selected="true"] {
  background: var(--crm-acento-fraco, rgba(23, 26, 24, .05));
}

/* Esperando o servidor sem apagar a tela: o conteúdo que ainda é o ANTERIOR
   esmaece até a resposta chegar. É o mesmo vocabulário da prévia do rascunho
   no negócio — dizer "isto ainda não é a sua resposta" em vez de exibir dado
   velho com cara de novo. */
[data-pagina="crm"] .crm-aguardando,
[data-pagina="crm-deal"] .crm-aguardando {
  opacity: .45; transition: opacity .15s ease; pointer-events: none;
}

/* Documento da proposta: coluna direita do bloco do vendedor (representante),
   como no documento que o Ploomes emite. */
.prop-vend-dir{ text-align:right; }

/* Selo das normas na proposta de cordoalha — some junto com a condição 5
   quando a proposta não tem cordoalha. */
.prop-selo{ margin-top:2mm; }
.prop-selo img{ height:14mm; }

/* Negócio no celular: a página inteira rola, em vez da capa comer a tela.
   Com os termos do documento editáveis, a capa passou de 6 para 14 campos —
   empilhados em 390px ela ocupava 639px dos 844 e sobravam 26px para a
   proposta e o acompanhamento, que são o trabalho. Numa tela estreita a
   rolagem única é o gesto natural; a altura cheia continua valendo do tablet
   para cima, onde a capa é uma fita e não uma coluna. */
@media (max-width: 767.98px) {
  .main:has(> .content--altura-cheia):has([data-pagina="crm-deal"]) {
    height: auto; overflow: visible;
  }
  [data-pagina="crm-deal"] .crm-corpo { overflow-y: visible; }
  /* O rodapé de decisão para de flutuar e fecha a página: preso ao pé numa
     página que rola, ele cobriria os últimos itens da proposta. */
  [data-pagina="crm-deal"] .crm-rodape { position: static; }
}

/* Itens da proposta no celular: cartão, não tabela que rola de lado.
   Sete colunas em 337px espremiam o campo de preço a 41px — largo o
   bastante para mostrar "5,3" cortado e estreito demais para digitar. O
   padrão de rolar na horizontal serve para LER uma tabela; aqui se escreve,
   e escrever num campo que está meio fora da tela não é possível.
   Cada item vira um bloco com rótulo à esquerda e valor à direita. */
@media (max-width: 767.98px) {
  [data-pagina="crm-deal"] #dl-itens thead { display: none; }
  [data-pagina="crm-deal"] #dl-itens,
  [data-pagina="crm-deal"] #dl-itens tbody,
  [data-pagina="crm-deal"] #dl-itens tfoot,
  [data-pagina="crm-deal"] #dl-itens tr { display: block; width: 100%; }
  [data-pagina="crm-deal"] #dl-itens tbody tr {
    border: 1px solid var(--crm-borda); border-radius: 8px;
    padding: .6rem .75rem; margin-bottom: .6rem;
  }
  [data-pagina="crm-deal"] #dl-itens td {
    display: flex; align-items: center; justify-content: space-between;
    gap: .75rem; width: 100%; padding: .3rem 0; border: 0; text-align: right;
  }
  /* A primeira célula é o produto: nome inteiro, sem rótulo e sem alinhar
     à direita — é o título do cartão. */
  [data-pagina="crm-deal"] #dl-itens td:first-child {
    display: block; text-align: left; padding-bottom: .5rem;
  }
  [data-pagina="crm-deal"] #dl-itens td[data-rotulo]::before {
    content: attr(data-rotulo); color: var(--crm-tinta-2);
    font-size: var(--bi-fs-compact); text-transform: uppercase; letter-spacing: .06em;
    text-align: left; flex: 0 0 auto;
  }
  /* Célula vazia (a das ações quando não se edita) não vira linha em branco. */
  [data-pagina="crm-deal"] #dl-itens td:empty { display: none; }
  /* No cartão, o campo tem a largura toda que sobra do rótulo — menos a
     busca de produto, que é a linha inteira e não tem rótulo ao lado. */
  [data-pagina="crm-deal"] #dl-itens td[data-rotulo] .form-control { max-width: 10rem; }
  [data-pagina="crm-deal"] #dl-add-corpo td { display: block; padding: .2rem 0; }
  [data-pagina="crm-deal"] #dl-add-busca { max-width: none; width: 100%; }
  /* Achado de produto: linha inteira, texto à esquerda, alvo alto. */
  [data-pagina="crm-deal"] .crm-linha-achado > td {
    display: block; text-align: left; padding: .55rem .75rem; }
  [data-pagina="crm-deal"] .crm-campo-un > .form-control { width: 7rem; }
  /* "vender por embalagem" é uma AÇÃO, não um sufixo da quantidade: ao lado
     do campo ela aparecia cortada ("vender por em"). Vira linha própria. */
  [data-pagina="crm-deal"] #dl-itens td[data-rotulo="Quantidade"] { flex-wrap: wrap; }
  [data-pagina="crm-deal"] #dl-itens td[data-rotulo="Quantidade"] > .crm-btn-3 {
    flex: 1 0 100%; margin: .35rem 0 0 !important; justify-content: flex-end; }
  /* Coluna de embalagem (10/08, entre Preço e Total): sem rótulo (cabeçalho
     oculto — a coluna fica em branco na maioria das linhas) e sem um único
     "valor" para emparelhar com label nenhum — é uma pilha de até quatro
     blocos já rotulados por si (tipo, nº de volumes, conteúdo, ações). O
     `display:flex; justify-content:space-between` genérico da célula
     serve para PAR rótulo→valor; aqui não há par, e ele espalhava os blocos
     rente às bordas do cartão, cortando os do meio. Bloco puro empilha os
     filhos na ordem natural, sem flex nenhum. */
  /* As colunas de apoio deixam de ser escondidas: como cartão, elas cabem. */
  [data-pagina="crm-deal"] #dl-itens td.crm-col-md,
  [data-pagina="crm-deal"] #dl-itens td.crm-col-lg { display: flex; }
  /* Rodapé de totais: mesma leitura de rótulo e valor. */
  [data-pagina="crm-deal"] #dl-itens tfoot tr { display: flex;
    justify-content: space-between; padding: .2rem .75rem; }
  [data-pagina="crm-deal"] #dl-itens tfoot td:empty { display: none; }
}

/* O "X" de fechar painel e modal: 16×16 no sistema inteiro, abaixo dos 24px
   que a WCAG 2.5.8 pede para alvo de toque. A causa não era o Bootstrap —
   ele desenha o botão com `content-box` (16px de ícone + 8px de padding =
   32px de alvo); a regra global de `border-box` do projeto fez o padding
   comer o próprio tamanho. Devolver a caixa que o componente espera
   restaura os 32px SEM mexer no ícone nem no espaçamento visual. */
.btn-close {
  box-sizing: content-box;
  min-width: 1em;
  min-height: 1em;
}

/* ── BOARD DE COBRANÇA (/acompanhamento-inadimplencia) ───────────────────────
   Reescrita total (spec docs/superpowers/specs/2026-08-07-inadimplencia-frontend-fromzero-design.md):
   kanban horizontal, decisão do dono ("Vamos de kanban") sobre um benchmark
   que apontava fila agrupada — ver o `## Escopo` do spec para o registro.
   Fidelidade de estilo é QUASE PIXEL-PERFECT ao mockup normativo (mesma pasta,
   `2026-08-07-inadimplencia-fromzero-mockup.html`): larguras, gaps, paddings,
   radii, cores e tipografia em px vêm de lá, literais. Os tokens abstratos do
   mockup (--bg, --surface, --ink*, --line, --amber*, --red*) mapeiam 1:1 nos
   tokens FCDS já existentes (--bg, --surf, --ink*, --line, --warning*,
   --negative*) — só o
   acento "forte" do mockup (#334155, slate escuro) não tem equivalente FCDS
   limpo (o `--acc` do app é o azul do Bootstrap) e fica literal, numa custom
   property `--inad-acento` escopada à página — não um `--crm-*` novo. */

[data-pagina="acompanhamento_inadimplencia"]{
  --inad-acento:#334155;
  --inad-acento-tinta:#ffffff;
}

/* ── BUSCA NO TOPBAR ─────────────────────────────────────────────────────── */
/* Encolhe em vez de sumir: a permanência usa `w-25 d-none d-md-flex`, mas aqui o
   board vira pilha vertical no celular com 109 cartões numa coluna só, e busca
   inalcançável ali seria o mesmo defeito do board que não rolava. `flex:0 1` com
   piso de 9rem deixa o topbar estreito espremê-la até o mínimo utilizável. */
/* 26rem desde 09/08/2026: a contagem passou a dizer as duas unidades ("110
   clientes · 112 cobranças") e comeu a largura do campo, cortando o
   placeholder no meio da palavra outra vez. */
.inad-busca{flex:1 1 26rem;min-width:9rem;max-width:56rem;position:relative;
  flex-wrap:nowrap}
/* `flex-wrap:nowrap` NÃO é redundante: `.input-group` do Bootstrap quebra linha
   por padrão, e esta caixa carrega três filhos que não encolhem — o ícone e os
   dois addons somam 355px de texto `nowrap`. Um piso de largura no input (a
   primeira tentativa desta mudança) empurrava um addon para uma segunda linha
   abaixo de 1500px, medido a 1280 e a 1366: a caixa virava dois andares dentro
   de uma faixa de 3.25rem. Sem piso e sem quebra, o input fica com a sobra —
   que é o que a faixa tem para dar. */
/* A LISTA DE RESULTADOS (04/09/2026). A busca filtrava o board no lugar, e o
   board tem 3418px de largura para 1832px de viewport: o cartão encontrado
   podia nascer atrás da borda direita, com colunas vazias no caminho e nada
   rolando até ele. Agora o termo responde aqui, e escolher é o que move o
   board. `position:absolute` sobre o `.inad-busca` relativo — a topbar não
   pode crescer, senão o board (que é `altura-cheia`) encolhe a cada tecla. */
.inad-resultados{position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:1040;
  max-height:60vh;overflow-y:auto;background:var(--surf);
  border:1px solid var(--line);border-radius:6px;
  box-shadow:0 8px 24px rgba(0,0,0,.14)}
.inad-resultados__cliente{display:flex;justify-content:space-between;gap:.5rem;
  align-items:baseline;padding:.4rem .6rem .2rem;border-top:1px solid var(--line)}
.inad-resultados__cliente:first-child{border-top:0}
.inad-resultados__nome{font-weight:600;font-size:12px;color:var(--ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.inad-resultados__meta{font-size:11px;color:var(--ink-3);white-space:nowrap}
/* Uma grade de três colunas, não flex: a fase e o valor têm largura previsível
   e o fato fica com a sobra. Com flex, um nome de fase longo empurrava o valor
   para fora e as linhas deixavam de alinhar entre si. */
.inad-resultado{display:grid;grid-template-columns:minmax(7rem,auto) auto 1fr;
  gap:.5rem;align-items:baseline;padding:.25rem .6rem .25rem 1.1rem;
  font-size:12px;cursor:pointer}
.inad-resultado__fase{color:var(--ink-2);white-space:nowrap}
.inad-resultado__valor{color:var(--ink);font-weight:600;
  font-variant-numeric:tabular-nums;text-align:right;white-space:nowrap}
.inad-resultado__fato{color:var(--ink-3);overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
/* Teclado e mouse acendem o MESMO realce: duas aparências para "esta é a linha
   que Enter vai ativar" é como o operador aprende a desconfiar da tela. */
.inad-resultado:hover,.inad-resultado--realcado{background:var(--surf-2)}
.inad-resultados__teto{margin:0;padding:.3rem .6rem;font-size:11px;
  color:var(--ink-3);border-top:1px solid var(--line)}

/* ── ORDENAÇÃO E CONTAGEM, NO TOPBAR ─────────────────────────────────────── */
/* Ficavam numa faixa própria abaixo do cabeçalho. Dois controles não pagam uma
   faixa de 39px num board cuja métrica é quantos cartões cabem na tela. */
.inad-ordenar{flex:0 0 auto;margin:0}
/* `width:auto` num <select> mede a MAIOR opção: com os rótulos carregando campo
   e direção ("Previsão: mais distante") a caixa passou a pedir ~11rem. O teto
   existe para a faixa não roubar do título da página — a opção escolhida cabe,
   o excesso corta só nos rótulos mais longos. */
.inad-ordenar .form-select{font-size:0.8125rem;width:auto;min-width:8.5rem;max-width:13rem}
/* O seletor de representante é irmão da ordenação na mesma faixa flex: sem o
   `0 0 auto` ele encolhe até o gatilho cortar o próprio rótulo. */
.inad-representante{flex:0 0 auto}
/* Mesmo teto de 13rem da ordenação, pela mesma razão: "CBACOS REPRESENTACOES
   LTDA" escolhido empurrava o título da página. Reticencia em vez de empurrar. */
.inad-representante .colfilter-multi__trigger{max-width:13rem}
.inad-representante .colfilter-multi__trigger span{overflow:hidden;text-overflow:ellipsis}
/* Addon do próprio campo de busca: o número é o resultado da consulta, não um
   fato solto na faixa. Fundo transparente para ler como leitura, não como
   botão — a caixa já é do input-group. */
.inad-busca .inad-contagem{font-size:0.75rem;color:var(--ink-3);white-space:nowrap;
  background:transparent;border-left:0;padding-left:.25rem}

/* ── O BOARD ──────────────────────────────────────────────────────────────
   Mockup literal: coluna flex-basis 292px, gap 14px, raio 12px, cartão 9px,
   sombra rasa (`0 1px 2px rgba(15,23,42,.06)` — exceção sancionada à regra
   "zero sombra de repouso" do app: esta página já era a exceção CRM antes
   desta reescrita, e o dono pediu fidelidade quase pixel-perfect ao mockup).
   `overflow-x:auto` mora SÓ no board — a página nunca rola de lado (spec §4).
   A altura vem do shell (`content--altura-cheia`): `.page` já é uma coluna
   flex até o fim da janela, e o board herda o resto dela — é o que amarra a
   rolagem vertical de cada coluna à VIEWPORT sem um número mágico de px
   (spec §1), em vez do `max-height:840px` fixo do mockup. */
.inad-board{display:flex;gap:14px;overflow-x:auto;padding-bottom:14px;
  flex:1 1 auto;min-height:0}
/* `min-width:0` NÃO é decorativo: sem ele o `min-width:auto` do flex item
   trava a coluna no min-content, que aqui é a DESCRIÇÃO (`white-space:nowrap`)
   — a largura passava a ser ditada pelo comprimento da frase, não pela carga.
   Medido em 1536px antes do fix: 436/380/441/577/398/292/428px, e a mais larga
   era "Enviar", com ZERO cartões e a frase mais comprida; board de 3036px para
   1456 visíveis, mais da metade fora da tela rolando para mostrar vazio. O
   `text-overflow:ellipsis` da descrição nunca disparava porque o pai crescia.
   (Mesmo bug, mesmo fix, comentado na seção do CRM mais abaixo.)
   DOIS PATAMARES, `flex:0 0` nos dois: `flex:1 1 320px` com `min-width:0`
   recém-posto faz o único item encolhível absorver o déficit inteiro e a
   coluna vai a 20px em 1280. */
/* ── A FOLHA (rebrand 09/08/2026) ──────────────────────────────────────────
   A coluna era uma caixa cinza com cartões brancos flutuando dentro: caixa
   dentro de caixa, sombra em cada cartão, 8px de vão entre eles. É o grid de
   cartões idênticos que todo board de SaaS repete — e num board de 110 itens
   ele cobra ~19px por item só em borda, vão e sombra, sem dizer nada.
   Agora a coluna é uma FOLHA (superfície branca, hairline, um raio só) e cada
   cobrança é uma LINHA dessa folha, separada por fio. É a linguagem do extrato
   que o operador já lê no ERP ao lado — sem virar o grid cinza do ERP, porque
   a folha tem respiro, tipografia com hierarquia e cor racionada a significado.
   O canvas frio do shell (--surface-app) continua atrás; nada de creme. */
.inad-coluna{min-width:0;background:var(--surf);border:1px solid var(--line);
  border-radius:10px;padding:0;display:flex;flex-direction:column;min-height:0;
  overflow:hidden}
/* LARGURA FIXA, e a rolagem lateral do board abaixo de 1536 é aceita (decisão
   do dono, 09/08): sete fases não cabem numa tela de notebook sem espremer a
   linha a ponto de o nome do cliente quebrar em três. A coluna com carga
   mantém os 320px do desenho; a vazia encolhe de 180 para 140 — ela só precisa
   do nome da fase e do zero, e cada 40px devolvidos são 40px a menos de
   rolagem para chegar na fase que tem trabalho. */
/* SETE COLUNAS IGUAIS, dividindo a viewport (decisão do dono, 10/08/2026). Os
   dois patamares por carga (320px com cartão, 96px vazia) saíram: o funil é uma
   régua, e régua com passo variável faz o olho comparar tamanho de coluna em
   vez de comparar carga — o número e o subtotal já dizem quanto há em cada
   fase. `flex:1 1 0` (base ZERO, não `auto`) é o que reparte a largura em
   partes iguais independentemente do conteúdo; `min-width` segura o piso e
   devolve a rolagem horizontal em tela estreita, onde 7 colunas não cabem sem
   virar tira. `min-width:0` continua obrigatório contra o `min-content` do
   flex — sem ele a descrição no `title` volta a ditar largura. */
/* 250px DE PISO, todas iguais (decisão do dono, 12/08/2026). O `flex:1 1 0`
   anterior repartia a viewport por um número de colunas que ninguém escolheu —
   o funil cresceu de 7 para 9 (e vai a 11 com a prorrogação) e a conta nunca
   foi refeita: medido a 1536px, dava 168px por coluna, com o nome do cliente
   truncado e o "também em" cortado no meio da palavra. E já rolava 88px, curto
   demais para o olho perceber que havia mais coluna à direita.
   Base igual + crescimento igual = largura igual, então a régua do funil
   continua de passo constante (decisão de 10/08) enquanto o piso devolve a
   largura fixa e a rolagem franca (decisão de 09/08). */
.inad-coluna[data-carga]{flex:1 0 250px;min-width:250px}
/* Grade fixa em vez de flex-wrap: sem ela os cabeçalhos desalinham entre si
   conforme a coluna estreita (medidos 58/72/97/113px de altura), e o
   desalinhamento aparece sozinho no dia em que as colunas encherem. */
/* `flex:none` NÃO é redundante: a coluna é um flex container vertical e o
   cabeçalho é item dele — medido ao vivo, a coluna com 109 cartões ESPREMIA o
   próprio cabeçalho de 93px para os 86px do `min-height`, enquanto a coluna
   com 3 cartões ficava nos 93. Era o desalinhamento que a grade veio evitar,
   reintroduzido pela carga. */
/* Duas linhas, não três: a descrição da fase saiu do fluxo e virou `title` do
   próprio cabeçalho (ela custava 30px dos 93px e repetia a mesma narração nas
   sete colunas). `min-height` cai junto — a grade continua garantindo que os
   sete cabeçalhos tenham a MESMA altura, que é o que alinha o topo dos
   cartões entre colunas vizinhas. */
/* Cabeçalho da folha: gruda no topo enquanto a coluna rola (com 109 linhas, o
   operador perdia de vista em qual fase estava e quanto ela vale) e fecha com
   um fio, que é o que faz a folha ler como folha. */
/* 64px, não 56: o `min-height` existia para igualar os sete cabeçalhos, mas
   media o piso errado — a coluna COM carga tem subtotal e mede 64, a vazia não
   tem e parava nos 56 (medido a 1536px: 64/64/64/56/56/56/56). Oito pixels de
   desalinhamento entre folhas vizinhas no topo do funil, justamente onde o olho
   compara as fases. Com o piso na altura real, as sete réguas começam juntas. */
.inad-coluna__cabeca{display:grid;grid-template-columns:1fr auto;
  grid-template-areas:"t n" "s s";row-gap:2px;align-items:baseline;
  align-content:start;min-height:64px;padding:10px 12px;flex:none;
  position:sticky;top:0;z-index:1;background:var(--surf);
  border-bottom:1px solid var(--line)}
.inad-coluna__titulo{grid-area:t;font-size:13.5px;font-weight:700;margin:0}
/* O DINHEIRO ERA O ELEMENTO MAIS FRACO do cabeçalho: "107" vinha em 700 e
   "R$ 5.921.223,62" em 400/--ink-3. Invertido — o subtotal manda, a contagem
   vira sufixo. `tabular-nums` para as colunas alinharem verticalmente. */
.inad-coluna__contagem{grid-area:n;color:var(--ink-3);font-size:11.5px;font-weight:500;
  font-variant-numeric:tabular-nums}
/* O subtotal é a manchete da folha — 15px contra os 13,5 do nome da fase. Na
   linguagem de extrato quem responde "quanto tem aqui" vem primeiro; a fase
   é o rótulo da coluna, não o dado. */
.inad-coluna__subtotal{grid-area:s;margin-left:0;color:var(--ink);font-size:15px;
  font-weight:700;letter-spacing:-.01em;
  font-variant-numeric:tabular-nums lining-nums}
/* O toggle ▲/▼ de direção POR COLUNA saiu daqui (08/08): a ordenação virou uma
   escolha só, no seletor da faixa, com a direção escrita por extenso na opção.
   Sete botões de 24×24 dentro dos cabeçalhos diziam a mesma coisa que a faixa
   agora diz uma vez — e diziam por glifo. */
/* "Enviar" é a única fase que não pode esperar — âmbar no título e na
   contagem (spec §1), a mesma família de cor dos chips de alerta do cartão. */
.inad-coluna--urgente .inad-coluna__titulo{color:var(--warning-text)}
/* NUNCA SÓ POR COR (PRODUCT.md §Acessibilidade): a urgência de "Enviar" era
   apenas o tom âmbar do título — invisível para quem não distingue âmbar de
   cinza, que é justamente o eixo vermelho/âmbar/verde onde há daltônicos no
   time. A contagem vira pílula preenchida: forma e peso dizem o mesmo que a
   cor, e o número continua legível. */
.inad-coluna--urgente .inad-coluna__contagem{background:var(--warning-subtle);
  color:var(--warning-text);border-radius: var(--raio-chip);padding:0 .4rem;font-weight:700}
/* TRACEJADO = SEM CARTÃO, e não "coluna terminal": o tratamento era exclusivo
   das Encerradas, mas o que ele diz ("aqui não há o que fazer agora") vale
   para qualquer coluna vazia — generalizado, a terminal deixa de precisar de
   estilo próprio e volta a parecer as outras no dia em que tiver carga. */
.inad-coluna[data-carga="vazia"]{background:transparent;border:1px dashed var(--line-3)}
.inad-coluna[data-carga="vazia"] .inad-coluna__cabeca{background:transparent;border-bottom:0}
.inad-coluna[data-carga="vazia"] .inad-coluna__titulo{color:var(--ink-3);font-size:12.5px}
/* SOB RECORTE DE TERMO A COLUNA VAZIA SAI (09/09/2026). Ela não encolhe — todas
   valem `flex:1 0 250px` —, e é isso que tinha derrubado o filtro do board em
   04/09: buscando "cleverton" na carteira real os 3 casados nasciam em x=73,
   1393 e 2185 numa viewport de 1744, com 10 colunas vazias de 250px entre eles,
   e o terceiro ficava fora da tela. Sem as vazias sobram 3 colunas (750px) e os
   3 aparecem juntos. Só sob `termo`: sob `cliente` a coluna vazia carrega a
   frase "Nenhuma cobrança deste cliente nesta fase", que é a resposta à
   pergunta que o operador fez — e sem recorte a régua do funil fica inteira,
   de passo constante (decisão de 10/08). O `data-recorte` é escrito pelo JS em
   `renderizarBoard`. */
.inad-board[data-recorte="termo"] .inad-coluna[data-carga="vazia"]{display:none}
/* `padding:4px` (10/08/2026): com o contorno de volta em cada cartão, sem este
   respiro a borda do cartão encostava na borda da coluna e as duas viravam um
   fio grosso só. */
.inad-coluna__cartoes{display:flex;flex-direction:column;overflow-y:auto;min-height:0;padding:4px}
/* Só sobra a frase da BUSCA ("Nenhum cliente encontrado.") — o "Nenhum cliente
   nesta fase." saiu: a tela parava para narrar um vazio que o `0` do
   cabeçalho já anuncia. */
.inad-coluna__vazia{padding:.75rem .5rem;text-align:center;color:var(--ink-3);font-size:0.75rem}

/* ── O CARTÃO ─────────────────────────────────────────────────────────────── */
/* RITMO: dois valores só — 4px dentro do grupo, 10px entre grupos. Antes eram
   5/2/6/6/9px, uma escadinha sem intenção. */
/* A LINHA DA FOLHA (rebrand 09/08/2026): sem borda própria, sem raio, sem
   sombra e sem vão — o que separa uma cobrança da seguinte é um fio, como num
   extrato. Só o que sobrou de "cartão" foi o nome da classe (o JS e os testes
   dependem dele; renomear seria diff de centenas de linhas sem ganho).
   Devolveu ~19px por item (borda 2px + vão 8px + sombra + raio) num board de
   110: é altura que vira linha visível em vez de moldura. */
/* CONTORNO FECHADO EM CADA CARTÃO (ordem do dono, 10/08/2026). O fio único
   entre linhas — a "folha de extrato" descrita acima — separava um cartão do
   seguinte mas não dizia onde ele COMEÇA e onde ACABA: numa coluna de 96
   linhas o olho perdia o par nome+valor. Volta a borda inteira, no tom mais
   escuro da família (`--line-3`), com 4px de vão para que o contorno de um
   não encoste no do outro. Custo medido e aceito: ~5px por cartão. */
.inad-card{background:var(--surf);border:1px solid var(--line-3);border-radius:0;
  padding:9px 12px;box-shadow:none;text-align:left;width:100%;
  line-height:1.45;display:flex;flex-direction:column;gap:4px;
  transition:background .12s,border-color .12s}

/* Modal "Registrar cobrança": a linha indisponível pela regra do escopo
   homogêneo (descontado e negociável não dividem cobrança — ADR-0007, emenda de
   17/08/2026). A caixa `disabled` sozinha não se distinguia da disponível num
   relance, medido ao vivo no cartão da CONSTRUCITY: seis linhas, quatro
   descontadas, e o olho não achava quais tinham saído de jogo. Escopo de
   página, nenhum token tocado. */
.cobranca-criar-linha--fora{opacity:.42}
.cobranca-criar-linha--fora td{text-decoration:line-through;
  text-decoration-color:var(--line-3)}
.inad-card + .inad-card{margin-top:4px}
/* Clicável: a linha inteira abre a cobrança, então precisa dizer isso ao
   passar o mouse — sem a moldura do cartão, o hover é o que resta de
   afordância. `--surf-2` é o mesmo tom das superfícies secundárias do app. */
.inad-card:hover{background:var(--surf-2);cursor:pointer}
.inad-card:focus-visible{outline:2px solid var(--acc);outline-offset:-2px}
/* `line-height:1.45` acima é literal do `body{font:14px/1.45 ...}` do mockup —
   sem ela o cartão herda o 1.5 do reset do Bootstrap, e cada elemento sem
   line-height próprio (valor/meta/situação) fica ~0.6px mais alto; num board
   de 5+ cartões empilhados isso se acumula em desvio visível de várias
   dezenas de px no pixel-diff (task 5, verificado por medição). */
/* LINHA 1: nome à esquerda, dinheiro à direita — e o dinheiro LIDERA. Antes o
   valor era 14px/700 contra um nome 13px/600 em caixa alta ocupando duas
   linhas: razão 1,077, isto é, empate. O nome desce a 12px/500/--ink-2 e o
   valor sobe a 18px/700; o nome ganha clamp de 2 linhas (o de 3+ linhas
   empurrava o cartão inteiro), com o nome completo no `title`. */
/* `align-items:start`, não `baseline`: medido ao vivo, 92 dos 112 cartões têm
   nome de duas linhas, e alinhar o valor de 18px pela PRIMEIRA linha de base
   do nome empurrava a caixa 6px para baixo em cada um deles (38px de linha 1
   contra os 32px do nome). Com `start` o dinheiro encosta no topo — que é
   onde o olho o procura — e a linha volta a medir o que o nome mede. */
/* NOME EM CIMA, VALOR EMBAIXO (10/08/2026, quando as sete colunas passaram a
   dividir a viewport em partes iguais). Lado a lado, o valor levava 119px fixos
   dos ~196 de uma coluna a 1536px e o nome sobrava com 60px: "CONSTRUCITY OLEO
   E GAS ENGENHARIA" virava "CONSTR OLEO …" em duas linhas de seis letras. Um
   layout só, não dois: empilhado, o nome tem a linha inteira e o valor continua
   alinhado verticalmente entre os cartões, que é o que o olho usa para
   comparar. */
.inad-card__topo{display:flex;flex-direction:column;align-items:stretch;gap:2px}
.inad-card__cliente{font-weight:500;font-size:12px;line-height:1.3;color:var(--ink-2);
  min-width:0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden}
/* O código do homônimo anda colado ao nome porque é parte do identificador,
   não um dado à parte. Só nasce quando o serviço marca `nome_ambiguo`. */
.inad-card__codigo{font-size:11px;color:var(--ink-3);font-variant-numeric:tabular-nums;
  margin-left:.3rem}
.inad-card__empresa{display:inline-block;margin-left:6px;font-size:10px;font-weight:600;
  color:var(--ink-3);border:1px solid var(--line);border-radius:4px;padding:0 5px;
  vertical-align:1px}
/* "também em Em negociação": um cliente com cobrança aberta E título solto
   rende dois cartões, e sem esta linha o segundo lê como duplicata. */
/* `nowrap` sem `overflow` cortava no meio da palavra: medido em 12/08/2026 o
   cartão do CLEVERTON exibia "também em Com assessoria/S". A linha é uma frase
   curta que pode não caber na coluna de 250px — reticencia, não decepa.
   `min-width:0` é obrigatório: o pai é flex e sem ele o `min-content` do texto
   impede o encolhimento e o `text-overflow` nunca dispara. */
.inad-card__tambem{font-size:11px;color:var(--ink-3);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis;min-width:0}
.inad-card__valor{flex:none;font-weight:700;font-size:18px;line-height:1.2;
  font-variant-numeric:tabular-nums lining-nums;text-align:right}
/* O TOTAL VENCIDO DO CLIENTE, embaixo do valor do cartão e em segundo plano: o
   número grande continua sendo o do recorte que o cartão representa, e este é a
   referência que o operador confere contra o Sênior (12/08/2026). Bloco próprio
   para não competir com o de cima na mesma linha de 250px. */
.inad-card__valor-total{display:block;font-weight:500;font-size:11px;
  color:var(--ink-3);line-height:1.2}
/* LINHA 2: o fato DAQUELA fase. O atraso/dia em --ink-2 e o resto em --ink-3
   não cabem numa classe só (é uma frase montada), então a linha inteira fica
   em --ink-2 e o que está vencido/liberado vira `--alerta` — antes "vencido há
   201 dias" tinha exatamente o mesmo peso de "últ. contato 09/07". */
.inad-card__fato{color:var(--ink-2);font-size:12px;line-height:1.35}
.inad-card__fato--alerta{color:var(--negative-text);font-weight:600}
/* A IDADE DA DÍVIDA VIRA COR (08/08). Era a única variável que muda de cartão
   para cartão na primeira coluna — 1 dia e 576 dias saíam no mesmo cinza de
   12px, e o olho não tinha como triar 206 cartões sem ler número por número.
   Duas cores, não oito: até 90 dias é rotina e fica em cinza; 91–360 é atenção;
   361+ é o dinheiro que provavelmente já não volta. A cor NUNCA é o único
   sinal — o número de dias e a faixa canônica no `title` dizem o mesmo. */
.inad-card__fato--atencao{color:var(--warning-text)}
.inad-card__fato--critico{color:var(--negative-text);font-weight:600}
/* UMA FAIXA, DUAS LEITURAS: o fato da fase à esquerda, a situação à direita.
   Eram duas linhas empilhadas, e a de baixo dizia "Sem contato" em 204 dos 209
   cartões — 19px por linha gastos num rótulo que quase nunca varia. Lado a
   lado, a linha some quando não há chip, e a pílula segue visível para o caso
   em que ela de fato diz algo (promessa quebrada, jurídico liberado).
   `wrap` porque em coluna estreita a pílula desce sozinha em vez de espremer
   o fato. */
.inad-card__linha{display:flex;align-items:baseline;justify-content:space-between;
  gap:.4rem;flex-wrap:wrap;min-width:0}
.inad-card__linha .inad-card__fato{min-width:0;flex:1 1 auto}
/* `flex:0 1 auto` + `min-width:0` (10/08/2026): com `0 0 auto` o bloco não
   encolhia nem quebrava, e a oitava coluna (Encontro de contas) estreitou a
   régua de 196 para 170px — "Aguardando · 1 de 2 promessas" passou a vazar 21px
   para fora do cartão, cortando "promessas" no meio da palavra (medido).
   Podendo encolher, o placar desce para a própria linha em vez de sangrar. */
.inad-card__situacao{display:flex;align-items:baseline;gap:.3rem;flex-wrap:wrap;
  flex:0 1 auto;min-width:0;justify-content:flex-end}
.inad-card__pilula{flex:none;padding:.05rem .4rem;border-radius: var(--raio-chip);font-size:10.5px;
  line-height:15.8px;font-weight:600;white-space:nowrap;background:var(--surf-2);color:var(--ink-2)}
/* `line-height:15.8px` acima: a pílula não existe no mockup (que só tem
   `.sit` em texto corrido, 12px) — spec §1 pede a pílula mesmo assim. Sem a
   declaração ela herda 1.45 do `.inad-card`, ficando ~0.6px mais baixa que a
   linha `.sit` do mockup por cartão; medido no pixel-diff (task 5), esse era
   o ÚNICO elemento do cartão ainda fora do alinhamento depois dos ajustes
   acima — 0,6px por cartão acumula visivelmente ao longo da coluna. */
.inad-card__pilula--neutro{background:var(--surf-2);color:var(--ink-2)}
.inad-card__pilula--quebrada{background:var(--negative-subtle);color:var(--negative-text)}
.inad-card__pilula--novo{background:var(--warning-subtle);color:var(--warning-text)}
.inad-card__pilula--aguardando{background:var(--info-subtle);color:var(--info-text)}
/* Os chips ficam na MESMA linha da pílula (linha 3), não numa quarta linha
   própria — o `margin-top:6px` que os empurrava saiu junto do `.inad-card__
   acao`. O `<span>` que fingia ser botão (`.inad-card__botao`) foi REMOVIDO:
   era um falso alvo repetido em cada um dos 110 cartões dentro de um cartão
   que já é inteiro clicável, e custava 35px de altura por cartão. O verbo que
   ele mostrava vive agora no `aria-label` do cartão. */
.inad-chip{display:inline-block;font-size:11px;font-weight:600;border-radius:5px;
  padding:1px 7px}
.inad-chip--amber{background:var(--warning-subtle);color:var(--warning-text)}
.inad-chip--red{background:var(--negative-subtle);color:var(--negative-text)}
/* NEUTRO: o chip que INFORMA em vez de alertar (comprovante tem/falta,
   12/08/2026). O comprovante é opcional — pintar "sem comprovante" de âmbar
   poria um aviso de atenção em quase todo cartão do board. */
.inad-chip--slate{background:var(--surf-3);color:var(--ink-2)}
/* O QUE O CLIENTE DISSE, em área própria. Era uma linha de 11px em `--ink-3`
   com reticências — a frase mais importante da conversa tratada como rodapé,
   e ilegível justamente na coluna onde a conversa está viva (ordem do dono,
   08/08). Agora é um bloco citado: fundo `--surf-2`, tinta `--ink-2`, duas
   linhas antes de cortar. Só nasce quando há observação, então o cartão só
   paga a altura quando há o que ler. Vem INTEIRA do serviço — quem corta é o
   `line-clamp` e o texto todo fica no `title`; não há limite que o JS conheça. */
/* O corte mora no FILHO, não na caixa: `overflow:hidden` recorta na caixa de
   PADDING, então uma terceira linha vazava para dentro do respiro de baixo,
   meio cortada, visível (medido em observação real de 211 caracteres). Com o
   `-webkit-box` no span, o corte acontece antes do padding começar. */
/* A FALA DO CLIENTE TEM COR PRÓPRIA — e é a do `info`, não a do alerta: o que
   ele disse não é bom nem ruim, é a evidência mais fresca que a cobrança tem.
   O bloco era cinza sobre cinza (--surf-2 no cartão branco) e sumia dentro da
   miudeza. Texto em `--info-text` (tom mais escuro da MESMA matiz do fundo, não
   cinza sobre colorido, que lava).
   AS ASPAS SAÍRAM: o glifo decorativo custava 13px de recuo em toda linha da
   citação para dizer o que a assinatura agora diz com dado — quem falou e
   quando. Ornamento fora, atribuição dentro. */
.inad-card__obs{min-width:0;font-size:12px;line-height:1.4;color:var(--info-text);
  background:var(--info-subtle);border:1px solid color-mix(in srgb, var(--info) 22%, var(--surf));
  border-radius:6px;padding:5px 7px}
.inad-card__obs-texto{display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;overflow:hidden}
/* A assinatura é metadado da citação, não a citação: fica um degrau abaixo em
   TAMANHO — e só nele. Clarear a cor (medido: `--info-text` a 82% do fundo caía
   para 3,39:1) reprovaria em AA num texto de 10,5px; a hierarquia sai de graça
   pelo tamanho, sem pagar em legibilidade. */
.inad-card__obs-fonte{display:block;margin-top:2px;font-size:10.5px;line-height:1.3;
  font-variant-numeric:tabular-nums}

/* O ATALHO PARA O HISTÓRICO (31/08/2026), no lugar da citação emprestada.
   Discreto de propósito: é uma porta, não um aviso — quem tem citação própria
   não o recebe, e nos que recebem ele ocupa a linha que a citação desocupou.
   Sem fundo nem borda para não competir com a caixa da citação dos cartões
   vizinhos na mesma coluna; a afordância vem do sublinhado ao passar o mouse.
   `text-align:left` porque `button` centraliza por padrão e o cartão inteiro é
   alinhado à esquerda. */
.inad-card__historico{align-self:flex-start;padding:0;border:0;background:none;
  font-size:11px;line-height:1.35;color:var(--ink-3);text-align:left;
  font-variant-numeric:tabular-nums;cursor:pointer}
.inad-card__historico:hover,.inad-card__historico:focus-visible{
  color:var(--ink);text-decoration:underline}

/* ── GRADE DE ENCAMINHAMENTOS (14/08/2026) ────────────────────────────────── */
/* Para onde a dívida já foi e quando — Serasa, Consulth, protesto, jurídico.
   `<dl>` e não tabela: são pares termo/valor, não uma matriz — e a semântica de
   lista de definição é o que faz o leitor de tela anunciar "Enviada para
   Serasa: 12/08" como um par, em vez de duas células soltas.
   MUDO POR PADRÃO, como o resto dos metadados do cartão: a grade é referência
   de consulta, não alerta — quem precisa de atenção já tem a pílula e o fato.
   `tabular-nums` alinha as datas em coluna sem precisar de grid: em fonte
   proporcional, `12/08` e `01/11` não fecham à direita e a coluna serrilha. */
.inad-card__encaminhamentos{margin:0;font-size:11px;line-height:1.35;
  color:var(--ink-2);border-top:1px dashed var(--line);padding-top:5px}
.inad-card__encaminhamento{display:flex;align-items:baseline;gap:6px;
  justify-content:space-between}
.inad-card__encaminhamento + .inad-card__encaminhamento{margin-top:2px}
/* O NOME DO DESTINO NÃO PODE SER CORTADO — é o dado que a grade existe para
   dar. A primeira versão punha `text-overflow:ellipsis` no termo para proteger
   a data, e na largura real da coluna do board isso virou "Enviada para
   Prote…" (medido em 14/08/2026, cartão da LMD): o operador ficava sem saber se
   foi protesto ou outra coisa, que é a pergunta inteira.
   Agora o termo QUEBRA e a data (largura fixa, `flex:none`) continua onde
   está — duas linhas ocasionais custam menos que uma palavra escondida. */
.inad-card__encaminhamento dt{min-width:0;font-weight:500}
.inad-card__encaminhamento dd{margin:0;flex:none;font-variant-numeric:tabular-nums}
/* "há quanto tempo" é o segundo grau da mesma informação que a data já dá —
   fica um degrau abaixo, entre parênteses, sem virar uma terceira coluna. */
.inad-card__encaminhamento-dias{margin-left:4px;color:var(--ink-3)}
.inad-card__encaminhamento-dias::before{content:"("}
.inad-card__encaminhamento-dias::after{content:")"}

/* ── RESPONSIVO (spec §4) ─────────────────────────────────────────────────── */
/* ≤760px: o board deixa de ser kanban e vira pilha vertical de seções por
   fase, na mesma ordem do fluxo — único formato viável em tela estreita (o
   dono aceitou o custo de scroll horizontal no notebook, não no celular). O
   shell já devolve `.main`/`.content--altura-cheia` para fluxo normal nesta
   largura; aqui só o board precisa parar de ser flex-row com altura amarrada. */
@media (max-width:760px){
  .inad-board{flex-direction:column;overflow-x:visible;flex:0 0 auto}
  /* `[data-carga]` (0,2,0), não `.inad-coluna` (0,1,0): media query NÃO soma
     especificidade, então a regra de classe pura PERDIA dos dois patamares
     `.inad-coluna:not([data-carga="vazia"])`/`[data-carga="vazia"]` lá de cima
     e o `flex-basis` virava ALTURA na pilha vertical — coluna de 320px para
     13.689px de conteúdo, com o resto dos cartões inalcançável. Empatando em
     0,2,0 esta ganha por ordem de fonte. O JS emite `data-carga` em toda
     coluna, então o seletor casa sempre. */
  .inad-coluna[data-carga]{flex:0 0 auto}
  .inad-coluna__cartoes{overflow-y:visible}
}

/* ALVOS DE TOQUE DO PAINEL (10/08/2026). Medidos a 390px com toque: 12 dos 13
   controles tinham menos de 44px de altura — o "Ligar agora" (a ação mais
   provável de quem abre isto no celular) vinha com 31px, e o × do canto com
   30. A regra vale só dentro do painel e só na largura onde o dedo é o
   ponteiro; no desktop os tamanhos do app continuam.
   Links de e-mail na ficha ficam como estão: são links dentro de uma frase,
   que a própria WCAG 2.5.8 dispensa do alvo mínimo — engordá-los quebraria a
   linha "victor@… , nfe@…" em duas. */
@media (max-width:760px){
  .inad-painel .form-control,
  .inad-painel .form-select,
  .inad-painel .btn{min-height:44px}
  /* 46, não 44: o `padding` do cabeçalho comia 3px do alvo medido. */
  .inad-painel .btn-close{width:46px;height:46px;flex:none}
  /* Botão principal na largura do polegar, e o link destrutivo com área de
     toque sem virar botão. */
  .inad-painel .btn-link{display:inline-flex;align-items:center;justify-content:center;
    min-height:44px;min-width:44px}
  /* Os e-mails da ficha param de ser dois links colados numa linha de 15px:
     viram uma linha cada, com área de toque. No desktop continuam separados
     por vírgula, que é como se lê um par de endereços. */
  .inad-painel .inad-ficha a[href^="mailto:"]{display:block;min-height:44px;
    display:flex;align-items:center}
  /* A CALCULADORA DESGRUDA NO CELULAR. Grudada ela comia ~200 dos 844px da
     tela — um quarto permanente. No desktop ela continua colada ao topo: lá
     sobra altura e o operador precisa dos totais à vista enquanto rola a lista
     de títulos. */
  .inad-calculadora{position:static;box-shadow:none;
    border-bottom:1px solid var(--line)}
  /* O LUGAR LIBERADO VAI PARA A AÇÃO. "Registrar contato" era o que rolava
     para fora da tela enquanto a calculadora ficava presa — prioridade
     invertida para o polegar.
     `fixed`, não `sticky`: sticky só gruda dentro do PAI, e o pai aqui é uma
     `.col-12` de 44px — o botão saía de cena junto com ela (medido: topo em
     -182px depois de rolar). Fixo no rodapé da janela é o padrão de ação
     primária em celular, e a grade ganha o respiro para o conteúdo não
     terminar debaixo dele. */
  .inad-painel #btn-salvar-contato{position:fixed;left:0;right:0;bottom:0;width:auto;
    border-radius:0;z-index:3;box-shadow:0 -.5rem .9rem -.5rem rgba(20,26,32,.35)}
  .inad-painel-grade{padding-bottom:3.5rem}
  /* A coluna grudada é ganho no desktop (a tabela rola pouco e "Últ. pgto."
     seria o que sumia); a 390px ela come 80 dos 358 disponíveis e passa a
     cobrir "Vencimento" — a tabela inteira rola de lado ali de qualquer jeito. */
  .inad-painel .cobranca-tabela th:last-child,
  .inad-painel .cobranca-tabela td:last-child{position:static;box-shadow:none}
}

/* ── PAINEL DE COBRANÇA (tela 2, spec §2) ────────────────────────────────── */
/* `height` E `max-height` em 100%: o `.modal-dialog-scrollable` do Bootstrap
   calcula `calc(100% - 1rem)` contando com a margem que aqui foi zerada. */
.inad-painel .modal-dialog{margin:0 0 0 auto;max-width:min(85rem,100%);
  height:100%;max-height:100%}
.inad-painel .modal-content{height:100%;max-height:100%;border:0;border-radius:0;
  background:var(--surf);border-left:1px solid var(--line)}
/* FOLHA LATERAL OU TELA CHEIA — NUNCA UMA FRESTA. O teto de 85rem combinado
   com `100%` produzia uma faixa de board acidental: 176px de contexto a 1536,
   mas SEIS PIXELS a 1366 e zero a 1280 (medido). Seis pixels não são contexto,
   são um artefato — a folha parece mal encaixada em vez de sobreposta. Abaixo
   de 1536 ela assume a tela inteira (e devolve a largura à tabela de parcelas,
   que a 1366 já estava com folga zero); de 1536 para cima continua folha, com
   board suficiente atrás para dizer de onde ela saiu. */
@media (max-width:1535.98px){.inad-painel .modal-dialog{max-width:100%}}
.inad-painel .modal-body{display:flex;flex-direction:column;overflow:hidden;padding-bottom:0}
.inad-painel .modal-body > .alert{flex:0 0 auto}

/* O STEPPER: as seis fases da cobrança em linha, o ponto atual destacado, as
   anteriores preenchidas — e o placar de promessas encostado à direita. Vazio
   até a Task 3/4 montar (`cobranca.fase`/`cobranca.placar`). */
/* ── O RITMO DO PAINEL (10/08/2026) ───────────────────────────────────────
   Os vãos verticais do painel eram .2 / .25 / .3 / .7 / .75 / .85 / .9 / 1rem
   — oito valores, sete deles entre 11 e 16px. Todo intervalo media quase o
   mesmo, então NADA agrupava: ficha, tarja, notas e títulos chegavam ao olho
   como um bloco cinza só. Agora há três degraus e cada um significa uma coisa:
     4px  — dentro de um par (rótulo/valor, nota e sua lista)
     16px — entre blocos do mesmo assunto
     24px — entre SEÇÕES (quem é o cliente | o que se cobra | quanto dá hoje)
   Os números não mudam de tamanho; muda o que o espaço diz. */
.inad-stepper{display:flex;align-items:center;gap:.35rem;flex-wrap:wrap;margin:0 0 1rem;
  font-size:0.75rem;color:var(--ink-3)}
.inad-stepper__etapa{display:flex;align-items:center;gap:.3rem}
.inad-stepper__ponto{width:.5rem;height:.5rem;border-radius:50%;background:var(--line-3)}
.inad-stepper__etapa--feita .inad-stepper__ponto{background:var(--ink-3)}
.inad-stepper__etapa--atual{color:var(--ink);font-weight:600}
.inad-stepper__etapa--atual .inad-stepper__ponto{background:var(--acc)}
.inad-stepper__seta{color:var(--line-3)}
.inad-stepper__placar{margin-left:auto;font-weight:600;color:var(--ink-2)}
/* "· fase N de 6": só existe para o colapso móvel (spec §4) — no desktop as
   seis etapas já dizem a posição pela ordem visual, então o texto fica
   redundante e escondido até a media query de 760px virar o único lugar
   onde ele é a ÚNICA pista de posição (a etapa atual é a única visível). */
.inad-stepper__pos{display:none;color:var(--ink-3);font-size:0.7rem;margin-left:.3rem;font-weight:400}
@media (max-width:760px){
  .inad-stepper__etapa:not(.inad-stepper__etapa--atual){display:none}
  .inad-stepper__seta{display:none}
  .inad-stepper__pos{display:inline}
}

/* A FICHA: código/telefone/contato/e-mail/vencido total, na coluna de dados
   do painel — lista rótulo/valor compacta, sem tabela (só 5 linhas). */
/* 24px abaixo dela: a ficha FECHA a seção "quem é o cliente". Era .85rem, a
   mesma distância que separava a tarja do escopo da lista de títulos — dois
   assuntos diferentes com o mesmo vão. */
/* GRADE, não pilha (10/08/2026): medido a 1760px, as cinco linhas usavam 482
   dos 923px da coluna — 441px de vazio à direita, e 150px de altura para dizer
   cinco coisas curtas. Em duas colunas o mesmo conteúdo cabe em menos da
   metade da altura e o vazio some. `auto-fit` com piso de 22rem devolve UMA
   coluna sozinho quando o painel empilha no celular — sem media query. */
/* `max-content` + `space-between`, não `1fr`: com colunas iguais a segunda
   ficava com meia largura vazia à direita (255px medidos). Medindo pelo
   conteúdo, cada par rótulo/valor ocupa só o que precisa, e o espaço que
   sobra vira o vão ENTRE as duas colunas — que é o que faz a faixa parecer
   ocupada em vez de abandonada. */
.inad-ficha{margin:0 0 1.5rem;display:grid;
  grid-template-columns:repeat(auto-fit, minmax(18rem, max-content));
  justify-content:space-between;
  gap:.25rem 2rem;font-size:0.8125rem}
/* Contato e e-mail são os únicos textos longos da ficha: em meia coluna o
   endereço quebraria no meio. Ocupam a faixa inteira. */
.inad-ficha__linha--largo,.inad-ficha__promessa{grid-column:1/-1}
.inad-ficha__linha{display:flex;gap:.5rem;align-items:baseline;min-width:0}
.inad-ficha__valor{min-width:0}
.inad-ficha__rotulo{color:var(--ink-3);flex:0 0 6.5rem}
.inad-ficha__valor{color:var(--ink-2);font-variant-numeric:tabular-nums lining-nums}
.inad-ficha__promessa{margin-top:.2rem;font-size:0.75rem;color:var(--ink-3)}

/* AS DUAS COLUNAS: dados à esquerda com scroll próprio (a calculadora sticky
   continua funcionando DENTRO dela), ação à direita sempre visível — o
   operador registra sem rolar por cima das NFs. `order` (não posição no DOM)
   é o que faz a AÇÃO vir antes dos DADOS em tela estreita (spec §4). */
.inad-painel-grade{display:flex;gap:1.25rem;flex:1 1 auto;min-height:0}
.inad-painel-coluna{min-height:0;overflow-y:auto}
/* `.row` do Bootstrap tem margem NEGATIVA lateral (metade da calha) e conta
   com o pai ter o padding correspondente. A coluna do painel não tem, então o
   formulário da ligação vazava 8px para fora dela em toda resolução (medido:
   form 363px, conteúdo 371px) — 8px que empurravam a barra de rolagem
   horizontal dentro do modal. Zerar a calha na origem é o que faz o form caber
   sem mexer no espaçamento entre os campos, que vem do `g-*` de cada linha. */
.inad-painel-coluna .row{--bs-gutter-x:0}
.inad-painel-coluna--dados{flex:1 1 0;order:1}
/* `col-md-6` DECIDE PELA VIEWPORT, não pelo pai — e o pai aqui tem 24rem
   fixos. Numa janela de 1760px o Bootstrap achava que "md" cabia e punha
   Canal e Previsão lado a lado com 182px cada, colados, enquanto "Próximo
   contato" ficava com 182px de vazio ao lado (medido). Um container query
   devolve a decisão a quem tem a informação: os campos ocupam a faixa inteira
   e só voltam a dividir quando a COLUNA de fato tiver largura — que é o caso
   quando o painel empilha e ela vira a tela toda. */
.inad-painel-coluna--acao{flex:0 0 24rem;order:2;border-left:1px solid var(--line);
  padding-left:1.25rem;container-type:inline-size}
.inad-painel-coluna--acao .row > [class*="col-"]{flex:0 0 100%;max-width:100%}
@container (min-width:34rem){
  .inad-painel-coluna--acao .row > .col-md-6{flex:0 0 50%;max-width:50%}
}
@media (max-width:1100px){
  .inad-painel-grade{flex-direction:column;overflow-y:auto}
  /* `flex:0 0 auto` NÃO é enfeite: empilhadas, as bases do desktop viram
     ALTURA — `flex:0 0 24rem` da coluna de ação virava 384px de altura para um
     formulário de 548, e os 164px que sobravam eram desenhados POR CIMA da
     ficha do cliente (medido a 390px: ação 184→568, ficha começando em 604,
     sobreposição de 604 a 794). Cada coluna passa a ter a altura do seu
     conteúdo; quem rola é a grade. */
  .inad-painel-coluna{overflow:visible;flex:0 0 auto}
  .inad-painel-coluna--dados{order:2}
  .inad-painel-coluna--acao{order:1;border-left:0;padding-left:0;margin-bottom:1rem}
}
.inad-painel-grade form{max-width:100%}

/* A CALCULADORA MUDOU DE PONTA (10/08/2026, decisão do dono): saiu do rodapé
   da coluna e foi para logo abaixo da ficha do cliente, acima da lista de
   cobranças. Ela é a ENTRADA da conversa — a data de "Calcular para" é a data
   que o operador promete —, então pertence ao começo. Continua colada, agora
   ao topo: o ganho da versão de baixo era ter os totais à vista enquanto se
   rola a lista de notas, e isso se preserva. A sombra inverte de direção junto
   com o lado que ela guarda. */
.inad-calculadora{position:sticky;top:0;z-index:2;background:var(--surf);
  border-bottom:1px solid var(--line);box-shadow:0 .5rem .7rem -.4rem rgba(20,26,32,.14)}

/* MOVIMENTO DE FASE na linha do tempo (10/08/2026). O que o SISTEMA fez
   sozinho (promessa vencida, saldo zerado) ganha fundo próprio: numa lista em
   que todo o resto foi alguém que ligou, "automático" escrito em cinza passa
   batido. Fundo, não faixa colorida na borda — barra lateral é enfeite banido
   no design system do app. */
.inad-movimento--auto{background:var(--surf-2);
  margin-left:-.35rem;margin-right:-.35rem;padding-left:.35rem;padding-right:.35rem;
  border-radius:4px}

/* O SELO DE CAMPO OBRIGATÓRIO. Âmbar, não vermelho: nada deu errado ainda —
   é o que falta, não um erro cometido. 11px em `--warning-text` sobre o branco
   do painel; o campo ganha o mesmo tom na borda para o olho ligar as duas
   coisas sem precisar de seta. */
.inad-exigido{font-size:11px;font-weight:600;color:var(--warning-text);
  margin-left:.35rem;letter-spacing:.01em}
/* Escopado no painel porque é só lá que a classe existe — não por disputa de
   especificidade: `.form-control` do Bootstrap tem (0,1,0) e custom.css vem
   depois, então a classe pura já venceria. (Fica o registro do susto: medindo
   `borderColor` no mesmo instante do clique, o valor lido era o cinza padrão —
   `.form-control` tem `transition: border-color .15s`, e getComputedStyle
   devolve o quadro CORRENTE da transição. O defeito era a régua, não a regra.) */
.inad-painel .inad-campo-exigido{border-color:var(--warning)}
.inad-painel .inad-campo-exigido:focus{border-color:var(--warning);
  box-shadow:0 0 0 .2rem color-mix(in srgb, var(--warning) 28%, transparent)}
/* A previsão apontando o que falta lê como instrução, não como valor. */
.inad-previsao--falta{color:var(--warning-text);font-size:0.8125rem}

/* A ÚLTIMA COLUNA NÃO SOME. A tabela de parcelas rola dentro do
   `.table-responsive`, e a coluna da ponta é "Situação" — a que diz se aquela
   linha está vencida, paga ou descontada. Grudada, ela fica visível com a
   tabela rolada. */
/* Padding de célula devolve 44px sem tirar do operador nenhum número — a
   alternativa era apagar uma coluna que ele lê no telefone. Seletor no formato
   do Bootstrap 5 (`> :not(caption) > * > *`) porque o dele é (0,1,3) e uma
   regra de classe pura perderia. */
.cobranca-tabela > :not(caption) > * > *{padding-left:.15rem;padding-right:.15rem}

/* `--surf-1` NÃO EXISTE (os tokens são --surf/--surf-2/--surf-3): a coluna
   grudada ficava com fundo transparente e era desenhada POR CIMA da vizinha.
   Fundo opaco + z-index é o que faz sticky funcionar sobre conteúdo. */
.cobranca-tabela th:last-child,
.cobranca-tabela td:last-child{position:sticky;right:0;z-index:1;background:var(--surf);
  box-shadow:-.4rem 0 .4rem -.4rem rgba(20,26,32,.18)}
/* O separador de grupo fica FORA do grude: ele é um colspan da largura toda, e
   grudado desenharia um retângulo branco com sombra por cima do próprio grupo. */
.cobranca-tabela .cobranca-grupo > :last-child{position:static;box-shadow:none}

/* A LINHA É O TÍTULO (12/08/2026): a NF virou coluna e o grupo virou separador,
   que NOMEIA e só — o cabeçalho de nota anterior repetia o valor da linha de
   baixo (medido na LMD: R$ 11.869,24 duas vezes, cinco vezes seguidas). Foram
   embora com ele o subtotal por nota e o aviso por nota: o aviso vive na célula
   de encargos de cada linha, e o subtotal de uma linha só era a própria linha. */
.cobranca-tabela .cobranca-grupo > *{background:var(--surf-2);
  border-top:1px solid var(--line-3);padding-top:.35rem;padding-bottom:.35rem}
.cobranca-tabela .cobranca-grupo th{font-size:0.8125rem}

/* A tarja do escopo: DECLARADA, não escolhida — ou o título estava vencido, ou
   não estava. Por isso não há checkbox nela. */
/* 8px abaixo dela, não 11: a tarja descreve a LISTA logo abaixo — ela pertence
   àquele bloco, e o vão tem que dizer isso. */
.inad-escopo{margin:0 0 .5rem;padding:.5rem .7rem;background:var(--surf-2);
  border:1px solid var(--line);border-radius:8px;font-size:0.75rem;color:var(--ink-2);
  display:flex;align-items:baseline;gap:.5rem;flex-wrap:wrap}
.inad-escopo:empty{display:none}
.inad-escopo strong{font-variant-numeric:tabular-nums lining-nums}
.inad-escopo__nota{margin-left:auto;color:var(--ink-3);font-size:0.75rem}
/* A diferença entre o congelado e o que o board mede. Quebra linha inteira
   (flex-basis:100%) porque é uma frase, não um par rótulo/valor. */
.inad-escopo__fora{flex:0 0 100%;color:var(--warning-text)}

/* O botão que fecha a cobrança usa o MESMO acento "forte" do cartão que a
   abriu — não `btn-primary` (o `--bs-primary` do app é o azul de fábrica do
   Bootstrap, e a única cor fria da tela não pode ser justo a ação final). */
.inad-painel-salvar{background:var(--inad-acento);border:0;color:var(--inad-acento-tinta);
  font-weight:600}
.inad-painel-salvar:hover,.inad-painel-salvar:focus{background:var(--inad-acento);
  color:var(--inad-acento-tinta);opacity:.88}
.inad-painel-salvar:focus-visible{outline:2px solid var(--acc);outline-offset:2px}

/* O prazo da assessoria ainda correndo: informa, não alarma — o botão do
   jurídico ao lado está habilitado de qualquer jeito. */
.inad-prazo--correndo{color:var(--warning-text)}

/* O remendo daqui (`padding:0 1rem !important`) saiu em 18/08/2026: o eixo
   horizontal voltou a ser reposto na própria regra de altura cheia, para todas
   as telas, não só para o board. */

/* ===========================================================================
   CRM — auditoria visual de 05/08/2026 (desktop + celular real)
   =========================================================================== */

/* 1. O SELECT QUE ARRASTAVA A TELA NO SAFARI
   Item flex nasce com `min-width: auto`: não encolhe abaixo da largura
   INTRÍNSECA do conteúdo. E um `<select>` reserva a largura da MAIOR opção,
   não da escolhida — "0000 · Tabela utilizada para preços negociados fora da
   tabela de preços" exige 800px num painel de 400px.

   O Chromium encolhe assim mesmo e por isso a medição automatizada dava
   "zero overflow" nas quatro larguras testadas. O Safari do iOS respeita a
   largura intrínseca do controle nativo: o corpo do offcanvas ganhava
   rolagem horizontal e o vendedor ARRASTAVA a tela para o lado (registrado
   em foto de aparelho, 05/08).

   Já existia um `min-width: 0` no CRM — um só, preso à capa
   (`.crm-capa .crm-linha > .form-select`). Alguém bateu neste bug, remendou
   onde doeu e deixou o painel de detalhes, o cadastro do cliente, o contato
   e o fechamento com o mesmo defeito latente. Aqui a regra vira geral. */
[data-pagina^="crm"] .crm-cresce,
[data-pagina^="crm"] [class*="crm-campo-"],
[data-pagina^="crm"] .offcanvas-body .crm-linha > * { min-width: 0; }
[data-pagina^="crm"] .offcanvas-body .form-select,
[data-pagina^="crm"] .offcanvas-body .form-control { max-width: 100%; }
/* A opção longa vira reticências em vez de empurrar a caixa. */
[data-pagina^="crm"] .form-select { text-overflow: ellipsis; }
/* Cinto de segurança: se algum campo novo escapar da régua acima, ele fica
   preso no painel em vez de transformar a tela num carrossel horizontal. */
[data-pagina^="crm"] .offcanvas-body { overflow-x: hidden; }

/* 2. ALVO DE TOQUE
   Os botões do CRM têm 31px de altura e `.crm-cartao__acao` tem 24px — menos
   da metade da polpa de um dedo. O mínimo do WCAG 2.5.5 é 44px. Só em
   ponteiro grosso: no mouse, 31px é preciso e engordar o desktop inteiro
   seria pagar o preço no lugar errado. */
@media (pointer: coarse) {
  [data-pagina^="crm"] .crm-btn,
  [data-pagina^="crm"] .crm-btn-2,
  [data-pagina^="crm"] .crm-btn-3,
  [data-pagina^="crm"] .crm-cartao__acao,
  [data-pagina^="crm"] .btn-close {
    min-height: 44px; display: inline-flex; align-items: center;
    justify-content: center; }
}

/* 3. CONTRASTE
   `--crm-tinta-3` dava 4,20:1 em 12px — abaixo dos 4,5:1 que o WCAG pede
   para texto pequeno. Medido em "07/08/2026 — Ligar", "Prospecção" e nos
   rótulos dos KPIs do funil. Um passo mais escuro resolve sem mudar a
   hierarquia: ele continua sendo o cinza de apoio, só que legível. */
[data-pagina^="crm"] { --crm-tinta-3: #5b6660; }

/* CRM — CONTORNOS VISÍVEIS COM BRILHO BAIXO
   Relato de uso: com o brilho da tela baixo, os contornos sumiam. Medido:
   83 elementos abaixo de 3:1 (WCAG 1.4.11), a maioria em 1,16:1 — quase três
   vezes abaixo do mínimo. `#e2e6e3` sobre branco é praticamente nada.

   A correção separa por FUNÇÃO, porque a norma separa:

   - No CAMPO, a borda É a afordância: é a única coisa que diz onde começa a
     caixa em que se digita. Sem ela o campo deixa de existir para quem olha.
     Vai para 3:1 de verdade (3,34:1 no branco, 3,08:1 no fundo do CRM).
   - No CARTÃO, a borda é separador: o fundo e a sombra já delimitam a caixa,
     e a norma não pede 3:1 para o que é decorativo. Fica firme o bastante
     para aparecer com brilho baixo (1,88:1 contra os 1,26:1 de antes) sem
     transformar a tela num quadriculado de linhas escuras. */
/* `acompanhamento_inadimplencia` entra aqui porque usa o MESMO bloco de tokens
   (ver o seletor lá em cima) e tinha ficado de fora desta correção: seguia com
   as bordas antigas a 1,26:1 enquanto as duas telas de CRM já estavam em 1,88:1.
   O comentário do bloco original promete "se mudar aqui, muda nas duas telas" —
   esta linha é o que torna a promessa verdadeira. `crm-agenda` entra pelo
   mesmo motivo: sem isto `--crm-borda-campo` fica indefinida na Agenda e
   `.form-select`/`.form-control` (regra por PREFIXO logo abaixo) renderizam
   com o contorno quase preto do incidente de `crm_produtividade.html`. */
[data-pagina="crm"], [data-pagina="crm-deal"], [data-pagina="crm-agenda"],
[data-pagina="crm-tabelas-preco"], [data-pagina="crm-clientes"],
[data-pagina="crm-representantes"], [data-pagina="crm-usuarios"],
[data-pagina="crm-classificacao"],
[data-pagina="acompanhamento_inadimplencia"] {
  --crm-borda: #b6bfb9;          /* separador de cartão/faixa */
  --crm-borda-forte: #98a29c;    /* divisor que precisa pesar mais */
  --crm-borda-campo: #858f89;    /* 3:1 — a borda que É o campo */
}
[data-pagina^="crm"] .form-control,
[data-pagina^="crm"] .form-select,
[data-pagina^="crm"] textarea.form-control {
  border-color: var(--crm-borda-campo); }
/* O foco continua sendo o acento, não a borda cinza — sem isto o campo em
   foco fica igual ao campo em repouso, que é trocar um problema por outro. */
[data-pagina^="crm"] .form-control:focus,
[data-pagina^="crm"] .form-select:focus {
  border-color: var(--crm-acento); }

/* ── CRM · documentos do cliente ───────────────────────────────────────────
   Lista dentro do trilho: nome primeiro (é o que se procura), metadados numa
   linha fraca embaixo, e o estado da cópia no SharePoint como etiqueta à
   direita. Sem card por item — cartão dentro de cartão é ruído, e o trilho
   já é um. */
.crm-docs { list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: .1rem; }
.crm-doc { display: grid; align-items: center; gap: .15rem .5rem;
  grid-template-columns: 1fr auto auto;
  grid-template-areas: "nome copia excluir" "meta copia excluir";
  padding: .45rem 0; border-top: 1px solid var(--crm-borda); }
.crm-doc:first-child { border-top: 0; }
.crm-doc-nome { grid-area: nome; display: flex; align-items: center; gap: .4rem;
  color: var(--crm-tinta); font-weight: 600; text-decoration: none;
  /* Nome de arquivo é longo e não quebra bem: corta com reticências em vez de
     empurrar a etiqueta de estado para fora do trilho. */
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.crm-doc-nome:hover, .crm-doc-nome:focus-visible { text-decoration: underline;
  color: var(--crm-acento); }
.crm-doc-meta { grid-area: meta; color: var(--crm-tinta-3); font-size: 0.75rem; }
.crm-doc-copia { grid-area: copia; align-self: center; white-space: nowrap;
  font-size: 0.75rem; font-weight: 600; padding: .1rem .4rem;
  border-radius: var(--raio-chip); border: 1px solid currentColor; text-decoration: none; }
.crm-doc-copia--ok { color: var(--crm-ok); background: var(--crm-ok-fundo); }
.crm-doc-copia--avi { color: var(--crm-avi); background: var(--crm-avi-fundo); }
.crm-doc-copia--erro { color: var(--crm-mal); background: var(--crm-mal-fundo); }
.crm-doc-excluir { grid-area: excluir; align-self: center; }
/* A porta para o acervo inteiro, no fim da lista curta da ficha. Não é item
   de arquivo: linha própria, sem borda de topo, para não parecer um documento
   a mais. */
.crm-doc-porta { padding: .5rem 0 .1rem; }
.crm-doc-porta a { color: var(--crm-acento); font-weight: 600; font-size: .8125rem;
  text-decoration: none; }
.crm-doc-porta a:hover, .crm-doc-porta a:focus-visible { text-decoration: underline; }

/* ── CRM · acervo de documentos (o terceiro canvas) ────────────────────────
   A lista do canvas reusa a casca do histórico (`hst-*`); o que muda é o
   ITEM, que aqui é um link para baixar e não um texto que expande. */
.dac-lista { display: flex; flex-direction: column; gap: .1rem; }
.dac-item { display: flex; align-items: flex-start; gap: .55rem;
  padding: .5rem .25rem; border-top: 1px solid var(--crm-borda);
  color: var(--crm-tinta); text-decoration: none; }
.dac-item:first-child { border-top: 0; }
.dac-item:hover, .dac-item:focus-within { background: var(--crm-fundo-2); }
/* O link é o corpo do item; o Excluir é irmão dele (04/09/2026 — botão dentro
   de <a> é HTML inválido, e o Excluir precisava voltar a existir aqui). */
.dac-item__link { display: flex; align-items: flex-start; gap: .55rem;
  min-width: 0; color: var(--crm-tinta); text-decoration: none; }
.dac-item__link:hover .dac-item__nome { text-decoration: underline; }
/* Só aparece quando o ponteiro está na linha ou o foco entra nela: a lista
   tem centenas de arquivos, e uma coluna de botões vermelhos em todas as
   linhas transformaria "excluir" no gesto mais visível de uma tela que serve
   para ACHAR arquivo. Em toque, onde não há hover, ele fica sempre visível —
   senão não haveria como alcançá-lo. */
.dac-item__excluir { align-self: center; opacity: 0; transition: opacity .12s; }
.dac-item:hover .dac-item__excluir,
.dac-item__excluir:focus-visible { opacity: 1; }
@media (hover: none) { .dac-item__excluir { opacity: 1; } }
.dac-item__icone { margin-top: .15rem; color: var(--crm-tinta-3); }
.dac-item__corpo { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
/* Nome de arquivo do acervo chega a 184 caracteres: quebra em vez de cortar,
   porque aqui ele é o conteúdo, não um rótulo ao lado de outra coisa. */
.dac-item__nome { font-weight: 600; overflow-wrap: anywhere; }
.dac-item__descricao { font-style: italic; }
/* Linha do arquivo em trânsito: nome, percentual e uma barra fina embaixo.
   A barra ocupa a faixa inteira (grid-column) para não competir com a
   etiqueta de estado, que nesta linha ainda não existe. */
.crm-doc--enviando { grid-template-areas: "nome nome nome" "meta meta meta"
  "barra barra barra"; color: var(--crm-tinta-2); }
.crm-doc--enviando .crm-doc-nome { color: var(--crm-tinta-2); }
.crm-doc-barra { grid-area: barra; height: 3px; margin-top: .35rem;
  background: var(--crm-borda); border-radius: var(--raio-chip); overflow: hidden; }
.crm-doc-barra__cheia { display: block; height: 100%;
  background: var(--crm-acento); border-radius: var(--raio-chip);
  transition: width .15s linear; }
@media (prefers-reduced-motion: reduce) {
  .crm-doc-barra__cheia { transition: none; }
}
/* Rede terminada, servidor ainda trabalhando: a barra deixa de medir e passa
   a só dizer "ainda estou aqui". Sem animação para quem pediu menos
   movimento — aí ela fica cheia e quieta. */
.crm-doc-barra--indefinida .crm-doc-barra__cheia {
  animation: crm-doc-pulsa 1.1s ease-in-out infinite; }
@keyframes crm-doc-pulsa { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) {
  .crm-doc-barra--indefinida .crm-doc-barra__cheia { animation: none; }
}
/* Motivo do "Preço base" vazio, embaixo do traço. Estreito de propósito: é
   explicação, não dado — não pode competir com os números da linha. */
.crm-sem-base { font-size: 0.75rem; line-height: 1.25; max-width: 22ch;
  margin-top: .1rem; }
/* Tabela de preço na própria linha do item, embaixo do número que ela explica.
   Sem rótulo: o cabeçalho da coluna já diz "Preço base", e um rótulo por cima
   empurrava o campo para baixo e o desalinhava dos vizinhos. */
/* Altura e fonte são as do `.form-control` ao lado (decisão do dono, 10/08):
   o campo era `form-select-sm` com padding próprio e ficava 7px mais baixo e
   3px mais embaixo que os vizinhos da mesma linha. O que sobrou de próprio é
   só o espaço da seta: a seta padrão do Bootstrap come 36px de um campo de
   120px e não sobraria largura para "0002 · R$ 5,30". */
.crm-tabela-item { padding-right: 1.5rem; background-position: right .4rem center;
  margin-left: auto; text-overflow: ellipsis; }
.crm-tabela-legenda { margin-top: .15rem; font-size: 0.75rem; }

/* --- ficha do cliente: o CANVAS sobre o funil ---
   Era página própria (`crm-ficha`) com duas colunas; virou painel (decisão do
   dono, 10/08/2026). A largura é o ponto: `crm-oc--larga` (30rem) é medida de
   formulário, e aqui dentro há duas tabelas de cinco colunas. 64rem cabe o
   extrato sem rolagem horizontal em tela de trabalho, e `96vw` garante que em
   telas menores o painel não fique maior que a janela. */
/* 25/08/2026 — O MOSAICO (direção A, escolhida pelo dono sobre três mockups).
   A ficha é leitura rápida: caixa para o que tem ação dentro (agendar,
   contatar), grade de caixas para os números, e o detalhe fechado embaixo.
   Medido em 15" a 125% (1536x864 CSS, ~750px úteis): o mosaico inteiro cabe
   acima da dobra e ainda sobram ~170px de folga.

   Largura de 52rem, não os 88rem de antes: com quatro colunas, 88rem dava
   230px de caixa para dizer "2", e o painel comia dois terços da tela sem
   usar. Estreito também devolve o funil ao fundo, que é o ponto de a ficha
   ser canvas e não página. */
/* 01/09/2026 — DUAS COLUNAS, e a largura volta a 88rem. Pedido do dono, com um
   print do Ploomes na mão: "quando busco um cliente para ligar, aparece o
   cadastro dele e ao lado o histórico dos contatos".

   Isto REVERTE a largura decidida em 25/08 (o parágrafo acima) — de propósito,
   e com autorização explícita dele. O que muda em relação àquela medição: os
   88rem de então eram UMA coluna com quatro caixinhas de 230px, espaço sem
   uso; aqui os 88rem são duas colunas com trabalho dentro das duas. E 88rem
   não é tamanho novo no sistema — é o mesmo do canvas de histórico, que este
   painel já abria ao lado. A segunda razão de 25/08 (o funil ao fundo) é a que
   se perde: quem quiser voltar a estreitar, saiba que perde o arranjo do
   print, e pergunte ao dono antes.

   Esquerda, 30rem (01/09/2026, entrevista com o dono): AGENDADOS em cima e a
   CONVERSA embaixo — o que está marcado e o que foi falado, cada caixa com a
   própria ação no cabeçalho. Direita: os cards de trabalho (pessoas, o que
   compra, propostas) e a referência fechada no fundo, cadastro incluído.
   `align-items: start` para a coluna curta não esticar os cards dela até a
   altura da outra. */
#crm-modal-ficha { --bs-offcanvas-width: min(88rem, 96vw); }
/* CHÃO (03/09/2026). O corpo do canvas não declarava fundo e herdava o branco
   do Bootstrap; os cards são `--crm-superficie`, que também é branco. Fundo,
   card e card-vazio no mesmo valor deixavam a tela sem figura e sem fundo — só
   um emaranhado de molduras de peso igual, e um vão vazio lia como BURACO em
   vez de chão. Com fundo por baixo, a borda de cada card vira redundante: quem
   sustenta a caixa passa a ser a sombra. */
#crm-modal-ficha .crm-painel, #crm-modal-ficha .crm-cartao {
  border-color: transparent; }
/* HIERARQUIA DO NOME (03/09/2026). `#fc-nome` usava `.crm-titulo` (13px) e os
   títulos de seção descem para 11px: TODO cabeçalho da ficha vivia num degrau
   só, e o assunto do painel inteiro ficava tipograficamente MENOR que
   "R$ 0,00" (15-17px). Sobe para 20px e o tracking DESCE: os .08em existem
   para abrir versal de 11px e, a 20px, espalham. Continua em caixa alta
   (decisão do dono, 03/09/2026) — o contraste vem de corpo, peso e tracking,
   não da caixa. */
#crm-modal-ficha #fc-nome { font-size: 1.25rem; letter-spacing: .02em; }
/* O título de seção cede a tinta cheia ao nome: dois degraus de cor onde antes
   havia um. */
#crm-modal-ficha #fc-leitura .crm-titulo { color: var(--crm-tinta-2); }
/* O TELEFONE é a ação do card de pessoas (03/09/2026): ocupa o lugar que era
   do botão "Ocultar" e disca de verdade (`tel:` abre o discador). Peso de
   leitura, não de metadado — era o terceiro campo de uma sublinha de 11px numa
   tela usada para ligar vinte vezes por dia. Empilha quando a pessoa tem
   celular E fixo; `nowrap` porque número quebrado no meio não se lê. */
#crm-modal-ficha .fc-discar { display: flex; align-items: center; gap: .35rem;
  color: var(--crm-acento); font-size: var(--bi-fs-compact); font-weight: 600;
  text-decoration: none; white-space: nowrap; }
#crm-modal-ficha .fc-discar + .fc-discar { margin-top: .15rem; }
#crm-modal-ficha .fc-discar:hover, #crm-modal-ficha .fc-discar:focus-visible {
  text-decoration: underline; }
/* TRILHO da coluna de telefones (03/09/2026). Sem largura mínima, o ícone de
   cada linha nascia num x diferente conforme o tamanho do número — 88px de
   avanço entre a linha de dois telefones e as demais. E o `margin-top` era
   resíduo de um empilhamento que não acontece: os dois <a> são irmãos num flex
   `align-items:center`, e o deslocamento só desalinhava o par em 1px. */
#crm-modal-ficha .crm-linha-lista .fc-discar {
  justify-content: flex-end; min-width: 7.5rem; }
/* Na coluna de identidade o telefone abre a linha, não a fecha: o
   trilho de 7,5rem empurrava o número para a direita e derrubava o
   ícone de WhatsApp para a linha de baixo (medido no print de
   09/09/2026). */
#crm-modal-ficha #fc-contato-principal .fc-discar {
  justify-content: flex-start; min-width: 0; gap: .35rem; }
/* O par número + WhatsApp anda junto (`fc-fone`). No card de Pessoas o
   embrulho é transparente ao flex da linha, para o trilho de 7,5rem continuar
   valendo lá; na coluna de identidade ele é a linha. */
#crm-modal-ficha .crm-linha-lista .fc-fone { display: contents; }
#crm-modal-ficha .fc-principal__fones { display: flex; flex-direction: column;
  align-items: flex-start; gap: .15rem; }
#crm-modal-ficha .fc-principal__fones .fc-fone {
  display: inline-flex; align-items: center; gap: .25rem; }
#crm-modal-ficha .fc-discar + .fc-discar { margin-top: 0; }
/* Ancorado em `#fc-contatos-todos`: `.crm-linha-lista` também serve o bloco
   Características, onde `.crm-rotulo` é o rótulo À ESQUERDA de um par
   rótulo/valor — encostá-lo à direita ali quebraria a leitura. */
#crm-modal-ficha #fc-contatos-todos .crm-linha-lista > .crm-rotulo {
  min-width: 7.5rem; text-align: right; }
/* O glifo media 1,44x a altura de versal do número ao lado. */
#crm-modal-ficha .fc-discar .fa-phone { font-size: .8em; }
/* Ícone de WhatsApp ao lado do `fc-discar`, só quando o número normalizado é
   celular (`crm_cliente.whatsapp_de`) — mesma régua da grade, escopo
   diferente: a ficha é `#crm-modal-ficha`, `.cl-fone--zap` é
   `[data-pagina="crm-clientes"]` e não alcançaria aqui. Mesmo acento das
   outras ações, não o verde da marca — o ícone já diferencia. */
#crm-modal-ficha .fc-zap { color: var(--crm-acento); margin-left: .15rem; }
#crm-modal-ficha .fc-zap:hover, #crm-modal-ficha .fc-zap:focus-visible { opacity: .7; }
/* O fio entre pessoas usava a MESMA borda do cartão e do cabeçalho de mês —
   onze fios estruturais a 56px de passo dentro de um card que agora tem chão e
   sombra. O fio de item é o mesmo da conversa, ao lado. Separação não se perde:
   o vão dentro da pessoa é 11px e entre pessoas 24px. */
#crm-modal-ficha #fc-contatos-todos .crm-linha-lista { border-top-color: var(--bi-border-color-subtle); }
/* UM vão entre cards: estava declarado .6rem nas colunas e .75rem na grade. */
#crm-modal-ficha .fc-col-identidade,
#crm-modal-ficha .fc-col-trabalho { gap: .75rem; }
/* 12px é o piso do DESIGN.md; os títulos de seção estavam a 11px. */
#crm-modal-ficha #fc-leitura h2.crm-titulo,
#crm-modal-ficha .fc-faixa { font-size: .75rem; }
/* A MOLDURA NÃO ROLA (09/09/2026). O corpo do offcanvas rolava inteiro:
   1.671 px de conteúdo para 641 px de dobra a 1366×768, e o topo saía da vista
   junto com o resto. Agora o corpo é o palco de altura fixa e quem rola são as
   regiões marcadas com `.fc-rola`.
   `min-height: 0` nas duas: sem ele o item de grid usa a altura do CONTEÚDO
   como piso e a rolagem interna nunca acontece — o erro clássico de flex/grid,
   e ele falha em silêncio (a barra simplesmente não aparece). */
#crm-modal-ficha .offcanvas-body { background: var(--crm-fundo);
  display: flex; flex-direction: column; overflow: hidden; min-height: 0; }
#crm-modal-ficha #fc-leitura.fc-moldura { flex: 1; min-height: 0;
  display: grid; align-items: stretch;
  grid-template-columns: minmax(0, 19.5rem) minmax(0, 1fr); gap: 0 1.25rem; }
#crm-modal-ficha .fc-rola { min-height: 0; overflow-y: auto;
  overscroll-behavior: contain; padding-bottom: 1.5rem; }
/* A BARRA DE ABAS fica parada no topo da coluna de trabalho; quem rola é o
   painel. `overflow-x: auto` é rede de segurança, não plano: nove abas é o
   teto combinado com o dono, e a décima faz a barra rolar de lado — levando
   junto a memória de posição, que é o que ela existe para preservar. */
#crm-modal-ficha .fc-col-trabalho { min-height: 0; }
#crm-modal-ficha .fc-abas { flex: none; display: flex; gap: .1rem;
  overflow-x: auto; padding: 0 .25rem;
  border-bottom: 1px solid var(--crm-borda); background: var(--crm-superficie); }
#crm-modal-ficha .fc-aba { display: flex; align-items: center; gap: .3rem;
  white-space: nowrap; padding: .7rem .45rem; border: 0;
  border-bottom: 2px solid transparent; background: transparent;
  color: var(--crm-tinta-2); font: 500 .8125rem/1 inherit; cursor: pointer; }
#crm-modal-ficha .fc-aba:hover { color: var(--crm-tinta); }
#crm-modal-ficha .fc-aba[aria-selected="true"] { color: var(--crm-acento);
  border-bottom-color: var(--crm-acento); font-weight: 700; }
#crm-modal-ficha .fc-aba:focus-visible { outline: 2px solid var(--crm-acento);
  outline-offset: -2px; }
#crm-modal-ficha .fc-painel { flex: 1; display: flex; flex-direction: column;
  gap: .6rem; }
#crm-modal-ficha .fc-painel[hidden] { display: none; }
#crm-modal-ficha .fc-aba__n { font-variant-numeric: tabular-nums; font-weight: 700;
  font-size: .75rem; color: var(--crm-tinta); background: var(--crm-fundo);
  border-radius: 9px; padding: .05rem .35rem; min-width: 1.25rem; text-align: center; }
#crm-modal-ficha .fc-aba__n:empty { display: none; }
#crm-modal-ficha .fc-aba[aria-selected="true"] .fc-aba__n {
  background: var(--crm-acento-fundo); color: var(--crm-acento); }
/* Zero fica no lugar, apagado: aba que some conforme o cliente destrói a
   memória de posição, que é como esta gente navega. */
#crm-modal-ficha .fc-aba__n--zero { color: var(--crm-tinta-3); font-weight: 400; }
/* A COLUNA DE IDENTIDADE (09/09/2026): par rótulo/valor, sem caixa em volta.
   Caixa dentro de caixa foi o que deixou a ficha pesada antes. */
#crm-modal-ficha .fc-dinheiro { display: grid; grid-template-columns: 1fr auto;
  gap: .25rem .5rem; margin: 0; }
#crm-modal-ficha .fc-dinheiro dt { color: var(--crm-tinta-3); font-weight: 400; }
#crm-modal-ficha .fc-dinheiro dd { margin: 0; text-align: right; font-weight: 500;
  font-variant-numeric: tabular-nums; }
/* Cor significa dinheiro: só o vencido acende, e só quando o servidor diz que
   ele está inadimplente. Vermelho permanente vira ruído. */
#crm-modal-ficha .fc-dinheiro dd.fc-dinheiro__mal { color: var(--crm-mal); }
/* A porta do cadastro: contorno tracejado para dizer "isto abre" sem competir
   com o único botão cheio da tela ("Nova proposta"). */
#crm-modal-ficha .fc-porta-cadastro { display: block; width: 100%; text-align: left;
  background: transparent; border: 1px dashed var(--crm-borda-forte);
  border-radius: 6px; padding: .5rem .65rem; cursor: pointer; font: inherit; }
#crm-modal-ficha .fc-porta-cadastro:hover,
#crm-modal-ficha .fc-porta-cadastro:focus-visible {
  border-color: var(--crm-acento); background: var(--crm-acento-fundo); }
#crm-modal-ficha .fc-porta-cadastro__verbo { display: block; font-weight: 500;
  color: var(--crm-acento); }
#crm-modal-ficha .fc-col-identidade,
#crm-modal-ficha .fc-col-trabalho { display: flex; flex-direction: column; gap: .6rem;
  min-width: 0; }
/* Empilha cedo: duas colunas só valem quando as duas cabem inteiras. Abaixo
   disto a ficha volta a ser UMA coluna na ordem do documento — agendados e
   conversa primeiro, que é o que se quer ao abrir; o `order:-1` de antes
   subia o trabalho porque agendamento e contato moravam lá, o que deixou de
   ser verdade em 01/09/2026. */
@media (max-width: 1200px) {
  #crm-modal-ficha .offcanvas-body { display: block; overflow-y: auto; }
  #crm-modal-ficha #fc-leitura.fc-moldura {
    grid-template-columns: 1fr; align-items: start; }
  #crm-modal-ficha .fc-rola { overflow-y: visible; padding-bottom: 0; }
}
/* A conversa: a lista usa o item do canvas de histórico (ver `.hst-item`), e
   aqui só se ajusta o que é de bloco — o último item não precisa do fio de
   baixo, que o card já dá, e a porta para o arquivo inteiro fica à direita,
   onde termina a leitura. */
#crm-modal-ficha .fc-conversa-lista .hst-item:last-of-type { border-bottom: 0; }
#crm-modal-ficha .fc-conversa-rodape { display: flex; justify-content: flex-end;
  padding-top: .5rem; }
/* Densidade da ficha (01/09/2026, segunda rodada — "reduzir a rolagem"):
   painel um degrau mais justo que o 1rem/1.15rem global, SÓ aqui — a régua
   global serve páginas de leitura; a ficha é bancada de trabalho e paga
   rolagem por cada .2rem de almofada. */
#crm-modal-ficha .crm-painel { padding: .8rem 1rem; }
/* Link dentro de tabela da ficha (proposta → negócio, auditoria → negócio):
   a tinta de acento do sistema, não o azul do navegador. */
#crm-modal-ficha .crm-tabela a { color: var(--crm-acento);
  text-decoration: none; font-weight: 600; }
#crm-modal-ficha .crm-tabela a:hover,
#crm-modal-ficha .crm-tabela a:focus-visible { text-decoration: underline; }
/* DESCENDENTE, não filho direto: com as duas colunas as seções passaram a
   morar a dois e a três níveis (`#fc-leitura > .fc-col-trabalho > .fc-acoes >
   section`). Os seletores `>` de antes deixavam de casar exatamente as
   caixas de ação — e o `:empty` abaixo é o que impede um bloco vazio de abrir
   um vão do tamanho de um card que não existe (filiais, triangulações, os
   blocos do ERP num lead, esvaziados em `ficha.js`). Não há `<section>` na
   ficha que NÃO queira estas duas regras, então descendente é a forma
   honesta. */
#crm-modal-ficha #fc-leitura section { margin-bottom: 0; }
#crm-modal-ficha #fc-leitura section:empty { display: none; }

/* Par de cards na mesma linha (Pessoas cadastradas · Cadastro). Empilha cedo:
   card espremido esconde e-mail e telefone, que são o motivo do card.
   `align-items: start` para o cadastro fechado não esticar até a altura do
   vizinho. */
#crm-modal-ficha .fc-caixa { display: flex; flex-direction: column; height: 100%; }
#crm-modal-ficha .fc-caixa-topo { margin-bottom: .35rem; }
/* O valor da caixa: caixa mista, 15px. É o único texto de conteúdo em corpo
   maior da ficha — o nome de quem se liga e o que se combinou. */
#crm-modal-ficha .fc-caixa-valor { font-size: .9375rem; font-weight: 600;
  color: var(--crm-tinta); line-height: 1.3; }

/* A faixa rotulada do mosaico: rótulo curto e um fio até a borda. Separa os
   grupos sem dar a cada um uma caixa em volta — caixa dentro de caixa foi o
   que deixou a ficha pesada. */
#crm-modal-ficha .fc-faixa { display: flex; align-items: center; gap: .5rem;
  font-size: .6875rem; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--crm-tinta-3); margin-bottom: .35rem; }
#crm-modal-ficha .fc-faixa::after { content: ""; flex: 1; height: 1px;
  background: var(--crm-borda); }
/* A grade: quatro colunas iguais em tela de trabalho. `.measures` é o
   componente do design system (o mesmo do funil e da separação) — aqui só
   troca o flex por grade, para as caixas terem a MESMA largura: número que
   não alinha não se compara. */
/* `auto-fit` de novo desde 01/09/2026: as faixas passaram a ter contagens
   diferentes (Abrir = 3, medidas = 4, posição = 3) e um número fixo obriga a
   4ª medida a quebrar sozinha numa linha — era o whitespace que o dono
   circulou. Cada faixa preenche a própria linha; o mínimo de 12rem segura o
   rótulo comprido ("Adiantamentos a consumir") sem espremer. */
#crm-modal-ficha .fc-mosaico { display: grid; gap: .5rem; margin: 0;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); }
@media (max-width: 1200px) {
  #crm-modal-ficha .fc-mosaico { grid-template-columns: repeat(auto-fit, minmax(10.5rem, 1fr)); }
}
/* Porta: a caixa que ABRE outra tela. Mesma forma da medida, mais o alvo de
   clique e o verde do valor, que é o que diz "isto leva a algum lugar". */
#crm-modal-ficha .fc-porta { text-align: left; cursor: pointer;
  text-decoration: none; font: inherit; }
#crm-modal-ficha .fc-porta .measure__v { color: var(--crm-acento); }
#crm-modal-ficha .fc-porta:hover, #crm-modal-ficha .fc-porta:focus-visible {
  border-color: var(--crm-acento); background: var(--crm-superficie); }
#crm-modal-ficha .fc-porta-sub { font-size: .75rem; color: var(--crm-tinta-3);
  margin-top: .1rem; }
/* O verbo na sub-linha da porta: mesma anatomia das irmãs (rótulo, número,
   sub-linha), só que a sub-linha AGE em vez de informar. Sublinhado porque
   é o que diz "isto responde ao clique" — a caixa inteira também abre, mas
   quem procura "anexar" procura a palavra, não a caixa. */
#crm-modal-ficha .fc-porta-anexar { display: inline-block; padding: 0;
  border: 0; background: none; font: inherit; color: var(--crm-acento);
  text-decoration: underline; cursor: pointer; }
#crm-modal-ficha .fc-porta-anexar:hover,
#crm-modal-ficha .fc-porta-anexar:focus-visible { text-decoration: none; }

/* Os títulos dos blocos de detalhe recuam meio tom: eles são a etiqueta de
   uma gaveta fechada, não uma manchete. */
#crm-modal-ficha #fc-leitura h2.crm-titulo { font-size: .6875rem;
  font-weight: 600; letter-spacing: .1em; color: var(--crm-tinta-2); }
/* Bloco dobrável: o cabeçalho do bloco É o <summary> — título, resumo do
   fechado ("4 produtos", "6") e a ação na mesma linha. O marcador é o
   `.drill-plus`; o resumo é rótulo, não número grande. */
#crm-modal-ficha .fc-bloco > summary { align-items: center; gap: .5rem; }
#crm-modal-ficha .fc-bloco-resumo::before { content: '· '; }
/* O cabeçalho é uma coluna (nome em cima, identidade embaixo), não a linha
   padrão do Bootstrap — o nome do cliente é o título do painel e não pode
   competir com as pílulas. */
#crm-modal-ficha .fc-cabecalho { align-items: flex-start; }
/* "Nova proposta" (28/08/2026): entre a identidade (que cresce) e o X de
   fechar — sem `gap` no `.offcanvas-header` do Bootstrap, o botão colava
   no X. */
#crm-modal-ficha #fc-capa-acao { flex: none; margin-inline-end: .5rem; }
#crm-modal-ficha .fc-identidade { display: flex; flex-wrap: wrap;
  align-items: center; gap: .5rem; margin-top: .35rem; width: 100%; }
/* Título de bloco é <h2> de verdade (leitor de tela navega por cabeçalho);
   o tamanho continua sendo o do `.crm-titulo`, só o margin do h2 sai. */
#crm-modal-ficha h2.crm-titulo, #crm-modal-ficha h3 { margin: 0; }
#crm-modal-ficha #fc-nome:focus-visible { outline: 2px solid var(--acc-line); outline-offset: 2px; }
/* Cadastro em grade: são nove pares rótulo/valor curtos, e um por linha
   esticava o bloco a uma tela inteira de leitura vertical para nada. */
#crm-modal-ficha .fc-cadastro-grade { display: grid; gap: .5rem 1.25rem;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); }
/* `overflow-wrap`: com o painel a 64rem a grade do cadastro chega a quatro
   colunas, e um e-mail longo passava por baixo da borda do card. */
#crm-modal-ficha .fc-campo { min-width: 0; overflow-wrap: anywhere; }
/* A barra de atalhos (25/08/2026): Conversas · Documentos · Negócios viraram
   chips, e o corpo da ficha ficou com o trabalho. O chip é navegação — cor de
   texto, contorno leve, contagem em pílula — para não disputar com o botão
   preenchido de registrar contato, que é a ação da faixa. */
#crm-modal-ficha .fc-atalhos { display: flex; flex-wrap: wrap; gap: .5rem;
  align-items: center; }
#crm-modal-ficha .fc-atalho { display: inline-flex; align-items: center; gap: .4rem;
  padding: .3rem .6rem; border: 1px solid var(--crm-borda); border-radius: .35rem;
  background: transparent; color: var(--crm-tinta-2); font-size: var(--bi-fs-compact);
  text-decoration: none; }
#crm-modal-ficha .fc-atalho:hover, #crm-modal-ficha .fc-atalho:focus-visible {
  border-color: var(--crm-borda-forte); color: var(--crm-tinta); }
#crm-modal-ficha .fc-atalho__conta { font-variant-numeric: tabular-nums;
  background: var(--crm-fundo); border-radius: var(--raio-chip); padding: 0 .4rem; }
/* O componente de anexar mudou de endereço para dentro do canvas do acervo, e
   a lista curta dele não tem o que fazer ali: o acervo inteiro, com filtro e
   facetas, está logo abaixo. */
#crm-modal-documentos .dac-anexar .crm-docs { display: none; }
#crm-modal-documentos .dac-anexar .crm-painel { margin-top: 0; }
/* A lacuna do cadastro de um LEAD. Itálico no cinza-3: tem de se distinguir à
   primeira passada de olho de um campo que alguém já preencheu, sem virar um
   segundo tom de cinza no design system. */
#crm-modal-ficha .fc-campo-convite { color: var(--crm-tinta-3);
  font-style: italic; }
/* A frase do bloco vazio. Cinza-3 (não o cinza-4 de placeholder): é conteúdo
   — "este CNPJ nunca comprou" é resposta, não ausência de resposta. */
#crm-modal-ficha .fc-vazio { color: var(--crm-tinta-3);
  font-size: var(--bi-fs-compact); }
/* Documentos (Task 6): o componente compartilhado nasce com `mt-3` (o
   espaço que separa dele de um bloco anterior no negócio/funil) — aqui já
   está dentro de `section.mb-3`, então o espaço de cima duplicava. */
#crm-modal-ficha #fc-doc-painel { margin-top: 0; }
/* Texto livre do vendedor (observações do cadastro), no MESMO tratamento
   âmbar da capa do negócio: preserva as quebras que a limpeza do HTML, no
   servidor, já reduziu a `\n`. */
#crm-modal-ficha .crm-obs-cliente { white-space: pre-line; }
/* Observações do cadastro: clamp de 4 linhas no CONJUNTO (P0 da dobra,
   19/08/2026) — a caixa âmbar de LEONARDI tinha 1.201px de procedimento
   fiscal e a dobra inteira era isso. */
#crm-modal-ficha .fc-obs { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; overflow: hidden; }
#crm-modal-ficha .fc-obs--inteira { display: block; -webkit-line-clamp: unset; overflow: visible; }
/* Observações do cadastro em EDIÇÃO (19/08/2026, "tudo editável"): cada
   item = rótulo/seletor de tipo + Remover + textarea. Removida fica
   rebaixada até o Salvar — é decisão, não gesto; o Cancelar desfaz. */
#crm-modal-ficha .fc-obs-lista { display: grid; gap: .75rem; }
#crm-modal-ficha .fc-obs-item--removida textarea { opacity: .45; text-decoration: line-through; }
#crm-modal-ficha .fc-obs-campo { width: auto; }

/* `.fc-tl-*` (o item da linha do tempo que a ficha desenhava até 25/08/2026)
   foi DELETADO em 01/09/2026: o bloco saiu do corpo naquela data e virou o
   chip "Conversas", e desde então nenhum JS emitia essas classes nem o
   `data-expandir-texto` que as abria — CSS e handler órfãos. A conversa
   voltou à ficha em 01/09, mas com o item do canvas de histórico
   (`.hst-item`, logo abaixo), que é o mesmo desenho nas duas telas. Ressuscitar
   o `.fc-tl-*` teria dado à ficha um segundo desenho de conversa. */
/* Os dois botões de revelar da capa ("ver o texto inteiro", "ver as N
   observações") são `.crm-btn-3` — 12px, sem borda e sem sublinhado, que a
   390px lê como legenda. O marcador é o `.drill-plus` dentro do botão,
   dirigido pelo `aria-expanded` que `ficha.js` já mantém (regra global do
   componente). */

/* Próximo passo — a faixa de decisão no topo da capa (19/08/2026). Único
   elemento em caixa mista de 16px (`.crm-pergunta`). Âmbar só quando atrasado:
   cor com significado, e só aí — mesmos tokens de `.crm-aviso--avi`. */
#crm-modal-ficha .fc-passo-linha { gap: .5rem; flex-wrap: wrap; margin-top: .35rem; }
/* #f0d9a7: a MESMA borda âmbar de `.crm-aviso--avi` (custom.css:9805), copiada
   e não tokenizada porque o par fundo/borda do aviso ainda não tem token de
   borda — mudou lá, muda aqui. */
#crm-modal-ficha .fc-passo--atrasado { background: var(--crm-avi-fundo); border-color: #f0d9a7; }

/* Compromisso vencido na lista da agenda do cliente. Mesmo fundo de aviso da
   faixa acima, para o mesmo fato ler igual nos dois lugares; quem classifica é
   o servidor (campo `atrasado`), aqui só se pinta. */
#crm-modal-ficha .fc-compromisso--atrasado > td { background: var(--crm-avi-fundo); }

/* <details> nativo para o que é referência (cadastro, extrato de pedidos):
   fechado por padrão, sem JS. Summary no tom de rótulo, cursor de alvo. O
   marcador é o `.drill-plus` canônico (+ ↔ −) que `bloco()` põe no summary;
   o do navegador some. */
#crm-modal-ficha .fc-details > summary { cursor: pointer; list-style: none; }
/* Pedidos usa <h2> dentro do <summary> (título do bloco = rótulo do
   fechado, "menos DOM"). `h2` é bloco por padrão — sem isto o marcador
   quebrava linha antes do texto. */
#crm-modal-ficha .fc-details > summary h2.crm-titulo { display: inline; }
#crm-modal-ficha .fc-details > summary::-webkit-details-marker { display: none; }
#crm-modal-ficha .fc-details > summary:focus-visible { outline: 2px solid var(--acc-line); outline-offset: 2px; }

/* No telefone as cinco medidas em fita (`.measures` é flex com `min-width: 7rem`)
   se quebravam em três linhas irregulares — 112, 112 e 157px na mesma linha,
   cada uma começando num lugar diferente. Número que não alinha não se compara,
   que é o motivo de o componente existir. Em duas colunas iguais as três linhas
   viram uma grade: mesma largura, mesma margem, e a quinta ficha ocupa a sua
   coluna sem esticar. Medido a 390x844. */
@media (max-width: 575.98px) {
  #crm-modal-ficha .measures { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* Os 96vw da largura padrão davam 374px no telefone contra os 390px do canvas
     de histórico, que já é 100vw: trocar de painel ("Ver a conversa inteira" e
     "Voltar à ficha") mexia a janela 16px para os lados a cada ida e volta, e
     sobrava uma faixa do funil que não é para tocar. No telefone os dois
     canvas ocupam a tela inteira. */
  #crm-modal-ficha { --bs-offcanvas-width: 100vw; }
}

/* --- CRM · histórico do cliente: o SEGUNDO canvas sobre o funil (19/08/2026) ---
   `.hst-*` escopado em :is(#crm-modal-historico, #crm-modal-documentos). Canvas de leitura longa com
   filtros: largura máxima do sistema; o corpo rola, cabeçalho/filtros/régua
   ficam. Selecionado = fundo + peso do rótulo (sem faixa lateral); canal é
   texto, não cor. */
:is(#crm-modal-historico, #crm-modal-documentos) { --bs-offcanvas-width: min(88rem, 96vw); }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-cabecalho { align-items: center; gap: .75rem; }
/* No telefone o rótulo quebrava em três linhas e esmagava o cabeçalho: o botão
   é controle de tamanho fixo, quem quebra é o nome do cliente. */
:is(#crm-modal-historico, #crm-modal-documentos) #hst-voltar { white-space: nowrap; }
:is(#crm-modal-historico, #crm-modal-documentos) h2.crm-titulo, :is(#crm-modal-historico, #crm-modal-documentos) h3 { margin: 0; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-filtros-faixa { padding: .5rem 1.25rem; border-bottom: 1px solid var(--crm-borda); }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-busca-linha { gap: .75rem; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-filtros { margin-top: .5rem; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-filtros__summary { cursor: pointer; list-style: none; min-height: 2rem; display: flex; align-items: center; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-filtros__summary::-webkit-details-marker { display: none; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-filtros__summary .drill-plus { margin-right: .35rem; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-filtros__corpo { display: grid; gap: 1rem 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); padding: .5rem 0 .25rem; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-grupo { display: flex; flex-direction: column; gap: .3rem; margin: 0; padding: 0; border: 0; min-width: 0; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-grupo--periodo { grid-column: span 2; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-presets { display: flex; flex-wrap: wrap; gap: .25rem; }
/* Campo secundário do grupo: os presets são o caminho comum, o intervalo exato
   é a exceção — largura de data, não de coluna. */
:is(#crm-modal-historico, #crm-modal-documentos) #hst-periodo { max-width: 14rem; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-faceta { display: flex; align-items: center; gap: .5rem; min-height: 2rem; cursor: pointer; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-faceta:has(input:checked) { font-weight: 600; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-corpo { padding-top: 0; }
/* Mês: sub-bloco em caixa mista, 12px/600, sticky DENTRO do corpo rolante.
   `#crm-modal-negocios` reaproveita a MESMA classe para o cabeçalho
   aberto/anterior (28/08/2026) — é o mesmo mecanismo "cabeçalho quando o
   grupo muda", só que o grupo aqui não é mês. */
/* O cabeçalho de mês respirava 10px acima e 12px abaixo contra 19px entre duas
   conversas, e saía mais claro que as datas que ele agrupa — separava menos do
   que o que estava separando. */
:is(#crm-modal-historico, #crm-modal-documentos, #crm-modal-negocios) .hst-mes {
  padding: 1.25rem 0 .5rem; color: var(--crm-tinta); }
:is(#crm-modal-historico, #crm-modal-documentos, #crm-modal-negocios) .hst-mes { position: sticky; top: 0; z-index: 1; margin: 0;
  padding: .5rem 0; font-size: var(--bi-fs-micro); font-weight: 600; color: var(--crm-tinta-2);
  background: var(--bs-offcanvas-bg, #fff); border-bottom: 1px solid var(--crm-borda); }
/* Um alvo por item: a linha inteira é botão. Hover/focus autorais; aberto =
   fundo + peso (sem faixa lateral).

   `#crm-modal-ficha` entra no escopo em 01/09/2026: a ficha passou a mostrar
   as últimas conversas na coluna da direita, e o item é o MESMO — mesma
   anatomia, mesmo abrir. Só as regras DO ITEM (daqui até `.hst-campo`) valem
   na ficha; cabeçalho, faixa de filtros e régua continuam sendo do canvas,
   que é quem os tem. */
:is(#crm-modal-historico, #crm-modal-documentos, #crm-modal-ficha) .hst-item { display: flex; flex-direction: column; gap: .15rem; width: 100%;
  text-align: left; padding: .6rem .5rem; min-height: 44px; border: 0; border-bottom: 1px solid var(--bi-border-color-subtle);
  background: transparent; color: inherit; font: inherit; cursor: pointer; transition: background-color .16s ease-out; }
:is(#crm-modal-historico, #crm-modal-documentos, #crm-modal-ficha) .hst-item:hover { background: var(--bi-bg-hover); }
:is(#crm-modal-historico, #crm-modal-documentos, #crm-modal-ficha) .hst-item:focus-visible { outline: 2px solid var(--acc-line); outline-offset: -2px; }
:is(#crm-modal-historico, #crm-modal-documentos, #crm-modal-ficha) .hst-item[aria-expanded="true"] { background: var(--surf-2); border-bottom-color: transparent; }
:is(#crm-modal-historico, #crm-modal-documentos, #crm-modal-ficha) .hst-item[aria-expanded="true"] .hst-item__topo { font-weight: 600; }
:is(#crm-modal-historico, #crm-modal-documentos, #crm-modal-ficha) .hst-item[aria-expanded="true"] .hst-item__texto { display: none; }
:is(#crm-modal-historico, #crm-modal-documentos, #crm-modal-ficha) .hst-item--auto { opacity: .85; }
:is(#crm-modal-historico, #crm-modal-documentos, #crm-modal-ficha) .hst-item__topo { display: flex; gap: .5rem; flex-wrap: wrap; font-size: var(--bi-fs-micro); }
/* A linha é o único elemento interativo da lista e em repouso nada dizia isso
   (hover não existe no toque). O `.drill-plus` no fim do topo conta as duas
   metades — "esta linha abre" e "está aberta" — pelo `aria-expanded` que
   `historico.js` já mantém (regra global do componente), sem JS. */
:is(#crm-modal-historico, #crm-modal-documentos, #crm-modal-ficha) .hst-item .hst-item__topo .drill-plus { margin-left: auto; }
/* No CANVAS o item tem 1368px, e o `margin-left:auto` jogava o `+` a 1089px do
   rótulo que ele abre — longe demais do que nomeia. Na ficha (coluna de 466px)
   o encosto à direita continua certo. */
:is(#crm-modal-historico, #crm-modal-documentos) .hst-item .hst-item__topo .drill-plus { margin-left: 0; }
:is(#crm-modal-historico, #crm-modal-documentos, #crm-modal-ficha) .hst-item__texto { white-space: pre-line; display: -webkit-box; -webkit-box-orient: vertical;
  -webkit-line-clamp: 3; overflow: hidden; }
:is(#crm-modal-historico, #crm-modal-documentos, #crm-modal-ficha) .hst-detalhe { padding: 0 .5rem .85rem; background: var(--surf-2);
  border-bottom: 1px solid var(--bi-border-color-subtle); }
:is(#crm-modal-historico, #crm-modal-documentos, #crm-modal-ficha) .hst-texto { white-space: pre-line; margin-bottom: .6rem; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-campo { margin-top: .3rem; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-vazio { color: var(--crm-tinta-3); font-size: var(--bi-fs-compact); padding: 1rem 0; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-mais { padding: .75rem 0; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-regua { align-items: center; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-frase { margin: 0; flex: 1 1 12rem; }
:is(#crm-modal-historico, #crm-modal-documentos) .hst-regua > #hst-registrar { flex: 0 0 auto; }
@media (prefers-reduced-motion: reduce) { :is(#crm-modal-historico, #crm-modal-documentos) * { transition-duration: 0ms !important; } }
@media (max-width: 575.98px) {
  :is(#crm-modal-historico, #crm-modal-documentos) { --bs-offcanvas-width: 100vw; }
  :is(#crm-modal-historico, #crm-modal-documentos) .hst-grupo--periodo { grid-column: auto; }
  :is(#crm-modal-historico, #crm-modal-documentos) .crm-btn, :is(#crm-modal-historico, #crm-modal-documentos) .crm-btn-2, :is(#crm-modal-historico, #crm-modal-documentos) .crm-btn-3,
  :is(#crm-modal-historico, #crm-modal-documentos) .pill, :is(#crm-modal-historico, #crm-modal-documentos) .form-select { min-height: 44px; }
}
/* A 390x844 os filtros abertos empilham numa coluna só e a faixa passava de
   830px: o corpo da conversa sobrava com 16px de altura e a régua "Registrar
   contato" caía 144px ABAIXO da janela (medido). A faixa é um item de flex que
   não encolhe (bloco, sem overflow próprio), então o teto tem de estar aqui: o
   corpo dos filtros rola dentro de si e a conversa continua sendo o que ocupa a
   tela. Vale até 991,98px porque no tablet os filtros nascem ABERTOS (768px é o
   ponto em que historico.js os abre) e sem o teto sobravam 220px de conversa. */
@media (max-width: 991.98px) {
  :is(#crm-modal-historico, #crm-modal-documentos) .hst-filtros__corpo { max-height: 38vh; overflow-y: auto; }
}
/* Alvo de toque no canvas de histórico: o mínimo do WCAG 2.5.5 é 44px e aqui
   ficavam abaixo dele os presets de período (29,6px), as facetas de canal e
   origem (32px) e a busca (32,6px). A regra por LARGURA acima não alcançava o
   tablet a 768px, que é dedo igual ao telefone — quem responde por dedo é
   `pointer: coarse`, não a largura da tela. */
@media (pointer: coarse) {
  :is(#crm-modal-historico, #crm-modal-documentos) .pill,
  :is(#crm-modal-historico, #crm-modal-documentos) .hst-faceta,
  :is(#crm-modal-historico, #crm-modal-documentos) .form-control,
  :is(#crm-modal-historico, #crm-modal-documentos) .form-select { min-height: 44px; }
}

/* ==========================================================================
   IMPRESSÃO — o entregável declarado das telas de diretoria É o print/PDF de
   reunião (PRODUCT.md), e até 2026-08-07 a app inteira tinha ZERO regra
   própria de @media print (critique /despesas/, P2): o PDF saía com sidebar
   de ícones, topbar de filtros e controles mortos. Regra global do shell —
   o conteúdo imprime; o chrome do app, não.
   ========================================================================== */
@media print {
  .side, #topbar, .filtbtn, .fcds-filters-host, .fcds-stale { display: none !important; }
  .main { margin: 0 !important; }
  .content { padding: 0 !important; }
  body { background: #fff !important; }
  /* Cartão não quebra no meio da página; sombras/anéis fora. */
  .card, section.card { break-inside: avoid; box-shadow: none !important; }
  /* Controles de tela não fazem sentido no papel. */
  .state-error__botao-retry, [data-mostrar-mais], #bi-vazio-restaurar { display: none !important; }
  /* O skip link (`.skip`, base_fcds.html) é chrome do SHELL, igual a `.side`/
     `#topbar` acima — em nenhuma tela ele deveria ir para o papel. Achado
     16/09/2026 no pedido impresso: `position: fixed` do skip link, pensado
     para ficar fora da viewport (`top: -4rem`) até o foco de teclado, não
     respeita o recorte de página do Chromium ao gerar PDF — ele reaparece
     dentro da folha (canto inferior esquerdo da página 1). Regra global
     porque a causa é do SHELL, não desta tela: qualquer página que imprima
     está sujeita ao mesmo comportamento do Chromium. */
  .skip { display: none !important; }
}

/* ==========================================================================
   CRM · PEDIDO IMPRESSO (`[data-pagina="crm-pedido-imprimir"]`, 16/09/2026)
   — a folha do pedido no layout do modelo do Sênior
   `RVPE148.GER` ("[FOUR] Pedido de Vendas Steel"), decisão do dono
   (15-16/09/2026): o app REPLICA esse modelo, não inventa um novo.
   `crm/templates/crm/pedido_interno.html` é o único consumidor.

   Página NOMEADA (mesmo padrão de `simulacao`, acima): o `@page` anônimo já
   pertence à proposta do CRM (margens 30/40mm e cabeçalho corrido), que
   este documento não usa.
   ========================================================================== */
@page pedido-impresso { size: A4; margin: 12mm; }

/* Visual com o RVPE148 como BASE (dono, 16/09/2026): "o objetivo é não
   replicar pixel perfect, mas sim usar o Sênior como base para uma entrega
   superior". Daí: tinta preta, Arial compacta, rótulo em NEGRITO e valor
   regular, caixa fina em volta de faixa + cliente, itens em Courier — a
   cara que o leitor do pedido já conhece. A melhoria que o Sênior não tem:
   NENHUM valor é cortado ("NÃO CORTAR E-MAIL, é dado e pode comprovar uma
   entrega para endereço errado") — quebra de linha, nunca reticências. */
[data-pagina="crm-pedido-imprimir"] { background: var(--bg); min-height: 100vh; padding: 24px 0 48px; }

[data-pagina="crm-pedido-imprimir"] .folha {
  page: pedido-impresso;
  max-width: 210mm; margin: 0 auto; background: #fff; color: #000;
  padding: 12mm; font-family: Arial, Helvetica, sans-serif;
  font-size: 11.5px; line-height: 1.3; letter-spacing: 0;
  box-shadow: 0 1px 4px rgba(0, 0, 0, .12);
}
[data-pagina="crm-pedido-imprimir"] .folha b,
[data-pagina="crm-pedido-imprimir"] .folha strong { font-weight: 700; }

[data-pagina="crm-pedido-imprimir"] .folha__cabecalho {
  display: flex; align-items: flex-end; gap: 14px;
  border-top: 1px solid #000; padding-top: 8px; margin-bottom: 6px;
}
/* Marca empilhada (463×276) a ~130px: ~340 ppi no A4, nítida no papel. */
[data-pagina="crm-pedido-imprimir"] .folha__logo { width: 130px; height: auto; flex: none; }
/* Cabeçalho da empresa todo em negrito, com CEP e IE na mesma linha do
   endereço/CNPJ, como o RVPE148. */
[data-pagina="crm-pedido-imprimir"] .folha__empresa { flex: 1; min-width: 0; font-size: 11.5px; font-weight: 700; }
[data-pagina="crm-pedido-imprimir"] .folha__empresa strong { display: block; font-size: 13.5px; margin-bottom: 1px; }
[data-pagina="crm-pedido-imprimir"] .folha__empresa div span + span { margin-left: 3em; }

/* Faixa e bloco do cliente numa caixa fina só (a faixa fecha em cima, o
   bloco continua embaixo sem borda dupla). */
[data-pagina="crm-pedido-imprimir"] .folha__faixa {
  display: flex; justify-content: space-around; align-items: center; gap: 12px;
  font-size: 14px; font-weight: 700; border: 1px solid #000; padding: 4px 8px;
}
/* Pedido cancelado inteiro sai com os itens e esta marca no meio da faixa
   (dono, 16/09/2026) — sem ela a folha parece um pedido vivo. */
[data-pagina="crm-pedido-imprimir"] .folha__cancelado {
  color: var(--negative-text); border: 1px solid currentColor; padding: 0 8px; letter-spacing: .04em;
}

/* `minmax(0, 1fr)` nas duas colunas (achado de revisão, 16/09/2026): sem o
   `0`, o Grid usa o CONTEÚDO da coluna como largura MÍNIMA — os e-mails
   longos puxavam a coluna do cliente, a folha passava ~10px da área
   imprimível do A4 e o Chromium CORTAVA o texto na borda física da página
   ("Terceiros(6923)" perdia o fecha-parênteses). Não voltar a `auto`.
   `.folha__bloco--largo` (Cliente/CNPJ/Endereço) ocupa as duas colunas, e
   as condições começam na altura de "Bairro", como no RVPE148. */
[data-pagina="crm-pedido-imprimir"] .folha__duas-colunas {
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: 0 16px; border: 1px solid #000; border-top: 0; padding: 4px 6px; margin-bottom: 0;
}
[data-pagina="crm-pedido-imprimir"] .folha__bloco--largo { grid-column: 1 / -1; }
/* `.folha__bloco` também é o par de colunas dos TOTAIS, mais abaixo — os
   dois lêem o mesmo rótulo:valor de `.folha__linha` (Reuse before create). */
[data-pagina="crm-pedido-imprimir"] .folha__bloco { margin: 0; min-width: 0; }
[data-pagina="crm-pedido-imprimir"] .folha__linha { display: flex; gap: 4px; margin: 0; }
[data-pagina="crm-pedido-imprimir"] .folha__linha dt { font-weight: 700; white-space: nowrap; flex: none; }
/* `min-width: 0` (mesmo motivo do Grid, um nível abaixo) + `anywhere`: a
   lista de e-mails vem colada por `;`, sem espaço — `break-word` sozinho
   não reduz a largura mínima do item flex, `anywhere` reduz, e o e-mail
   quebra DENTRO da coluna em vez de ser cortado ou empurrar a folha. */
[data-pagina="crm-pedido-imprimir"] .folha__linha dd { margin: 0; font-weight: 400; min-width: 0; overflow-wrap: anywhere; }

/* Itens: cabeçalho em negrito entre dois fios, linhas em Courier como o
   RVPE148 (números alinham pela coluna); valores à direita. */
[data-pagina="crm-pedido-imprimir"] .folha__itens {
  width: 100%; border-collapse: collapse; margin: 0 0 6px; font-size: 11px;
  border-bottom: 1px solid #000;
}
[data-pagina="crm-pedido-imprimir"] .folha__itens th {
  border-bottom: 1px solid #000; padding: 2px 4px; text-align: right;
  font-weight: 700; white-space: nowrap;
}
[data-pagina="crm-pedido-imprimir"] .folha__itens td {
  padding: 1px 4px; text-align: right; vertical-align: top; border-bottom: 1px solid var(--line);
  font-family: "Courier New", Courier, monospace; font-size: 10.5px; overflow-wrap: anywhere;
}
[data-pagina="crm-pedido-imprimir"] .folha__itens td:nth-child(n+3) { white-space: nowrap; }
[data-pagina="crm-pedido-imprimir"] .folha__itens th:nth-child(-n+2),
[data-pagina="crm-pedido-imprimir"] .folha__itens td:nth-child(-n+2) { text-align: left; }

/* Mesmo `minmax(0, 1fr)` do `.folha__duas-colunas` acima, por prevenção. */
[data-pagina="crm-pedido-imprimir"] .folha__totais {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 16px;
  padding: 0 6px 6px; margin-bottom: 4px; border-bottom: 1px solid #000;
}
[data-pagina="crm-pedido-imprimir"] .folha__totais .folha__linha dd { font-weight: 700; }

[data-pagina="crm-pedido-imprimir"] .folha__clausulas { font-size: 10px; line-height: 1.3; }
[data-pagina="crm-pedido-imprimir"] .folha__clausulas p { margin: 0; }
[data-pagina="crm-pedido-imprimir"] .folha__clausula { margin: 0 0 5px; }
/* Títulos das seções e as cláusulas 1-2 em negrito, corpo miúdo (RVPE148). */
[data-pagina="crm-pedido-imprimir"] .folha__clausula strong { display: block; font-size: 11.5px; margin-bottom: 1px; }
[data-pagina="crm-pedido-imprimir"] .folha__clausula--destaque { font-size: 11.5px; font-weight: 700; }
[data-pagina="crm-pedido-imprimir"] .folha__remessa,
[data-pagina="crm-pedido-imprimir"] .folha__armazem { margin-top: 8px; }
[data-pagina="crm-pedido-imprimir"] .folha__remessa { border-top: 1px solid #000; padding-top: 2px; }
[data-pagina="crm-pedido-imprimir"] .folha__remessa p,
[data-pagina="crm-pedido-imprimir"] .folha__armazem p { margin: 0 0 2px; overflow-wrap: anywhere; }

/* A folha do pedido é o único documento do app pensado para se espalhar por
   VÁRIAS páginas — a regra global acima (linha ~13027) trava `.card` numa
   página só, o que não se aplica aqui (o novo layout nem usa `.card`).
   Nunca uma linha de item partida entre duas páginas impressas. */
@media print {
  [data-pagina="crm-pedido-imprimir"] { background: #fff; padding: 0; }
  /* `width: 100%` explícito (16/09/2026): no impresso a folha deixa de ser
     centralizada (era `margin: 0 auto` sobre `max-width: 210mm`, o layout de
     TELA) e passa a OCUPAR toda a área imprimível que o `@page
     pedido-impresso` (acima) já reservou — sem isso o `max-width: none`
     sozinho ainda deixava a largura ao sabor do conteúdo, a mesma armadilha
     do Grid resolvida logo abaixo. */
  [data-pagina="crm-pedido-imprimir"] .folha {
    box-shadow: none; width: 100%; max-width: none; padding: 0;
  }
  [data-pagina="crm-pedido-imprimir"] tr { break-inside: avoid; }
}

/* ==========================================================================
   CRM PRODUTIVIDADE — escopo de página (data-pagina="produtividade-comercial")

   A tela é um MOSTRADOR, não um documento: lê-se de relance, para decidir quem
   cobrar hoje. Daí três decisões que valem para o bloco inteiro:
   1. medida é monoespaçada e tabular — número que não alinha não se compara;
   2. magnitude tem UMA linguagem só (preenchimento atrás do número, `.massa`),
      nunca três jeitos de dizer "quanto" na mesma tela;
   3. cor semântica (verde/vermelho) responde SÓ "bateu a meta?"; volume usa a
      tinta neutra de gráfico, para nenhuma cor responder duas perguntas.
   Tudo escopado à página: nada aqui vaza para as outras ~28 telas.
   ========================================================================== */
/* ---------------------------------------------------------------------------
   CRM · Agenda. O calendário é o FullCalendar vendorizado pela tela de salas;
   o tema dele sai dos tokens FCDS pelas próprias vars da lib, e os botões por
   classe (o v6 fixa as cores por classe, não por var — mesma abordagem de
   agendamento-salas.html, só trocando #ag-cal por #crm-cal).
   `.ag-*` é o escopo desta página. Cuidado: `.fc-` é o prefixo do FullCalendar
   E o prefixo do canvas da ficha do cliente (`#crm-modal-ficha .fc-caixa`,
   `.fc-porta`, `.fc-col-*`…) — os dois estão escopados por id justamente para
   não se encontrarem.
   --------------------------------------------------------------------------- */
/* A grade ocupa a altura que sobra do shell (a página declara
   `content--altura-cheia`), e cada coluna rola dentro de si. Sem o
   `min-height: 0`, um filho que cresce empurra o grid para além da tela e a
   rolagem volta para a página inteira — que é justamente o que a altura cheia
   veio evitar. */
/* UM cartão só, não dois. Calendário e atrasados são a mesma leitura — o que
   está marcado e o que ficou para trás —, e duas molduras lado a lado faziam a
   tela parecer duas telas. A divisa entre eles é uma linha, não uma borda de
   caixa; quem tem moldura é o conjunto. */
.ag-tela { display: grid; grid-template-columns: minmax(0, 1fr) 300px;
  flex: 1 1 auto; min-height: 0;
  background: var(--bi-bg-surface); border: 1px solid var(--bi-border-color);
  border-radius: var(--bi-radius-lg); overflow: hidden; }
.ag-tela > * { min-height: 0; }
@media (max-width: 992px) {
  /* No telefone a altura cheia atrapalha: duas caixas rolando dentro de uma
     tela de 844px dão 300px úteis cada. Ali a página rola inteira, como antes. */
  .ag-tela { grid-template-columns: minmax(0, 1fr); flex: 0 0 auto; }
  /* A caixa não tem altura própria aqui, então não pode recortar o que o
     calendário desenhar (o JS o põe em `height: auto` nesta faixa). */
  #crm-cal { overflow: visible; }
  #ag-atrasados { overflow-y: visible; }
  .ag-atrasados { border-left: 0; border-top: 1px solid var(--bi-border-color); }
}
#crm-cal { padding: var(--bi-space-sm) var(--bi-space-md);
  display: flex; flex-direction: column; overflow: hidden; }
/* O calendário preenche a caixa (o JS pede `height: 100%` ao FullCalendar) e
   a grade dos dias absorve a sobra. */
#crm-cal > .fc { flex: 1 1 auto; min-height: 0; }
#crm-cal {
  --fc-border-color: var(--bi-border-color-subtle);
  --fc-today-bg-color: color-mix(in srgb, var(--brand) 6%, #fff);
  --fc-now-indicator-color: var(--negative-text);
  --fc-list-event-hover-bg-color: var(--bi-bg-hover);
  --fc-neutral-bg-color: var(--bi-bg-hover);
}
#crm-cal .fc-toolbar-title { font-size: 1.05rem; font-weight: var(--bi-fw-semibold); color: var(--bi-text-primary); }
#crm-cal .fc-button-primary { background: var(--bi-bg-surface); border: 1px solid var(--bi-border-color); color: var(--bi-text-secondary); box-shadow: none; text-transform: capitalize; font-weight: var(--bi-fw-medium); transition: background-color .15s ease, color .15s ease, border-color .15s ease; }
#crm-cal .fc-button-primary:not(:disabled):hover { background: var(--bi-bg-hover); border-color: var(--bi-border-color); color: var(--bi-text-primary); }
#crm-cal .fc-button-primary:not(:disabled).fc-button-active,
#crm-cal .fc-button-primary:not(:disabled):active { background: var(--brand); border-color: var(--brand); color: var(--bi-text-on-accent); }
#crm-cal .fc-button:focus, #crm-cal .fc-button:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; box-shadow: none; }
#crm-cal .fc-col-header-cell-cushion, #crm-cal .fc-timegrid-axis-cushion, #crm-cal .fc-timegrid-slot-label-cushion { color: var(--bi-text-muted); text-decoration: none; }
#crm-cal .fc-event { cursor: pointer; border: none; font-size: .78rem; border-radius: var(--bi-radius-sm); }
#crm-cal .fc-event .fc-event-main { padding: 1px 4px; }

.ag-atrasados { padding: var(--bi-space-md);
  border-left: 1px solid var(--bi-border-color);
  display: flex; flex-direction: column; }
/* A lista rola dentro da coluna: atraso antigo não empurra a página. */
#ag-atrasados { overflow-y: auto; min-height: 0; }
/* `<a>` desde o reporte #67 (o cadastro tem endereço, e link é o que o botão
   direito entende); segue desenhada como a linha de lista que sempre foi —
   sem tinta de link, sem sublinhado. */
.ag-linha { display: block; width: 100%; text-align: left; background: none; border: 0; border-bottom: 1px solid var(--bi-border-color-subtle); padding: .5rem 0; cursor: pointer; color: inherit; text-decoration: none; }
.ag-linha:last-child { border-bottom: 0; }
.ag-linha:hover { background: var(--bi-bg-hover); color: inherit; }
/* Mesma ideia no painel do compromisso: o nome do cliente leva ao cadastro. */
#ag-modal .ag-cliente { color: inherit; text-decoration: none; }
#ag-modal .ag-cliente:hover, #ag-modal .ag-cliente:focus-visible { text-decoration: underline; }
.ag-contexto-texto { white-space: pre-line; color: var(--bi-text-secondary); }
/* CAIXA ALTA no cromo da agenda (dono, 03/09/2026: "quero tudo em maiúsculo",
   e sobre o alcance: "exceto texto corrido, apenas aqui"). É escopo de PÁGINA
   de propósito — `custom.css` é lido por ~28 telas, e um token global levaria
   isto para todas elas.

   Entra o cromo: cabeçalho do calendário, botão, título de painel, rótulo,
   e a linha forte que traz o cliente (na grade, na coluna de atrasados e
   no painel). NÃO entra texto corrido — `.ag-contexto-texto` (a observação do
   compromisso), o que a pessoa digita, ajuda e mensagem de erro ficam como
   foram escritos. */
#crm-cal .fc-toolbar-title,
#crm-cal .fc-col-header-cell-cushion,
#crm-cal .fc-button,
#crm-cal .fc-event-title,
.ag-atrasados .crm-titulo,
.ag-linha .crm-forte,
.ag-linha .crm-rotulo,
#ag-modal .offcanvas-title,
#ag-modal .crm-forte,
#ag-modal .form-select,
#ag-modal .crm-rotulo,
#ag-modal .form-label,
#ag-modal .crm-btn, #ag-modal .crm-btn-2, #ag-modal .crm-btn-3,
#ag-lote .form-label, #ag-lote label, #ag-lote .btn, #ag-lote #ag-lote-conta {
  text-transform: uppercase; }
/* `text-transform` não herda para dentro de <button> pela folha do agente: o
   cabeçalho ordenável e os botões do FullCalendar precisam da regra neles
   mesmos — foi essa a armadilha que deixou um `text-transform` viver morto na
   lista de pedidos. Por isso `.fc-button` e `.btn` estão na lista acima, e não
   só o contêiner. */

/* Estado do compromisso. Cor por ESTADO, e atraso é a coisa mais vermelha da
   tela — o canal (Ligar/Visita/…) vai no texto, não na cor. */
/* A cor do TEXTO tem de ir na var do FullCalendar: ele pinta o título por
   `--fc-event-text-color` (branco por padrão) num elemento mais fundo, então
   `color` no evento de fora perde — era isso que deixava letra branca sobre
   fundo claro, com o compromisso ilegível. */
#crm-cal .ag-atrasado, .ag-linha.ag-atrasado { background: var(--negative-subtle); color: var(--negative-text); }
#crm-cal .ag-atrasado { --fc-event-text-color: var(--negative-text); }
/* Compromisso em pé é VERDE: hoje em verde cheio (o mais forte da tela depois
   do atraso), o que vem pela frente no mesmo verde diluído. O cinza de antes
   sumia contra o fundo do calendário — um compromisso quase invisível é um
   compromisso esquecido. */
#crm-cal .ag-hoje { background: var(--crm-acento); color: #fff;
  --fc-event-text-color: #fff; }
#crm-cal .ag-futuro { background: color-mix(in srgb, var(--crm-acento) 14%, #fff);
  color: var(--crm-acento); --fc-event-text-color: var(--crm-acento); }
/* Canal: ícone, não cor — a cor já está dizendo o estado. Font Awesome já é
   carregado pelo shell; o glifo entra por `content` na família certa.
   O título traz só o cliente (sem "Ligar ·"): o texto depois da `/` é o nome
   do canal para leitor de tela, que num glifo sozinho não ouve nada. Vale na
   grade do mês, na lista da semana e na coluna de atrasados. */
#crm-cal .fc-event-title::before, #crm-cal .fc-list-event-title a::before, .ag-linha .crm-forte::before { font-family: 'Font Awesome 6 Free'; font-weight: 900; margin-right: .3rem; }
#crm-cal .ag-canal-ligar :is(.fc-event-title, .fc-list-event-title a)::before, .ag-linha.ag-canal-ligar .crm-forte::before { content: '\f095' / 'Ligar'; }
#crm-cal .ag-canal-email :is(.fc-event-title, .fc-list-event-title a)::before, .ag-linha.ag-canal-email .crm-forte::before { content: '\f0e0' / 'E-mail'; }
#crm-cal .ag-canal-visita :is(.fc-event-title, .fc-list-event-title a)::before, .ag-linha.ag-canal-visita .crm-forte::before { content: '\f3c5' / 'Visita'; }
#crm-cal .ag-canal-whatsapp :is(.fc-event-title, .fc-list-event-title a)::before, .ag-linha.ag-canal-whatsapp .crm-forte::before { content: '\f232' / 'WhatsApp'; font-family: 'Font Awesome 6 Brands'; font-weight: 400; }
#crm-cal .ag-canal-reuniao :is(.fc-event-title, .fc-list-event-title a)::before, .ag-linha.ag-canal-reuniao .crm-forte::before { content: '\f0c0' / 'Reunião'; }
#crm-cal .ag-canal-outro :is(.fc-event-title, .fc-list-event-title a)::before, .ag-linha.ag-canal-outro .crm-forte::before { content: ''; margin-right: 0; }

[data-pagina="produtividade-comercial"] .n {
  font-variant-numeric: tabular-nums; letter-spacing: -0.01em;
}
[data-pagina="produtividade-comercial"] .magro { color: var(--ink-2); }
/* `.text-secondary` do Bootstrap dá 4,1 sobre o cinza da app — abaixo do piso AA
   de 4,5 que o PRODUCT.md trata como piso, não meta. Mesmo papel, tinta que passa. */
[data-pagina="produtividade-comercial"] .crm-rotulo-campo { color: var(--ink-2); }

/* Número auditável: um clique abre de onde ele vem. Marca discreta, não ícone —
   e alvo de teclado de verdade, com foco visível (o `?` só serve se chegar nele
   sem mouse). */
[data-pagina="produtividade-comercial"] .aud { cursor: help; }
[data-pagina="produtividade-comercial"] .aud:focus-visible {
  outline: 2px solid var(--chart-azul); outline-offset: 2px; border-radius: 2px;
}

/* ── CHIP DE ESCOPO ───────────────────────────────────────────────────────
   O recorte por vendedor muda TODOS os números da tela. Sem um aviso persistente
   isso vira estado invisível: o usuário lê 289.224 kg achando que é a equipe. */
[data-pagina="produtividade-comercial"] .crm-escopo {
  display: flex; align-items: center; gap: .5rem; width: max-content;
  margin-bottom: 1rem; padding: .25rem .375rem .25rem .875rem;
  border: var(--bs-border-width) solid var(--chart-azul); border-radius: var(--raio-chip);
  background: color-mix(in srgb, var(--chart-azul) 10%, transparent);
  font-size: var(--bi-fs-compact);
}
[data-pagina="produtividade-comercial"] .crm-escopo__sair {
  font: inherit; border: 0; border-radius: var(--raio-chip); padding: .125rem .5rem;
  background: var(--bi-bg-surface); color: var(--ink-2); cursor: pointer;
}
[data-pagina="produtividade-comercial"] .crm-escopo__sair:hover { color: var(--ink); }

/* ── ESPERA / VAZIO / ERRO ────────────────────────────────────────────────
   Três estados com PESOS diferentes. Antes eram um só: `mostrarErro()` chamava
   `mostrarVazio()` com uma string na frente, então "o Ploomes caiu" e "não há
   negócio neste mês" saíam idênticos — uma linha cinza, sem saída. */
[data-pagina="produtividade-comercial"] .crm-espera,
[data-pagina="produtividade-comercial"] .crm-estado {
  max-width: 46rem; margin: 3rem auto; text-align: center;
}
[data-pagina="produtividade-comercial"] .crm-espera__oque {
  font-size: 1.0625rem; font-weight: 600; color: var(--ink); margin: 1rem 0 .25rem;
}
[data-pagina="produtividade-comercial"] .crm-espera__porque,
[data-pagina="produtividade-comercial"] .crm-espera__recorte {
  font-size: var(--bi-fs-compact); color: var(--ink-2); margin: 0 0 .25rem;
}
[data-pagina="produtividade-comercial"] .crm-espera__recorte { color: var(--ink-2); }
[data-pagina="produtividade-comercial"] .crm-espera__tempo {
  font-variant-numeric: tabular-nums; font-size: var(--bi-fs-compact);
  color: var(--ink-2); margin: .75rem 0 0;
}
/* Pulso, NÃO barra de progresso: são quatro chamadas sequenciais no servidor e o
   cliente não recebe progresso. Uma barra que enche seria informação inventada;
   o que enche de verdade é o cronômetro ao lado, que conta o tempo real. */
[data-pagina="produtividade-comercial"] .crm-espera__barra {
  height: .375rem; max-width: 18rem; margin: 0 auto; overflow: hidden;
  background: var(--surf-2); border-radius: var(--raio-chip);
}
[data-pagina="produtividade-comercial"] .crm-espera__pulso {
  width: 40%; height: 100%; border-radius: inherit; background: var(--chart-azul);
  animation: crm-pulso 1.4s ease-in-out infinite;
}
@keyframes crm-pulso {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(250%); }
}
@media (prefers-reduced-motion: reduce) {
  [data-pagina="produtividade-comercial"] .crm-espera__pulso {
    animation: none; width: 100%; opacity: .45;
  }
}
[data-pagina="produtividade-comercial"] .crm-estado__titulo {
  font-size: 1.0625rem; font-weight: 600; color: var(--ink); margin: 0 0 .5rem;
}
[data-pagina="produtividade-comercial"] .crm-estado__corpo {
  font-size: var(--bi-fs-compact); color: var(--ink-2); margin: 0 0 .75rem;
}
[data-pagina="produtividade-comercial"] .crm-estado__diag {
  font-family: var(--bi-font-mono); font-size: .75rem; color: var(--ink-2);
  margin: 0 0 1rem; overflow-wrap: anywhere;
}
[data-pagina="produtividade-comercial"] .crm-estado--erro .crm-estado__titulo {
  color: var(--negative-text);
}

/* ── MOSTRADOR ────────────────────────────────────────────────────────────
   A manchete é uma PERGUNTA respondida. À esquerda a resposta com o instrumento
   que a situa contra a meta; à direita as medidas de apoio. */
[data-pagina="produtividade-comercial"] .crm-mostrador {
  display: grid; grid-template-columns: minmax(18rem, 1.1fr) minmax(16rem, 1fr);
  gap: clamp(1.25rem, 4vw, 3rem);
}
@media (max-width: 767.98px) {
  [data-pagina="produtividade-comercial"] .crm-mostrador { grid-template-columns: 1fr; }
}
[data-pagina="produtividade-comercial"] .crm-pergunta {
  font-size: var(--bi-fs-compact); color: var(--ink-2); margin: 0 0 .375rem;
}
[data-pagina="produtividade-comercial"] .crm-resposta {
  display: flex; align-items: baseline; gap: .625rem; flex-wrap: wrap;
}
[data-pagina="produtividade-comercial"] .crm-resposta__taxa {
  font-size: clamp(2.25rem, 6vw, 2.875rem); font-weight: 600; line-height: 1;
  letter-spacing: -0.04em;
}
[data-pagina="produtividade-comercial"] .crm-selo {
  font-size: var(--bi-fs-compact); font-weight: 600; white-space: nowrap;
  padding: .1875rem .5rem; border-radius: var(--raio-chip);
}
[data-pagina="produtividade-comercial"] .crm-selo--ruim {
  color: var(--negative-text); background: color-mix(in srgb, var(--negative) 8%, transparent);
}
[data-pagina="produtividade-comercial"] .crm-selo--bom {
  color: var(--positive-text); background: color-mix(in srgb, var(--positive) 9%, transparent);
}

/* Bullet (Few, 2006): medida contra alvo. Trilha de 0 a 2× a meta, então o tique
   do alvo cai sempre no meio e a escala não dança entre recortes. Cor só na
   medida; trilha e tique são estrutura, em tinta neutra. */
[data-pagina="produtividade-comercial"] .crm-bullet {
  position: relative; height: .6875rem; margin-top: 1rem;
  background: var(--surf-2); border: var(--bs-border-width) solid var(--line);
  border-radius: 2px;
}
[data-pagina="produtividade-comercial"] .crm-bullet__medida {
  position: absolute; inset-block: 0; left: 0; background: var(--negative); border-radius: 1px;
}
[data-pagina="produtividade-comercial"] .crm-bullet__medida--bom { background: var(--positive); }
[data-pagina="produtividade-comercial"] .crm-bullet__alvo {
  position: absolute; inset-block: -4px; width: 2px; background: var(--ink);
}
[data-pagina="produtividade-comercial"] .crm-bullet__eixo {
  display: flex; justify-content: space-between; margin-top: .4375rem;
  font-variant-numeric: tabular-nums; font-size: .6875rem; color: var(--ink-2);
}

[data-pagina="produtividade-comercial"] .crm-apoio {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: 1.25rem; align-self: center; margin: 0;
}
[data-pagina="produtividade-comercial"] .crm-apoio dt {
  font-size: .6875rem; color: var(--ink-2); text-transform: uppercase;
  letter-spacing: .055em; margin-bottom: .25rem; font-weight: 400;
}
[data-pagina="produtividade-comercial"] .crm-apoio dd {
  margin: 0; font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.02em;
}
[data-pagina="produtividade-comercial"] .crm-apoio small {
  display: block; margin-top: .1875rem; font-size: .6875rem; font-weight: 400;
  letter-spacing: 0; line-height: 1.3; color: var(--ink-2);
}

/* ── ESTADO DE HOJE ───────────────────────────────────────────────────────
   As duas medidas gerenciais que não seguem o período do topo. Reusa a grade
   do `.crm-apoio` do mostrador de propósito: são medidas da mesma família
   visual, e um segundo desenho para a mesma coisa só cria dialeto. O que muda
   é o corpo, que aqui é a seção inteira e precisa do próprio respiro. */
[data-pagina="produtividade-comercial"] .crm-hoje__corpo {
  padding: 1rem 1.25rem 1.25rem;
}
[data-pagina="produtividade-comercial"] .crm-hoje__corpo .crm-apoio {
  align-self: start;
}
[data-pagina="produtividade-comercial"] .crm-hoje__nota,
[data-pagina="produtividade-comercial"] .crm-fora-coorte {
  margin: .75rem 0 0; font-size: var(--bi-fs-compact); color: var(--ink-2);
}
[data-pagina="produtividade-comercial"] .crm-fora-coorte { margin-top: .5rem; }
/* Composição das duas fontes, colada na taxa que ela explica. Tabular para os
   números alinharem entre um recorte e outro; a mesma tinta secundária da
   exclusão de coorte, porque as duas são nota de rodapé da manchete. */
[data-pagina="produtividade-comercial"] .crm-composicao {
  margin: .25rem 0 0; font-size: var(--bi-fs-compact); color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}

/* Duas seções por linha quando cabe. `auto-fit` com piso de 22rem: abaixo disso
   as tabelas cortariam coluna, que é o defeito que a grade existe para evitar. */
[data-pagina="produtividade-comercial"] .crm-par {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(22rem, 1fr));
  gap: 1rem;
  /* `start`, não o `stretch` padrão: as duas listas têm comprimentos diferentes
     (5 motivos em agosto, 9 em julho) e esticar a mais curta abria um vazio do
     tamanho da diferença DENTRO do cartão. Cada um tem a altura do que diz. */
  align-items: start;
}

/* ── TABELAS DA PÁGINA ────────────────────────────────────────────────── */
[data-pagina="produtividade-comercial"] .crm-tbl { width: 100%; border-collapse: collapse; }
[data-pagina="produtividade-comercial"] .crm-tbl th {
  font-size: .6875rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .055em; color: var(--ink-2); text-align: left;
  padding: .25rem .625rem; white-space: nowrap; vertical-align: bottom;
}
[data-pagina="produtividade-comercial"] .crm-tbl td {
  padding: .25rem .625rem; line-height: 1.3; white-space: nowrap;
  border-top: var(--bs-border-width) solid var(--line);
}
[data-pagina="produtividade-comercial"] .crm-tbl th.dir,
[data-pagina="produtividade-comercial"] .crm-tbl td.dir { text-align: right; }
[data-pagina="produtividade-comercial"] .crm-tbl tbody tr:hover td { background: var(--surf-2); }
/* Linha de Total: negrito e borda mais firme separam a soma das parcelas. Sem
   `hover`, porque não é uma linha em que se clique. */
/* Cabeçalho de GRUPO ("Interações" cobrindo as duas colunas de CRM): alinhado à
   direita como as colunas que ele cobre, com uma régua que termina onde elas
   terminam. Centrado, ele flutuava no meio do vão e não se ligava a nada. */
[data-pagina="produtividade-comercial"] #crm-atividade th.grupo {
  text-align: right; border-bottom: var(--bs-border-width) solid var(--line-3);
  padding-bottom: .1875rem;
}
/* As colunas de número têm largura FIXA e o nome absorve a sobra. Sem isto as
   cinco colunas dividiam 1.300px em partes iguais e os números da mesma linha
   ficavam a um palmo um do outro — o olho perdia a linha no caminho. */
[data-pagina="produtividade-comercial"] #crm-atividade th.dir,
[data-pagina="produtividade-comercial"] #crm-atividade td.dir { width: 7.5rem; }
/* O rótulo composto do recorte de uma fonte só ("Interações · CRM Four") pede
   mais que as 7,5rem das colunas normais. */
[data-pagina="produtividade-comercial"] #crm-atividade thead tr:only-child th.dir {
  width: 11rem;
}
[data-pagina="produtividade-comercial"] #crm-atividade .nome { width: 100%; }
/* Vendedor escolhido: a linha fica MARCADA em vez de a lista encolher, porque é
   ela que permite trocar de vendedor. Fundo + barra à esquerda + `aria-current`,
   nunca só cor — há daltônico no time e a marcação é informação, não enfeite. */
[data-pagina="produtividade-comercial"] .crm-tbl tbody tr.crm-linha--escolhida > td {
  background: color-mix(in srgb, var(--chart-azul) 9%, transparent);
}
[data-pagina="produtividade-comercial"] .crm-tbl tbody tr.crm-linha--escolhida > td:first-child {
  box-shadow: inset 2px 0 0 var(--chart-azul);
}
[data-pagina="produtividade-comercial"] .crm-tbl tbody tr.crm-linha--escolhida .crm-quem {
  font-weight: 700;
}
[data-pagina="produtividade-comercial"] .crm-tbl tfoot td {
  border-top-width: 2px; font-weight: 600;
}
[data-pagina="produtividade-comercial"] .crm-tbl .posto {
  width: 1.5rem; text-align: right; font-variant-numeric: tabular-nums;
  font-size: .75rem; color: var(--ink-2);
}
/* Nome longo trunca em vez de quebrar: linha de altura variável faz o olho
   perder a linha ao correr para a direita, o pior defeito numa grade. */
[data-pagina="produtividade-comercial"] .crm-tbl .nome {
  max-width: 22rem; overflow: hidden; text-overflow: ellipsis;
}
[data-pagina="produtividade-comercial"] #crm-drill td:nth-child(1) {
  max-width: 22rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* O gatilho do filtro de coluna acompanha a largura do <th>, e na coluna Cliente
   (a mais larga da grade) isso vira uma caixa vazia de 400px com "Todos" perdido
   no meio. Encostado à esquerda e com teto, ele lê como controle e não como
   segunda linha de cabeçalho. */
[data-pagina="produtividade-comercial"] #crm-drill .th-filter .colfilter-multi {
  max-width: 12rem;
}

/* Magnitude ATRÁS do número, na própria célula — uma linguagem só para "quanto".
   Tinta de gráfico (neutra), porque volume não é bom nem ruim; quem responde
   valência é a régua de conversão, ao lado. */
[data-pagina="produtividade-comercial"] .crm-tbl td.massa {
  position: relative; isolation: isolate;
}
[data-pagina="produtividade-comercial"] .crm-tbl td.massa::before {
  content: ""; position: absolute; inset-block: 1px; right: 0; z-index: -1;
  width: var(--p, 0%); border-radius: 2px;
  background: color-mix(in srgb, var(--ink-4) 30%, transparent);
}

/* Lista longa rola DENTRO da seção, com o cabeçalho grudado. Quinze vendedores
   esticavam a página em 538px para mostrar uma cauda de 2.200 kg. */
[data-pagina="produtividade-comercial"] .crm-rolagem { overflow-x: auto; }
[data-pagina="produtividade-comercial"] .crm-rolagem--lista {
  max-height: 17.5rem; overflow-y: auto;
}
[data-pagina="produtividade-comercial"] .crm-rolagem--lista thead th {
  position: sticky; top: 0; z-index: 1; background: var(--bi-bg-surface);
}

/* Régua de conversão na célula. Ocupa a coluna INTEIRA em vez de uma largura
   fixa: a folga da tabela caía toda nesta célula (225px de branco, medido) e
   régua comprida ainda lê melhor — a distância até o tique da meta é a
   informação, e ela ganha resolução com o comprimento. */
[data-pagina="produtividade-comercial"] td.cel-regua {
  display: flex; align-items: center; gap: .5rem;
}
[data-pagina="produtividade-comercial"] .crm-micro {
  position: relative; flex: 1; min-width: 5.75rem; height: .5rem;
  background: var(--surf-2); border: var(--bs-border-width) solid var(--line);
  border-radius: 1px;
}
[data-pagina="produtividade-comercial"] .crm-micro__v {
  position: absolute; inset-block: 0; left: 0; border-radius: 1px;
}
[data-pagina="produtividade-comercial"] .crm-micro__v--bom  { background: var(--positive); }
[data-pagina="produtividade-comercial"] .crm-micro__v--ruim { background: var(--negative); }
/* Tique da meta no meio, pela mesma escala 0–2× do bullet do topo. */
[data-pagina="produtividade-comercial"] .crm-micro__regua {
  position: absolute; inset-block: -2px; left: 50%; width: 1px; background: var(--ink-2);
}
[data-pagina="produtividade-comercial"] .crm-micro__num {
  font-size: .8125rem; min-width: 3rem; text-align: right;
}

/* ── COMPOSIÇÃO — barra empilhada 100% ────────────────────────────────────
   Partes disjuntas comparadas por COMPRIMENTO. Ângulo não compara; e custa 28px
   de altura no lugar de um círculo de 280px.
   "Em aberto" é NEUTRO e claro de propósito: é a fatia que ainda não virou
   dinheiro, e costuma ser três quartos da barra — pintá-la punha a maior massa
   de cor da tela justamente no que não decidiu nada. Clara, ela recua e deixa
   ganho (verde) e perda (vermelho) saltarem, que é a regra "cor significa
   dinheiro". Rótulo em tinta escura, porque o fundo agora é claro. */
[data-pagina="produtividade-comercial"] .crm-empilhada {
  display: flex; height: 1.75rem; overflow: hidden;
  border-radius: var(--bi-radius-sm); background: var(--surf-2);
}
[data-pagina="produtividade-comercial"] .crm-empilhada__parte {
  display: flex; align-items: center; justify-content: center; min-width: 0;
  overflow: hidden; font-size: .75rem; font-weight: 600; color: #fff; white-space: nowrap;
}
[data-pagina="produtividade-comercial"] .crm-empilhada__parte--aberto  { background: var(--surf-2); color: var(--ink); }
[data-pagina="produtividade-comercial"] .crm-empilhada__parte--ganha   { background: var(--positive-text); }
[data-pagina="produtividade-comercial"] .crm-empilhada__parte--perdida { background: var(--negative-text); }
[data-pagina="produtividade-comercial"] .crm-legenda {
  display: flex; flex-wrap: wrap; gap: 1rem; margin-top: .5rem;
  font-size: .75rem; color: var(--ink-2);
}
[data-pagina="produtividade-comercial"] .crm-chave::before {
  content: ""; display: inline-block; width: .5rem; height: .5rem;
  border-radius: 50%; margin-right: .375rem;
}
[data-pagina="produtividade-comercial"] .crm-chave--aberto::before  { background: var(--line-3); }
[data-pagina="produtividade-comercial"] .crm-chave--ganha::before   { background: var(--positive-text); }
[data-pagina="produtividade-comercial"] .crm-chave--perdida::before { background: var(--negative-text); }

/* A ressalva que a manchete esconde, no espaço que a fileira deixava vazio. */
[data-pagina="produtividade-comercial"] .crm-fecho {
  display: flex; align-items: baseline; gap: .75rem;
  margin-top: 1.125rem; padding-top: .75rem;
  border-top: var(--bs-border-width) solid var(--line);
}
[data-pagina="produtividade-comercial"] .crm-fecho__num {
  flex: none; font-size: 1.375rem; font-weight: 700; letter-spacing: -0.03em;
  color: var(--positive-text);
}
[data-pagina="produtividade-comercial"] .crm-fecho__txt {
  margin: 0; font-size: var(--bi-fs-compact); color: var(--ink-2);
}
[data-pagina="produtividade-comercial"] .crm-fecho__txt b { color: var(--ink); font-weight: 600; }

/* ── MOTIVOS DE PERDA ─────────────────────────────────────────────────── */
[data-pagina="produtividade-comercial"] .crm-causa {
  position: relative; isolation: isolate;
  display: grid; grid-template-columns: 1fr auto; gap: 0 .75rem;
  align-items: baseline; padding: .3125rem .5rem;
  border-top: var(--bs-border-width) solid var(--line);
}
[data-pagina="produtividade-comercial"] .crm-causa::before {
  content: ""; position: absolute; inset-block: 1px; left: 0; z-index: -1;
  width: var(--p, 0%); border-radius: 2px;
  background: color-mix(in srgb, var(--ink-4) 30%, transparent);
}
[data-pagina="produtividade-comercial"] .crm-causa__kg {
  font-size: var(--bi-fs-compact); color: var(--ink-2);
}
/* "ruído" = cotação-teste, que infla o denominador de perdas. Marca com TEXTO,
   não só cor — a informação não pode depender de enxergar a cor. */
[data-pagina="produtividade-comercial"] .crm-marca {
  font-size: .6875rem; padding: 0 .375rem; border-radius: var(--raio-chip);
  background: var(--surf-2); color: var(--ink-2);
}

/* ── NOME DE VENDEDOR = PORTA PARA O RECORTE DELE ─────────────────────────
   Botão de verdade: cor de link, sublinhado no hover, cursor de ponteiro, foco
   visível. O que é clicável tem de parecer clicável. */
[data-pagina="produtividade-comercial"] .crm-quem {
  font: inherit; font-weight: 500; color: var(--chart-azul); background: none;
  border: 0; padding: 0; text-align: left; white-space: nowrap; cursor: pointer;
}
[data-pagina="produtividade-comercial"] .crm-quem:hover { text-decoration: underline; }
[data-pagina="produtividade-comercial"] .crm-quem:focus-visible {
  outline: 2px solid var(--chart-azul); outline-offset: 2px; border-radius: 2px;
}

/* Uma régua de densidade para TODAS as grades da tela. Medido antes: quatro
   tabelas com quatro alturas de linha (27 / 39 / 53 / 60px). A de 27px prova que
   o piso é legível; as outras eram 44% a 122% mais altas sem motivo, e era daí
   que vinha a altura da página. O piso tipográfico não muda — só o respiro. */
[data-pagina="produtividade-comercial"] .tbl > tbody > tr > td,
[data-pagina="produtividade-comercial"] .tbl > tfoot > tr > td,
[data-pagina="produtividade-comercial"] table.dataTable > tbody > tr > td {
  padding-block: .25rem; line-height: 1.25;
}
[data-pagina="produtividade-comercial"] .tbl > thead > tr > th,
[data-pagina="produtividade-comercial"] table.dataTable > thead > tr > th {
  padding-block: .25rem;
}

/* ==========================================================================
   PREVISÃO DE CAIXA — título ignorado
   A linha marcada "ignorar" sai dos números (isso é backend) mas continua na
   tabela como referência: esmaecida, com o valor ainda legível. Só cor/opacidade
   — nada de esconder, que é o ponto de deixá-la à vista.
   ========================================================================== */
/* Na barra da grade, ao lado da busca: texto de controle, não de rodapé. */
[data-pagina="previsao_caixa"] .grade .pc-pagos { flex: 0 0 auto; white-space: nowrap; }
[data-pagina="previsao_caixa"] .grade .pc-pagos .form-check-label { font-size: .8125rem; }
[data-pagina="previsao_caixa"] tr.pc-linha-ignorada > td {
  color: var(--bi-text-muted);
  text-decoration: line-through;
  text-decoration-color: color-mix(in srgb, var(--bi-text-muted) 45%, transparent);
}
[data-pagina="previsao_caixa"] tr.pc-linha-ignorada > td:has(.pc-ignorar) {
  text-decoration: none;
}

/* ==========================================================================
   COCKPIT — pipeline strip (Faturamento/Margem/Despesas/Resultado)
   Remade as a flat 2×2 metric panel. The old layout was a rigid 7-track grid
   (1.2fr 28px 1fr 28px 1fr 28px 1fr) — an "equation" row with fixed operator
   columns. Its content needed ~1040px but each strip is only span-6 (~440–670px),
   so it overflowed and clipped at every real width. The 2×2 fits the strip and
   stacks to 1 col on phones; operators dropped (labels $/⬆/⬇/= carry the relation).

   Inadimplência (snapshot of a different date, never part of the period's
   equation) was cut from here — it duplicated the TODOS row already in the
   Desempenho por Segmento table below and needed a full-width exception cell
   to avoid breaking these 4-cell positional borders. Its position note now
   lives beside that table's card-hd (`.n`); its drill-down moved into the
   table's Inadimplência `<th>`.
   ========================================================================== */
.cockpit-pipeline {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: stretch;
  background: var(--bi-bg-surface);
  border: var(--bi-border);
  border-radius: var(--bi-radius-md);
  overflow: hidden;
}
.cockpit-pipeline__cell {
  padding: var(--bi-space-sm) var(--bi-space-md);
  border-right: var(--bi-border);
  border-bottom: var(--bi-border);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--bi-space-2xs);
  min-width: 0;
}
.cockpit-pipeline__cell:nth-child(2n) { border-right: none; }
.cockpit-pipeline__cell:nth-last-child(-n+2) { border-bottom: none; }
.cockpit-pipeline__operator { display: none; }
.cockpit-pipeline__label {
  font-size: 0.75rem;
  font-weight: var(--bi-fw-semibold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bi-text-muted);
  margin-bottom: var(--bi-space-xs);
  white-space: nowrap;
}
.cockpit-pipeline__hero {
  font-family: var(--bi-font-display);
  font-size: 1.55rem;
  font-weight: 700;
  color: var(--bi-text-primary);
  line-height: 1.1;
}
.cockpit-pipeline__row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--bi-space-2xs) var(--bi-space-xs);
  margin-bottom: var(--bi-space-xs);
  min-width: 0;
}
.cockpit-pipeline__row:last-child { margin-bottom: 0; }
.cockpit-pipeline__badge {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: var(--bi-space-3xs) var(--bi-space-xs);
  border-radius: var(--bi-radius-sm);
  flex-shrink: 0;
  line-height: 1.4;
}
/* BRUTA vs CONTRIB. are categorical label TYPES — flat tinted chips (FCDS chip
   vocabulary), not heavy dark fills. */
.cockpit-pipeline__badge--bruta   { background: var(--surf-3); color: var(--ink-2); }
.cockpit-pipeline__badge--contrib { background: var(--acc-soft); color: var(--acc-ink); }
.cockpit-pipeline__val {
  font-family: var(--bi-font-display);
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--bi-text-primary);
  line-height: 1;
  white-space: nowrap;
}
.cockpit-pipeline__pct {
  font-size: 0.75rem;
  color: var(--bi-text-secondary);
  margin-left: auto;
}
/* Faixa da inadimplência (02/09/2026) — irmã da tira acima, não uma quinta
   célula dela: a tira é a equação do PERÍODO e tem bordas posicionais de 4
   células (ver o bloco acima; a inadimplência já saiu dali uma vez).
   Faixa, não cartão: como cartão de KPI ela ocupava a largura inteira com um
   número pequeno encostado à esquerda e dois terços de vazio — "feio demais"
   (dono, 02/09/2026). Aqui o número fica numa ponta e a frase que o explica na
   outra, então a largura toda é largura USADA. Reusa `__label`/`__hero` da tira
   de propósito: mesmo tipo, mesma altura de leitura. */
.cockpit-inadimplencia {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bi-space-md);
  flex-wrap: wrap;
  padding: var(--bi-space-sm) var(--bi-space-md);
  background: var(--bi-bg-surface);
  border: var(--bi-border);
  border-radius: var(--bi-radius-md);
}
.cockpit-inadimplencia__stat { min-width: 0; }
.cockpit-inadimplencia__nota {
  margin: 0;
  font-size: 0.8125rem;
  color: var(--bi-text-muted);
  text-align: right;
  min-width: 0;
}
/* Empilhado, a nota alinha com o número — texto à direita numa coluna só é
   ruído de leitura. */
@media (max-width: 767.98px) {
  .cockpit-inadimplencia__nota { text-align: left; }
}

@media (max-width: 479.98px) {
  .cockpit-pipeline { grid-template-columns: 1fr; }
  .cockpit-pipeline__cell { border-right: none; }
  .cockpit-pipeline__cell:nth-last-child(-n+2) { border-bottom: var(--bi-border); }
  .cockpit-pipeline__cell:last-child { border-bottom: none; }
}

/* "ver registros" — quiet drill-down trigger, not a floating link-blue button.
   Reuses Bootstrap's .btn/.btn-sm for sizing (no .btn-link, so no blue/
   underline-by-default); muted ink here, underline on hover/focus only. The
   keyboard focus ring lives in §23 ACCESSIBILITY (dropping .btn-link also
   drops the --bs-btn-focus-shadow-rgb it supplied). The Inadimplência trigger
   lives beside its nota in the "Desempenho por Segmento" card-hd, not in the
   table's <th> — a two-line header cell there sat 25px off the other six
   single-line column labels (all thead th are vertical-align:bottom). */
.cockpit-drill-btn {
  color: var(--bi-text-muted);
  text-decoration: none;
  text-transform: none;
  letter-spacing: normal;
}
.cockpit-drill-btn:hover,
.cockpit-drill-btn:focus-visible {
  color: var(--bi-text-primary);
  text-decoration: underline;
}
/* Left-aligned like the cell's own text (not Bootstrap's centered .btn),
   pinned to the cell's bottom edge regardless of how tall the row is —
   margin-top:auto claims the free space above it, so the label/value stay
   flush at the top and the button lands in the same place cell to cell. */
.cockpit-pipeline__cell .cockpit-drill-btn {
  align-self: flex-start;
  margin-top: auto;
}

/* Espaçamento real entre os grupos (BRUTA/CONTRIB./"N registros") do totalizador
   do modal Registros — antes era um `<span class="mx-3"></span>` vazio só para
   empurrar via margin. Cada grupo (badge+valor, ou o "N registros") chega da JS
   como um único <span>, item direto do flex; o gap fica no container, não em
   elemento decorativo. */
#bi-registros-modal-totais {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2rem;
}

#bi-tabela-segmentos-cockpit,
#bi-tabela-subsegmentos-modal {
  font-size: 0.8125rem;
}
#bi-tabela-segmentos-cockpit thead th,
#bi-tabela-subsegmentos-modal thead th {
  font-size: 0.75rem;
}

/* ==========================================================================
   Tabelas de Preço (CRM) — auditoria do cadastro do ERP
   ========================================================================== */

/* Gatilho de descer um degrau (abrir a tabela, abrir o produto). É um <button>
   porque a ação acontece na própria página, e parece um link porque é isso que
   ele faz — não há uma classe de "botão-link" no CRM, e um .crm-btn cheio numa
   célula de código transformaria a coluna inteira numa fileira de botões. */
[data-pagina="crm-tabelas-preco"] .crm-link,
#tp-painel .crm-link {
  background: none;
  border: 0;
  padding: 0;
  color: var(--crm-acento);
  font: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}
[data-pagina="crm-tabelas-preco"] .crm-link:hover,
#tp-painel .crm-link:hover { opacity: .84; }
[data-pagina="crm-tabelas-preco"] .crm-link:focus-visible,
#tp-painel .crm-link:focus-visible {
  outline: 2px solid var(--crm-acento);
  outline-offset: 2px;
}

/* O painel divide dois níveis (itens da tabela, produto entre tabelas) e ambos
   trazem grade: mais largo que o padrão do offcanvas, senão a coluna de
   descrição do produto quebra em três linhas. */
#tp-painel { width: min(64rem, 96vw); }

/* A lista é a grade da casa (`tabelas-preco.js`, 15/09/2026), na altura da
   janela: a folha é branca como nas outras telas da grade, e o recuo de cima
   volta porque a altura cheia zera o do shell. */
.content:has(> .page[data-pagina="crm-tabelas-preco"] > .grade),
.page[data-pagina="crm-tabelas-preco"]:has(> .grade) { background: #fff; }
.content--altura-cheia > .page[data-pagina="crm-tabelas-preco"] {
  padding-top: var(--content-pad-y); }
/* A descrição é o texto longo da linha ("Comissão: 2%; Condição de pagamento:
   A Prazo; Frete: FOB; ICMS: Importado (4%)"): ela fica com a SOBRA da linha e
   corta na reticência, com o texto inteiro no `title`. `max-width:0` é o teto
   que faz a coluna ceder; o invólucro herdaria esse zero e sumiria com o
   texto, então quem corta é o `td` (mesmo caso da Cobertura). */
[data-pagina="crm-tabelas-preco"] .grade .tp-col-descricao {
  width: 100%; max-width: 0; min-width: 14rem; }
[data-pagina="crm-tabelas-preco"] .grade .tp-col-descricao .grade-celula {
  max-width: none; }
/* Três achados numa célula só é o caso comum desta lista — a coluna nasce
   larga o bastante para os três, em vez de cortar o terceiro sempre. */
[data-pagina="crm-tabelas-preco"] .grade .tp-col-achados { min-width: 21rem; }
[data-pagina="crm-tabelas-preco"] .grade .tp-col-validade { min-width: 11rem; }

/* ==========================================================================
   Clientes (CRM) — a base inteira, trabalhável  (/crm/clientes/)
   --------------------------------------------------------------------------
   Escopo de página: tudo aqui é prefixado `cl-` e vive sob
   [data-pagina="crm-clientes"], que já herda os tokens `--crm-*` do bloco da
   rampa do funil (esta página entrou naquele seletor por IGUALDADE, nunca por
   prefixo). Nenhum token global é redefinido.
   ========================================================================== */

/* A folha ocupa a JANELA INTEIRA e sangra para fora do recuo do `.content`, em
   cima e embaixo. Sem isto sobrava o cinza do shell nas duas pontas (medido em
   03/09/2026: 16px em cima, 36px embaixo) — duas cores de fundo na mesma tela,
   com costura no meio —, e na tela vazia ou carregando, em que a grade é
   curta, o cinza tomava metade do que se vê. Mesmo conserto da tela de
   Pedidos (955defd3), pelas mesmas variáveis: sangra só na VERTICAL (na
   horizontal a folha entraria por baixo da barra lateral) e o respiro volta
   como padding, para acompanhar sozinho o dia em que o shell mudar o recuo. */
[data-pagina="crm-clientes"] {
  /* LONGHAND de propósito: a forma curta zerava o padding horizontal que a
     página já tinha, e a faixa de abas encostava (e sumia) sob a barra
     lateral — visto na primeira tentativa. Aqui só o eixo vertical é tocado. */
  margin-top: calc(var(--content-pad-y) * -1);
  margin-bottom: calc(var(--content-pad-b) * -1);
  padding-top: var(--content-pad-y);
  padding-bottom: var(--content-pad-b);
  min-height: calc(100vh - 52px);
  box-sizing: border-box;
}

/* Abas e busca dividem a mesma faixa: sao a mesma pergunta ("qual recorte?").
   A busca cruza as abas, então pô-la longe delas sugeriria que ela procura
   dentro do recorte — o oposto do que o servidor faz. */
:is([data-pagina="crm-clientes"], [data-pagina="crm-negocios"], [data-pagina="crm-representantes"], [data-pagina="crm-usuarios"]) .cl-topo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  margin-bottom: .75rem;
}
:is([data-pagina="crm-clientes"], [data-pagina="crm-negocios"], [data-pagina="crm-representantes"], [data-pagina="crm-usuarios"]) .cl-abas { display: flex; flex-wrap: wrap; gap: .35rem; }
:is([data-pagina="crm-clientes"], [data-pagina="crm-negocios"], [data-pagina="crm-representantes"], [data-pagina="crm-usuarios"]) .cl-busca { flex: 1 1 18rem; max-width: 26rem; }

:is([data-pagina="crm-clientes"], [data-pagina="crm-negocios"], [data-pagina="crm-representantes"], [data-pagina="crm-usuarios"]) .cl-aba {
  display: inline-flex;
  align-items: baseline;
  gap: .4rem;
  padding: .3rem .7rem;
  border: 1px solid var(--crm-borda);
  border-radius: var(--raio-chip);
  background: var(--crm-superficie);
  color: var(--crm-tinta-2);
  font-size: var(--bi-fs-compact);
  font-weight: 500;
  line-height: 1.3;
  cursor: pointer;
}
:is([data-pagina="crm-clientes"], [data-pagina="crm-negocios"], [data-pagina="crm-representantes"], [data-pagina="crm-usuarios"]) .cl-aba:hover { border-color: var(--crm-borda-forte); }
:is([data-pagina="crm-clientes"], [data-pagina="crm-negocios"], [data-pagina="crm-representantes"], [data-pagina="crm-usuarios"]) .cl-aba:focus-visible {
  outline: 2px solid var(--crm-acento);
  outline-offset: 2px;
}
:is([data-pagina="crm-clientes"], [data-pagina="crm-negocios"], [data-pagina="crm-representantes"], [data-pagina="crm-usuarios"]) .cl-aba--ativa {
  background: var(--crm-acento);
  border-color: var(--crm-acento);
  color: #fff;
}
/* A contagem é o que faz a aba se explicar sem clique — fica legível, mas não
   disputa peso com o rótulo. */
:is([data-pagina="crm-clientes"], [data-pagina="crm-negocios"], [data-pagina="crm-representantes"], [data-pagina="crm-usuarios"]) .cl-aba__conta {
  font-variant-numeric: tabular-nums;
  font-size: var(--bi-fs-micro);
  opacity: .78;
}


/* O ✕ da busca (A3): dentro da caixa, só visível com termo. */
:is([data-pagina="crm-clientes"], [data-pagina="crm-negocios"], [data-pagina="crm-representantes"], [data-pagina="crm-usuarios"]) .cl-busca { position: relative; }
:is([data-pagina="crm-clientes"], [data-pagina="crm-negocios"], [data-pagina="crm-representantes"], [data-pagina="crm-usuarios"]) .cl-busca__limpar {
  position: absolute; right: .4rem; top: 50%; transform: translateY(-50%);
  border: 0; background: none; padding: .15rem .3rem;
  color: var(--crm-tinta-3); cursor: pointer; line-height: 1;
}
:is([data-pagina="crm-clientes"], [data-pagina="crm-negocios"], [data-pagina="crm-representantes"], [data-pagina="crm-usuarios"]) .cl-busca__limpar:hover { color: var(--crm-tinta); }
:is([data-pagina="crm-clientes"], [data-pagina="crm-negocios"], [data-pagina="crm-representantes"], [data-pagina="crm-usuarios"]) .cl-busca__limpar[hidden] { display: none; }
/* O ✕ nativo do Chrome sai — dois ✕ na mesma caixa é um a mais. */
[data-pagina="crm-clientes"] #cl-busca::-webkit-search-cancel-button { display: none; }

/* A linha inteira é o gatilho da ficha. */
[data-pagina="crm-clientes"] #cl-linhas tr { cursor: pointer; }
[data-pagina="crm-clientes"] #cl-linhas tr:hover { background: var(--crm-acento-fundo); }

/* O selo do feedback: lead buscado que já virou cliente diz isso, na visão de
   leads. Verde de conclusão, não o âmbar do selo "lead" — promover é chegada. */
[data-pagina="crm-clientes"] .crm-selo--promovido {
  background: #d1e7dd; color: #0a3622; border: 1px solid #a3cfbb;
  border-radius: .35rem; padding: 0 .3rem;
  font-size: var(--bi-fs-micro); font-weight: 600;
}

:is([data-pagina="crm-clientes"], [data-pagina="crm-negocios"], [data-pagina="crm-representantes"], [data-pagina="crm-usuarios"]) .cl-cliente__nome {
  font-weight: 600;
  color: var(--crm-tinta);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .35rem;
}
/* O nome virou `<a href>` para ganhar botão direito e Ctrl+clique (reportes
   #72 e #67). Ele não pode PARECER outro elemento por isso: herda a tinta da
   linha e só sublinha quando o ponteiro está nele. */
.cl-cliente__link { color: inherit; text-decoration: none; }
.cl-cliente__link:hover, .cl-cliente__link:focus-visible { text-decoration: underline; }
/* O CNPJ é linha secundária: é o desempate entre dois cadastros de nome
   parecido, não a identidade que se lê primeiro. */
:is([data-pagina="crm-clientes"], [data-pagina="crm-negocios"], [data-pagina="crm-representantes"], [data-pagina="crm-usuarios"]) .cl-cliente__doc {
  font-size: var(--bi-fs-micro);
  color: var(--crm-tinta-3);
  font-variant-numeric: tabular-nums;
}

/* Grade de LEADS: cada coluna ordena e filtra (03/09/2026). O cabeçalho passa
   a ter duas alturas — o botão de ordenar e o controle de recorte —, e por
   isso o `th` deixa de ser só texto. Quem ordena e recorta é o servidor: aqui
   é só o comando. */
[data-pagina="crm-clientes"] .cl-ordenar {
  display: flex;
  align-items: center;
  gap: .35rem;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}
[data-pagina="crm-clientes"] .cl-ordenar__seta {
  font-size: .65em;
  opacity: .35;
}
[data-pagina="crm-clientes"] .cl-ordenar--ativa .cl-ordenar__seta { opacity: 1; }
[data-pagina="crm-clientes"] .cl-ordenar:hover .cl-ordenar__seta { opacity: .7; }
[data-pagina="crm-clientes"] .cl-filtro {
  display: flex;
  gap: .25rem;
  margin-top: .3rem;
  font-weight: 400;
}
[data-pagina="crm-clientes"] .cl-filtro__texto,
[data-pagina="crm-clientes"] .cl-filtro__data {
  width: 100%;
  min-width: 0;
  padding: .15rem .35rem;
  border: 1px solid var(--crm-borda, #dee2e6);
  border-radius: .25rem;
  background: #fff;
  font-size: var(--bi-fs-micro);
  color: var(--crm-tinta);
  text-transform: none;
}
/* Duas colunas de identificação com número: tabular para o olho comparar
   dígito com dígito, e largura própria para o CNPJ não quebrar. */
[data-pagina="crm-clientes"] .cl-col-doc {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Um lead pode ter até seis telefones (medido no Ploomes, 04/09/2026), e o
   dono mandou mostrar todos: cada número em sua linha dentro da mesma célula.
   Um por linha, e não separados por ponto, porque telefone se lê inteiro — o
   olho que procura um DDD não quer caçá-lo no meio de uma tira de dígitos. */
[data-pagina="crm-clientes"] .cl-fone {
  display: block;
  line-height: 1.35;
}
[data-pagina="crm-clientes"] .cl-fone + .cl-fone { margin-top: .1rem; }
/* Só o celular vira link — quem decide isso é o servidor. O ícone à esquerda
   dá a diferença sem depender da cor, que sozinha não serve a quem não a
   enxerga. */
[data-pagina="crm-clientes"] .cl-fone--zap {
  color: var(--crm-acento);
  text-decoration: none;
}
[data-pagina="crm-clientes"] .cl-fone--zap:hover,
[data-pagina="crm-clientes"] .cl-fone--zap:focus-visible {
  text-decoration: underline;
}
[data-pagina="crm-clientes"] .cl-fone--zap i {
  margin-right: .3rem;
  opacity: .75;
}
[data-pagina="crm-clientes"] .cl-col-uf { width: 3.5rem; }
/* Próximo contato vencido (item 19): quem decide é o SERVIDOR (`tom`), aqui
   só a cor — mesmo token de `--crm-mal` que a pílula de erro já usa. */
[data-pagina="crm-clientes"] .cl-col-vencido {
  color: var(--crm-mal);
  font-weight: 600;
}
/* E-mail longo cortado com reticências, e não quebrado em três linhas: quebrar
   dobrava a altura de toda linha da grade (medido em 03/09/2026) e o endereço
   inteiro continua a um `title` de distância. */
[data-pagina="crm-clientes"] .cl-col-email {
  max-width: 13rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Ficha: a faixa de "quem atende" (responsável + representante). Uma linha por
   papel, com o nome em destaque e os dois gestos à direita — assumir é um
   clique, delegar abre a lista. */
.fc-quem-atende { display: flex; flex-wrap: wrap; gap: .35rem 1.5rem; margin-top: .35rem; }
.fc-atende { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
/* Tinta de apoio: com `#fc-nome` a 20px, o nome do representante em tinta
   cheia e caixa alta virava uma SEGUNDA manchete na mesma faixa — medido em
   03/09/2026: mesma cor, mesmo peso, só 1,36x de diferença de corpo. */
.fc-atende__nome { color: var(--crm-tinta-2); }
.fc-atende__lista { width: auto; min-width: 12rem; }

/* ============================================================================
   DRE GERENCIAL  (/dre-gerencial/)
   ----------------------------------------------------------------------------
   Escopo de página: tudo aqui é prefixado `dre-` e vive sob `.page.dre`. Os
   tokens `--dre-*` são LOCAIS — nascem no `.page.dre` e não vazam para as outras
   telas. Nenhum token global é redefinido.

   O desenho reproduz o protótipo aprovado: acento steel, polo negativo óxido,
   serifa de balanço nos totais e números tabulares. As duas cores de série
   passaram o validador de paleta (banda de luminosidade, croma, separação para
   daltonismo e contraste sobre o papel).
   ============================================================================ */
.page.dre {
    --dre-papel: #ffffff;
    --dre-papel-alt: #fafbfc;
    --dre-papel-fundo: #f1f4f6;
    --dre-tinta: #141b22;
    --dre-tinta-media: #47535f;
    --dre-tinta-fraca: #6b7885;
    --dre-regua: #dfe5ea;
    --dre-regua-forte: #c3ccd4;
    --dre-acento: #136a95;
    --dre-oxido: #a3342a;
    --dre-verde: #1c6b52;
    --dre-ambar: #8a6410;
--dre-ambar-fundo: #fdf7e8;   /* fundo do âmbar: distorção na tabela e pisca da linha focada */
}

/* --- barra de visões ----------------------------------------------------- */
.dre-instrumentos {
    background: var(--dre-papel);
    border: 1px solid var(--dre-regua);
    border-radius: 3px;
    padding: 14px 16px;
    display: flex;
    flex-wrap: wrap;
    gap: 18px 28px;
    align-items: flex-end;
    margin-bottom: 1rem;
}
/* `.page > section` zera padding lateral com !important (regra global do shell);
   aqui a barra é um cartão com moldura própria, então devolvemos os 16px. */
.page > section.dre-instrumentos { padding-inline: 16px !important; }
.dre-controle { display: flex; flex-direction: column; gap: 6px; }
.dre-par { display: flex; align-items: center; gap: 8px; }
.dre-instrumentos select {
    font: inherit;
    font-size: 14px;
    color: var(--dre-tinta);
    background: var(--dre-papel-alt);
    border: 1px solid var(--dre-regua-forte);
    border-radius: 2px;
    padding: 6px 8px;
}
.dre-ate { color: var(--dre-tinta-fraca); font-size: 13px; }
.dre-fichas { display: flex; flex-wrap: wrap; gap: 6px; }
.dre-instrumentos-acoes { margin-left: auto; display: flex; gap: 8px; align-items: flex-end; }
.page.dre .dre-rotulo {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .09em;
    color: var(--dre-tinta-fraca);
    font-weight: 600;
}
.dre-ficha {
    font: inherit;
    font-size: 13px;
    padding: 5px 11px;
    border-radius: 2px;
    border: 1px solid var(--dre-regua-forte);
    background: var(--dre-papel-alt);
    color: var(--dre-tinta-media);
    cursor: pointer;
}
/* Ficha marcada é azul (recorte: quais unidades entram); a visão em vigor é
   preta, porque é escolha exclusiva e não filtro — cores diferentes, papéis diferentes. */
.dre-ficha[aria-pressed="true"] { background: var(--dre-acento); border-color: var(--dre-acento); color: #fff; }
.dre-visoes .dre-ficha[aria-pressed="true"] { background: var(--dre-tinta); border-color: var(--dre-tinta); }
.dre-ficha:hover { border-color: var(--dre-acento); }
.dre-botao-texto {
    font: inherit;
    font-size: 13px;
    background: none;
    border: none;
    border-bottom: 1px solid var(--dre-regua-forte);
    color: var(--dre-tinta-media);
    padding: 4px 2px;
    cursor: pointer;
}
.dre-botao-texto:hover { color: var(--dre-acento); border-color: var(--dre-acento); }

/* --- faixa de indicadores ------------------------------------------------ */
.dre-indicadores {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(168px, 1fr));
    gap: 1px;
    background: var(--dre-regua);
    border: 1px solid var(--dre-regua);
    border-radius: 3px;
    overflow: hidden;
    margin-bottom: 1rem;
}
.dre-indicador { background: var(--dre-papel); padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 4px; }
.dre-indicador .dre-rotulo { font-size: 10.5px; }
.dre-indicador .dre-valor {
    font-size: 25px;
    font-weight: 600;
    letter-spacing: -.01em;
    font-variant-numeric: tabular-nums;
    color: var(--dre-tinta);
}
.dre-indicador .dre-nota { font-size: 12px; color: var(--dre-tinta-fraca); font-variant-numeric: tabular-nums; }
.page.dre .dre-positivo { color: var(--dre-verde); }
.page.dre .dre-negativo { color: var(--dre-oxido); }
.page.dre .atencao { color: var(--dre-ambar); }
.page.dre .positivo { color: var(--dre-verde); }
.page.dre .negativo { color: var(--dre-oxido); }

/* --- avisos do envelope -------------------------------------------------- */
.dre-avisos { margin-bottom: .75rem; }
.dre-aviso {
    border-left: 2px solid var(--dre-ambar);
    padding-left: 12px;
    margin: 0 0 .25rem;
    font-size: 13px;
    color: var(--dre-tinta-media);
}

/* --- cabeçalho da visão -------------------------------------------------- */
.dre-cabecalho-visao { display: flex; flex-wrap: wrap; gap: 4px 16px; align-items: baseline; margin-bottom: .5rem; }
.dre-titulo-visao { font-size: 18px; font-weight: 600; margin: 0; color: var(--dre-tinta); }
.dre-dica { font-size: 12.5px; color: var(--dre-tinta-fraca); }
.dre-rolagem { overflow-x: auto; }
.dre-vazio { padding: 12px 0; font-size: 13.5px; color: var(--dre-tinta-fraca); }

/* --- tabela da DRE ------------------------------------------------------- */
table.dre-quadro-linhas { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
table.dre-quadro-linhas th, table.dre-quadro-linhas td { padding: 7px 16px; text-align: right; white-space: nowrap; }
table.dre-quadro-linhas thead th {
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--dre-tinta-fraca);
    font-weight: 600;
    border-bottom: 1px solid var(--dre-regua-forte);
    background: var(--dre-papel-alt);
}
table.dre-quadro-linhas th.dre-nome, table.dre-quadro-linhas td.dre-nome { text-align: left; white-space: normal; }
table.dre-quadro-linhas tbody tr { border-bottom: 1px solid var(--dre-regua); }
table.dre-quadro-linhas tbody tr:last-child { border-bottom: none; }
table.dre-quadro-linhas tr.dre-grupo td { color: var(--dre-tinta-media); }
table.dre-quadro-linhas tr.dre-total td {
    font-weight: 600;
    color: var(--dre-tinta);
    background: var(--dre-papel-alt);
    border-top: 1px solid var(--dre-regua-forte);
}
table.dre-quadro-linhas tr.dre-total.dre-destaque td { font-size: 16px; }
table.dre-quadro-linhas tr.dre-conta td {
    background: var(--dre-papel-alt);
    color: var(--dre-tinta-media);
    font-size: 13.5px;
    padding-top: 4px;
    padding-bottom: 4px;
}
table.dre-quadro-linhas tr.dre-conta td.dre-nome { padding-left: 40px; }
.page.dre .dre-codigo { font-variant-numeric: tabular-nums; font-size: 12px; color: var(--dre-tinta-fraca); margin-right: 8px; }
.page.dre .dre-fraco { color: var(--dre-tinta-fraca); font-size: 12px; }
.dre-abridor {
    font: inherit;
    background: none;
    border: none;
    padding: 0;
    color: inherit;
    cursor: pointer;
    text-align: left;
    display: inline-flex;
    align-items: baseline;
    gap: 7px;
}
.dre-abridor:hover { color: var(--dre-acento); }
.dre-seta { color: var(--dre-tinta-fraca); font-size: 10px; width: 11px; text-align: center; flex: none; }
.dre-abridor[aria-expanded="true"] .dre-seta { color: var(--dre-acento); }
.dre-delta { font-size: 13px; }

/* --- matrizes: primeira coluna fixa, o resto rola na horizontal ---------- */
table.dre-matriz th, table.dre-matriz td { padding: 6px 12px; font-size: 13px; border-bottom: 1px solid var(--dre-regua); }
table.dre-matriz th.dre-nome, table.dre-matriz td.dre-nome {
    position: sticky;
    left: 0;
    background: var(--dre-papel);
    border-right: 1px solid var(--dre-regua);
    min-width: 250px;
}
table.dre-matriz thead th.dre-nome { background: var(--dre-papel-alt); z-index: 2; }
table.dre-matriz tr.dre-total td.dre-nome { background: var(--dre-papel-alt); }
table.dre-matriz th.dre-coluna-total, table.dre-matriz td.dre-coluna-total { background: var(--dre-papel-alt); }
table.dre-matriz tr.dre-secao-titulo td {
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--dre-tinta-fraca);
    font-weight: 600;
    background: var(--dre-papel-fundo);
    padding-top: 10px;
}

/* --- terceiro nível: itens dentro da conta ------------------------------- */
table.dre-quadro-linhas tr.dre-detalhe > td { padding: 0; background: var(--dre-papel-fundo); }
.dre-caixa-itens { padding: 12px 16px 14px 40px; display: flex; flex-direction: column; gap: 10px; }
.dre-itens-topo { display: flex; flex-wrap: wrap; gap: 10px 16px; align-items: center; }
.dre-itens-titulo { font-size: 13px; color: var(--dre-tinta); font-weight: 600; }
.dre-itens-topo input[type="search"] {
    min-width: 210px;
    font-size: 13px;
    padding: 5px 8px;
    color: var(--dre-tinta);
    background: var(--dre-papel);
    border: 1px solid var(--dre-regua-forte);
    border-radius: 2px;
}
.dre-fechar { margin-left: auto; }
table.dre-itens { width: 100%; border-collapse: collapse; font-size: 13px; font-variant-numeric: tabular-nums; background: var(--dre-papel); }
table.dre-itens th, table.dre-itens td { padding: 5px 10px; text-align: right; border-bottom: 1px solid var(--dre-regua); white-space: nowrap; }
table.dre-itens th { background: var(--dre-papel-alt); border-bottom: 1px solid var(--dre-regua-forte); padding: 0; }
table.dre-itens th.dre-texto, table.dre-itens td.dre-texto { text-align: left; white-space: normal; }
table.dre-itens tbody tr:last-child td { border-bottom: none; }
.dre-ordenador {
    font: inherit;
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: .07em;
    font-weight: 600;
    color: var(--dre-tinta-fraca);
    background: none;
    border: none;
    padding: 7px 10px;
    width: 100%;
    text-align: inherit;
    cursor: pointer;
    display: inline-flex;
    gap: 5px;
    align-items: center;
    justify-content: flex-end;
}
th.dre-texto .dre-ordenador { justify-content: flex-start; }
.dre-ordenador:hover { color: var(--dre-acento); }
.dre-ordenador[aria-sort="descending"], .dre-ordenador[aria-sort="ascending"] { color: var(--dre-acento); }
.dre-sinal { font-size: 10px; margin-left: .3em; }
.dre-corte { font-size: 12.5px; color: var(--dre-ambar); margin: 0; }
.dre-barra {
    display: inline-block;
    height: 3px;
    background: var(--dre-acento);
    border-radius: 2px;
    vertical-align: middle;
    margin-left: 8px;
    min-width: 1px;
}

/* --- gráficos ------------------------------------------------------------ */
.dre-legenda { display: flex; flex-wrap: wrap; gap: 14px; font-size: 12.5px; color: var(--dre-tinta-media); margin-bottom: .25rem; }
.dre-legenda span { display: inline-flex; align-items: center; gap: 6px; }
.dre-marca { width: 11px; height: 11px; border-radius: 2px; display: inline-block; }
.dre-marca-acento { background: var(--dre-acento); }
.dre-marca-oxido { background: var(--dre-oxido); }
.dre-marca-linha { background: var(--dre-oxido); height: 2px; border-radius: 1px; }
.dre-quadro { position: relative; }
svg.dre-grafico { width: 100%; height: auto; display: block; overflow: visible; }
svg.dre-grafico text { font-size: 10.5px; fill: var(--dre-tinta-fraca); }
.dre-balao {
    position: absolute;
    pointer-events: none;
    background: var(--dre-papel);
    border: 1px solid var(--dre-regua-forte);
    border-radius: 3px;
    padding: 8px 10px;
    font-size: 12.5px;
    line-height: 1.45;
    box-shadow: 0 6px 18px rgba(15, 25, 35, .14);
    opacity: 0;
    transition: opacity .1s ease;
    z-index: 5;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    color: var(--dre-tinta);
}

@media (max-width: 620px) {
    .dre-indicador .dre-valor { font-size: 21px; }
    .dre-caixa-itens { padding-left: 16px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   MAPEAMENTO DO GALPÃO (/mapa-galpao/) — duas vistas do mesmo envelope
   ═══════════════════════════════════════════════════════════════════════════
   Escopo de PÁGINA: tudo abaixo mora sob `.mg`, então nada aqui vaza para as
   outras ~28 telas. Os tokens vêm do FCDS (`--surf`, `--line`, `--ink-*`); as
   seis cores de família são locais e dessaturadas de propósito — a cor
   identifica a FAMÍLIA do produto e não pode competir com o azul do acento,
   que é quem marca seleção e foco.
   A vista "Espaço" usa transformações 3D do próprio CSS: são caixas
   ortogonais num plano, que é exatamente o que `preserve-3d` faz bem — não há
   biblioteca envolvida. */
.mg, .wms, .wms-tela {
  /* A cartela do galpão: oito cores nomeadas, escolhidas UMA VEZ por família
     na Configurar WMS. Não são tokens de tema e não vazam para outras telas —
     são o vocabulário de cor do chão de fábrica ("a amarela é cordoalha nua").
     Saturação média de propósito: precisa ser lida a três metros e de esguelha,
     sem competir com o acento, que marca seleção e foco. */
  --mg-cor-laranja:#d9752b; --mg-cor-amarelo:#cfa016; --mg-cor-azul:#2f6fb5;
  --mg-cor-verde:#3f8f5a;   --mg-cor-vermelho:#c04a3f; --mg-cor-roxo:#7a5aa8;
  --mg-cor-marrom:#8a6a41;  --mg-cor-cinza:#8e8e99;
  --mg-chao:var(--surf-3); --mg-pista:var(--surf-2);
}
.mg-secao {
  font-size:0.8125rem; font-weight:600; letter-spacing:0.05em; text-transform:uppercase;
  color:var(--ink-2); margin:0 0 0.75rem; padding-bottom:0.375rem;
  border-bottom:var(--bs-border-width) solid var(--line);
}
.mg-secao span { color:var(--ink-3); font-weight:400; }
.mg-vazio { color:var(--ink-3); font-size:0.8125rem; padding:0.75rem 0; margin:0; }
.mg-dica { color:var(--ink-3); font-size:0.75rem; }

.mg-corpo { display:grid; grid-template-columns:minmax(0,1fr); gap:1rem; align-items:start; }
.mg-instrucao { margin:0.625rem 0; font-size:0.75rem; color:var(--ink-2);
  border-left:3px solid var(--acc-line); padding-left:0.5rem; }
.mg-instrucao--erro { color:var(--bs-danger-text-emphasis); font-weight:600;
  border-left-color:var(--bs-danger); background:var(--bs-danger-bg-subtle);
  padding:0.375rem 0.5rem; }
.mg-provisoria { font-size:0.625rem; letter-spacing:0.05em; text-transform:uppercase;
  color:#8a5a00; background:var(--bs-warning-bg-subtle); border-radius:var(--fc-radius-sm);
  padding:0.0625rem 0.3125rem; }

/* os três selects que endereçam, dentro da grade */
.mg-campo-td { padding-top:0.25rem; padding-bottom:0.25rem; }
.mg-campo-td .mg-campo { min-width:4.5rem; max-width:14rem; }
.mg-campo-td .mg-campo[data-campo="posicao"],
.mg-campo-td .mg-campo[data-campo="nivel"] { min-width:4rem; width:4.5rem;
  font-family:var(--bs-font-monospace); }
/* A grade escreve a família por extenso numa coluna: repetir isso como faixa
   colorida na borda da linha seria a mesma informação duas vezes. A cor de
   família fica onde é a única leitura possível — os volumes da vista Espaço. */
.mg--gravando #mg-grade { opacity:0.55; pointer-events:none; }
/* Disputa na Grade: ícone e o lugar em disputa, porque o lote disputante está
   SEM posição — sem dizer qual lugar, a linha não aponta onde é a briga. */
/* Linha de filtros de coluna: sem seta de ordenação (o DataTables desenha o
   indicador em toda célula de cabeçalho, e aqui ele não ordena nada) e sem o
   negrito de título — ela é controle, não cabeçalho. */
.mg-linha-filtros td { padding:0.25rem 0.5rem; font-weight:400; }
/* O DataTables desenha o indicador de ordenação em TODA célula do cabeçalho, e
   marca as da segunda linha com `!important` — daí o `!important` aqui, único
   jeito de calar uma seta que não ordena nada. */
table.dataTable thead tr.mg-linha-filtros td::before,
table.dataTable thead tr.mg-linha-filtros td::after { display:none !important; }
.mg-conflito { color:var(--bs-danger); }
.mg-conflito-lugar { font-family:var(--bs-font-monospace); font-size:0.75rem;
  color:var(--bs-danger-text-emphasis); }

.mg-legenda { display:flex; flex-wrap:wrap; gap:0.25rem 1rem; list-style:none;
  margin:0.5rem 0 0; padding:0; font-size:0.75rem; color:var(--ink-2); }
.mg-legenda__item { display:flex; align-items:center; gap:0.375rem; }
.mg-legenda__cor { width:0.75rem; height:0.75rem; border-radius:2px; }

/* ── Mapa 3D ────────────────────────────────────────────────────────────────
   O desenho é SVG, e a projeção é aritmética do JS (isometria de 30° ou planta
   ortogonal). A versão anterior usava transformações 3D do CSS: funciona para
   caixa e falha para rolo — no CSS a circunferência é um retângulo de canto
   arredondado, o topo do cilindro nunca casa com o casco, e não existe
   ordenação por profundidade. Aqui a elipse é elipse e a ordem é a nossa. */
.mg-cena { position:relative; height:30rem; overflow:hidden; cursor:grab;
  background:var(--surf-2); border:var(--bs-border-width) solid var(--line);
  border-radius:var(--fc-radius); touch-action:none; }
.mg--3d .mg-cena { height:min(70vh, 44rem); }
.mg-mundo { display:block; width:100%; height:100%; }

/* O galpão: parede, chão e as pistas dos corredores. Sem contorno o chão é um
   retângulo flutuando e não há como se localizar. */
.mg-svg-parede { fill:color-mix(in srgb, var(--ink-4) 5%, transparent);
  stroke:var(--line-3); stroke-width:2; }
.mg-svg-chao { fill:var(--mg-chao); stroke:var(--line-3); stroke-width:1; }
.mg-svg-pista { fill:var(--mg-pista); stroke:var(--line-3); stroke-width:1; }
.mg-svg-portao { fill:var(--ink-4); font-size:9px; letter-spacing:0.08em; }

/* A vaga livre é o que o teto declarado permitiu desenhar: sem ela o mapa
   mostrava "o que está lá"; com ela mostra o galpão inteiro, e "cabe mais?" se
   responde olhando. */
.mg-vaga { fill:color-mix(in srgb, var(--ink-4) 8%, transparent);
  stroke:var(--line-3); stroke-width:1; stroke-dasharray:3 3; }

.mg-svg-rua { fill:var(--ink-2); font-family:var(--bs-font-monospace);
  font-size:19px; font-weight:700; paint-order:stroke; stroke:var(--surf);
  stroke-width:3px; }
.mg-svg-rua__ocupacao { fill:var(--ink-4); font-size:10px; font-weight:400;
  stroke-width:2px; }
.mg-svg-regua { fill:var(--ink-3); font-family:var(--bs-font-monospace); font-size:9px; }

/* O volume: a cor vem do cadastro da família e o relevo, do brilho de cada
   face. Caixa é plana por natureza; o rolo tem o degradê cilíndrico por cima
   da própria cor, num gradiente só, reaproveitado por todos. */
.mg-vol { cursor:pointer; }
.mg-svg-topo { fill:var(--mg-cor, var(--mg-cor-cinza)); filter:brightness(1.16); }
.mg-svg-frente { fill:var(--mg-cor, var(--mg-cor-cinza)); filter:brightness(0.92); }
.mg-svg-lado { fill:var(--mg-cor, var(--mg-cor-cinza)); filter:brightness(0.76); }
.mg-svg-corpo { fill:var(--mg-cor, var(--mg-cor-cinza)); }
.mg-svg-cilindrico { fill:url(#mg-cilindro); }
.mg-svg-furo { fill:var(--surf); stroke:color-mix(in srgb, #000 18%, transparent);
  stroke-width:0.75; }
.mg-vol--sobra { opacity:0.5; }
.mg-vol--fora .mg-svg-topo { stroke:var(--bs-danger); stroke-width:1.5;
  stroke-dasharray:2 2; }
/* Conflito: o volume MANTÉM a cor da família (o mapa não mente sobre o que
   está lá) e ganha um alerta por cima. */
.mg-svg-alerta { fill:var(--bs-danger); font-family:'Font Awesome 6 Free';
  font-weight:900; font-size:12px; paint-order:stroke; stroke:#fff; stroke-width:2px; }
/* Seleção é CONTORNO, nunca troca de matiz: com "engraxada = azul" escolhido no
   cadastro, pintar o volume selecionado de acento faria a seleção mentir sobre
   a família. */
.mg-vol:hover :is(.mg-svg-topo, .mg-svg-frente, .mg-svg-lado, .mg-svg-corpo),
.mg-vol:focus-visible :is(.mg-svg-topo, .mg-svg-frente, .mg-svg-lado, .mg-svg-corpo) {
  stroke:#fff; stroke-width:1.5; filter:brightness(1.12); }
.mg-vol:focus-visible { outline:none; }
/* Na legenda a bobina se anuncia pelo mesmo furo do mapa — a legenda tem de
   ensinar a forma, não só a cor. */
.mg-legenda__cor--bobina { border-radius:50%;
  background-image:radial-gradient(circle at 50% 50%,
    var(--surf) 0 26%, transparent 27%); }

/* Gaveta do detalhe: SPLIT, não cortina. Clicar num volume abre o card ao lado
   e a página cede a largura — escurecer o galpão justamente quando a pessoa
   quer conferir o card CONTRA o lugar no mapa seria esconder a resposta.
   `margin-right` e não `padding`: o shell trava `.page { padding: … !important }`,
   e vencer isso exigiria outro `!important` numa regra de página. */
.page.mg--3d #mg-gaveta { --bs-offcanvas-width:min(420px, 92vw);
  background:var(--surf); border-left:1px solid var(--line); }
@media (min-width: 1200px) {
  .page.mg--3d { transition:margin-right 0.3s ease-in-out; }
  .page.mg--3d.mg-com-gaveta { margin-right:min(420px, 92vw); }
}
@media (prefers-reduced-motion: reduce) {
  .page.mg--3d { transition:none; }
}
.mg-cena-controles { display:flex; gap:0.375rem; align-items:center; flex-wrap:wrap;
  margin-top:0.5rem; }
.mg-detalhe { margin-top:0.5rem; min-height:2.5rem; }
.mg-detalhe__lista { display:grid; grid-template-columns:auto 1fr; gap:0.25rem 0.75rem;
  margin:0; font-size:0.8125rem; }
.mg-detalhe__lista dt { font-size:0.625rem; letter-spacing:0.08em; text-transform:uppercase;
  color:var(--ink-3); align-self:center; }
.mg-detalhe__lista dd { margin:0; font-family:var(--bs-font-monospace); }

/* A cor vem do CADASTRO (bi_familiagalpao.cor), não de um índice sorteado: o
   serviço manda o nome e aqui ele vira tinta. Uma família nova entrando no
   galpão não repinta mais as outras. */
.mg-cor-laranja  { --mg-cor:var(--mg-cor-laranja); }
.mg-cor-amarelo  { --mg-cor:var(--mg-cor-amarelo); }
.mg-cor-azul     { --mg-cor:var(--mg-cor-azul); }
.mg-cor-verde    { --mg-cor:var(--mg-cor-verde); }
.mg-cor-vermelho { --mg-cor:var(--mg-cor-vermelho); }
.mg-cor-roxo     { --mg-cor:var(--mg-cor-roxo); }
.mg-cor-marrom   { --mg-cor:var(--mg-cor-marrom); }
.mg-cor-cinza    { --mg-cor:var(--mg-cor-cinza); }
/* `background-COLOR`, não o atalho: o atalho zeraria o `background-image` que
   desenha o furo e o enrolamento da bobina — e estas regras vêm depois. */
.mg-legenda__cor { background-color:var(--mg-cor, var(--mg-cor-cinza)); }

.mg-nova-rua { display:flex; align-items:center; gap:0.5rem; flex-wrap:wrap;
  margin-top:0.75rem; }
.mg-nova-rua input { width:12rem; }

/* ── Configurar WMS ─────────────────────────────────────────────────────────
   Escopo de página (`.wms`). A mini-planta é o único desenho da tela e existe
   por um motivo prático: o número de posições é abstrato até virar tiras, e é
   olhando as tiras que alguém percebe ter declarado 20 numa rua de 12. */
.wms .wms-num { width:5.5rem; font-family:var(--bs-font-monospace); }
.wms-planta { display:flex; flex-wrap:wrap; gap:2px; align-items:center;
  min-width:8rem; max-width:22rem; }
.wms-tira { display:block; width:0.5rem; height:1.125rem; border-radius:2px;
  border:1px dashed var(--line-3); }
.wms-tira--cheia { border-style:solid; border-color:transparent;
  background:var(--ink-4); }
.wms-planta-td { vertical-align:middle; }
.wms-amostra { display:inline-block; width:1.75rem; height:1.125rem;
  border-radius:3px; background:var(--mg-cor, var(--mg-cor-cinza)); }
.wms-amostra--bobina { border-radius:0.5625rem / 50%; }
.wms-detalhes { margin:0.375rem 0 0; padding-left:1.125rem; font-size:0.75rem; }

/* ── Coletor ────────────────────────────────────────────────────────────────
   Tela de uma mão só: o endereço engatado é o único texto que precisa ser lido
   de longe, com o leitor na mão e a mercadoria na outra. Daí a mono enorme —
   endereço é código, não prosa, e é o alinhamento que deixa conferir de
   relance. O resto da tela fica quieto de propósito. */
.cl-rotulo { display:block; font-size:0.6875rem; letter-spacing:0.09em;
  text-transform:uppercase; color:var(--ink-3); }
.cl-engate__topo { display:flex; align-items:center; justify-content:space-between;
  gap:0.5rem; }
/* A tela NÃO ROLA (decisão do dono, 27/08/2026): altura cheia via
   content--altura-cheia, cartão de trabalho flexível e a câmera ocupando
   exatamente a sobra. Tudo visível o tempo todo; o histórico virou modal. */
.content--altura-cheia > .page.cl { display:flex; flex-direction:column;
  padding-top:0.5rem; padding-bottom:0.5rem; overflow:hidden; }
.page.cl .cl-trabalho { flex:1 1 auto; min-height:0; display:flex; flex-direction:column; }
/* Sem endereço selecionado o card de trabalho não existe — e o `display:flex`
   acima venceria o [hidden] se não fosse esta linha. */
.page.cl .cl-trabalho[hidden] { display:none; }
.page.cl .cl-trabalho > .card-body { flex:1 1 auto; min-height:0;
  display:flex; flex-direction:column; }
/* Compacto de propósito (27/08/2026): cada rem vertical economizado é vídeo
   maior — a tela não rola, então o espaço é orçamento. */
.page.cl .card-body { padding:0.625rem 0.75rem; }
.page.cl .cl-acoes .btn { padding:0.375rem 0.5rem; font-size:0.875rem; }
.page.cl #cl-desfazer { padding:0.5rem 1rem; font-size:1rem; }
.cl-engate__botoes { display:flex; gap:0.375rem; }
.cl-camera { flex:1 1 auto; min-height:0; display:flex; }
.cl-camera[hidden] { display:none; }
.cl-endereco { margin:0.25rem 0 0; font-family:var(--bs-font-monospace);
  font-weight:700; font-size:clamp(1.75rem, 6vw, 2.75rem); line-height:1.05;
  letter-spacing:0.02em; color:var(--ink-1); }
/* Vazio é INSTRUÇÃO ("Selecione um endereço…"), não valor: sai do monospace
   gigante e vira frase legível. */
.cl-endereco--vazio { font-size:1.0625rem; font-weight:400; color:var(--ink-4);
  font-family:inherit; }
.cl-endereco-nota { margin:0 0 0.5rem; }
/* Posição ocupada: a nota deixa de ser medida da rua e passa a declarar o que
   está lá — âmbar porque a próxima leitura mexe nisso. A descrição do produto
   é longa; duas linhas bastam para reconhecer a mercadoria. */
.cl-historico:empty::after { content:'Nada lido ainda nesta sessão.';
  font-size:0.8125rem; color:var(--ink-3); }
.cl-escolha { display:flex; flex-direction:column; gap:0.5rem; }
.cl-escolha__linha { display:flex; flex-wrap:wrap; gap:0.5rem; align-items:flex-end; }
.cl-escolha select { width:auto; min-width:9rem; }
/* Todo campo da linha diz o próprio nome: três controles lado a lado, um sem
   rótulo, faz o operador adivinhar. */
.cl-campo { display:flex; flex-direction:column; }
.cl-campo .cl-rotulo { margin-bottom:0.125rem; }
.cl-campo[hidden] { display:none; }   /* o flex acima venceria o [hidden] */
.cl-rua { min-width:5rem; font-family:var(--bs-font-monospace); font-weight:700; }
/* Alvo de toque: o galpão opera de luva. 2,75rem é o piso, igual ao da grade. */
.cl-escolha select, .cl-escolha .cl-num { min-height:2.75rem; }
/* A ocupação da rua encabeça a grade que ela conta, alinhada à direita. */
.cl-posicoes__topo { display:flex; align-items:baseline;
  justify-content:space-between; gap:0.5rem; }
.cl-rua-conta { font-size:0.8125rem; color:var(--ink-2); font-variant-numeric:tabular-nums; }
/* A mercadoria do lugar: cada valor com o próprio nome, em coluna, para
   conferir lendo de cima a baixo em vez de decorar a ordem de uma frase. */
.cl-item { display:grid; grid-template-columns:auto 1fr; gap:0.125rem 0.625rem;
  align-items:baseline; margin:0 0 0.5rem; }
.cl-item[hidden] { display:none; }
.cl-item dt { padding-top:0.125rem; }
.cl-item dd { margin:0; font-size:0.875rem; color:var(--ink-1); }
.cl-item__dado { font-family:var(--bs-font-monospace); font-weight:700; }
/* A GRADE DE POSIÇÕES: o corredor inteiro à vista, uma célula por posição.
   Mínimo de 2.75rem porque o dedo do galpão usa luva; o resto é a grade se
   acomodando à largura do celular. */
.cl-posicoes { display:grid; gap:0.25rem;
  grid-template-columns:repeat(auto-fill, minmax(2.75rem, 1fr)); }
.cl-posicao { min-height:2.75rem; border-radius:8px; font-weight:700;
  font-size:0.9375rem; font-family:var(--bs-font-monospace); cursor:pointer;
  border:1px solid #cfd6e0; background:#fff; color:var(--ink-1); }
.cl-posicao:hover { border-color:#1d4fd8; }
.cl-posicao:active { transform:translateY(1px); }
/* Livre, ocupada e em disputa: as três cores saem do envelope, não de conta
   feita aqui. Ocupada em âmbar porque tocar nela é substituir alguém. */
.cl-posicao--livre { background:#f2f7f3; border-color:#bcd8c4; color:#137333; }
.cl-posicao--ocupada { background:#fdf1e4; border-color:#e6c393; color:#8a5a00; }
.cl-posicao--conflito { background:#fde8e8; border-color:#e3a9a6; color:#b3261e; }
/* Onde eu estou: reabrir a grade sem marcar a posição em uso faz o operador
   procurar de novo. O anel não substitui a cor de ocupação — soma a ela. */
.cl-posicao--atual { outline:2px solid #1d4fd8; outline-offset:1px;
  border-color:#1d4fd8; }
.cl .cl-num { width:5.5rem; font-family:var(--bs-font-monospace); }
.cl-codigo { font-family:var(--bs-font-monospace); font-size:1.125rem;
  padding:0.5rem 0.75rem; }
/* O FAROL: a voz da tela — o que está acontecendo agora (grande) e a próxima
   ação (embaixo), com cor por estado. Substituiu o eco em 27/08/2026. */
/* A voz mora entre o lote lido e a câmera: a margem é de cima, e o respiro de
   baixo é o `margin-top` da própria câmera. Faixa e botão herdam a MESMA
   margem — dividem o lugar, então o vídeo não muda de tamanho na troca. */
.cl-farol { border-left:4px solid #c5cad3; background:#f6f7f9; border-radius:8px;
  padding:0.5rem 0.75rem; margin:0.5rem 0 0; }
.cl-farol__agora { display:block; margin:0; font-weight:700; font-size:1rem;
  overflow-wrap:anywhere; }
.cl-farol__proximo { display:block; margin:0.125rem 0 0; font-size:0.84375rem;
  color:#495057; min-height:1.125rem; }
/* A voz é UMA SÓ, no mesmo lugar (decisão do dono, 27/08/2026): a faixa FALA
   (estado, resultado) e o botão AGE (a operação por extenso) — nunca os dois
   juntos, porque diziam a mesma coisa. Por isso o botão HERDA o desenho da
   faixa: mesma caixa, mesma tipografia, mesmo lugar. É a mesma entidade
   mudando de modo, não um segundo componente. Sem ícone: o texto é a frase. */
.cl-capturar { display:block; width:100%; text-align:left; font:inherit;
  color:inherit; border-width:0 0 0 4px; border-style:solid;
  white-space:normal; cursor:pointer; }
.cl-capturar[hidden] { display:none; }   /* `display:block` acima venceria o [hidden] */
.cl-capturar:disabled { cursor:default; }
.cl-capturar:hover:not(:disabled) { filter:brightness(0.97); }
.cl-capturar:active:not(:disabled) { transform:translateY(1px); }
/* Tom de AÇÃO: é o único estado tocável da voz, e o azul mais firme o separa
   do azul de "estou lendo". */
.cl-farol--acao { border-color:#1d4fd8; background:#dfe8fc; }
.cl-farol--acao .cl-farol__agora { color:#1a3fa8; }
.cl-farol--lendo { border-color:#2563eb; background:#e7eefc; }
/* Gravação em voo: o farol PULSA enquanto a escrita viaja até o servidor —
   sem isso o operador não sabe se o toque pegou e toca de novo. */
.cl-farol--gravando { border-color:#2563eb; background:#e7eefc;
  animation:cl-farol-pulso 0.9s ease-in-out infinite; }
.cl-farol--gravando .cl-farol__agora { color:#1d4fd8; }
@keyframes cl-farol-pulso { 50% { background:#c9d9f8; } }
.cl-farol--achou { border-color:#2563eb; background:#e7eefc; }
.cl-farol--achou .cl-farol__agora { color:#1d4fd8; }
.cl-farol--ok { border-color:#137333; background:#e6f4ea; }
.cl-farol--ok .cl-farol__agora { color:#137333; }
.cl-farol--aviso { border-color:#e08b3c; background:#fdf1e4; }
.cl-farol--aviso .cl-farol__agora { color:#8a5a00; }
.cl-farol--erro { border-color:#b3261e; background:#fde8e8; }
.cl-farol--erro .cl-farol__agora { color:#b3261e; }
/* Ações em grade, não em pilha (pedido do dono, 27/08/2026): duas por linha,
   e o Capturar atravessado — é o botão de polegar, com a mercadoria na mão. */
.cl-acoes { display:grid; grid-template-columns:1fr 1fr; gap:0.375rem; margin:0 0 0.5rem; }
.cl-acoes .btn { white-space:nowrap; }
#cl-desfazer { grid-column:1 / -1; padding:0.625rem 1rem; }
/* Linha 1: obturador | próxima. Linha 2: Capturar atravessado. O DOM mantém o
   Capturar junto do obturador (é o par lógico); a ordem VISUAL é da grade. */
#cl-camera-abrir { order:1; }
#cl-proxima { order:2; }
#cl-desfazer { order:3; }
/* A câmera do Coletor mora NA tela (não em modal), e tudo que se toca fica
   ACIMA do vídeo: no celular, vídeo + teclado ocupam metade da tela e botão
   abaixo some. Ordem: ações → campo (mostrador da etiqueta) → vídeo. */
.cl-camera { margin-top:0.5rem; }
.cl-video { width:100%; height:100%; min-height:0; object-fit:cover;
  border-radius:8px; background:#000; display:block; }
.cl-historico { list-style:none; margin:0; padding:0; display:grid; gap:0.25rem;
  max-height:18rem; overflow:auto; }
.cl-linha { display:flex; align-items:center; gap:0.5rem; font-size:0.8125rem;
  font-family:var(--bs-font-monospace); }
.cl-linha__marca { width:0.5rem; height:0.5rem; border-radius:50%;
  background:var(--ink-4); flex:0 0 auto; }
.cl-linha--ok .cl-linha__marca { background:var(--bs-success); }
.cl-linha--aviso .cl-linha__marca { background:var(--bs-warning); }
.cl-linha--erro .cl-linha__marca { background:var(--bs-danger); }
.cl-candidato { display:block; width:100%; text-align:left; padding:0.625rem 0.75rem;
  margin-bottom:0.375rem; border:var(--bs-border-width) solid var(--line);
  border-radius:var(--fc-radius); background:var(--surf); }
.cl-candidato:hover, .cl-candidato:focus-visible { border-color:var(--acc);
  background:var(--surf-2); }
.cl-candidato .mg-dica { display:block; }
.mg-origem { font-family:var(--bs-font-monospace); font-size:0.6875rem; color:var(--ink-3); }


/* --- WMS: Grade e Mesa (conceito 26/08/2026) ------------------------------
   As duas telas novas de endereçar. Escopo `.wms-tela`: nada aqui vaza para as
   outras ~28 páginas, e por isso elas podem ter tipografia e densidade
   próprias — são telas de trabalho de oito horas, não painéis de leitura.

   Três decisões, todas do desenho aprovado em 26/08:
   1. CHAPADO. Nenhuma sombra em repouso; a única sombra do conjunto é o halo
      de foco, porque foco é a informação mais importante de uma tela onde se
      digita coluna abaixo.
   2. ACENTO AZUL (#2563eb, o mesmo --chart-azul do app inteiro) para foco,
      seleção e a ação primária; âmbar (#a24a00) só para inconsistência. O
      roxo da primeira versão morreu em 26/08 ("odiei as cores") — o acento
      voltou para a família de azul que o usuário já conhece do resto do app.
      A cor da FAMÍLIA (pastilhas `.mg-cor-*`) é identidade de mercadoria,
      não estado.
   3. Neue Haas Display, a fonte da marca, escopada a estas telas: o resto do
      app continua na tipografia do FCDS. */
@font-face {
  font-family:'Neue Haas Display';
  src:url("../fonts/NeueHaasDisplayRoman.13568ea57eda.ttf") format('truetype');
  font-weight:400; font-style:normal; font-display:swap;
}
@font-face {
  font-family:'Neue Haas Display';
  src:url("../fonts/NeueHaasDisplayMediu.c00931e8b3cc.ttf") format('truetype');
  font-weight:500; font-style:normal; font-display:swap;
}
@font-face {
  font-family:'Neue Haas Display';
  src:url("../fonts/NeueHaasDisplayBold.822ebe551ca0.ttf") format('truetype');
  font-weight:700; font-style:normal; font-display:swap;
}

.wms-tela {
  --wms-superficie:#fff; --wms-superficie-2:#f6f7f9; --wms-superficie-3:#eef0f4;
  --wms-tinta:#0b0d11; --wms-tinta-2:#464d59; --wms-tinta-fraca:#6b7280;
  --wms-linha:#e1e4e9; --wms-linha-forte:#c5cad3;
  --wms-vivo:#2563eb; --wms-vivo-tinta:#fff;
  --wms-marca:#2563eb; --wms-marca-fraca:#e7eefc;
  --wms-alerta:#a24a00; --wms-alerta-borda:#e08b3c; --wms-alerta-fraca:#fdf1e4;
  font-family:'Neue Haas Display', 'Helvetica Neue', Arial, sans-serif;
  font-size:0.9375rem; line-height:1.4; letter-spacing:-0.01em;
  font-variant-numeric:tabular-nums;
  color:var(--wms-tinta);
  display:flex; flex-direction:column; gap:0.875rem;
}
.wms-tela [hidden] { display:none !important; }
.wms-tela button { cursor:pointer; }
.wms-tela button[disabled] { cursor:not-allowed; opacity:0.35; }
.wms-tela :focus-visible { outline:2px solid var(--wms-marca); outline-offset:1px; }
.wms-tela kbd { font:inherit; font-size:0.6875rem; font-weight:500;
  color:inherit; background:none; border:1px solid currentColor; border-radius:3px;
  padding:0 0.375rem; opacity:0.7; }

.wms-tela .wms-rotulo { font-size:0.6875rem; font-weight:500; letter-spacing:0.11em;
  text-transform:uppercase; color:var(--wms-tinta-fraca); }
.wms-tela .wms-espaco { flex:1; }
.wms-tela .wms-direita { text-align:right; }

.wms-tela .wms-cabeca { display:flex; align-items:center; gap:0.75rem; flex-wrap:wrap; }
.wms-tela .wms-atalho { font-size:0.875rem; font-weight:500; color:var(--wms-marca);
  text-decoration:none; }
.wms-tela .wms-atalho:hover { text-decoration:underline; }
.wms-tela .wms-fila-conta { font-size:0.8125rem; color:var(--wms-tinta-fraca); }

.wms-tela .wms-select, .wms-tela .wms-campo {
  border:1px solid var(--wms-linha-forte); border-radius:6px; padding:0.4375rem 0.625rem;
  background:var(--wms-superficie-2); color:inherit; font:inherit; outline:0; }
.wms-tela .wms-select:focus, .wms-tela .wms-campo:focus {
  border-color:var(--wms-marca); background:var(--wms-superficie);
  box-shadow:0 0 0 3px var(--wms-marca-fraca); }
.wms-tela .wms-campo::placeholder { color:var(--wms-tinta-fraca); letter-spacing:0; }
.wms-tela .wms-campo--busca { min-width:13rem; }
.wms-tela .wms-campo--curto { width:5rem; }

/* Contagens: o estado do galpão em números, tudo vindo do `resumo` do
   envelope. Cada uma carrega `data-auditoria`, então o `?` da tela abre o
   verbete no ponto de uso. */
.wms-tela .wms-contagens { display:flex; flex-wrap:wrap; gap:1.625rem; margin:0; }
.wms-tela .wms-conta dt { margin-bottom:1px; font-size:0.6875rem; font-weight:500;
  letter-spacing:0.11em; text-transform:uppercase; color:var(--wms-tinta-fraca); }
.wms-tela .wms-conta dd { margin:0; font-size:1.25rem; font-weight:700; letter-spacing:-0.03em; }
.wms-tela .wms-conta--alerta dd { color:var(--wms-alerta); }

.wms-tela .wms-alerta { display:flex; align-items:center; gap:0.875rem; flex-wrap:wrap;
  background:var(--wms-alerta-fraca); border:1px solid var(--wms-alerta-borda);
  border-radius:8px; padding:0.75rem 1rem; }
.wms-tela .wms-alerta__titulo { font-weight:600; color:var(--wms-alerta); }
.wms-tela .wms-alerta__corpo { font-size:0.84375rem; color:var(--wms-tinta-2); flex:1; min-width:15rem; }
.wms-tela .wms-alerta__botao { border:1px solid var(--wms-alerta); border-radius:5px;
  padding:0.375rem 0.75rem; font-size:0.84375rem; font-weight:500;
  color:var(--wms-alerta); background:none; }

.wms-tela .wms-painel { background:var(--wms-superficie); border:1px solid var(--wms-linha);
  border-radius:10px; }

/* --- Grade: a planilha ---------------------------------------------------- */
.wms-tela .wms-ferramentas { display:flex; align-items:center; gap:0.625rem; flex-wrap:wrap;
  padding:0.8125rem 1rem; border-bottom:1px solid var(--wms-linha); }
.wms-tela .wms-pilulas { display:flex; gap:0.3125rem; flex-wrap:wrap; }
.wms-tela .wms-pilula { border:1px solid var(--wms-linha-forte); border-radius:99px;
  padding:0.3125rem 0.8125rem; font-size:0.84375rem; color:var(--wms-tinta-2);
  background:none; }
.wms-tela .wms-pilula[aria-pressed="true"] { background:var(--wms-vivo);
  border-color:var(--wms-vivo); color:var(--wms-vivo-tinta); font-weight:500; }
.wms-tela .wms-pilula--alerta { border-color:var(--wms-alerta-borda); color:var(--wms-alerta); }
.wms-tela .wms-pilula--alerta[aria-pressed="true"] { background:var(--wms-alerta);
  border-color:var(--wms-alerta); color:#fff; }
.wms-tela .wms-ajuda { font-size:0.78125rem; color:var(--wms-tinta-fraca); }

/* A Grade cabe na viewport via `content--altura-cheia` (declarado no template):
   o painel vira coluna flex e a rolagem é quem cresce — nada de calc de altura,
   que deixava sobra no pé da página. */
.wms-grade .wms-painel { flex:1 1 auto; min-height:0; display:flex; flex-direction:column; }
.wms-tela .wms-rolagem { overflow:auto; flex:1 1 auto; min-height:0; }
/* `content--altura-cheia` zera o padding vertical do shell; o respiro do topo
   volta aqui, do tamanho do gap interno da tela. */
.content--altura-cheia > .page.wms-grade,
.content--altura-cheia > .page.wms-mesa { padding-top:0.875rem; }
/* Mesa na viewport: a bancada é quem cresce; rodapé e teclado ficam do tamanho
   que são. `overflow:auto` é a guarda de janela baixa — a Mesa não tem scroller
   interno como a rolagem da Grade, e sem ele o botão Colocar sumiria num
   notebook pequeno. */
.content--altura-cheia > .page.wms-mesa { padding-bottom:0.875rem; overflow:auto; }
.wms-mesa .wms-bancada { flex:1 1 auto; min-height:0; }
.wms-tela .wms-tabela { border-collapse:collapse; width:100%; min-width:54rem; }
/* A folga da tabela mora DEPOIS da última coluna: sem isto o navegador
   distribui a sobra entre as colunas largas e abre um vão entre Produto e
   Quantidade. */
.wms-grade .wms-tabela th:last-child { width:100%; }
.wms-tela .wms-tabela thead th { position:sticky; top:0; z-index:2;
  background:var(--wms-superficie); text-align:left; font-size:0.6875rem;
  font-weight:600; letter-spacing:0.09em; text-transform:uppercase;
  color:var(--wms-tinta-fraca); padding:0.5625rem 0.75rem;
  border-bottom:1px solid var(--wms-linha-forte); white-space:nowrap; }
.wms-tela .wms-tabela thead th.wms-direita { text-align:right; }
.wms-tela .wms-tabela tbody td { padding:0 0.75rem; border-bottom:1px solid var(--wms-linha);
  height:2.375rem; white-space:nowrap; }
.wms-tela .wms-tabela tbody tr:hover td { background:var(--wms-superficie-2); }
.wms-tela .wms-tabela tbody tr.wms-linha--alerta td { background:var(--wms-alerta-fraca); }
.wms-tela .wms-tabela tbody tr.wms-linha--nova td { animation:wms-acende 1.1s ease-out; }
@keyframes wms-acende { from { background:var(--wms-marca-fraca); } to { background:transparent; } }
.wms-tela .wms-tabela td.wms-lote { font-weight:600; letter-spacing:-0.02em; }
.wms-tela .wms-tabela td.wms-leve { color:var(--wms-tinta-fraca); font-size:0.84375rem; }
.wms-tela .wms-tabela td.wms-situacao { font-size:0.84375rem; color:var(--wms-tinta-fraca); }
.wms-tela .wms-tabela tr.wms-linha--alerta td.wms-situacao { color:var(--wms-alerta); font-weight:500; }
/* Última conferência do lugar. "Nunca" não é um valor entre outros: é o estado
   que a recontagem existe para eliminar, e por isso é o único destacado. */
.wms-tela .wms-tabela td.wms-conferencia { font-size:0.84375rem;
  color:var(--wms-tinta-fraca); white-space:nowrap; font-variant-numeric:tabular-nums; }
.wms-tela .wms-tabela td.wms-conferencia--nunca { color:var(--wms-alerta); font-weight:500; }
/* O estado de conferência do CORREDOR — só aparece com um corredor em foco. */
.wms-conferencia-rua { margin:0 0 0.5rem; font-size:0.84375rem;
  color:var(--wms-tinta-fraca); }
.wms-conferencia-rua--alerta, .wms-conta-conferencia--alerta { color:var(--wms-alerta); font-weight:500; }
.wms-tela .wms-pastilha { display:inline-block; width:9px; height:9px; border-radius:2px;
  margin-right:9px; vertical-align:-1px;
  background:var(--mg-cor, var(--mg-cor-cinza)); }

/* A célula editável é invisível até o mouse ou o foco chegarem: uma tabela com
   300 caixas desenhadas é uma tabela que ninguém lê. */
.wms-tela .wms-tabela td.wms-edita { padding:1px 6px; }
.wms-tela .wms-tabela td.wms-edita--rua { width:5.375rem; }
.wms-tela .wms-tabela td.wms-edita--posicao { width:6rem; }
.wms-tela .wms-tabela td.wms-edita--nivel { width:4.75rem; }
/* Produto é código + descrição numa célula só (pedido do dono, 26/08): o
   código identifica, a descrição confirma — separados eram duas colunas
   dizendo meia coisa cada. */
.wms-tela .wms-produto { white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  max-width:26rem; }
.wms-tela .wms-produto__descricao { color:var(--wms-tinta-fraca); margin-left:0.5rem; }
/* A linha de filtros mora no thead para rolar junto com os títulos. */
.wms-tela .wms-filtros-colunas td { padding:8px 6px; border-bottom:1px solid var(--wms-linha-forte); }
.wms-tela .wms-select--filtro { width:100%; padding:0.25rem 0.375rem; font-size:0.8125rem; }
/* A última coluna absorve a folga da tabela; o filtro dela dimensiona pelo
   conteúdo para não esticar junto. */
.wms-grade .wms-filtros-colunas td:last-child .wms-select--filtro { width:auto; min-width:9rem; }
.wms-tela .wms-celula { width:100%; height:2.25rem; border:1px solid var(--wms-linha);
  border-radius:5px; background:var(--wms-superficie); padding:0 0.5rem; outline:0;
  font-size:0.90625rem; font-weight:600; letter-spacing:-0.02em; }
.wms-tela .wms-celula::placeholder { font-weight:400; color:var(--wms-linha-forte); letter-spacing:0; }
.wms-tela .wms-celula:hover { border-color:var(--wms-linha-forte); }
.wms-tela .wms-celula:focus { border-color:var(--wms-marca); background:var(--wms-superficie);
  box-shadow:0 0 0 3px var(--wms-marca-fraca); }
.wms-tela .wms-celula--erro { border-color:var(--wms-alerta); background:var(--wms-alerta-fraca); }

.wms-tela .wms-nada { padding:2.125rem 1rem; text-align:center; color:var(--wms-tinta-fraca); margin:0; }
.wms-tela .wms-recado { padding:0.625rem 1rem; border-top:1px solid var(--wms-linha);
  font-size:0.84375rem; color:var(--wms-tinta-2); min-height:2.5rem; margin:0; }
.wms-tela .wms-recado--erro { color:var(--wms-alerta); font-weight:500; }

/* --- Mesa: um lote de cada vez -------------------------------------------- */
.wms-tela .wms-bancada { display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr); }
.wms-tela .wms-lado { padding:1.375rem 1.5rem 1.5rem; display:grid; gap:0.875rem; align-content:start; }
.wms-tela .wms-lado + .wms-lado { border-left:1px solid var(--wms-linha); }
.wms-tela .wms-grupo { display:grid; gap:0.375rem; }
.wms-tela .wms-dica { font-size:0.78125rem; color:var(--wms-tinta-2); min-height:1.0625rem; margin:0; }
.wms-tela .wms-dica--erro { color:var(--wms-alerta); }

.wms-tela .wms-familia { display:flex; align-items:center; gap:0.5rem; font-size:0.8125rem;
  color:var(--wms-tinta-2); }
.wms-tela .wms-lote-grande { font-size:clamp(1.625rem, 3.2vw, 2.25rem); font-weight:700;
  letter-spacing:-0.045em; line-height:1.05; word-break:break-word; }
.wms-tela .wms-desc { font-size:0.84375rem; color:var(--wms-tinta-fraca); margin:0; }
.wms-tela .wms-quantidade { font-size:1.375rem; font-weight:600; letter-spacing:-0.03em; }
.wms-tela .wms-tag { justify-self:start; font-size:0.78125rem; color:var(--wms-alerta);
  background:var(--wms-alerta-fraca); border:1px solid var(--wms-alerta-borda);
  border-radius:4px; padding:0.1875rem 0.5625rem; }
.wms-tela .wms-vazio-mao { font-size:1rem; color:var(--wms-tinta-fraca); padding:1.75rem 0; margin:0; }

/* O endereço é o que se lê de longe, com a mercadoria na mão — é ele, e não o
   botão, o centro da metade direita. */
.wms-tela .wms-endereco { font-size:clamp(3rem, 6.4vw, 4.5rem); font-weight:700;
  letter-spacing:-0.06em; line-height:0.94; }
.wms-tela .wms-porque { font-size:0.84375rem; color:var(--wms-tinta-fraca); margin:0.25rem 0 0; }
.wms-tela .wms-porque--ocupado { color:var(--wms-alerta); }

/* A régua é o corredor visto de cima: barra cheia é lugar ocupado, barra alta e
   roxa é onde este lote vai. Clicar numa barra escolhe o lugar. */
.wms-tela .wms-regua { display:grid; gap:0.5625rem; }
.wms-tela .wms-regua__cabeca { display:flex; justify-content:space-between; align-items:baseline;
  gap:0.625rem; }
.wms-tela .wms-lugares { display:flex; gap:3px; align-items:flex-end; }
.wms-tela .wms-lugar { flex:1; height:1.625rem; border-radius:2px; background:var(--wms-superficie-2);
  border:1px solid var(--wms-linha); position:relative; padding:0; }
/* Ocupado é fato, não alarme: cinza médio, não a tarja quase-preta da 1ª versão. */
.wms-tela .wms-lugar--cheio { background:var(--wms-linha-forte); border-color:var(--wms-linha-forte); }
.wms-tela .wms-lugar--aqui { background:var(--wms-marca); border-color:var(--wms-marca); height:2.125rem; }
.wms-tela .wms-lugar b { position:absolute; top:-1rem; left:50%; transform:translateX(-50%);
  font-size:0.625rem; color:var(--wms-marca); }

.wms-tela .wms-gesto { display:flex; gap:0.5rem; align-items:center; flex-wrap:wrap; }
.wms-tela .wms-gesto .wms-grupo { flex:1; min-width:8rem; }
.wms-tela .wms-gesto .wms-grupo--nivel { flex:0 0 auto; min-width:0; }
.wms-tela .wms-botao { border-radius:7px; padding:0.875rem 1rem; font-weight:600; font-size:1rem;
  background:var(--wms-vivo); color:var(--wms-vivo-tinta); border:1px solid var(--wms-vivo);
  display:flex; justify-content:space-between; align-items:center; gap:0.75rem; }
.wms-tela .wms-botao--quieto { background:none; color:var(--wms-tinta-2);
  border-color:var(--wms-linha-forte); font-weight:500; font-size:0.875rem;
  padding:0.625rem 0.875rem; }

.wms-tela .wms-rodape { display:grid; grid-template-columns:minmax(0,1.3fr) minmax(0,1fr);
  gap:0.875rem; }
.wms-tela .wms-bloco { padding:1rem 1.125rem; display:grid; gap:0.625rem; align-content:start; }
.wms-tela .wms-entrou { display:flex; align-items:baseline; justify-content:space-between;
  gap:0.75rem; font-size:0.84375rem; width:100%; text-align:left; }
.wms-tela .wms-entrou .wms-onde { font-weight:700; }
.wms-tela .wms-desfazer { font-size:0.78125rem; color:var(--wms-tinta-fraca);
  text-decoration:underline; background:none; border:0; padding:0; }
.wms-tela .wms-vaga { background:none; border:0; padding:0.125rem 0; color:inherit; }
.wms-tela .wms-vaga:hover { color:var(--wms-marca); }
.wms-tela .wms-nada-bloco { font-size:0.84375rem; color:var(--wms-tinta-fraca); margin:0; }
.wms-tela .wms-teclado { display:flex; gap:1rem; flex-wrap:wrap; font-size:0.75rem;
  color:var(--wms-tinta-fraca); margin:0; padding:0 2px; }
.wms-tela .wms-teclado kbd { border:1px solid var(--wms-linha-forte); border-bottom-width:2px;
  background:var(--wms-superficie); opacity:1; }

@media (max-width:820px) {
  .wms-tela .wms-bancada { grid-template-columns:1fr; }
  .wms-tela .wms-lado + .wms-lado { border-left:0; border-top:1px solid var(--wms-linha); }
  .wms-tela .wms-rodape { grid-template-columns:1fr; }
}
@media (prefers-reduced-motion:reduce) {
  .wms-tela *, .wms-tela *::before, .wms-tela *::after {
    animation:none !important; transition:none !important; }
}

/* --- Insights: gaveta lateral ---------------------------------------------
   Cartão em vez de tabela porque cada achado é um argumento — a frase, a forma
   da série e a evidência viajam juntas. A cor da borda vem de `direcao`, que o
   backend decide; o CSS não sabe o que é melhora.

   Gaveta (offcanvas do Bootstrap) e não visão: o insight se lê AO LADO do
   demonstrativo, conferindo a linha enquanto o card a explica. Como o `<aside>`
   mora dentro do `.page.dre`, os tokens `--dre-*` chegam nele por herança, ainda
   que o offcanvas seja `position:fixed`. */
.page.dre #dre-insights {
  --bs-offcanvas-width: min(600px, 96vw);
  background: var(--dre-papel-fundo); color: var(--dre-tinta);
  border-left: 1px solid var(--dre-regua-forte);
}
/* Split de verdade: a página cede a largura da gaveta em vez de ficar por baixo
   dela. Sem isto o card manda olhar a linha da tabela que o painel está cobrindo.

   Era `margin-right` porque o shell travava `.page { padding: ... !important }`
   e vencer isso exigiria outro `!important` numa regra de página. A trava morreu
   em 18/08/2026 (`2484ae68`), então voltou a ser `padding-right`: o recuo é do
   conteúdo, não uma margem que muda a caixa da página. */
@media (min-width: 1200px) {
  .page.dre { transition: padding-right 0.3s ease-in-out; }
  .page.dre.dre-com-gaveta { padding-right: min(600px, 96vw); }
}
/* O pisca é o único jeito de o clique na gaveta se explicar: a tabela do outro
   lado muda, e sem a marca o olho não acha onde. */
.page.dre tr.dre-focada > td { animation: dre-piscar 1.6s ease-out; }
@keyframes dre-piscar { 0%, 30% { background: var(--dre-ambar-fundo); } 100% { background: transparent; } }
@media (prefers-reduced-motion: reduce) {
  .page.dre { transition: none; }
  .page.dre tr.dre-focada > td { animation: none; background: var(--dre-ambar-fundo); }
}
/* O texto de apoio da gaveta usa tinta MÉDIA, não fraca: `--dre-tinta-fraca` foi
   calibrada contra o papel branco (4,52:1) e cai para 4,09:1 sobre o fundo
   tingido do painel — reprova o AA. Escopo local; o token não muda para o app.
   O `:not(.dre-direcao)` existe porque este seletor tem id e venceria a cor da
   direção, que é semântica (vermelho = dinheiro saindo) e não pode virar cinza. */
.page.dre #dre-insights .dre-dica,
.page.dre #dre-insights .dre-rotulo,
.page.dre #dre-insights .dre-etiqueta:not(.dre-direcao) { color: var(--dre-tinta-media); }
/* Título + recorte empilhados: o header do Bootstrap centraliza por padrão. */
.page.dre #dre-insights .offcanvas-header { align-items: flex-start; }
.page.dre #dre-insights .offcanvas-title { font-size: 16px; font-weight: 600; margin: 0; }
.page.dre .dre-grupo-insight + .dre-grupo-insight { margin-top: 22px; }
.page.dre .dre-grupo-insight .dre-rotulo { display: block; margin-bottom: 3px; }

.page.dre .dre-cartoes { display: grid; gap: 12px; margin-top: 10px; }
.page.dre .dre-cartao {
  background: var(--dre-papel); border: 1px solid var(--dre-regua);
  border-radius: 6px; padding: 12px 16px;
}
/* A direção mora na ETIQUETA, com palavra e seta — não numa faixa colorida na
   borda. Faixa lateral era o único canal de "piorou" para quem não distingue
   vermelho de verde, e o eixo do MAD nem escreve a palavra na frase. */
.page.dre .dre-direcao { font-weight: 600; }
.page.dre .dre-direcao.melhora { color: var(--dre-verde); border-color: var(--dre-verde); }
.page.dre .dre-direcao.piora { color: var(--dre-oxido); border-color: var(--dre-oxido); }
.page.dre .dre-etiquetas { display: flex; gap: 5px; flex: none; }
.page.dre .dre-cartao > header {
  display: flex; align-items: baseline; gap: 10px; justify-content: space-between;
}
.page.dre .dre-cartao-titulo { font-size: 14.5px; font-weight: 600; color: var(--dre-tinta); }
/* min-height 24px: WCAG 2.2 AA (2.5.8) é o piso do alvo, e o título sozinho
   media 23. Um pixel a menos ainda reprova. */
.page.dre button.dre-cartao-titulo {
  font-family: inherit; background: none; border: 0 solid transparent; border-bottom-width: 1px;
  padding: 0; text-align: left; cursor: pointer; min-height: 24px;
}
.page.dre button.dre-cartao-titulo:hover { color: var(--dre-acento); border-color: var(--dre-acento); }
.page.dre .dre-cartao-conta {
  font-size: 11.5px; color: var(--dre-tinta-fraca); font-variant-numeric: tabular-nums;
}
/* Reusa .dre-botao-texto da barra de instrumentos — mesmo gesto, mesmo vestido. */
.page.dre .dre-ver-fornecedores { margin-top: 10px; min-height: 24px; }
.page.dre .dre-cartao-texto {
  margin: 6px 0 0; font-size: 13.5px; color: var(--dre-tinta-media);
  font-variant-numeric: tabular-nums;
}
.page.dre .dre-cartao > footer { display: flex; gap: 14px; margin-top: 6px; flex-wrap: wrap; }
.page.dre .dre-cartao .dre-nota { font-size: 12px; color: var(--dre-tinta-fraca); }
.page.dre .dre-etiqueta {
  font-size: 11px; color: var(--dre-tinta-fraca); background: var(--dre-papel-fundo);
  border: 1px solid var(--dre-regua); border-radius: var(--raio-chip); padding: 1px 8px;
  white-space: nowrap; flex: none;
}
/* Faixa da série: escala visual do que o backend já ordenou e já marcou. */
.page.dre .dre-faixa {
  display: flex; align-items: flex-end; gap: 3px; height: 34px; margin-top: 10px;
}
.page.dre .dre-faixa i { flex: 1; background: var(--dre-regua-forte); border-radius: 2px 2px 0 0; }
.page.dre .dre-faixa i.dre-pico { background: var(--dre-oxido); }
.page.dre .dre-cartao-contexto {
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--dre-regua);
}
.page.dre .dre-cartao-contexto .dre-quadro-linhas th,
.page.dre .dre-cartao-contexto .dre-quadro-linhas td { padding: 5px 10px; font-size: 12.5px; }
/* Distorção: quem o backend marcou com `motivo` ganha fundo âmbar e a frase logo
   abaixo, na mesma faixa — a acusação viaja colada na evidência. */
.page.dre .dre-contexto tr.dre-destacada > td { background: var(--dre-ambar-fundo); }
.page.dre .dre-contexto tr.dre-motivo > td {
  background: var(--dre-ambar-fundo); color: var(--dre-ambar); font-size: 12px;
  padding-top: 0; border-top: none; line-height: 1.45;
}
.page.dre .dre-nota-tabela {
  margin: 8px 0 0; font-size: 12px; color: var(--dre-tinta-fraca);
}

/* certificados-lote */
/* Widget compartilhado (chip, lista, anexador) — bi/static/bi/js/certificados-lote.js.
   Hairline, sem sombra, sem cor decorativa; tokens do design system global. */
.cl-chip {
  display: inline-flex; align-items: center; gap: 4px;
  background: var(--surf); border: 1px solid var(--line); border-radius: 6px;
  padding: 2px 8px; font-size: 13px; color: var(--ink); cursor: pointer;
}
.cl-chip:hover { border-color: var(--line-3); }
@media (pointer: coarse) {
  .cl-chip { min-height: 44px; padding: 0 12px; }
}

.cl-drop {
  border: 1px dashed var(--line-3); border-radius: 8px;
  padding: 16px; text-align: center; color: var(--ink-2); font-size: 13px;
}
.cl-drop.is-over { background: var(--surf-2); }

.cl-lista {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: 1fr auto auto; gap: 4px 10px;
}
.cl-doc {
  display: contents;
}
.cl-doc__nome { color: var(--ink); font-size: 13px; grid-column: 1; }
.cl-doc__meta { color: var(--ink-2); font-size: 13px; }
.cl-doc__confirma { color: var(--ink-2); font-size: 13px; }

.cl-relatorio__resumo { font-size: 14px; font-weight: 600; color: var(--ink); }
.cl-progresso { font-size: 13px; color: var(--ink-2); }
.cl-vazio { font-size: 13px; color: var(--ink-2); }

/* Linha de detalhe do lote — Estoques (row().child() do DataTables) e
   Separação (<tr> inserido à mão): mesma classe, mesmo tratamento. */
.cl-linha-detalhe > td { background: var(--surf-2); }

/* Rodapé fixo do modal "Saldo por lote" (Estoques) — aviso sobre o alcance
   dos certificados e o atalho para o pedido já faturado. */
.cl-rodape {
  margin-top: 0.5rem; padding-top: 0.5rem; border-top: 1px solid var(--line);
  font-size: 13px; color: var(--ink-2);
}

/* bancada — casca das telas-ferramenta (Gerar NF Sênior · Criar lotes) */
/* Uma tela-ferramenta é usada 8 h por dia ao lado do ERP: a ação que escreve
   nunca pode sumir. Aqui a página não rola — a grade ocupa a altura disponível,
   cada região rola sozinha e a régua fecha a página por baixo. Medido em
   18/08/2026: com a ação no fluxo do conteúdo ela caía para y=936 em 1600×900 e
   exigia 430 px de rolagem em 1280×720. Template: bi/templates/bi/components/
   _bancada.html. Variáveis próprias (`--bnc-*`), nenhum token global tocado. */
.page.bnc {
  /* Colunas laterais cedem em tela pequena e param de crescer em tela grande: em
     1280 a lista fixa de 320 px mais a prancheta comiam 736 px e sobravam 544
     para o trabalho, que é onde o operador digita. O trabalho fica com o resto
     (`minmax(0,1fr)`), sempre. */
  --bnc-lista: clamp(15rem, 20vw, 20rem);        /* 240 … 320 px */
  --bnc-prancheta: clamp(20rem, 28vw, 26rem);    /* 320 … 416 px */
  --bnc-alvo: 44px;            /* alvo de toque: mínimo físico, não escala */
  /* `rem` e não `px`: quem aumenta o corpo de texto no navegador tem de ser
     obedecido — a tela é usada 8 h por dia. */
  --bnc-fs-rotulo: 0.75rem;    /* 12 px no padrão — rótulo, unidade, contagem */
  --bnc-fs-dado: 0.8125rem;    /* 13 px — o dado em si, o tamanho de leitura */
  --bnc-fs-titulo: 1rem;       /* 16 px — título de região */
}

/* Três tamanhos, não seis. A tela media 12 · 12,25 · 13 · 14 · 16 · 20 px, e os
   dois primeiros são indistinguíveis a um palmo do monitor (TR-3). */
.page.bnc { font-size: var(--bnc-fs-dado); }
.page.bnc :is(small, .small, .lab, .n, .iof-sub, .iof-f__k, .iof-note, .bnc__frase) {
  font-size: var(--bnc-fs-rotulo);
}
.page.bnc :is(h1, h2, h3) { font-size: var(--bnc-fs-titulo); }
/* `code` traz 0.875em do Bootstrap e reintroduzia um quarto tamanho dentro da
   prancheta; aqui ele é só a fonte monoespaçada, no tamanho do texto ao redor. */
.page.bnc code { font-size: 1em; }
/* Bootstrap traz 14 px em botão, selo, cabeçalho de tabela e rótulo de campo —
   é o quarto tamanho que ninguém pediu. */
.page.bnc :is(.btn, .table, .iof-f__v, .iof-doc__t, .iof-lote, .iof-result) {
  font-size: var(--bnc-fs-dado);
}
.page.bnc :is(.badge, th, .iof-deprow, .iof-doc__sub, .iof-items th) {
  font-size: var(--bnc-fs-rotulo);
}
/* O valor informado da nota: era `.fs-5` (20 px com `!important` do Bootstrap). */
.iof-valor { font-size: var(--bnc-fs-titulo); font-weight: 600;
  font-variant-numeric: tabular-nums; }

/* Alvo de toque: valia 44 px só na régua, e a busca, o depósito e as ações do
   corpo ficavam em 31 px (TR-1). Vale para todo controle da bancada. */
.page.bnc :is(.btn, .form-control, .form-select) { min-height: var(--bnc-alvo); }
.page.bnc .btn-close { width: var(--bnc-alvo); height: var(--bnc-alvo); }

/* O que é clicável tem de parecer, e o teclado tem de ver onde está (TR-2). */
.bnc__lista .list-group-item { transition: background-color .16s ease-out; }
.bnc__lista .list-group-item:hover:not(:disabled) { background: var(--surf-3); }
.page.bnc :is(.list-group-item, .btn, .form-control, .form-select):focus-visible {
  outline: 2px solid var(--acc-line); outline-offset: 2px; box-shadow: none;
}
@media (prefers-reduced-motion: reduce) {
  .page.bnc *, .page.bnc *::before, .page.bnc *::after { transition-duration: 0ms !important; }
}
.content--altura-cheia > .page.bnc {
  display: grid;
  grid-template-columns: var(--bnc-lista) minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr) auto;
  gap: 0; min-height: 0; overflow: hidden;
  background: var(--surf); border: 1px solid var(--line); border-radius: var(--r);
}
/* Prancheta aberta = terceira coluna. `:has` porque quem manda é o `hidden` do
   próprio elemento — sem classe de estado no pai para o JS esquecer de tirar. */
.content--altura-cheia > .page.bnc:has(> .bnc__prancheta:not([hidden])) {
  grid-template-columns: var(--bnc-lista) minmax(0, 1fr) var(--bnc-prancheta);
}

.bnc__lista {
  display: flex; flex-direction: column; min-height: 0;
  border-right: 1px solid var(--line); background: var(--surf-2);
}
.bnc__busca {
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0.75rem; border-bottom: 1px solid var(--line);
}
.bnc__busca .n { color: var(--ink-2); font-size: 12px; white-space: nowrap; }
.bnc__rolagem { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

.bnc__trabalho { display: flex; flex-direction: column; min-height: 0; overflow-y: auto; }
.bnc__vazio { padding: 3rem 1rem; text-align: center; color: var(--ink-2); }

.bnc__prancheta {
  display: flex; flex-direction: column; min-height: 0; overflow: hidden;
  border-left: 1px solid var(--line); background: var(--surf-2);
}
.bnc__prancheta[hidden] { display: none; }
.bnc__prancheta-cab {
  display: flex; align-items: flex-start; gap: 0.5rem;
  padding: 0.75rem 1rem; border-bottom: 1px solid var(--line);
}
.bnc__prancheta-cab h2 { margin: 0; font-size: 13px; font-weight: 600; color: var(--ink); }
.bnc__prancheta-cab .n { color: var(--ink-2); font-size: 12px; }
.bnc__prancheta-corpo { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 1rem; }

/* Régua: a linha que fecha a página. Uma frase (do backend) e a ação primária. */
.bnc__regua {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap;
  padding: 0.625rem 1rem;
  border-top: 1px solid var(--line); background: var(--surf);
}
.bnc__frase { flex: 1 1 12rem; margin: 0; font-size: 13px; color: var(--ink-2); }
.bnc__frase b { color: var(--ink); font-variant-numeric: tabular-nums; }
.bnc__regua .btn { min-height: var(--bnc-alvo); }
.bnc__regua .btn:disabled { opacity: 0.55; }

@media (max-width: 991.98px) {
  .content--altura-cheia > .page.bnc,
  .content--altura-cheia > .page.bnc:has(> .bnc__prancheta:not([hidden])) {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr) auto;
  }
  .bnc__lista { max-height: 14rem; border-right: 0; border-bottom: 1px solid var(--line); }
  .bnc__prancheta { border-left: 0; border-top: 1px solid var(--line); }
}

/* bancada · importar certificado */
/* A tela entrou na bancada em 18/08/2026: histórico à esquerda, envio e bloco
   extraído no trabalho, avisos do parse na prancheta. Estas regras viviam num
   `<style>` dentro do template (regra dura: CSS autoral só aqui). */
.cert-envio { display: flex; flex-direction: column; gap: 0.5rem; padding: 1rem;
  border-bottom: 1px solid var(--line); }
.cert-envio .lab, .cert-resultado .lab { margin: 0; color: var(--ink-2);
  text-transform: uppercase; letter-spacing: .04em; }

.cert-drop { display: flex; align-items: center; gap: 1rem; width: 100%;
  border: 1.5px dashed var(--line-3); border-radius: var(--r-sm); background: var(--surf-2);
  padding: 1.1rem 1.25rem; cursor: pointer; text-align: left;
  transition: border-color .16s ease-out, background-color .16s ease-out; }
.cert-drop:hover { border-color: var(--acc-line); background: var(--surf-3); }
.cert-drop--drag { border-color: var(--brand); background: var(--brand-soft); }
/* O input de arquivo é 1 px e invisível — mas continua sendo o que recebe o
   Tab. Sem isto o foco de teclado pousava num ponto que ninguém vê (IC-5). */
.cert-drop:focus-within { outline: 2px solid var(--acc-line); outline-offset: 2px; }
.cert-drop__input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.cert-drop__icon { font-size: 1.6rem; color: var(--ink-3); flex: none; }
.cert-drop__txt { display: flex; flex-direction: column; gap: .1rem; }
.cert-drop__hint { color: var(--ink); }
.cert-drop__sub { color: var(--ink-3); font-size: var(--bnc-fs-rotulo); }

.cert-foot { display: flex; align-items: center; gap: .75rem; }
.cert-chip { display: inline-flex; align-items: center; gap: .5rem;
  padding: .35rem .6rem; background: var(--surf-2); border: 1px solid var(--line);
  border-radius: var(--r-xs); color: var(--ink-2); max-width: 60%; }
.cert-chip__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cert-chip__x { border: 0; background: transparent; color: var(--ink-3);
  font-size: 1.05rem; line-height: 1; cursor: pointer; padding: 0 .1rem; }
.cert-erro { color: var(--negative-text); margin: 0; }
.cert-loading { display: flex; align-items: center; gap: .6rem; color: var(--ink-2); padding: 1.4rem; }

.cert-resultado { display: flex; flex-direction: column; gap: 0.75rem; padding: 1rem; min-height: 0; }
.cert-resultado #cert-tabela { font-size: var(--bnc-fs-rotulo); }
/* Os cartões de resumo vinham com `.fs-4`/`.fs-5` do Bootstrap (24 e 20 px) —
   o quarto e o quinto tamanho da tela. O maior número da bancada é o título. */
.cert-resultado #cert-kpis :is(.fs-4, .fs-5) { font-size: var(--bnc-fs-titulo) !important; }
.cert-resultado #cert-kpis .card-body { padding: 0.625rem 0.75rem; }
.cert-resultado #cert-tabela tbody td { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* Linha do histórico: abre o import. Era uma `<tr>` de DataTables com
   `cursor: auto` — clicável e sem parecer (IC-4). */
.cert-hist__arquivo { font-weight: 600; }
.cert-hist__sub { color: var(--ink-2); font-size: var(--bnc-fs-rotulo); }
.cert-aviso { padding: .5rem .75rem; border-radius: var(--r-sm);
  background: var(--warning-subtle); color: var(--warning-text); margin: 0 0 .5rem; }

@media (max-width: 640px) {
  .cert-drop { flex-direction: column; text-align: center; align-items: center; }
  .cert-chip { max-width: 100%; }
}

/* criar lotes (URL /romaneio/) */
/* A tela entrou na bancada em 18/08/2026: colunas, rolagem, régua e prancheta
   são `.bnc*` — daqui para baixo é só o conteúdo do lançamento. As regras de
   grade, lista e painel lateral que moravam aqui morreram junto com o
   offcanvas. Tokens do design system global. */

.rom__ok { color: var(--positive-text); font-weight: 700; }

.rom__corpo { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; padding: 1rem; gap: 0.75rem; }
.rom__cabecalho { display: flex; align-items: center; gap: 0.75rem; }
.rom__cab { font-weight: 600; color: var(--ink); }
.rom__item { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.rom__item .lab { color: var(--ink-2); font-size: 12px; margin: 0; }
.rom__item select { width: auto; min-width: 18rem; max-width: 100%; }

/* Alvo do item: os três números que a conferência tem de fechar. Era um `dl`
   com `margin-left:auto` dentro da linha do item; sem espaço sobrando, ele
   colapsava para `width: 0` na borda direita e os três números sumiam da tela
   (CL-1, medido em 18/08/2026). Agora é linha própria, com largura garantida. */
.rom__alvo { display: flex; flex-wrap: wrap; gap: 1.5rem; margin: 0;
  padding: 0.625rem 0.75rem; border-radius: var(--r-sm); background: var(--surf-2); }
.rom__alvo:empty { display: none; }
.rom__alvo > div { min-width: 7rem; }
.rom__alvo dt { color: var(--ink-2); font-size: var(--bnc-fs-rotulo); font-weight: 400; }
.rom__alvo dd { margin: 0; font-variant-numeric: tabular-nums; color: var(--ink);
  font-size: var(--bnc-fs-titulo); }

.rom__textarea {
  flex: 1 1 auto; min-height: 12rem; resize: vertical;
  font-family: var(--mono); font-size: 13px;
}
.rom__linhas { color: var(--ink-2); font-size: var(--bnc-fs-rotulo); }
.rom__lancado {
  padding: 0.5rem 0.75rem; border-radius: var(--r-sm);
  background: var(--positive-subtle); color: var(--positive-text); font-size: 13px;
}

/* Topo fixo da prancheta: a soma vs. alvo não rola com as 74 linhas. */
.rom__painel-topo { padding: 0 1rem; border-bottom: 1px solid var(--line); }
.rom__painel-topo:empty { display: none; }
.rom__painel-topo .rom-result { margin-bottom: 0.75rem; }
#rom-painel-titulo:focus-visible { outline: 2px solid var(--acc-line); outline-offset: 2px; }
.rom__painel-rodape {
  position: sticky; bottom: 0; display: flex; align-items: center; gap: 0.5rem;
  padding: 0.75rem 1rem; border-top: 1px solid var(--line); background: var(--surf);
}
.rom__painel-rodape:empty { display: none; }
.rom-confirma__texto { flex: 1 1 auto; color: var(--ink); font-size: 13px; }

/* Situação da conferência: texto colorido com glifo, nunca cor sozinha. */
.rom-result { display: flex; align-items: center; gap: 0.5rem; padding: 0.75rem; border-radius: var(--r-sm); font-size: 13px; }
.rom-result__ic { flex: none; font-weight: 700; }
.rom-result--ok { background: var(--positive-subtle); }
.rom-result--ok, .rom-result--ok b { color: var(--positive-text); }
.rom-result--warn { background: var(--warning-subtle); }
.rom-result--warn, .rom-result--warn b { color: var(--warning-text); }
.rom-result--err { background: var(--negative-subtle); }
.rom-result--err, .rom-result--err b { color: var(--negative-text); }
.rom-muted { color: var(--ink-2); }
.rom-items { font-size: 13px; font-variant-numeric: tabular-nums; }
.rom-items th { font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-2); }
.rom-erros {
  margin: 0.75rem 0; padding: 0.75rem; border-radius: var(--r-sm);
  background: var(--negative-subtle); color: var(--negative-text); font-size: 13px;
}
.rom-dup-list { margin: 0.25rem 0 0; padding-left: 1rem; }

/* Chips-contadores: FILTRO DE APRESENTAÇÃO (escondem <tr>). O N do botão Gravar
   vem de `contadores` e não muda com o filtro. */
.rom-chips { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; margin: 0.75rem 0; }
.rom-chip {
  background: var(--surf); border: 1px solid var(--line); border-radius: 6px;
  padding: 2px 8px; font-size: 13px; color: var(--ink); cursor: pointer;
}
.rom-chip[aria-pressed="true"] { background: var(--surf-2); border-color: var(--line-3); font-weight: 600; }
.rom-chip__n { font-variant-numeric: tabular-nums; color: var(--ink-2); }
.rom-chips__estado { color: var(--ink-2); font-size: 12px; }
.rom-gravando { padding: 2rem 1rem; text-align: center; color: var(--ink-2); }

/* Etapa Certificados — opcional: o lote já está gravado, o papel pode vir depois. */
.rom-cert__linha { color: var(--ink); font-size: 14px; }
.rom-cert__aviso {
  padding: 0.75rem; border-radius: var(--r-sm);
  background: var(--warning-subtle); color: var(--warning-text); font-size: 13px;
}
.rom-cert__lista { list-style: none; margin: 1rem 0 0; padding: 0; }
.rom-cert__lote {
  display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap;
  padding: 0.25rem 0; border-bottom: 1px solid var(--line); font-size: 13px;
}
.rom-cert__chip { margin-left: auto; }
/* Papéis do lote (abertos pelo chip) e anexador daquele lote — ocupam a linha
   inteira, logo abaixo dela: um anexador no fim da lista não diria de qual lote é. */
.rom-cert__docs, .rom-cert__anexar { flex: 0 0 100%; padding: 0.5rem 0 0.5rem 1rem; }

/* O alvo de 44 px agora é regra da bancada e vale sempre, não só em toque; aqui
   sobra o chip, que não é `.btn`. */
@media (pointer: coarse) { .rom-chip { min-height: 44px; } }

/* consulta-separacao */
/* "Documentos do pedido" (`/consulta-separacao/`, 17/08/2026) —
   bi/templates/bi/consulta-separacao.html + bi/static/bi/js/consulta-separacao.js.
   Uma linha por pedido, o detalhe num painel lateral sem backdrop (o pedido
   aberto convive com a lista). Hairline, sem sombra, números tabulares, cor só
   com significado: faturado em `--positive-text`, cancelado em `--negative-text`,
   o resto em `--ink-2` — e o glifo vai junto, nunca a cor sozinha.
   Tokens do design system global. */

.cs__busca { display: flex; align-items: flex-end; gap: 0.5rem; flex-wrap: wrap; }
.cs__campo { display: flex; flex-direction: column; gap: 2px; margin: 0; }
.cs__campo .lab { margin: 0; font-size: 12px; color: var(--ink-2); }
.cs__campo input { width: 9rem; }
.cs__aviso {
  margin: 0 0 0.75rem; padding: 0.5rem 0.75rem; border-radius: var(--r-sm);
  background: var(--surf-2); color: var(--ink-2); font-size: 13px;
}

#cs-tabela tbody tr { cursor: pointer; }
#cs-tabela tbody tr:hover { background: var(--surf-2); }
#cs-tabela tbody tr:focus-visible { outline: 2px solid var(--line-3); outline-offset: -2px; }
/* Hierarquia da linha: o pedido e o cliente são a identidade (tinta cheia,
   600); autor e data são contexto (tinta secundária). */
.cs-num { font-variant-numeric: tabular-nums; }
#cs-tabela tbody td:first-child,
#cs-tabela tbody td:nth-child(2) { color: var(--ink); font-weight: 600; }
.cs-vazio { color: var(--ink-2); font-size: 13px; text-align: center; padding: 1.5rem 0.75rem; }
.cs-autor { color: var(--ink-2); }
.cs-quando { display: block; color: var(--ink-2); font-size: 12px; font-variant-numeric: tabular-nums; }
.cs-casado { color: var(--ink-2); font-size: 12px; }
.cs-casado mark { background: var(--warning-subtle); color: var(--ink); padding: 0 2px; }
.cs-badge {
  background: var(--surf-2); border: 1px solid var(--line); color: var(--ink-2);
  font-weight: 400; font-size: 12px;
}

/* Situação: glifo + rótulo, ambos do backend. Cor só onde ela significa algo. */
.cs-sit { color: var(--ink-2); white-space: nowrap; }
.cs-sit--faturado { color: var(--positive-text); }
.cs-sit--cancelado { color: var(--negative-text); }

.cs-chip {
  display: inline-flex; align-items: center; gap: 4px; margin-right: 4px;
  background: var(--surf); border: 1px solid var(--line); border-radius: 6px;
  padding: 2px 8px; font-size: 12px; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.cs-chip--vazio { color: var(--ink-2); background: var(--surf-2); }

/* Painel lateral: mesma largura e ausência de backdrop do romaneio. */
.cs__painel { --bs-offcanvas-width: min(52rem, 96vw); }
.cs__painel .offcanvas-body { overflow-y: auto; }
.cs__painel-sub { color: var(--ink-2); font-size: 12px; }
#cs-painel-titulo:focus-visible { outline: 2px solid var(--line-3); outline-offset: 2px; }

.cs-bloco { margin-bottom: 1.25rem; }
.cs-bloco__t {
  margin: 0 0 0.5rem; font-size: 12px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .04em; color: var(--ink-2);
}
.cs-bloco__rodape { margin: 0.5rem 0 0; color: var(--ink-2); font-size: 12px; }
/* Documentos ficam no topo: é o que a pessoa veio buscar. */
.cs-bloco--docs { padding-bottom: 1rem; border-bottom: 1px solid var(--line); }
.cs-docs { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.cs-doc {
  display: inline-flex; align-items: baseline; gap: 6px; font-size: 13px;
  padding: 4px 8px; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--surf); color: var(--ink); text-decoration: none;
}
.cs-doc:hover { border-color: var(--line-3); }
/* Botão desabilitado não recebe evento: quem carrega o motivo é o invólucro. */
.cs-zip-wrap { display: inline-flex; }
.cs-doc--ausente { color: var(--ink-2); background: var(--surf-2); }
.cs-doc__meta { color: var(--ink-2); font-size: 12px; font-variant-numeric: tabular-nums; }

.cs-tempo { list-style: none; margin: 0; padding: 0; }
.cs-evento {
  display: flex; align-items: baseline; gap: 0.5rem; flex-wrap: wrap;
  padding: 0.25rem 0; border-bottom: 1px solid var(--line); font-size: 13px;
}
.cs-evento__quando { color: var(--ink-2); font-variant-numeric: tabular-nums; min-width: 11rem; }
.cs-evento__t { color: var(--ink); }
.cs-evento__meta { color: var(--ink-2); }

.cs-lotes { list-style: none; margin: 0; padding: 0; }
.cs-lote {
  display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap;
  padding: 0.375rem 0; border-bottom: 1px solid var(--line); font-size: 13px;
}
.cs-lote__id { color: var(--ink); font-family: var(--mono); }
.cs-lote__qtd { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.cs-lote__end { color: var(--ink-2); }
.cs-lote__chip { margin-left: auto; }
/* Papéis do lote e o anexador daquele lote ocupam a linha inteira, logo abaixo
   dela: um anexador no fim da lista não diria de qual lote é. */
.cs-lote__docs, .cs-lote__anexar { flex: 0 0 100%; padding: 0.5rem 0 0.5rem 1rem; }

@media (pointer: coarse) {
  .cs-chip, .cs__busca .btn, .cs-doc { min-height: 44px; }
  .cs__campo input { min-height: 44px; }
}
@media (prefers-reduced-motion: reduce) {
  .cs__painel, .cs__painel.offcanvas { transition: none; }
}

/* wms-expedicao */
/* Expedição (`/wms/expedicao/`, 03/09/2026) — bi/templates/bi/expedicao.html +
   bi/static/bi/js/expedicao.js. Duas abas sobre a MESMA tabela (a fila troca
   de fonte, a forma da linha não). Botão único por linha, sempre azul sólido
   (`.btn-primary`) — cinza lê como desabilitado, regra da casa. Tokens do
   design system global; segue o FCDS sem desvio (o override é só da tela de
   Pedidos). */

/* `gap` escopado à página, não em `.card-hd` (componente de ~29 templates —
   mudar o global exige aval do dono, ver task-9-report.md "Fix round 1/2").
   Sem ele, o `margin-left:auto` de `.exp__busca` consome o espaço livre antes
   do `space-between` de `.card-hd` ter o que distribuir, e "Notas" cola no
   botão da aba (achado ao vivo em /wms/expedicao/, 03/09/2026). */
[data-pagina="wms-expedicao"] .card-hd { gap: 0.75rem; }

.exp__abas { display: flex; gap: 0.375rem; }
.exp__aba.active { background: var(--acc); border-color: var(--acc); color: #fff; }

.exp__busca { display: flex; align-items: flex-end; gap: 0.5rem; flex-wrap: wrap; margin-left: auto; }
.exp__campo { display: flex; flex-direction: column; gap: 2px; margin: 0; }
.exp__campo .lab { margin: 0; font-size: 12px; color: var(--ink-2); }
.exp__campo input { width: 9rem; }

.exp__aviso {
  margin: 0 0 0.75rem; padding: 0.5rem 0.75rem; border-radius: var(--r-sm);
  background: var(--surf-2); color: var(--ink-2); font-size: 13px;
}
.exp__aviso--erro { background: var(--negative-subtle); color: var(--negative-text); }

.exp-num { font-variant-numeric: tabular-nums; color: var(--ink); font-weight: 600; }
.exp-vazio { color: var(--ink-2); font-size: 13px; text-align: center; padding: 1.5rem 0.75rem; }
.exp-autor { color: var(--ink); }
.exp-quando { display: block; color: var(--ink-2); font-size: 12px; font-variant-numeric: tabular-nums; }

@media (pointer: coarse) {
  .exp__aba, .exp__busca .btn, #exp-tabela .btn { min-height: 44px; }
  .exp__campo input { min-height: 44px; }
}

/* ============================================================
   SIMULAÇÕES — DOCUMENTO DA SIMULAÇÃO (impressão / PDF WeasyPrint)
   Renderizado por bi/templates/bi/simulacao_pdf.html via
   bi/services/simulacoes_registro.py. Prefixo .simpdf-.
   Página NOMEADA de propósito: o @page anônimo lá em cima pertence à
   proposta do CRM (margens de 30/40 mm e cabeçalho corrido); este
   documento não tem cabeçalho corrido e precisa da sua própria caixa.
   ============================================================ */
@page simulacao { size: A4; margin: 18mm 14mm; }
.simpdf-doc{ page:simulacao; font-family:'DejaVu Sans', Arial, sans-serif;
  font-size:10.5pt; color:#1f2937; }
.simpdf-titulo{ font-size:15pt; margin:0 0 2mm; }
.simpdf-sub{ color:#6b7280; font-size:9pt; margin-bottom:6mm; }
.simpdf-tabela{ width:100%; border-collapse:collapse; margin-bottom:6mm; }
.simpdf-tabela th, .simpdf-tabela td{ padding:2mm 2.5mm;
  border-bottom:0.3mm solid #e5e7eb; text-align:right; }
.simpdf-tabela th:first-child, .simpdf-tabela td:first-child{ text-align:left; }
.simpdf-tabela th{ font-size:8.5pt; color:#6b7280; font-weight:500; }
.simpdf-soma td{ font-weight:600; border-top:0.5mm solid #1f2937; border-bottom:0; }
.simpdf-neg{ color:#b91c1c; }

/* ===========================================================================
   Simulações (/simulacoes/criar/ e /simulacoes/lista/).
   Porte do mockup aprovado docs/superpowers/mockups/simulacoes-a.html: MESMOS
   nomes de classe, prefixados `sim-`, mesmas medidas. Tudo local à tela — o
   prefixo mantém o alcance e nenhum token global é redefinido aqui.
   Da bancada (18/08/2026) ficou só o comportamento: a página não rola (mesa em
   `content--altura-cheia`, catálogo e coluna rolam sozinhos) e a régua de baixo
   fecha a página com piso + frase + a única ação. A versão de três colunas com
   controles de 44 px foi rejeitada pelo dono (19/08/2026): "o mockup é superior".
   =========================================================================== */
.sim-page{--sim-gap:0.75rem}
.sim-num{font-variant-numeric:tabular-nums}
/* `.sim-nota` é o `.sk` do mockup: a linha pequena, cinza, embaixo de um campo
   ou de um número. `.sim-atencao`/`--positivo`/`--negativo` são o pill-*. */
.sim-nota{font-size:0.75rem;color:var(--ink-3);display:block}
.sim-atencao{color:var(--chart-alerta-text)}
.sim-positivo{color:var(--positive-text)}
.sim-negativo{color:var(--negative-text)}
.sim-hint{margin-left:auto;font-weight:400;color:var(--ink-3);font-size:0.75rem}
/* Cor nesta tela (19/08/2026): UM contrato — o azul do sistema é a cor de
   ação e de seleção (Registrar, Sim/Não ativo, Próximo do assistente, linha
   selecionada do catálogo). Sem botão preto em lugar nenhum. Vermelho/âmbar/
   verde só onde significa margem (régua, KPI de MB, linhas divergentes).
   Teclas (`kbd`) são chips claros — o preto do Bootstrap em cima do azul
   destoava; dentro de botão azul o chip é translúcido. */
.sim-page kbd{font-family:inherit;font-size:0.6875rem;font-weight:600;line-height:1;
  padding:0.15rem 0.35rem;border-radius:4px;background:var(--surf-3);color:var(--ink-2);
  border:1px solid var(--line-3);box-shadow:none;vertical-align:baseline}
.sim-page .btn-primary kbd{background:rgba(255,255,255,.18);color:#fff;border-color:transparent}
#sim-contribuinte .btn-outline-secondary{color:var(--ink-2);border-color:var(--line-3)}
#sim-contribuinte .btn-outline-secondary:hover{background:var(--surf-2);color:var(--ink)}
/* Link de texto dentro de rótulo (o "usar o piso" do mockup): é botão de
   verdade por acessibilidade, mas tem de parecer o link que o mockup mostra. */
.sim-link{border:0;background:none;padding:0;color:var(--acc);font:inherit;
  cursor:pointer;text-decoration:none}
.sim-link:hover{text-decoration:underline}

/* Cartões: o mockup tem cabeçalho branco, 10/14, peso 600 — não o cabeçalho
   cinza do FCDS. Reescrito SÓ dentro de `.sim-page`. */
.sim-page .card{border-radius:10px}
.sim-page .card-header.sim-card-h{display:flex;align-items:baseline;gap:0.5rem;
  padding:0.625rem 0.875rem;background:var(--surf);font-weight:600;
  font-size:0.75rem;text-transform:uppercase;letter-spacing:0.04em;color:var(--ink-2);
  border-bottom:1px solid var(--line)}
.sim-page .card-header.sim-card-h .sim-hint,.sim-page .card-header.sim-card-h .sim-link{
  text-transform:none;letter-spacing:0;font-weight:400}
.sim-page .card-body.sim-card-b{padding:0.75rem 0.875rem}
.sim-card-b--tabela{padding:0.25rem 0.5rem 0.5rem}

/* Mesa: catálogo à esquerda, tudo o mais à direita (mockup: 320px 1fr) */
.sim-mesa{display:grid;grid-template-columns:320px minmax(0,1fr);
  gap:var(--sim-gap);align-items:start;
  /* altura cheia: a mesa ocupa o que sobra e cada coluna rola sozinha */
  flex:1 1 auto;min-height:0;grid-template-rows:minmax(0,1fr)}
.sim-mesa>.sim-coluna{max-height:100%;overflow-y:auto;padding-right:2px}
.sim-page.page{padding-top:var(--sim-gap)}
.sim-coluna{display:flex;flex-direction:column;gap:var(--sim-gap);min-width:0}
.sim-split{display:grid;grid-template-columns:5fr 6fr;gap:var(--sim-gap);
  align-items:start}

/* Catálogo */
.sim-catalogo{display:flex;flex-direction:column;max-height:100%;min-height:0}
.sim-catalogo__busca{padding:0.5rem 0.625rem;border-bottom:1px solid var(--line)}
.sim-catalogo__lista{overflow:auto;flex:1}
.sim-catalogo__vazio{font-size:0.8125rem;color:var(--ink-3);padding:0.75rem 0.875rem;
  margin:0}
.sim-catalogo__grupo{display:flex;align-items:baseline;gap:0.5rem;
  padding:0.5rem 0.875rem 0.15rem;font-size:0.75rem;font-weight:600;
  color:var(--ink-2);background:var(--surf);position:sticky;top:0;z-index:1}
.sim-catalogo__meta{margin-left:auto;font-weight:400;color:var(--ink-3)}
.sim-catalogo__item{display:flex;justify-content:space-between;align-items:center;
  gap:0.5rem;width:100%;text-align:left;padding:0.4375rem 0.875rem;border:0;
  border-bottom:1px solid var(--line);background:none;color:inherit;
  font-size:0.8125rem;cursor:pointer}
.sim-catalogo__item:hover,.sim-catalogo__item:focus-visible{background:var(--surf-2)}
.sim-catalogo__item.is-ativo{background:var(--acc-soft);box-shadow:inset 3px 0 var(--acc)}
.sim-catalogo__texto{min-width:0;display:flex;flex-direction:column;gap:0.1rem}
.sim-catalogo__nome{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sim-catalogo__codigo{color:var(--ink-3)}
.sim-catalogo__custo{font-size:0.75rem;color:var(--ink-3);white-space:nowrap}
.sim-catalogo__custo b{color:var(--ink)}
.sim-catalogo__ocultos{padding:0.25rem 0.875rem 0.5rem;font-size:0.75rem;
  color:var(--ink-3);border-bottom:1px solid var(--line)}

/* Ficha do item + KPIs */
.sim-item{display:flex;align-items:baseline;gap:0.625rem;flex-wrap:wrap}
.sim-item__nome{font-size:1.125rem;font-weight:600;margin:0;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:60%}
.sim-kpis{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  gap:0.625rem;margin-top:0.625rem}
.sim-kpi{border:1px solid var(--line);border-radius:10px;
  padding:0.625rem 0.875rem;background:var(--surf)}
.sim-kpi__rotulo{font-size:0.6875rem;color:var(--ink-3);font-weight:600;
  text-transform:uppercase;letter-spacing:0.04em}
.sim-kpi__valor{font-size:1.625rem;font-weight:600;line-height:1.1;margin-top:2px;
  letter-spacing:-0.01em;font-variant-numeric:tabular-nums;transition:color 220ms ease-out}
.sim-kpi__nota{font-size:0.78125rem;color:var(--ink-3);margin-top:3px}
.sim-kpi.sim-ok{background:var(--positive-subtle);
  border-color:color-mix(in srgb,var(--positive) 28%,var(--surf))}
.sim-kpi.sim-atencao{background:var(--warning-subtle);
  border-color:color-mix(in srgb,var(--warning) 28%,var(--surf))}
.sim-kpi.sim-ruim{background:var(--negative-subtle);
  border-color:color-mix(in srgb,var(--negative) 28%,var(--surf))}
.sim-kpi.sim-ok .sim-kpi__valor{color:var(--positive-text)}
.sim-kpi.sim-atencao .sim-kpi__valor{color:var(--chart-alerta-text)}
.sim-kpi.sim-ruim .sim-kpi__valor{color:var(--negative-text)}
.sim-kpi--alerta .sim-kpi__valor,.sim-kpi--alerta .sim-kpi__nota{color:var(--negative-text)}
.sim-aviso{color:var(--chart-alerta-text)}

/* Régua de preço — o instrumento da tela. Prejuízo (< custo) · abaixo da meta
   (custo → piso) · na meta (≥ piso). Os LIMITES são custo e piso, do serviço; o
   cursor é o preço líquido e se ARRASTA: a posição vira número no campo de
   preço e o backend recalcula. Barra alta (14 px), marcas com o número em
   destaque, cursor com alça de 44 px de alvo (o único controle grande da tela,
   e é o que se pega com o dedo). */
.sim-regua{margin-top:0.75rem;padding:0 0.375rem}
.sim-regua__vazia{font-size:0.8125rem;color:var(--ink-3);margin:1rem 0 0.25rem}
.sim-regua__barra{position:relative;height:14px;border-radius:7px;background:var(--surf-3);
  margin:2rem 3rem 2.25rem;cursor:pointer;touch-action:none}
.sim-regua__barra--fantasma{cursor:default;opacity:0.5}
.sim-regua__faixa{position:absolute;top:0;height:100%}
.sim-regua__faixa--ruim{background:color-mix(in srgb,var(--negative) 32%,var(--surf));
  border-radius:7px 0 0 7px}
.sim-regua__faixa--atencao{background:color-mix(in srgb,var(--warning) 38%,var(--surf))}
.sim-regua__faixa--ok{background:color-mix(in srgb,var(--positive) 32%,var(--surf));
  border-radius:0 7px 7px 0}
.sim-regua__marca{position:absolute;top:-5px;width:2px;height:24px;background:var(--ink);
  border-radius:1px}
.sim-regua__marca span{position:absolute;top:-1.375rem;left:50%;transform:translateX(-50%);
  white-space:nowrap;font-size:0.75rem;color:var(--ink-3);font-weight:400}
.sim-regua__marca em{font-style:normal;color:var(--ink);font-weight:600;
  font-variant-numeric:tabular-nums}
/* Cursor do preço: alça redonda de 22 px sobre a barra, alvo invisível de 44 px
   em volta, rótulo pendurado embaixo. A cor da alça é a situação da margem
   (classificada no backend: data-situacao na barra). */
.sim-regua__cursor{position:absolute;top:50%;left:0;transform:translate(-50%,-50%);
  width:44px;height:44px;border:0;background:transparent;padding:0;cursor:grab;
  transition:left 220ms cubic-bezier(.22,1,.36,1)}
.sim-regua__cursor::before{content:"";position:absolute;left:50%;top:50%;
  width:22px;height:22px;transform:translate(-50%,-50%);border-radius:50%;
  background:var(--surf);border:3px solid var(--acc);box-shadow:0 1px 3px rgba(25,28,34,.25)}
.sim-regua__barra[data-situacao="na_meta"] .sim-regua__cursor::before{border-color:var(--positive-text)}
.sim-regua__barra[data-situacao="abaixo_meta"] .sim-regua__cursor::before{border-color:var(--chart-alerta-text)}
.sim-regua__barra[data-situacao="prejuizo"] .sim-regua__cursor::before{border-color:var(--negative-text)}
.sim-regua__cursor:hover::before{transform:translate(-50%,-50%) scale(1.08)}
.sim-regua__cursor:focus-visible{outline:none}
.sim-regua__cursor:focus-visible::before{box-shadow:0 0 0 4px var(--acc-soft)}
.sim-regua.is-arrastando .sim-regua__cursor{cursor:grabbing;transition:none}
.sim-regua.is-arrastando .sim-regua__cursor::before{transform:translate(-50%,-50%) scale(1.12)}
.sim-regua__preco{position:absolute;top:calc(100% - 4px);left:50%;transform:translateX(-50%);
  white-space:nowrap;font-size:0.75rem;color:var(--ink-3)}
.sim-regua__preco em{font-style:normal;font-weight:600;font-size:0.875rem;
  font-variant-numeric:tabular-nums;color:var(--ink)}
.sim-regua__barra[data-situacao="na_meta"] .sim-regua__preco em{color:var(--positive-text)}
.sim-regua__barra[data-situacao="abaixo_meta"] .sim-regua__preco em{color:var(--chart-alerta-text)}
.sim-regua__barra[data-situacao="prejuizo"] .sim-regua__preco em{color:var(--negative-text)}
@media (prefers-reduced-motion:reduce){.sim-regua__cursor{transition:none}}
/* Sem item: a ficha é um convite */
.sim-vazio{padding:0.5rem 0.25rem 0}
.sim-vazio__titulo{font-size:1rem;font-weight:600;margin:0 0 0.25rem}
.sim-vazio__texto{font-size:0.8125rem;color:var(--ink-3);margin:0;max-width:60ch}

/* Parâmetros da venda */
.sim-parametros{display:grid;grid-template-columns:1fr 1fr;gap:0.5rem 0.75rem}
.sim-campo{display:flex;flex-direction:column;gap:0.15rem;margin:0}
.sim-campo--largo{grid-column:1/3}
.sim-campo__rotulo{font-size:0.75rem;color:var(--ink-3);font-weight:500}

/* Tabelas (tributos e entradas): a `.t` do mockup */
.sim-tributos,.sim-entradas{margin:0}
.sim-tributos th,.sim-entradas th{font-size:0.75rem;color:var(--ink-3);font-weight:500;
  padding:0.375rem 0.4rem;border-bottom:1px solid var(--line);white-space:nowrap}
.sim-tributos td,.sim-entradas td{padding:0.375rem 0.4rem;border-bottom:1px solid var(--line);
  white-space:nowrap;vertical-align:top}
.sim-tributos .sim-op{display:inline-block;width:0.875rem;color:var(--ink-4);text-align:center}
.sim-tributos td:nth-child(2),.sim-tributos td:nth-child(3),.sim-tributos td:nth-child(4){
  font-variant-numeric:tabular-nums}
.sim-tributos tbody tr:hover{background:var(--surf-2)}
.sim-tributos .sim-base{white-space:normal;color:var(--ink-3);font-size:0.78125rem;min-width:8.5rem}
.sim-tributos__linha--soma td{font-weight:600;border-top:2px solid var(--ink);
  border-bottom:0}
.sim-tributos__linha--mute td{color:var(--ink-3)}
.sim-tributos__nota td{color:var(--ink-3);font-size:0.78125rem}
/* Fornecedor é campo livre e vem longo ("DINGHZOU YIKANG METAL PRODUCTS
   CO., LTD."): sem o corte ele empurra kg e R$/kg para fora do cartão. */
.sim-entradas__fornecedor{max-width:13rem;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap}
/* 12 meses de compra podem ser dezenas de notas — a lista rola dentro do
   cartão em vez de esticar a coluna inteira. */
#sim-entradas{max-height:11rem;overflow:auto}
/* Gráfico das entradas (um só: linhas de preço + barras de volume): altura fixa
   em 190 px — a mesma que o JS passa ao Plotly. Sem ela o card pula de tamanho. */
.sim-grafico{min-height:11.875rem;margin-bottom:0.375rem}
.sim-grafico:empty{display:none}
/* Assistente de montar a venda: um passo por vez, em cima dos campos. Compacto —
   é ajuda, não dado: uma linha de pergunta, uma de dica, os botões pequenos. */
.sim-assistente{background:var(--surf-2);border:1px solid var(--line);border-radius:8px;
  padding:0.5rem 0.625rem;margin:0 0 0.625rem;display:flex;flex-direction:column;gap:0.125rem;
  font-size:0.8125rem}
.sim-assistente[hidden]{display:none}
.sim-assistente__topo{display:flex;align-items:center;gap:0.5rem;font-size:0.75rem;color:var(--ink-3)}
.sim-assistente__topo .btn-close{margin-left:auto;font-size:0.625rem}
.sim-assistente__pergunta{margin:0}
.sim-assistente__dica{margin:0;color:var(--ink-2);font-size:0.75rem}
.sim-assistente__acoes{display:flex;gap:0.375rem;flex-wrap:wrap;margin-top:0.25rem}
.sim-assistente__acoes .btn{padding:0.125rem 0.5rem;font-size:0.75rem}
.sim-assistente__acoes kbd{margin-left:0.25rem;font-size:0.6875rem}
.sim-campo.is-assistido :is(.form-control,.form-select,.btn-group){outline:2px solid var(--acc-line);
  outline-offset:1px;border-radius:6px}
.sim-tabela-scroll{overflow-x:auto}

/* Régua: fecha a página por baixo — piso, frase do backend e a única ação */
.sim-rodape{flex:0 0 auto;display:flex;align-items:center;
  gap:0.625rem;flex-wrap:wrap;padding:0.625rem 1.25rem;margin-top:var(--sim-gap);
  background:var(--surf);border-top:1px solid var(--line)}
.sim-rodape__frase{color:var(--ink-2);font-size:0.8125rem;margin-left:0.5rem}
.sim-rodape__frase b{color:var(--ink)}
.sim-rodape__piso{font-size:1.125rem}
.sim-rodape__acoes{margin-left:auto;display:flex;gap:0.5rem;align-items:center}

/* Estado REGISTRADA: a ficha congela e o único caminho de edição é duplicar */
.sim-registrada .sim-parametros .form-control,
.sim-registrada .sim-parametros .form-select,
.sim-registrada .sim-catalogo{opacity:0.6;pointer-events:none}
.sim-registrada__aviso{margin:0 0 var(--sim-gap);border-radius:10px}

/* Responsividade do mockup: 1400 → catálogo 280; 1100 → colunas empilham e
   KPIs 2×2; 900 → catálogo no topo e alvos de 44px; 600 → KPIs em coluna. */
@media (max-width:1400px){.sim-mesa{grid-template-columns:280px minmax(0,1fr)}}
@media (max-width:1100px){
  .sim-split{grid-template-columns:1fr}
  .sim-kpis{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:900px){
  .sim-mesa{grid-template-columns:1fr}
  .sim-catalogo{max-height:16.25rem}
  .sim-page .form-control,.sim-page .form-select,.sim-page .btn,
  .sim-page .sim-catalogo__item{min-height:44px}}
@media (max-width:600px){
  .sim-kpis{grid-template-columns:1fr}
  .sim-parametros{grid-template-columns:1fr}
  .sim-campo--largo{grid-column:1}
  .sim-regua__barra{margin:2.125rem 0.5rem 1.875rem}}

/* ==========================================================================
   COMPRAS — pré-cadastro de solicitação de compra (lista + ficha).
   Tema claro, tokens do design system (--surf/--line/--ink-*). Escopo de
   página: tudo abaixo mora sob [data-pagina="compras"], então nada daqui
   vaza para as outras ~28 telas.
   ========================================================================== */

/* O campo buscável é o do CRM (`crm/js/combo.js`), e as regras dele são
   escopadas a [data-pagina="crm"]/[data-pagina="crm-deal"]. Reusar o
   COMPORTAMENTO exige repetir aqui a pintura — inclusive `.crm-oculto`, que é
   o que fecha a lista de sugestões: sem ela o typeahead ficaria aberto para
   sempre nesta página. */
[data-pagina="compras"] .crm-oculto { display: none !important; }
[data-pagina="compras"] .crm-combo { position: relative; display: block; }
[data-pagina="compras"] .crm-lista {
  background: var(--surf); border: 1px solid var(--line);
  border-radius: var(--r-sm); box-shadow: 0 8px 24px rgba(25, 28, 34, .12);
  overflow: hidden; overflow-y: auto; }
/* `fixed`, e não `absolute`: a grade de itens voltou a ter contêiner de
   rolagem próprio (ver `.compras-grade` abaixo), e um `absolute` seria
   recortado por ele — que foi o defeito que fez a grade renunciar ao
   contêiner. Fixo escapa o recorte; as coordenadas vêm de `crm/js/combo.js`,
   que ancora a caixa no campo quando a folha de estilo a põe em `fixed`. */
[data-pagina="compras"] .crm-lista--flutua {
  position: fixed; z-index: 1060; max-height: 16rem; }
[data-pagina="compras"] .crm-lista__item {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  border-bottom: 1px solid var(--line-2); padding: .5rem .75rem;
  font-size: .875rem; color: var(--ink); cursor: pointer; }
[data-pagina="compras"] .crm-lista__item:last-child { border-bottom: 0; }
[data-pagina="compras"] .crm-lista__item:hover,
[data-pagina="compras"] .crm-lista__item:focus,
[data-pagina="compras"] .crm-lista__item[data-destacado] { background: var(--surf-2); }
[data-pagina="compras"] .crm-vazio {
  color: var(--ink-3); font-size: .8125rem; padding: .6rem .75rem; }

/* Recorte da lista e capa da ficha: a mesma grade de campos nas duas telas. */
[data-pagina="compras"] .compras-filtros,
[data-pagina="compras"] .compras-capa {
  display: flex; flex-wrap: wrap; gap: .75rem; align-items: flex-end; }
[data-pagina="compras"] .compras-filtro,
[data-pagina="compras"] .compras-campo {
  display: flex; flex-direction: column; gap: .15rem; min-width: 9rem; }
[data-pagina="compras"] .compras-filtro--largo,
[data-pagina="compras"] .compras-campo--largo { flex: 1 1 18rem; min-width: 18rem; }
[data-pagina="compras"] .compras-filtro--acao { justify-content: flex-end; }
[data-pagina="compras"] .compras-filtro .form-label,
[data-pagina="compras"] .compras-campo .form-label {
  font-size: .75rem; font-weight: 500; color: var(--ink-3); margin: 0; }

/* Os números do envelope, lado a lado — o que o `?` explica. */
[data-pagina="compras"] .compras-derivados {
  display: flex; flex-wrap: wrap; gap: 1.25rem; align-items: flex-start;
  margin-top: 1rem; padding-top: .75rem; border-top: 1px solid var(--line); }
[data-pagina="compras"] .compras-derivado {
  display: flex; flex-direction: column; gap: .1rem; }
[data-pagina="compras"] .compras-derivado__rotulo {
  font-size: .75rem; color: var(--ink-3); }
[data-pagina="compras"] .compras-derivado__valor {
  font-size: 1rem; font-weight: 600; color: var(--ink); }
[data-pagina="compras"] .compras-derivado__nota {
  font-size: .6875rem; color: var(--ink-3); }
[data-pagina="compras"] .compras-derivado__aviso {
  flex-basis: 100%; margin: 0; font-size: .75rem; color: var(--ink-3); }
/* Formulário mexido: o número exibido ainda é o da última gravação. Esmaecer
   é dizer "isto não responde pelo que você acabou de digitar". */
[data-pagina="compras"] .compras-derivados--pendente .compras-derivado__valor,
[data-pagina="compras"] .compras-derivados--pendente .compras-derivado__nota {
  opacity: .4; transition: opacity .15s ease; }

[data-pagina="compras"] .compras-barra {
  display: flex; align-items: center; gap: .5rem; margin-bottom: .75rem; }
[data-pagina="compras"] .compras-barra__titulo {
  font-size: .8125rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .04em; color: var(--ink-2); margin-right: auto; }

/* A grade de itens não usa `.tbl-wrapper` (compartilhado por ~28 telas, não se
   mexe): tem contêiner próprio. Ela ROLA sozinha — sem isso as nove colunas
   com `min-width` empurravam a largura do documento e a PÁGINA inteira rolava
   na horizontal num notebook de 13".
   O motivo de ela ter renunciado ao contêiner antes era a lista do typeahead
   de produto, recortada pelo overflow (overflow num eixo torna o outro `auto`)
   — isso morreu na raiz: `.crm-lista--flutua` aqui é `fixed` e não é mais
   recortada por ancestral nenhum. */
[data-pagina="compras"] .compras-grade { overflow-x: auto; }
[data-pagina="compras"] .compras-itens td { vertical-align: middle; }
[data-pagina="compras"] .compras-itens .compras-produto-host { min-width: 16rem; }
[data-pagina="compras"] .compras-itens input { min-width: 6rem; }

/* Rascunho usa `text-bg-light`, que é quase branco: sobre o cartão branco
   a pílula sumiria sem contorno. Uma borda basta — o tom claro é o recado
   ("ainda não é nada"), e escurecer o fundo desfaria o recado. */
[data-pagina="compras"] .badge.text-bg-light { border: 1px solid var(--line); }

/* RESPIRO. A tela nasceu apertada: rótulo colado no campo, linha da grade sem
   altura, cartões encostados. Densidade de planilha serve para LER muita linha;
   esta é de DIGITAR, e digitar apertado erra. Os valores abaixo são folga de
   tela de entrada, não de painel. */
[data-pagina="compras"] .compras-filtros,
[data-pagina="compras"] .compras-capa { gap: 1.15rem 1.25rem; }
[data-pagina="compras"] .compras-filtro,
[data-pagina="compras"] .compras-campo { gap: .35rem; }
[data-pagina="compras"] .compras-derivados {
  gap: 2rem; margin-top: 1.35rem; padding-top: 1.1rem; }
[data-pagina="compras"] .compras-barra { margin-bottom: 1.1rem; }
[data-pagina="compras"] .card + .card { margin-top: 1.25rem; }
[data-pagina="compras"] .compras-itens th,
[data-pagina="compras"] .compras-itens td { padding: .6rem .65rem; }
[data-pagina="compras"] .compras-itens thead th { padding-bottom: .75rem; }

/* Ícone colado no rótulo: o Bootstrap não separa `<i>` de texto dentro do
   botão, e "Gravar" saía grudado no disquete. `inline-flex` + `gap` resolve
   para TODO botão da página, inclusive os que ainda não existem — melhor que
   `me-1` repetido em cada `<i>` do template, que a próxima pessoa esquece. */
[data-pagina="compras"] .btn {
  display: inline-flex; align-items: center; gap: .45rem; }

/* O chip de estado, na barra ao lado dos dois botões: ele é a diferença entre
   "está tudo salvo" e "o que você está vendo ainda não está gravado", e é o
   motivo visível de o envio ficar desligado. Fica ANTES dos botões porque se
   lê a frase e depois se decide o que apertar. */
[data-pagina="compras"] .compras-barra__vao { margin-left: auto; }
[data-pagina="compras"] .compras-chip {
  padding: .2rem .6rem; border-radius: var(--raio-chip); font-size: .75rem;
  font-weight: 600; border: 1px solid var(--line); color: var(--ink-2);
  background: var(--surf-2); white-space: nowrap; }
[data-pagina="compras"] .compras-chip--pendente {
  border-color: #f0c36d; background: #fdf6e3; color: #7a5b12; }
[data-pagina="compras"] .compras-chip--salvo {
  border-color: #bcd9c4; background: #eef7f0; color: #256b3a; }
[data-pagina="compras"] .compras-chip--senior {
  border-color: var(--line); background: var(--surf-2); color: var(--ink-2); }

/* A oferta da PTAX embaixo do campo de taxa: é um botão, mas não compete com
   os da barra — parece a nota que ele é ("a cotação de hoje é esta"), e é
   clicável porque preenche o campo. */
[data-pagina="compras"] .compras-oferta {
  align-self: flex-start; padding: 0; border: 0; background: none;
  font-size: .6875rem; color: var(--brand); text-decoration: underline;
  text-underline-offset: 2px; cursor: pointer; }

/* Marca de confirmação do fornecedor: alinha com o rodapé dos campos vizinhos
   da capa, que têm rótulo em cima e controle embaixo. */
[data-pagina="compras"] .compras-marca { margin-top: .15rem; }
[data-pagina="compras"] .compras-marca .form-check-label {
  font-size: .8125rem; color: var(--ink); }

/* As três datas numa célula só. Em colunas separadas a grade ia a treze e
   ganhava rolagem horizontal; empilhadas, cada uma leva o rótulo colada nela
   — sem rótulo, três campos de data iguais não se distinguem. */
[data-pagina="compras"] .compras-datas {
  display: flex; flex-direction: column; gap: .3rem; min-width: 11rem; }
[data-pagina="compras"] .compras-data {
  display: flex; align-items: center; gap: .4rem; margin: 0; }
[data-pagina="compras"] .compras-data > span {
  flex: 0 0 5.5rem; font-size: .6875rem; color: var(--ink-3);
  text-transform: uppercase; letter-spacing: .03em; }

/* O símbolo da moeda antes do valor unitário. `min-width` menor que o dos
   outros campos: o prefixo já ocupa parte da célula. */
[data-pagina="compras"] .compras-valor { min-width: 9rem; }
/* O saldo carrega até duas notas do ERP embaixo ("aprovado p/ OC", "cancelado
   no Senior"): sem largura mínima a coluna espremia cada uma em três linhas. */
[data-pagina="compras"] .compras-itens .item-saldo { min-width: 8rem; }
[data-pagina="compras"] .compras-valor .input-group-text {
  font-size: .75rem; color: var(--ink-3); }

/* O conserto da linha que discorda: mesmo peso da nota que ele resolve — é
   ação de conferência, não ação principal da tela. */
[data-pagina="compras"] .compras-adotar {
  margin-top: .15rem; padding: 0; border: 0; background: none;
  font-size: .6875rem; color: var(--brand); text-decoration: underline;
  text-underline-offset: 2px; cursor: pointer; }

/* A linha que discorda do Senior: nem erro nem alarme — é um fato que alguém
   precisa ver ao editar depois do envio. Cor de atenção, peso de nota. */
[data-pagina="compras"] .compras-divergencia {
  color: #7a5b12; font-weight: 600; }

/* As duas colunas editáveis da lista. Campo estreito e sem moldura pesada: a
   linha continua sendo uma linha de tabela, não um formulário. */
[data-pagina="compras"] .compras-editavel input[type="text"] {
  min-width: 7rem; font-size: .8125rem; }
[data-pagina="compras"] .compras-editavel input:disabled { opacity: .5; }

/* O log da solicitação. Lista de eventos, mais recente em cima: cabeça com
   tipo/hora/autor e, embaixo, uma linha por campo que mudou. Sem cartão por
   evento — são dezenas depois de algumas edições, e cartão empilhado vira
   parede. */
[data-pagina="compras"] .compras-historico {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: .85rem; }
[data-pagina="compras"] .compras-evento {
  padding-left: .85rem; border-left: 2px solid var(--line); }
[data-pagina="compras"] .compras-evento__cabeca {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem;
  font-size: .8125rem; color: var(--ink); }
[data-pagina="compras"] .compras-evento__quando,
[data-pagina="compras"] .compras-evento__autor {
  font-size: .75rem; color: var(--ink-3); }
[data-pagina="compras"] .compras-evento__mudancas {
  margin: .3rem 0 0; padding-left: 1.1rem;
  font-size: .8125rem; color: var(--ink-2); }
[data-pagina="compras"] .compras-evento__mudancas li { margin-bottom: .15rem; }

[data-pagina="compras"] .compras-familia {
  display: flex; flex-wrap: wrap; gap: .5rem; }
/* Desdobrar mora no cartão da família (é operação sobre EMBARQUE) e precisa de
   ar quando há cartões de pai/filha acima dele. */
[data-pagina="compras"] .compras-familia:not(:empty) + #ficha-desdobrar,
[data-pagina="compras"] .compras-familia + .compras-familia:not(:empty) ~ .btn {
  margin-top: .85rem; }
[data-pagina="compras"] .compras-familia__item {
  display: block; padding: .5rem .75rem; border: 1px solid var(--line);
  border-radius: var(--r-sm); background: var(--surf-2); color: var(--ink);
  font-size: .8125rem; text-decoration: none; }
[data-pagina="compras"] .compras-familia__item:hover { background: var(--surf-3); }
[data-pagina="compras"] .compras-familia__rotulo {
  display: block; font-size: .6875rem; color: var(--ink-3); }

/* A lista é a grade da casa (`solicitacoes.js`), na altura da janela: o
   cursor e o traço da linha sob o mouse vêm dela. O número continua link, sem
   cara de link até o mouse chegar. A folha é branca como nas outras telas da
   grade; o recuo de cima volta porque a altura cheia zera o do shell, e o
   cartão do recorte encostaria na barra do topo. */
.content:has(> .page[data-pagina="compras"] > .grade),
.page[data-pagina="compras"]:has(> .grade) { background: #fff; }
.content--altura-cheia > .page[data-pagina="compras"] { padding-top: var(--content-pad-y); }
/* Teto, não largura: o nome inteiro fica no `title` da célula. Em tela larga
   sobra lugar, e o nome cabe inteiro. */
[data-pagina="compras"] .grade .compras-col-fornecedor { max-width: 12rem; }
@media (min-width: 1800px) {
  [data-pagina="compras"] .grade .compras-col-fornecedor { max-width: 22rem; } }
[data-pagina="compras"] .compras-linha__link {
  color: inherit; text-decoration: none; }
[data-pagina="compras"] .compras-linha__link:hover { text-decoration: underline; }

/* Número com verbete: clicar abre a conta que o produziu (`ajuda.js`), e sem
   pintura nada dizia isso. Mesma dica do CRM (`.measure[data-auditoria]`),
   mais o pontilhado — discreto o bastante para não se passar por link. */
[data-pagina="compras"] [data-auditoria] {
  cursor: help; text-decoration: underline dotted;
  text-underline-offset: .2em; }
[data-pagina="compras"] [data-auditoria]:focus-visible {
  outline: 2px solid var(--acc-line); outline-offset: 2px; }

[data-pagina="compras"] .compras-linha__nota {
  font-size: .6875rem; color: var(--ink-3); }
/* A contagem do recorte, no rodapé da grade, ao lado da contagem dela. */

[data-pagina="compras"] .compras-aviso {
  border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: .5rem .75rem; margin-bottom: .75rem; font-size: .8125rem;
  background: var(--surf-2); color: var(--ink); }
[data-pagina="compras"] .compras-aviso--erro {
  border-color: var(--bs-danger-border-subtle, #f1aeb5);
  background: var(--bs-danger-bg-subtle, #f8d7da); }
[data-pagina="compras"] .compras-aviso--ok {
  border-color: var(--bs-success-border-subtle, #a3cfbb);
  background: var(--bs-success-bg-subtle, #d1e7dd); }
/* "O que você está vendo não é o que o Senior guarda": a tela funciona, então
   não é erro; mas o número na frente da pessoa não é o do dono dele, e isso
   não pode se parecer com um aviso informativo qualquer. */
[data-pagina="compras"] .compras-aviso--atencao {
  border-color: var(--bs-warning-border-subtle, #ffe69c);
  background: var(--bs-warning-bg-subtle, #fff3cd); }

/* ==========================================================================
   CRM · Lista de NEGÓCIOS (`[data-pagina="crm-negocios"]`)
   Reaproveita a faixa de abas e busca da lista de clientes (os seletores
   `.cl-*` acima valem nas duas telas por `:is()`). O que é próprio daqui é a
   linha de seletores e o rodapé de paginação — a lista tem ~16 mil negócios
   com o acervo do Ploomes dentro, e paginar é a única forma de trabalhá-la.
   ========================================================================== */

[data-pagina="crm-negocios"] .ng-filtros {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  margin-bottom: .75rem;
}
[data-pagina="crm-negocios"] .ng-filtro {
  display: flex;
  flex-direction: column;
  gap: .15rem;
  min-width: 9rem;
}
[data-pagina="crm-negocios"] .ng-filtro__rotulo {
  font-size: var(--bi-fs-micro);
  color: var(--crm-tinta-2);
}
/* O cadeado ao lado do título é o mesmo fato da pílula de origem, dito onde o
   olho já está: quem varre a coluna do negócio vê que aquela linha não abre
   para trabalhar. Discreto de propósito — repetir a informação em destaque
   duas vezes na mesma linha vira ruído. */
[data-pagina="crm-negocios"] .ng-cadeado {
  margin-left: .35rem;
  font-size: .7rem;
  color: var(--ink-3);
}
/* Densidade: 100 linhas por página pedem linha magra. O `<a>` do título e as
   pílulas puxavam a linha para ~52px; com o padding curto e a pílula sem
   respiro vertical a mesma página mostra ~40% mais negócios por tela. */
[data-pagina="crm-negocios"] #ng-tabela td { padding: .3rem .5rem; }
[data-pagina="crm-negocios"] #ng-tabela .crm-pilula { padding: .05rem .5rem; }
[data-pagina="crm-negocios"] #ng-tabela .crm-rotulo { font-size: var(--bi-fs-micro); }
/* Passo 2 do passe de compacidade: negócio e cliente truncam com reticência
   e o nome inteiro vai para o `title` (hover) — nome comprido não pode
   forçar a linha a quebrar em duas. */
[data-pagina="crm-negocios"] #ng-tabela .ng-truncar {
  max-width: 16rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Passo 1 do passe de compacidade do CRM (aprovado pelo dono, 28/08/2026):
   `#ng-tabela` já tinha o padding raso acima; `#cl-tabela` (clientes) ganha o
   MESMO tratamento agora, e as duas ganham corpo/entrelinha e cabeçalho mais
   secos — token existente (`--bi-fs-*`), sem cor/token novo — para ~30%
   menos altura de linha nas duas listas. */
:is([data-pagina="crm-negocios"] #ng-tabela, [data-pagina="crm-clientes"] #cl-tabela) {
  font-size: var(--bi-fs-compact);
}
:is([data-pagina="crm-negocios"] #ng-tabela, [data-pagina="crm-clientes"] #cl-tabela) tbody td {
  line-height: 1.25;
}
:is([data-pagina="crm-negocios"] #ng-tabela, [data-pagina="crm-clientes"] #cl-tabela) thead th {
  padding: .3rem .5rem;
  font-size: var(--bi-fs-micro);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--crm-tinta-2);
}
[data-pagina="crm-clientes"] #cl-tabela td { padding: .3rem .5rem; }
[data-pagina="crm-clientes"] #cl-tabela .crm-pilula { padding: .05rem .5rem; }

[data-pagina="crm-negocios"] .ng-rodape {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .75rem;
  margin-top: .75rem;
}
[data-pagina="crm-negocios"] .ng-rodape__contagem {
  font-size: var(--bi-fs-compact);
  color: var(--crm-tinta-2);
  font-variant-numeric: tabular-nums;
}
[data-pagina="crm-negocios"] .ng-rodape__paginas {
  display: flex;
  align-items: center;
  gap: .5rem;
}

/* ==========================================================================
   CRM · Negócio em MODO ARQUIVO (importado do Ploomes)
   O servidor decide o modo (`importado_do_ploomes`); aqui só se esconde o que
   não pode ser oferecido — formulário sobre negócio congelado é convite para
   um erro — e se dá corpo à ficha simples de conversas e documentos.
   ========================================================================== */

.crm-negocio--arquivo #dl-frete-card,
.crm-negocio--arquivo #dl-abrir-condicoes-alerta,
.crm-negocio--arquivo .crm-passo { display: none; }

/* O rodapé de decisão FICA: dentro dele mora o "Ver proposta (PDF)", que é o
   item 11 da triagem — e os 8.785 perdidos da base são todos importados, ou
   seja, esconder o rodapé inteiro apagava o link exatamente em quem precisa
   dele. Some só o GESTO DE ESCRITA (`<button>`); o selo de status e o link
   do papel continuam. Quem pode reabrir ou corrigir já é decidido no
   servidor (`pode_reabrir_perdido`, `pode_corrigir`) — este seletor é cinto,
   não a regra. */
.crm-negocio--arquivo #dl-decisao button { display: none; }

/* "Sem preço base" / "Sem IPI no cadastro" são cobrança de quem ainda vai
   vender — em arquivo são ruído em toda linha. O número continua lá; o
   carimbo de pendência some. */
.crm-negocio--arquivo .crm-pilula--tracejada { display: none; }

.crm-negocio--arquivo .crm-arquivo-texto {
  font-size: .95rem;
  padding: .35rem 0;
  color: var(--crm-tinta);
}

.crm-negocio--arquivo .crm-arquivo-grade {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1rem;
}
@media (max-width: 900px) {
  .crm-negocio--arquivo .crm-arquivo-grade { grid-template-columns: 1fr; }
}
.crm-negocio--arquivo .crm-arquivo-doc {
  display: flex;
  align-items: baseline;
  gap: .5rem;
  padding: .3rem 0;
  text-decoration: none;
}
.crm-negocio--arquivo .crm-arquivo-conversa {
  padding: .45rem 0;
  border-bottom: 1px solid var(--crm-borda);
}
.crm-negocio--arquivo .crm-arquivo-conversa:last-child { border-bottom: 0; }

/* A sequência do item no Senior (`seqSol`): número de referência, não dado de
   trabalho — fica ao lado sem competir com o que se digita. */
[data-pagina="compras"] .compras-item__senior {
  font-size: .75rem; color: var(--ink-3); white-space: nowrap; }

/* ══════════════════════════════════════════════════════════════════════
   PRODUTOS (estoque-2) — analítico da Movimentação + grade + dossiê em abas
   Escopo de página: tudo prefixado .e2, nada vaza para as outras ~28 telas.
   Só tokens que já existem neste arquivo — nenhuma cor nova nasce aqui.
   ══════════════════════════════════════════════════════════════════════ */

.e2-carteira {
  display: grid;
  grid-template-columns: minmax(190px, auto) minmax(0, 1fr) minmax(190px, auto);
  gap: 1.25rem;
  align-items: center;
  padding: .85rem 1rem;
  margin-bottom: .75rem;
  background: var(--surf);
  border: 1px solid var(--line);
  border-radius: var(--bi-radius-md);
}
.e2-carteira__total b { display: block; font-size: 1.6rem; line-height: 1.15;
  font-variant-numeric: tabular-nums; color: var(--ink); }
.e2-carteira__aside { display: flex; gap: 1.5rem; justify-content: flex-end; }
.e2-carteira__aside strong { display: block; font-variant-numeric: tabular-nums; }

/* A barra é proporção, e vem sempre com o número ao lado na legenda: cor
   sozinha não carrega informação nesta casa. */
.e2-barra { display: flex; height: 10px; border-radius: var(--raio-chip);
  overflow: hidden; background: var(--surf-3); }
.e2-barra > i { display: block; height: 100%; }
#e2-barra-livre { background: var(--positive); }
#e2-barra-bloqueado { background: var(--negative); }
.e2-legenda { display: flex; gap: 1.25rem; margin-top: .4rem;
  font-size: var(--bi-fs-compact); color: var(--ink-2); }
.e2-legenda b { font-variant-numeric: tabular-nums; color: var(--ink); }
.e2-marca { display: inline-block; width: .6rem; height: .6rem; border-radius: 2px;
  margin-right: .35rem; }
.e2-marca--livre { background: var(--positive); }
.e2-marca--bloqueado { background: var(--negative); }

/* UM scroller por painel, nunca dois.
   O `.datatable-scroll` do helper JÁ é um container que rola e já tem teto de
   altura (`--bi-dt-scroll-cap`); `utils.js` avisa que embrulhar isso num
   segundo `overflow:auto` dá DUAS barras de rolagem — foi exatamente o que
   esta tela fazia. Aqui o palco define a altura e a grade se amarra a ela pelo
   token que o helper já lê; o `.e2-lista` não rola mais. */
/* A grade ocupa a largura inteira: é ela a ferramenta de varredura. O dossiê
   entra por cima, num offcanvas do Bootstrap (o mesmo componente do CRM), com
   o dobro da largura do painel embutido que existia antes — porque ele tem
   gráfico, linha do tempo e tabela, e apertado não se lê nenhum dos três. */
.e2-palco {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  /* A página rola (gráficos em cima, grade embaixo): o palco tem a altura da
     janela abaixo da barra do topo, e quem rola até ele vê a grade inteira. */
  height: calc(100dvh - 52px);
  min-height: 420px;
}
.e2-oc { --bs-offcanvas-width: min(940px, 96vw); }

/* Sem cartão em volta da grade: nem fio, nem raio, nem fundo próprio. */
.e2-lista { min-width: 0; overflow: hidden; display: flex; flex-direction: column; }

/* Recorte vindo do gráfico/L1 — chip na barra da grade. */
.e2-recorte { display: inline-flex; align-items: center; gap: .5rem; }
.e2-recorte b { font-family: var(--bi-font-mono); font-size: .92em; }
/* Linha fantasma: produto só em trânsito, sem saldo — entra apagada, não some. */
.e2-so-transito > td { color: var(--bi-text-muted); font-style: italic; }
.e2-so-transito > td.e2-transito { color: var(--warning); font-style: normal; }
/* Dossiê em abas (igual ao modal de /estoques/). */
.e2-oc .nav-tabs { padding: 0 1rem; margin-top: .5rem; }
.e2-oc .tab-content { padding: 0 1rem 1rem; }
.e2-oc .tab-pane .datatable { margin-top: .5rem; }
.e2-deposito-inconsistente td { color: var(--negative-text); }
/* A grade ocupa a altura que sobra, sem número mágico e sem segunda barra.
   O `.tbl-wrapper` global tem `overflow-x:auto`, e o CSS promove o eixo Y a
   `auto` junto — por isso ele precisa ser flex e nunca transbordar: quem rola
   é só o `.datatable-scroll`, que cresce para preencher. */
.e2-lista > .datatable { flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column; }
/* O DataTables insere o próprio `.dataTables_wrapper` entre os dois. Sem ele
   na corrente flex, a altura não desce: o wrapper cresce até caber as 322
   linhas e o `.tbl-wrapper` volta a rolar. */
.e2-lista .dataTables_wrapper { flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column; }
.e2-lista .datatable-scroll { flex: 1 1 auto; min-height: 0; max-height: none; }
.e2-lista .datatable-toolbar,
.e2-lista .datatable-bottom { flex: 0 0 auto; }
/* A grade da casa dentro do painel: o palco dá a altura, a grade a preenche.
   Os controles da lista (recorte, interruptores, depósito) entram na barra
   dela, numa linha só, e o "N de M" vai para o rodapé. */
.e2-lista .grade .e2-interruptor,
.e2-lista .grade .e2-recorte,
.e2-lista .grade .e2-deposito {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: .4rem;
  font-size: .8125rem; color: var(--grade-tinta-2); white-space: nowrap;
}
/* O interruptor do Bootstrap se posiciona com margem negativa dentro do recuo
   do `.form-check`; numa fileira flex isso o jogava por cima do texto. */
.e2-lista .grade .e2-interruptor { padding: 0; min-height: 0; }
.e2-lista .grade .e2-interruptor .form-check-input { float: none; margin: 0; }
.e2-lista .grade .e2-deposito select {
  width: auto !important; height: var(--grade-altura-campo);
  padding-top: 0; padding-bottom: 0; font-size: .8125rem;
}
.e2-lista .grade .datatable-bottom .e2-badge { margin-left: .75rem; color: var(--ink-2); }


/* Densidade: a descrição do ERP tem 70+ caracteres e, espremida contra 11
   colunas mais o painel, quebrava em SEIS linhas — a linha virava um bloco de
   90px e cabiam 6 itens onde cabiam 20. Corta em uma linha, com o texto
   inteiro no `title`. A grade é ferramenta de varredura: quem precisa do nome
   completo abre o item. */
.e2-lista td, .e2-lista th { white-space: nowrap; }
.e2-lista .e2-descricao {
  max-width: var(--e2-descricao-largura, 26ch);
  overflow: hidden; text-overflow: ellipsis;
}
.e2-lista tbody td { padding-top: .35rem; padding-bottom: .35rem; }

/* Linha selecionada — o item que o sidecanvas está mostrando. */
.e2-lista tbody tr[aria-selected="true"] > td { background: var(--acc-soft); }
.e2-lista tbody tr[aria-selected="true"] > td:first-child { box-shadow: inset 2px 0 0 var(--acc); }

/* Item zerado: presente e legível, mas visivelmente sem saldo. */
.e2-zerado > td { color: var(--ink-3); }

/* ── Dossiê (offcanvas) ────────────────────────────────────────────────── */
/* Cabeçalho fixo e corpo rolando são do próprio `.offcanvas-header` /
   `.offcanvas-body` do Bootstrap; aqui só entra o que é desta tela. */
.e2-side__vazio { padding: 1.25rem; color: var(--ink-2); }
.e2-oc .offcanvas-header { border-bottom: 1px solid var(--line); align-items: flex-start; }
.e2-side__hd { flex: 1 1 auto; min-width: 0; }
.e2-side__titulo { font-weight: 600; color: var(--ink); }
.e2-side__trio { display: flex; gap: 1.25rem; margin-top: .5rem; flex-wrap: wrap; }
.e2-side__trio b { display: block; font-variant-numeric: tabular-nums; }
.e2-oc .offcanvas-body { display: flex; flex-direction: column; gap: 1.1rem; }
.e2-side__secao > .lab { display: block; margin-bottom: .4rem; }
/* A tabela de eventos vive dentro do corpo que já rola: ela não pode abrir
   um scroller próprio (o `--bi-dt-scroll-max: none` desarma o teto do helper). */
.e2-side .datatable { --bi-dt-scroll-max: none; }

/* Fluxo mensal: ruptura desenha zero, mês fora do alcance desenha buraco.
   São coisas diferentes e não podem virar o mesmo pixel. */
.e2-fluxo { display: flex; align-items: flex-end; gap: 3px; height: 96px; }
.e2-fluxo__mes { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;
  justify-content: flex-end; height: 100%; }
.e2-fluxo__barra { background: var(--acc); border-radius: 2px 2px 0 0; min-height: 1px; }
.e2-fluxo__mes--ruptura .e2-fluxo__barra { background: var(--negative); height: 3px; }
.e2-fluxo__mes--ausente { background: repeating-linear-gradient(45deg,
  var(--surf-3) 0 3px, transparent 3px 6px); border-radius: 2px; }
.e2-fluxo__eixo { display: flex; justify-content: space-between; margin-top: .3rem;
  font-size: var(--bi-fs-compact); color: var(--ink-3); }
.e2-fluxo__legenda { margin-top: .35rem;
  font-size: var(--bi-fs-compact); color: var(--ink-3); }

/* Chegadas: resumo à vista, lista a um clique. */
.e2-chegadas > summary { cursor: pointer; display: flex; align-items: baseline;
  gap: .5rem; flex-wrap: wrap; }
.e2-chegadas__resumo { font-size: var(--bi-fs-compact); color: var(--ink-2);
  font-variant-numeric: tabular-nums; }
.e2-chegadas > table { margin-top: .5rem; }

/* Bloqueio é transferência entre camadas: sai com seta, nunca com sinal. */
.e2-evento__camada { color: var(--ink-2); white-space: nowrap; }
.e2-evento__sinal { font-variant-numeric: tabular-nums; }

.e2-side__secao-hd { display: flex; align-items: center; justify-content: space-between;
  gap: .75rem; margin-bottom: .5rem; }

/* Linha do tempo: uma régua vertical, o dia como marco, o evento pendurado. */
.e2-tl { border-left: 2px solid var(--line); padding-left: .85rem; }
.e2-tl__dia { font-size: var(--bi-fs-compact); color: var(--ink-3);
  margin: .6rem 0 .25rem -1rem; padding-left: 1rem; position: relative; }
.e2-tl__dia::before { content: ""; position: absolute; left: -.2rem; top: .45em;
  width: 7px; height: 7px; border-radius: 50%; background: var(--line-3); }
.e2-tl__evento { padding: .3rem 0; border-bottom: 1px solid var(--line-2); }
.e2-tl__cabeca { display: flex; justify-content: space-between; gap: .75rem; }
.e2-tl__detalhe { font-size: var(--bi-fs-compact); color: var(--ink-2); }
.e2-tl__evento--entrada .e2-evento__sinal { color: var(--positive-text); }
.e2-tl__evento--saida .e2-evento__sinal { color: var(--negative-text); }

@media (max-width: 1180px) {
  .e2-palco { height: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .e2-palco * { transition: none !important; animation: none !important; }
}

/* ===== CAMPANHAS WHATSAPP (cw-*) ===== */
/* Funil-trapézio central (rampa azul, verde só na conversão — resposta é o
   dinheiro da tela), juntas tipográficas com a perda entre estágios, ritmo
   diário em micro-colunas e fila de conversas. Rótulos sempre em tinta. */
.cw-page { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2rem 3rem; padding: 1.75rem 2rem 3rem; align-items: start; }
@media (min-width: 992px) { .cw-page:has(.cw-respostas:not([hidden])) { grid-template-columns: minmax(0, 1.35fr) minmax(340px, 1fr); } }

.cw-campanha { margin-bottom: 2.5rem; max-width: 640px; }
.cw-cabecalho { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: 1rem; flex-wrap: wrap; }
.cw-titulo { display: flex; align-items: baseline; gap: .75rem; }
.cw-nome { font-size: 1.25rem; font-weight: 800; letter-spacing: -.01em; color: #212529; margin: 0; }
.cw-periodo { font-size: .85rem; color: #6b7280; font-variant-numeric: tabular-nums; }
.cw-notas { display: flex; gap: .9rem; }
.cw-nota { font-size: .8rem; color: #6b7280; }
.cw-nota-optout { color: #ca2a26; font-weight: 600; }

/* progresso da campanha: quanto da lista já foi trabalhado */
.cw-progresso { margin: 0 0 1.1rem; }
.cw-progresso-barra { height: 6px; border-radius: var(--raio-chip); background: #e9ecef; overflow: hidden; }
.cw-progresso-cheio { height: 100%; background: #2563eb; border-radius: var(--raio-chip); transition: width .5s cubic-bezier(.22,1,.36,1); }
@media (prefers-reduced-motion: reduce) { .cw-progresso-cheio { transition: none; } }
.cw-progresso-legenda { margin-top: .4rem; font-size: .82rem; color: #6b7280; font-variant-numeric: tabular-nums; }
.cw-progresso-legenda strong { color: #212529; }
.cw-progresso-legenda .cw-faltam { color: #1d4ed8; }

/* Faixa de operação: a saúde do chip (topo da tela) e a rodada de envio (dentro
   do cartão da campanha). O funil conta o passado; estas duas dizem se a
   máquina está de pé agora. Verde é "de pé"; vermelho é o único estado que
   pede alguém. */
/* Filho direto de `.cw-page`, que é grid de duas colunas: sem o span, o chip
   ocupava a primeira célula e empurrava o funil para a coluna das conversas. */
.cw-chip { grid-column: 1 / -1; justify-self: start;
           display: inline-flex; align-items: center; gap: .55rem; margin-bottom: 1.5rem;
           padding: .4rem .85rem; border: 1px solid #dee2e6; border-radius: var(--raio-chip);
           background: #f8f9fa; font-size: .85rem; color: #495057; font-weight: 600; }
.cw-chip-luz { width: 8px; height: 8px; border-radius: 50%; background: #16a34a; flex: none; }
.cw-chip-caida { border-color: #f5c2c0; background: #fdf2f2; color: #ca2a26; }
.cw-chip-caida .cw-chip-luz { background: #ca2a26; }

.cw-rodada { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem;
             margin: 0 0 1.4rem; padding: .7rem .85rem; border: 1px solid #dee2e6;
             border-radius: 8px; background: #f8f9fa; font-size: .85rem; color: #495057; }
.cw-rodada-rodando { border-color: #bfdbfe; background: #eff6ff; }
.cw-rodada-estado { font-weight: 600; color: #212529; font-variant-numeric: tabular-nums; }
.cw-rodada-detalhe { flex-basis: 100%; font-size: .8rem; color: #6b7280; }
.cw-rodada-rotulo { color: #6b7280; }
.cw-rodada-form { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; margin-left: auto; }
.cw-rodada-form input { width: 4.5rem; padding: .25rem .45rem; border: 1px solid #ced4da;
                        border-radius: 6px; background: #fff; color: #212529;
                        font-size: .85rem; font-variant-numeric: tabular-nums; }
.cw-rodada-limite { width: 3.5rem !important; font-weight: 700; }
.cw-rodada-disparar, .cw-rodada-parar { padding: .3rem .9rem; border: 0; border-radius: 6px;
                                        font-size: .85rem; font-weight: 600; color: #fff;
                                        cursor: pointer; }
.cw-rodada-disparar { background: #2563eb; }
.cw-rodada-disparar:hover:not(:disabled) { background: #1d4ed8; }
/* Parar é destrutivo e precisa parecer: mesmo peso do disparar, cor do risco. */
.cw-rodada-parar { background: #ca2a26; margin-left: auto; }
.cw-rodada-parar:hover:not(:disabled) { background: #a81f1c; }
.cw-rodada-disparar:disabled, .cw-rodada-parar:disabled { opacity: .55; cursor: default; }
.cw-rodada-erro { flex-basis: 100%; margin: 0; font-size: .82rem; color: #ca2a26; font-weight: 600; }

/* funil */
.cw-funil { display: flex; flex-direction: column; }
.cw-estagio { position: relative; }
.cw-forma { height: 58px; }
.cw-forma-fila        { background: #e2e8f0; }
.cw-forma-enviados    { background: #bfdbfe; }
.cw-forma-entregues   { background: #60a5fa; }
.cw-forma-lidos       { background: #2563eb; }
.cw-forma-responderam { background: #16a34a; }
.cw-rotulo { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; gap: .45rem; pointer-events: none; }
.cw-rotulo > * { background: rgba(255,255,255,.92); border-radius: var(--raio-chip); }
.cw-valor { font-size: 1.05rem; font-weight: 800; color: #212529; font-variant-numeric: tabular-nums; padding: .05rem .55rem; }
.cw-rotulo-nome { font-size: .85rem; color: #495057; padding: .15rem .55rem; }
.cw-taxa { font-size: .8rem; font-weight: 700; color: #1d4ed8; padding: .18rem .5rem; }
.cw-estagio:last-child .cw-taxa { color: #15803d; }
.cw-junta { display: flex; justify-content: center; padding: .3rem 0; }
.cw-junta-texto { font-size: .78rem; color: #6b7280; }

/* ritmo diário */
.cw-ritmo { margin-top: 1.5rem; }
.cw-ritmo-cabecalho { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: .4rem; }
.cw-ritmo-titulo { font-size: .8rem; font-weight: 700; text-transform: none; color: #495057; }
.cw-ritmo-legenda { font-size: .75rem; color: #6b7280; }
.cw-dot { display: inline-block; width: 8px; height: 8px; border-radius: 2px; vertical-align: baseline; }
.cw-dot-envio { background: #93c5fd; }
.cw-dot-resposta { background: #16a34a; }
.cw-trilha { display: flex; align-items: flex-end; gap: 5px; height: 72px; border-bottom: 1px solid #dee2e6; }
.cw-dia { position: relative; flex: 1 1 0; max-width: 26px; height: 100%; display: flex; align-items: flex-end; cursor: default; }
.cw-col-envio { width: 100%; background: #93c5fd; border-radius: 2px 2px 0 0; min-height: 2px; }
.cw-col-resposta { position: absolute; bottom: 0; left: 25%; width: 50%; background: #16a34a; border-radius: 2px 2px 0 0; }
.cw-dia-rotulo { position: absolute; top: 100%; left: 50%; transform: translateX(-50%); font-size: .62rem; color: #adb5bd; padding-top: 3px; font-variant-numeric: tabular-nums; }
.cw-dia:hover .cw-col-envio { background: #60a5fa; }

/* conversas */
.cw-respostas { border-top: 1px solid #dee2e6; padding-top: 1.25rem; }
/* A lista de conversas cresce sem fim (50 respostas) e empurrava a página para
   baixo do funil. Na coluna, ela gruda abaixo da topbar (sticky, 52px) e rola
   por dentro: o funil fica no lugar enquanto se percorre as conversas. */
@media (min-width: 992px) {
  .cw-respostas { border-top: 0; border-left: 1px solid #dee2e6; padding: 0 0 0 2.25rem;
                  position: sticky; top: calc(52px + 1.75rem);
                  max-height: calc(100vh - 52px - 3.5rem); display: flex; flex-direction: column; }
  .cw-respostas ul { overflow-y: auto; overscroll-behavior: contain; padding-right: .35rem; }
}
.cw-respostas h2 { font-size: 1.1rem; font-weight: 800; letter-spacing: -.01em; color: #212529; display: flex; align-items: center; gap: .5rem; margin: 0; }
.cw-badge { background: #16a34a; color: #fff; font-size: .75rem; font-weight: 700; border-radius: var(--raio-chip); padding: .1rem .6rem; }
.cw-respostas-hint { font-size: .85rem; color: #6b7280; margin: .3rem 0 1.1rem; }
.cw-respostas ul { list-style: none; margin: 0; padding: 0; }
.cw-resposta { display: flex; align-items: center; gap: .8rem; padding: .6rem .5rem; border-radius: 8px; }
.cw-resposta:hover { background: #f8f9fa; }
.cw-resposta + .cw-resposta { margin-top: 2px; }
.cw-avatar { flex: none; width: 36px; height: 36px; border-radius: 50%; background: #dcfce7; color: #15803d; font-size: .8rem; font-weight: 800; display: flex; align-items: center; justify-content: center; }
.cw-quem { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.cw-quem strong { color: #212529; font-size: .95rem; }
.cw-texto-resposta { display: block; margin-top: .2rem; font-size: .85rem; color: #212529; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.cw-resposta-optout .cw-texto-resposta { color: #ca2a26; }
.cw-detalhe { font-size: .8rem; color: #6b7280; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
.cw-abrir { flex: none; font-size: .82rem; font-weight: 700; color: #15803d; border: 1px solid #86efac; border-radius: var(--raio-chip); padding: .3rem .8rem; text-decoration: none; white-space: nowrap; }
.cw-abrir:hover, .cw-abrir:focus-visible { background: #dcfce7; color: #166534; }
.cw-resposta-optout .cw-avatar { background: #f1f3f5; color: #adb5bd; }
.cw-resposta-optout .cw-quem strong { color: #6b7280; text-decoration: line-through; }
.cw-saiu { flex: none; font-size: .72rem; font-weight: 700; color: #ca2a26; border: 1px solid currentColor; border-radius: 3px; padding: .1rem .45rem; }

/* conversa (gaveta) — o Four Cloud é o proxy de leitura da UazAPI, porque o
   link wa.me exigia o WhatsApp Web logado com o número da Four */
.cw-fundo { position: fixed; inset: 0; background: rgba(33, 37, 41, .35); z-index: 1040; }
.cw-drawer { position: fixed; top: 0; right: 0; bottom: 0; width: min(430px, 100vw); background: #fff; z-index: 1050; display: flex; flex-direction: column; box-shadow: -8px 0 28px rgba(0, 0, 0, .12); }
.cw-drawer-cabecalho { flex: none; display: flex; align-items: center; gap: .75rem; padding: 1rem 1.1rem; border-bottom: 1px solid #dee2e6; }
.cw-drawer-quem { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.cw-drawer-quem strong { font-size: .95rem; color: #212529; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cw-drawer-quem span { font-size: .8rem; color: #6b7280; font-variant-numeric: tabular-nums; }
.cw-fechar { flex: none; border: 0; background: none; font-size: 1.4rem; line-height: 1; color: #6b7280; cursor: pointer; padding: .2rem .4rem; border-radius: 6px; }
.cw-fechar:hover, .cw-fechar:focus-visible { background: #f1f3f5; color: #212529; }
.cw-thread { flex: 1; overflow-y: auto; padding: 1rem 1.1rem 1.4rem; background: #f8f9fa; display: flex; flex-direction: column; gap: .35rem; }
.cw-thread-dia { align-self: center; font-size: .72rem; font-weight: 700; color: #6b7280; background: #e9ecef; border-radius: var(--raio-chip); padding: .15rem .7rem; margin: .6rem 0 .35rem; }
.cw-balao { max-width: 84%; padding: .5rem .7rem; border-radius: 10px; font-size: .875rem; color: #212529; white-space: pre-wrap; word-break: break-word; box-shadow: 0 1px 1px rgba(0, 0, 0, .06); }
.cw-balao-lead { align-self: flex-start; background: #fff; border: 1px solid #e9ecef; border-bottom-left-radius: 3px; }
.cw-balao-nos { align-self: flex-end; background: #dcfce7; border-bottom-right-radius: 3px; }
.cw-balao-hora { display: block; margin-top: .2rem; font-size: .68rem; color: #6b7280; text-align: right; font-variant-numeric: tabular-nums; }
.cw-thread-aviso { margin: auto; text-align: center; font-size: .85rem; color: #6b7280; padding: 2rem 1rem; }
.cw-responder { flex: none; display: flex; gap: .5rem; align-items: flex-end; padding: .7rem .9rem; border-top: 1px solid #dee2e6; background: #fff; }
.cw-responder textarea { flex: 1; resize: none; max-height: 120px; border: 1px solid #ced4da; border-radius: 18px; padding: .5rem .85rem; font-size: .875rem; color: #212529; background: #fff; }
.cw-responder textarea:focus { outline: 2px solid #86efac; outline-offset: -1px; border-color: #86efac; }
.cw-enviar { flex: none; border: 0; border-radius: var(--raio-chip); background: #16a34a; color: #fff; font-size: .85rem; font-weight: 700; padding: .5rem 1.1rem; cursor: pointer; }
.cw-enviar:hover:not(:disabled), .cw-enviar:focus-visible:not(:disabled) { background: #15803d; }
.cw-enviar:disabled { background: #adb5bd; cursor: default; }
.cw-erro { flex: none; margin: 0; padding: .5rem .95rem .8rem; font-size: .82rem; color: #ca2a26; background: #fff; }
@media (max-width: 575.98px) { .cw-drawer { width: 100vw; } }

.cw-vazio { padding: 3rem 0; color: #495057; }
.cw-vazio-sub { font-size: .875rem; color: #6b7280; }

@media (max-width: 575.98px) {
  .cw-page { padding: 1.25rem 1rem 2.5rem; }
  .cw-forma { height: 48px; }
  .cw-detalhe { white-space: normal; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   DESPESAS — DIAGNÓSTICO DE INCONSISTÊNCIAS
   Escopo: /despesas/ apenas. Faixa-resumo (reaproveita .destaque dos alertas),
   offcanvas de tratamento e a flag por linha das duas tabelas. Zero token
   global tocado — todo seletor daqui para baixo é prefixado `diag-`, lido só
   por bi/templates/bi/despesas.html + bi/static/bi/js/despesas.js.
   ═══════════════════════════════════════════════════════════════════════════ */

/* A porta do painel na topbar. Vermelha por decisão do dono: inconsistência
   aberta é dívida, não aviso. Some com zero — botão que não tem o que abrir não
   ocupa a barra. Segue a forma do `.buscar` (pílula de 2rem) para não inventar
   uma terceira silhueta de botão na topbar. */
.diag-topo {
  display: inline-flex; align-items: center; gap: .4rem; height: 2rem;
  padding: 0 .85rem; flex: 0 0 auto; cursor: pointer;
  border: var(--bs-border-width) solid var(--negative-text);
  border-radius: var(--raio-chip);
  background: var(--negative-text); color: #fff;
  font-size: .8125rem; font-weight: 600; box-shadow: var(--sh1);
}
.diag-topo:hover {
  background: color-mix(in srgb, var(--negative-text) 85%, #000);
  border-color: color-mix(in srgb, var(--negative-text) 85%, #000);
}
.diag-topo i { font-size: .8125rem; }

/* Flag por linha — bandeira desenhada em CSS (mastro + pano) para não depender
   de ícone: cinza vazada = linha limpa e marcável, âmbar cheia = heurística
   aberta, vermelha cheia = marca manual, apagada = linha sem documento. */
.diag-celula { width: 38px; text-align: center; vertical-align: middle; }
.diag-flag {
  position: relative; display: inline-block; width: 14px; height: 15px;
  padding: 0; border: 0; background: none; cursor: pointer; vertical-align: middle;
}
.diag-flag::before {
  content: ""; position: absolute; left: 1px; top: 0; bottom: 0;
  width: 2px; border-radius: 1px; background: var(--ink-4);
}
.diag-flag::after {
  content: ""; position: absolute; left: 3px; top: 1px; width: 9px; height: 8px;
  border: 1.5px solid var(--ink-4); border-left: 0; border-radius: 0 2px 2px 0;
}
.diag-flag:hover::before, .diag-flag:focus-visible::before { background: var(--ink-2); }
.diag-flag:hover::after, .diag-flag:focus-visible::after { border-color: var(--ink-2); }
.diag-flag--heuristica::before { background: var(--warning); }
.diag-flag--heuristica::after { border-color: var(--warning); background: var(--warning); }
.diag-flag--manual::before { background: var(--negative); }
.diag-flag--manual::after { border-color: var(--negative); background: var(--negative); }
.diag-flag--inerte { cursor: default; opacity: .3; }

/* Offcanvas — largo por pedido do dono: tratar inconsistência é a tarefa da
   vez, não nota de rodapé. Vai pela VARIÁVEL do Bootstrap, como as gavetas do
   CRM (.crm-oc--larga): `width` solto empata em especificidade com
   `.offcanvas-end` e perdia — o painel ficava nos 400px do padrão por mais que
   a regra dissesse 480 ou 960. */
.diag-offcanvas { --bs-offcanvas-width: min(1920px, 94vw); }
.diag-offcanvas .offcanvas-body {
  display: flex; flex-direction: column; gap: .75rem;
  container: diag-painel / inline-size;
}

/* Os 4 indicadores ficam numa linha só, com teto de largura: esticar cada
   um para 470px deixaria número pequeno boiando em caixa gigante. */
.diag-indicadores {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 16rem));
  justify-content: start; gap: .5rem;
}
.diag-indicador {
  display: flex; flex-direction: column; gap: .1rem;
  padding: .45rem .6rem; border-radius: var(--r-sm); background: var(--surf-2);
}
.diag-indicador__rotulo {
  font-size: .7rem; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-3);
}
.diag-indicador__valor { font-size: .9375rem; font-weight: 600; color: var(--ink); }

.diag-erro { margin: 0; font-size: .8125rem; color: var(--negative-text); }

.diag-marcar {
  display: flex; flex-direction: column; gap: .4rem;
  padding: .7rem .8rem; border: 1px solid var(--line-3); border-radius: var(--r-sm); background: var(--surf);
}
.diag-marcar__titulo { font-size: .8125rem; font-weight: 700; color: var(--ink); }

/* A grade. A lista de <details> empilhados saiu: quem ordena, filtra e soma é
   o DataTables padrão da casa (opt-in por `.tbl-wrapper.datatable` no wrapper —
   sem essa classe a toolbar, a rolagem e a paginação ficam sem estilo e se
   sobrepõem à tabela). O corpo do painel é uma coluna e só a GRADE rola: o
   cabeçalho de filtros tem de continuar ao alcance com 187 linhas embaixo. */
/* Barra de "Limpar filtros" + aviso de omitidas: os dois nascem escondidos, e
   sem altura mínima ela não abre uma faixa vazia entre indicadores e grade. */
.diag-barra { display: flex; align-items: center; gap: .75rem; }
.diag-barra:not(:has(> :not([hidden]):not(.d-none))) { display: none; }
.diag-corpo .tbl-wrapper { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.diag-corpo .dataTables_wrapper { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.diag-corpo .datatable-scroll { flex: 1 1 auto; min-height: 0; max-height: none; }
.diag-controle { width: 28px; text-align: center; }
/* Chevron de abrir/fechar o detalhe: o ícone do app, que gira ao abrir. */
.diag-abrir {
  width: 20px; height: 20px; padding: 0; border: 0; background: none; cursor: pointer;
  color: var(--ink-3); font-size: 11px; line-height: 20px; transition: transform .12s ease;
}
#bi-diagnostico-tabela tbody tr { cursor: pointer; }
.diag-linha--aberta .diag-abrir { transform: rotate(90deg); color: var(--ink); }
/* A linha aberta é a âncora do dossiê logo abaixo: precisa se destacar da
   zebra, senão o cartão parece solto no meio da lista. */
.diag-linha--aberta > td {
  background: var(--acc-soft) !important; font-weight: 600;
  border-top: 1px solid var(--acc-line); border-bottom: 0;
}

/* A LINHA-FILHA é o dossiê da inconsistência, e não pode parecer "mais uma
   linha": vira um cartão embutido, com barra de acento à esquerda na cor do
   tipo, provas à esquerda e conversa à direita. Sem o cartão, motivo, provas e
   caixa de texto ficavam boiando entre duas linhas zebradas. */
/* `.child` é a classe que o próprio DataTables carimba na linha-filha. */
#bi-diagnostico-tabela tbody tr.child > td { padding: 0; background: var(--surf-2); }
.diag-item__corpo {
  display: grid; gap: .6rem 1.5rem; grid-template-columns: minmax(0, 1fr);
  margin: .35rem .5rem .6rem 2rem; padding: .7rem .9rem;
  border: 1px solid var(--line); border-left: 3px solid var(--warning);
  border-radius: var(--r-sm); background: var(--surf);
}
.diag-item__corpo .diag-motivo, .diag-item__corpo .diag-obs { grid-column: 1 / -1; }
@container diag-painel (min-width: 900px) {
  .diag-item__corpo { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }
}
.diag-item__meta { font-size: .75rem; color: var(--ink-3); }

/* O motivo: a frase que diz POR QUE a linha caiu, com as provas dentro. Abre o
   corpo do item porque é a primeira pergunta de quem abre. */
.diag-motivo {
  margin: 0; padding: .45rem .6rem; border-radius: var(--r-sm);
  background: var(--warning-subtle); color: var(--warning-text);
  font-size: .8125rem; line-height: 1.35;
}

/* Descrição da despesa (observação, ou histórico na falta dela): é a prova do
   obs_diverge — quem julga a inconsistência precisa ler o texto que citou a
   outra NF. Ocupa a linha inteira, acima das duas colunas. */
.diag-obs {
  display: flex; align-items: baseline; gap: .5rem;
  padding: .35rem .5rem; border-radius: var(--r-sm); background: var(--surf-2);
}
.diag-obs__rotulo {
  flex: 0 0 auto; font-size: .6875rem; text-transform: uppercase;
  letter-spacing: .04em; color: var(--ink-3); font-weight: 600;
}
.diag-obs__texto { font-size: .8125rem; color: var(--ink); overflow-wrap: anywhere; }

/* Dados da despesa: rótulo em cima, valor embaixo. Era uma linha corrida de
   texto cinza ("conta · doc X · data") que ninguém lia. */
.diag-dados {
  margin: 0; display: grid; gap: .5rem 1.25rem;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
}
.diag-dado { display: flex; flex-direction: column; gap: .05rem; min-width: 0; }
.diag-dado > dt {
  font-size: .6875rem; text-transform: uppercase; letter-spacing: .04em;
  color: var(--ink-3); font-weight: 600;
}
.diag-dado > dd {
  margin: 0; font-size: .8125rem; color: var(--ink);
  overflow-wrap: anywhere;
}
/* Teto na conversa: caixa de comentário de 1000px é pior de ler que uma de
   700px — o texto vira uma linha só e o olho perde o retorno. */
.diag-conversa { display: flex; flex-direction: column; gap: .5rem; min-width: 0; max-width: 46rem; }

/* Duas colunas a partir de 900px de OFFCANVAS (container query: a largura que
   importa é a do painel, não a da janela). */
@container diag-painel (min-width: 900px) {
  .diag-item__corpo {
    display: grid; grid-template-columns: 1fr minmax(28rem, 46rem);
    column-gap: 1.5rem; align-items: start;
  }
  .diag-motivo, .diag-obs { grid-column: 1 / -1; }
  .diag-dados { grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr)); }
}

.diag-pilula {
  flex-shrink: 0; padding: .1rem .45rem; border-radius: var(--r-full);
  font-size: .6875rem; font-weight: 700; white-space: nowrap;
}
.diag-pilula--heuristica { background: var(--warning-subtle); color: var(--warning-text); }
.diag-pilula--manual { background: var(--negative-subtle); color: var(--negative-text); }

.diag-feed { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .35rem; }
.diag-comentario {
  display: flex; flex-direction: column; gap: .1rem;
  padding: .35rem .5rem; border-radius: var(--r-sm); background: var(--surf-2);
  font-size: .8125rem; color: var(--ink); white-space: pre-wrap; word-break: break-word;
}
.diag-comentario__meta { font-size: .6875rem; color: var(--ink-3); }
.diag-comentario--vazio { background: none; padding: 0; color: var(--ink-3); font-size: .75rem; }

.diag-acoes { display: flex; gap: .4rem; justify-content: flex-end; }

/* Indicador que tem lista atrás vira botão de verdade (abertas, resolvidas,
   falsos positivos). Impacto e idade média continuam texto — não há balde para
   abrir. O ativo se declara pela borda, não por fundo colorido: o painel já é
   denso. */
.diag-indicador--balde {
  border: 1px solid transparent; text-align: left; cursor: pointer;
  font: inherit; color: inherit;
}
.diag-indicador--balde:hover { border-color: var(--line-3); }
.diag-indicador--balde.is-ativo { border-color: var(--acc); background: var(--surf); }

/* Linha já apontada abre o painel inteira — a bandeira de 12px não é o único
   alvo. Linha limpa segue sem cursor: nela só a bandeira marca. */
.diag-linha { cursor: pointer; }
.diag-linha:hover { background: var(--surf-2); }

@media (max-width: 575.98px) { .diag-offcanvas { --bs-offcanvas-width: 100vw; } }

/* ==========================================================================
   BAIXA DE RETORNO BANCÁRIO — /conferencia-retorno/
   ==========================================================================
   A tela é um CANO, lido de cima para baixo. Duas bocas alimentam (portal e
   arquivo do computador), o arquivo se reparte em veredito, e o dinheiro cai
   numa conta de tesouraria. A espinha da esquerda é o processo desenhado:
   chega e vê os três nós, só o primeiro aceso.

   NADA NAVEGA. Conferir não troca de tela — os nós acendem, o conteúdo cresce
   embaixo, e o que já passou encolhe numa linha e continua visível. O operador
   nunca perde de vista qual arquivo está conferindo.

   ESCOPO DE PÁGINA. Tudo aqui é `ret-`, inclusive o que no experimento não era
   (`.no`, `.boca`, `.barra`, `.selo`…): sem prefixo, `.destino` ou `.conta`
   vazariam para as outras 27 telas. Nenhum token global é redefinido — a
   paleta de papel/carbono vive em `--ret-*` sob o seletor da página.

   A TIPOGRAFIA é a `--sans` do app (Roboto). O experimento
   (`/static/bi/demo/retorno-fluxo.html`) usa Archivo; trocar exigiria carregar
   uma segunda webfont no `<head>` global, que é mudança global — fica de fora
   até o dono pedir.

   CONTRASTE: `--ret-tinta-3` (#8A909C) é tinta de APOIO e de valor apagado,
   nunca de dado que precise ser lido ao centavo. Texto pequeno normal usa
   `--ret-tinta-2` (#5C6270), que passa AA sobre o papel.                     */

.page[data-pagina="retorno_conferencia"] {
  --ret-papel: #F1F2EE;
  --ret-painel: #FFFFFF;
  --ret-tinta: #171B24;
  --ret-tinta-2: #5C6270;
  --ret-tinta-3: #8A909C;
  --ret-regua: #DEE0D9;
  --ret-regua-forte: #C7CAC1;
  /* Espinha e nó aceso usam o MESMO azul dos botões do app: dois azuis na
     mesma tela é família misturada, que é o que a regra proíbe. */
  --ret-carbono: var(--acc-ink);
  --ret-carbono-claro: var(--acc-soft);
  --ret-confere: #3F6B4E;
  --ret-aberto: #B0761B;
  --ret-diverge: #AE3126;
  --ret-info: #8A909C;
  --ret-raio: 3px;

  background: var(--ret-papel);
  color: var(--ret-tinta);
  font-variant-numeric: tabular-nums;
}

/* Cadeia de altura: page → fluxo → estação da grade → grade. Um elo sem
   `min-height:0` faz o scroller interno sumir e a PÁGINA voltar a rolar. */
.ret-cabeca {
  flex: 0 0 auto; display: flex; align-items: baseline; gap: 1rem;
  padding-block: var(--bi-space-sm) var(--bi-space-sm);
  border-bottom: 1px solid var(--ret-regua);
}
.ret-cabeca h1 {
  margin: 0; font-size: 1.0625rem; font-weight: var(--bi-fw-semibold);
  letter-spacing: -.01em; color: var(--ret-tinta);
}
.ret-cabeca__sub { color: var(--ret-tinta-2); font-size: var(--bi-fs-compact); }
.ret-cabeca__fim { margin-left: auto; }

/* ── O cano ─────────────────────────────────────────────────────────────── */
.ret-fluxo {
  flex: 1 1 auto; min-height: 0; overflow: hidden;
  display: flex; flex-direction: column; padding-bottom: var(--bi-space-md);
  position: relative;
}
.ret-estacao {
  position: relative; z-index: 1;
  display: grid; grid-template-columns: 3rem 1fr; align-items: start;
  padding-top: var(--bi-space-lg);
}
/* A linha contínua é o que diz "isto é UM caminho", não três cartões
   empilhados. Cada estação pinta o próprio trecho — assim ela nasce no
   primeiro nó e MORRE no último, em vez de descer pendurada no vazio. */
.ret-estacao::before {
  content: ''; position: absolute; left: 8px; top: 0; bottom: 0; width: 2px;
  background: var(--ret-regua); z-index: 0;
}
.ret-estacao:first-of-type::before { top: 1.65rem; }
.ret-estacao:last-of-type::before { bottom: auto; height: 1.65rem; }
/* A estação da grade é a que cede altura — mas só depois de acordar. Dormindo
   ela reservava a janela inteira e abria um buraco morto entre os nós. */
.ret-estacao--grade { flex: 1 1 auto; min-height: 0; align-items: stretch; }
.ret-estacao--grade.ret-dorme { flex: 0 0 auto; align-items: start; }
.ret-estacao--grade > .ret-no { align-self: start; }

/* O nó: vazado (não chegou), sólido (é a vez), com visto (já passou). O visto
   é `fa-solid fa-check` — desenhá-lo com duas bordas rotacionadas nascia fora
   do centro. */
.ret-no {
  grid-column: 1; width: 18px; height: 18px; border-radius: 50%;
  border: 2px solid var(--ret-regua-forte); background: var(--ret-papel);
  margin-top: .15rem; position: relative;
  display: flex; align-items: center; justify-content: center;
  transition: border-color .25s, background .25s;
}
.ret-estacao.ret-viva > .ret-no { border-color: var(--ret-carbono); background: var(--ret-carbono); }
.ret-estacao.ret-viva > .ret-no::after {
  content: ''; position: absolute; inset: 4px; border-radius: 50%;
  background: var(--ret-painel);
}
.ret-estacao.ret-feita > .ret-no { border-color: var(--ret-carbono); background: var(--ret-painel); }
.ret-no__v { display: none; font-size: 9px; line-height: 1; color: var(--ret-carbono); }
.ret-estacao.ret-feita .ret-no__v { display: block; }

.ret-corpo {
  grid-column: 2; min-width: 0; min-height: 0; overflow: hidden;
  display: flex; flex-direction: column;
  /* âncora do "Recomeçar", que fica no alto da estação em qualquer das fases */
  position: relative;
}
.ret-estacao h2 {
  margin: 0 0 .15rem; font-size: .9375rem; font-weight: var(--bi-fw-semibold);
  letter-spacing: -.005em; color: var(--ret-tinta);
}
.ret-estacao.ret-dorme h2 { color: var(--ret-tinta-3); }
/* Estação dormindo mostra só o próprio nome: as linhas de apoio que explicavam
   cada etapa foram removidas a pedido do dono. */
.ret-estacao h2 + * { margin-top: .8rem; }
.ret-estacao.ret-dorme .ret-corpo > :not(h2) { display: none; }

/* ── Estação 1: UMA lista de origens ───────────────────────────────────────
   Antes eram duas bocas lado a lado com um "ou" no meio, e a operação leu como
   duas coisas soltas: escolhia o Banco do Brasil e em seguida tentava clicar em
   "escolher arquivo". Agora é uma lista só — portal e envio manual são linhas
   irmãs, e a escolha de uma exclui a outra por construção. */
.ret-origens {
  background: var(--ret-painel); border: 1px solid var(--ret-regua);
  border-radius: var(--ret-raio); max-width: 56rem; padding: .35rem 1.15rem;
}
.ret-boca__s { font-size: var(--bi-fs-micro); color: var(--ret-tinta-2); }
.ret-boca__n { font-size: var(--bi-fs-micro); color: var(--ret-tinta-3); }
/* Recomeçar mora no alto da estação, fora do fluxo das duas fases: ele existe
   tanto antes de carregar (errei o arquivo) quanto depois (era outro dia). Não
   é botão cinza: cinza, nesta casa, quer dizer desabilitado. */
.ret-recomecar {
  position: absolute; top: 0; right: 0; padding: 0; border: 0; background: none;
  font: inherit; font-size: var(--bi-fs-micro); color: var(--ret-tinta-2);
  text-decoration: underline; cursor: pointer;
}
.ret-recomecar:hover { color: var(--ret-carbono); }

/* Instituição é ETAPA, não rótulo. Hoje só a Multiplike tem conector, mas a
   escolha existe desde já: quando forem seis, a tela não muda de forma — muda
   de tamanho. */
.ret-inst { border-top: 1px solid var(--ret-regua); }
.ret-inst:first-of-type { border-top: 0; }
.ret-inst__cab {
  display: flex; align-items: baseline; gap: .6rem; width: 100%; text-align: left;
  padding: .45rem .1rem; background: none; border: 0; font: inherit;
  cursor: pointer; color: var(--ret-tinta);
}
.ret-inst__cab:hover { color: var(--ret-carbono); }
.ret-inst__n { font-size: var(--bi-fs-compact); font-weight: var(--bi-fw-semibold); }
.ret-inst.is-aberta .ret-inst__n { color: var(--ret-carbono); }
.ret-inst__r { margin-left: auto; font-size: var(--bi-fs-micro); color: var(--ret-tinta-2); }
/* A marca ocupa o lugar do nome da instituição — mesma altura da linha de texto
   que ela substitui, para o cabeçalho não crescer. `align-self` porque a linha
   alinha por baseline, e imagem não tem baseline. */
/* CAIXA ÚNICA PARA TODA MARCA. As marcas têm proporções muito diferentes — o
   Banco do Brasil é uma faixa (7:1), a Multiplike é um lockup de duas linhas
   (4:1). Igualando só a ALTURA, o BB ficava duas vezes mais largo e a lista
   parecia desalinhada; igualando só a largura, o "(Portal)" da Multiplike
   fechava. A caixa fixa com `contain` normaliza as duas pela ÁREA: cada uma
   cresce até tocar o lado que a limita, e nenhuma distorce. Alinhadas à
   esquerda porque é por ali que o olho desce a lista. */
.ret-inst__logo {
  width: 8.5rem; height: 2.1rem; display: block; align-self: center;
  object-fit: contain; object-position: left center;
}
.ret-inst__cab:has(.ret-inst__logo) { padding-top: .25rem; padding-bottom: .25rem; }
.ret-inst__carteiras { display: none; }
/* O filete à esquerda repete, em miniatura, a espinha da página: as carteiras
   PENDEM da instituição, não são irmãs dela. */
.ret-inst.is-aberta .ret-inst__carteiras {
  display: flex; flex-direction: column; gap: .1rem;
  margin: 0 0 .5rem .35rem; padding-left: .65rem; border-left: 2px solid var(--ret-regua);
}

/* Carteira e data dividem uma linha. A data ocupa a MESMA caixa com e sem
   seletor: carteira de uma data só não pode desalinhar a coluna. */
.ret-carteira-linha { display: flex; align-items: center; gap: .5rem; }
.ret-carteira {
  flex: 1 1 auto; display: flex; align-items: center; gap: .6rem; width: 100%; text-align: left;
  padding: .4rem .55rem; border: 1px solid transparent; border-radius: var(--ret-raio);
  background: none; font: inherit; color: var(--ret-tinta-2); cursor: pointer;
}
.ret-carteira:hover { background: #F6F7F4; }
.ret-carteira.is-escolhida {
  border-color: var(--ret-carbono); background: var(--ret-carbono-claro); color: var(--ret-tinta);
}
.ret-carteira__n { font-size: var(--bi-fs-compact); color: var(--ret-tinta); }
.ret-carteira.is-escolhida .ret-carteira__n { font-weight: var(--bi-fw-semibold); }
.ret-carteira__q { margin-left: auto; font-size: var(--bi-fs-micro); color: var(--ret-tinta-2); }
/* A data ocupa a MESMA caixa com e sem seletor: carteira de uma data só não
   pode desalinhar a coluna. */
/* 8,5rem porque a data é dd/mm/aaaa E o `form-select` reserva o espaço da
   seta à direita: a 7rem o ano ficava por baixo dela. */
.ret-carteira__d, .ret-carteira__datas {
  flex: 0 0 auto; width: 8.5rem; font-size: var(--bi-fs-micro);
  color: var(--ret-tinta-2); text-align: right;
}
.ret-carteira__d { padding-right: .3rem; }
.ret-carteira__datas { padding-block: .1rem; }

/* O input de arquivo fica TRANSPARENTE cobrindo a área inteira: o rótulo é
   nosso e em português, e o arrastar-e-soltar continua sendo o do navegador —
   esconder o input mataria a soltura. */
.ret-solta {
  position: relative; flex: 1 1 auto; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: .5rem; padding: 1rem;
  border: 1px dashed var(--ret-regua-forte); border-radius: var(--ret-raio);
  color: var(--ret-tinta-2); font-size: var(--bi-fs-compact); text-align: center;
}
.ret-solta strong { font-weight: var(--bi-fw-regular); color: var(--ret-tinta); }
.ret-solta .ret-file {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer; font-size: 0;
}
.ret-solta .ret-file:focus-visible ~ .btn { box-shadow: var(--ring); }
.ret-file-nome {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--bi-fs-micro); color: var(--ret-tinta-2);
}
/* O painel do envio manual respira mais que uma lista de carteiras: são três
   coisas diferentes empilhadas (arquivo, banco, limites), não itens de lista. */
.ret-inst--manual.is-aberta .ret-inst__carteiras { gap: .55rem; padding-bottom: .5rem; }
.ret-leiaute { display: flex; align-items: center; gap: .6rem; }
.ret-leiaute__t { font-size: var(--bi-fs-micro); color: var(--ret-tinta-2); }
/* 12.5rem, não 9: "Detectar pelo arquivo" é a opção padrão e cortava em
   "Detectar pelo arquivc" — visto no preview em 08/09/2026. */
.ret-leiaute .form-select { flex: 0 0 auto; width: 12.5rem; }
/* A PERGUNTA DO BANCO tem peso de pergunta, não de rodapé: o rótulo sai do
   micro cinza do leiaute e o campo cresce, porque nele cabe "COOPERATIVA
   CENTRAL DE CRÉDITOS – AILOS (085)". É a única coisa que a estação 1 pede
   além do arquivo. */
.ret-banco { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.ret-banco__t {
  font-size: var(--bi-fs-body); color: var(--ret-tinta);
  font-weight: var(--bi-fw-semibold);
}
.ret-banco .form-select { flex: 1 1 16rem; min-width: 0; max-width: 26rem; }
/* Detalhe técnico dobrado: fechado é uma linha discreta, aberto é o seletor de
   leiaute com o mesmo desenho de antes. */
.ret-avancado > summary {
  font-size: var(--bi-fs-micro); color: var(--ret-tinta-2);
  cursor: pointer; width: fit-content; padding: .1rem 0;
}
.ret-avancado > summary:hover { color: var(--ret-tinta); }
.ret-avancado[open] > summary { margin-bottom: .45rem; }
.ret-acao { margin-top: .9rem; }

/* O que já passou fica na tela, encolhido: a estação cumprida troca a lista de
   origens por uma linha com o arquivo escolhido. */
.ret-estacao.ret-feita .ret-origens,
.ret-estacao.ret-feita .ret-acao { display: none; }
.ret-origem-fina { display: none; }
.ret-estacao.ret-feita .ret-origem-fina {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  font-size: var(--bi-fs-compact); color: var(--ret-tinta-2);
}
.ret-origem-fina .ret-dado { color: var(--ret-tinta); }

/* ── Estação 2: o arquivo se repartindo ─────────────────────────────────── */
.ret-medida { display: flex; align-items: baseline; gap: .7rem; margin-bottom: .65rem; }
.ret-medida__v {
  font-size: 1.75rem; font-weight: var(--bi-fw-semibold);
  letter-spacing: -.02em; line-height: 1;
}
.ret-medida__q { font-size: var(--bi-fs-compact); color: var(--ret-tinta-2); }
.ret-medida__f { margin-left: auto; font-size: var(--bi-fs-micro); color: var(--ret-tinta-2); }

/* A barra só é desenhada quando há MAIS DE UMA faixa (decidido no JS a partir
   de `kpis.faixas`, que o backend já somou): com uma faixa só ela vira uma
   tira de cor inteira dizendo o que a legenda já disse. */
.ret-barra { display: flex; height: 10px; border-radius: 2px; overflow: hidden; background: var(--ret-regua); }
.ret-naco { height: 100%; width: 0; transition: width .55s cubic-bezier(.22,.61,.36,1); }
.ret-naco--confere { background: var(--ret-confere); }
.ret-naco--aberto_no_erp { background: var(--ret-aberto); }
.ret-naco--baixa_divergente,
.ret-naco--encargo_nao_lancado,
.ret-naco--valor_divergente { background: var(--ret-diverge); }
.ret-naco--ambiguo, .ret-naco--nao_encontrado { background: var(--ret-info); }

.ret-chaves { display: flex; gap: 1.4rem; margin: .5rem 0 1rem; flex-wrap: wrap; }
.ret-chave {
  display: flex; align-items: baseline; gap: .4rem;
  font-size: var(--bi-fs-compact); color: var(--ret-tinta-2);
}
.ret-chave::before { content: ''; width: 8px; height: 8px; border-radius: 2px; flex: 0 0 auto; }
.ret-chave b { font-weight: var(--bi-fw-semibold); color: var(--ret-tinta); }
.ret-chave--confere::before { background: var(--ret-confere); }
.ret-chave--aberto_no_erp::before { background: var(--ret-aberto); }
.ret-chave--baixa_divergente::before,
.ret-chave--encargo_nao_lancado::before,
.ret-chave--valor_divergente::before { background: var(--ret-diverge); }
.ret-chave--ambiguo::before, .ret-chave--nao_encontrado::before { background: var(--ret-info); }
.ret-chave--aviso::before { background: var(--ret-info); opacity: .45; }

/* ── A grade (a grade da casa, `static/js/grade.js`) ─────────────────────── */
/* Sem moldura: o dono já rejeitou caixa+fio em volta da lista no piloto
   (`grade-minimalista-sem-moldura`, reporte #27, 15/09/2026) — "piorou, quero
   EVITAR AO MÁXIMO MOLDURAS e linhas". O visual da grade (cabeçalho, fio,
   selo de estado) é o padrão da casa; esta página só liga o `.grade` à
   cadeia de altura do próprio "cano" (`.ret-corpo`/`.ret-pane`, que É
   `display:flex`): sem isto o `.dataTables_wrapper` não recebe altura e as
   linhas de baixo ficam recortadas pelo `overflow:hidden` do wrapper — o
   mesmo sintoma que a caixa antiga (`.ret-grade-cx`) existia para evitar.
   Visto ao vivo com o arquivo de 02/09. */
.page[data-pagina="retorno_conferencia"] .grade {
  flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
  /* Folha branca, sem moldura: o corpo da grade é transparente e nas outras
     telas a página já é branca. Aqui o papel da estação é `--ret-papel`
     (#F1F2EE) e vazava por trás das linhas. */
  background: var(--ret-painel);
}
/* A estação tem altura fixa (o cano mostra as outras estações embaixo), então
   quem sobra é o CORPO da lista: ele rola por dentro, com a barra, o cabeçalho
   e o pé sempre à vista. Mesma cadeia das telas de altura cheia; aqui escopada
   na página porque o cano não é `content--altura-cheia`. */
.page[data-pagina="retorno_conferencia"] .grade .tbl-wrapper {
  flex: 1 1 auto; min-height: 0; overflow: hidden; display: flex; flex-direction: column;
}
.page[data-pagina="retorno_conferencia"] .grade .dataTables_wrapper {
  flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
}
.page[data-pagina="retorno_conferencia"] .grade .datatable-scroll {
  flex: 1 1 auto; min-height: 0; max-height: none; overflow: auto;
}
.ret-cel { display: flex; flex-direction: column; line-height: 1.2; }
.ret-cel__sub { font-size: var(--bi-fs-micro); color: var(--ret-tinta-2); }
/* Valor de aviso não é dinheiro que entrou: é o saldo do título, que o banco
   repete ao mudar um dado. Apagado para não competir com o herói. */
.ret-num--apagado { color: var(--ret-tinta-3); }
/* Observação/Impacto no ERP são as únicas colunas que se LEEM, mas quebrar o
   texto em três linhas triplicava a altura da linha e a estação, que é de
   altura fixa, passava a mostrar UMA linha da lista. Uma linha por título,
   com reticências e o texto inteiro no `title` da célula. */
.page[data-pagina="retorno_conferencia"] .grade .grade-tabela .ret-col-obs {
  min-width: 14rem;
}
.page[data-pagina="retorno_conferencia"] .grade .grade-tabela .ret-col-obs .grade-celula {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* Marcar a linha é o ato que escreve no ERP — errar o alvo tem custo. A caixa
   mantém os 14px do app; quem recebe o clique é o rótulo (30×25px). */
.ret-sel-alvo {
  display: inline-flex; align-items: center; justify-content: center;
  padding: .35rem .5rem; margin: -.35rem .1rem -.35rem -.5rem; cursor: pointer;
}
.ret-sel-linha { vertical-align: -.1em; accent-color: var(--ret-carbono); }

/* O veredito da linha virou `.grade-status` (ponto + palavra) da grade da
   casa — ver `TOM_VEREDITO` em `conferencia-retorno.js`. O selo próprio
   (`.ret-selo`) saiu daqui em 16/09/2026; a barra/legenda da repartição
   (`.ret-naco`/`.ret-chave`, acima) continua com as cores por veredito. */

/* MARCA DO BANCO. Monograma, não logotipo: a marca oficial é arte de
   terceiro e não entra no repositório. A sigla e o `slug` vêm do backend
   (`retorno_conferencia.BANCOS`), então acrescentar um banco não mexe aqui —
   só quem quiser cor própria escreve a regra `--slug`. Sem slug, cinza neutro. */
.ret-marca {
  flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
  min-width: 2.6rem; height: 1.6rem; padding: 0 .45rem;
  border-radius: var(--ret-raio); border: 1px solid var(--ret-regua);
  background: #fff; color: var(--ret-tinta-2);
  font-size: var(--bi-fs-micro); font-weight: var(--bi-fw-semibold);
  letter-spacing: .02em; line-height: 1;
}
.ret-marca--bb { background: #fbe64a; border-color: #e6d02f; color: #12467f; }
.ret-marca--itau { background: #ec7000; border-color: #d16400; color: #fff; }
/* A marca vive DENTRO do `#ret-origem-dita`, então o `gap` da linha não a
   separa do texto que vem depois — a margem é dela mesma. */
.ret-origem-fina .ret-marca { margin-right: .55rem; }
/* Com logotipo a caixa some: a marca já é a forma. Altura fixa e largura livre
   porque as marcas são horizontais e cada uma tem sua proporção. */
/* Mesma caixa da lista, em miniatura: a marca na linha de origem e na conta de
   destino ocupa sempre o mesmo espaço, seja qual for a proporção do logotipo. */
.ret-marca--img {
  width: 5.4rem; height: 1.35rem; min-width: 0; padding: 0;
  border: 0; background: none; border-radius: 0;
  object-fit: contain; object-position: left center;
}

/* ── Estação 3: para onde o dinheiro vai ────────────────────────────────── */
.ret-destino {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  background: var(--ret-painel); border: 1px solid var(--ret-regua);
  border-radius: var(--ret-raio); padding: .8rem 1.1rem;
}
.ret-destino + .ret-destino { margin-top: var(--bi-space-sm); }
.ret-conta { display: flex; flex-direction: column; gap: .1rem; min-width: 0; }
.ret-conta__n { font-size: var(--bi-fs-body); font-weight: var(--bi-fw-semibold); }
.ret-conta__d { font-size: var(--bi-fs-micro); color: var(--ret-tinta-2); }
.ret-destino__fim { margin-left: auto; display: flex; align-items: center; gap: .9rem; }
/* Trocar a conta é decisão de dinheiro: fica na MESMA pilha do destino e logo
   acima do botão que escreve, não escondida numa estação anterior. */
.ret-troca { display: flex; align-items: center; gap: .75rem; width: 100%; min-width: 0; }
.ret-troca__t {
  flex: 0 0 auto; font-size: var(--bi-fs-micro); color: var(--ret-tinta-2);
}
.ret-troca .form-select { max-width: 34rem; }
.ret-somatorio { text-align: right; font-size: var(--bi-fs-micro); color: var(--ret-tinta-2); }
.ret-somatorio b {
  display: block; font-size: var(--bi-fs-heading); color: var(--ret-tinta);
  font-weight: var(--bi-fw-semibold);
}

/* ── Botões: NÃO existem aqui ───────────────────────────────────────────
   Regra dura do dono: uma família de botão por tela, o azul de fábrica do
   Bootstrap — sólido para agir agora, contorno para navegar — e o desabilitado
   é o do próprio framework. Esta seção já teve uma família própria (carbono
   sólido + fantasma cinza + link sublinhado + `:disabled` pintado à mão): eram
   quatro aparências, e o cinza mentia dizendo "desabilitado" numa ação viável.
   Nada de botão mora mais aqui. Se aparecer `.ret-btn` de novo, é regressão. */

/* ── Baixas realizadas: a mesma casca, fora do cano ─────────────────────── */
.ret-pane { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
            padding-top: var(--bi-space-md); }
.ret-pane__topo {
  flex: 0 0 auto; display: flex; align-items: center; gap: var(--bi-space-sm);
  margin-bottom: var(--bi-space-sm); font-size: var(--bi-fs-compact);
  color: var(--ret-tinta-2);
}
/* O azul de link do Bootstrap é a única cor estranha à paleta desta tela. */
.page[data-pagina="retorno_conferencia"] .grade a { color: var(--ret-carbono); }
.ret-estornar { padding: 0 .45rem; font-size: var(--bi-fs-micro); min-height: 24px; line-height: 1.1; }
.ret-carteira:focus-visible, .ret-inst__cab:focus-visible {
  outline: 2px solid var(--ret-carbono); outline-offset: 2px;
}

/* ── Painéis de confirmação: é aqui que a escrita no ERP é travada ─────── */
.ret-oc { --bs-offcanvas-width: 30rem; }
.ret-oc .offcanvas-body { display: flex; flex-direction: column; gap: var(--bi-space-md); }
.ret-oc .offcanvas-footer {
  display: flex; justify-content: flex-end; gap: var(--bi-space-sm);
  padding: var(--bi-space-md); border-top: 1px solid var(--line);
}
.ret-impacto {
  display: grid; grid-template-columns: auto 1fr; gap: .3rem var(--bi-space-md);
  margin: 0; font-size: var(--bi-fs-compact);
}
.ret-impacto dt { color: var(--ink-2); font-weight: var(--bi-fw-regular); }
.ret-impacto dd { margin: 0; color: var(--ink); font-variant-numeric: tabular-nums; }
.ret-impacto__forte { font-size: var(--bi-fs-heading); font-weight: var(--bi-fw-semibold); }

/* ── Notas ─────────────────────────────────────────────────────────────── */
.ret-nota {
  flex: 0 0 auto; padding: var(--bi-space-sm) var(--bi-space-md);
  margin-top: var(--bi-space-sm); border-radius: var(--ret-raio);
  font-size: var(--bi-fs-compact);
}
.ret-nota--aviso { background: #fef1dd; color: var(--warning-text); }
.ret-nota--erro  { background: var(--negative-subtle); color: var(--negative-text); }

@media (max-width: 900px) {
  /* A lista de origens já é uma coluna só — nada a empilhar aqui desde que as
     duas bocas viraram linhas irmãs. */
  .ret-troca { flex-wrap: wrap; }
  .ret-estacao { grid-template-columns: 2rem 1fr; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   CURVA ABC  —  /curva-abc/
   Matriz mês × bitola (o desenho da aba `Curva ABC` da planilha Gerencial).
   Escopo de PÁGINA: nenhuma regra aqui vaza para fora de `.cabc`.
   ═══════════════════════════════════════════════════════════════════════════ */
/* A topbar fica FORA da `div.cabc` (bloco `topbar_actions` do base), então
   escopar em `.cabc .cabc-ano` não casa — a regra nunca aplicava e o
   `width:100%` do .form-select cobria o botão Fixadores. `.cabc-ano` é
   nome exclusivo desta página, então a regra nua continua page-scoped. */
.cabc-ano { flex: 0 0 auto; width: auto; min-width: 6rem; }

/* A tela usa a janela inteira — sem faixa morta no rodapé. O desconto é a
   topbar + o header do card, medidos, não chutados. */
.cabc-wrap { overflow: auto; max-height: calc(100vh - 9.5rem); }

.cabc-mx { width: 100%; border-collapse: separate; border-spacing: 0;
           font-size: .74rem; }
.cabc-mx th, .cabc-mx td { padding: .28rem .3rem; white-space: nowrap;
                           border-bottom: 1px solid var(--line-2); }

.cabc-mx thead th { position: sticky; top: 0; z-index: 2;
                    background: var(--surf-2); color: var(--ink-2);
                    font-weight: var(--bi-fw-semibold); text-align: right;
                    border-bottom: 1px solid var(--line); }
.cabc-mx thead tr:nth-child(2) th { top: 2.1rem; }
.cabc-mx th.cabc-grupo { text-align: center; background: var(--surf-3);
                         color: var(--ink); border-left: 1px solid var(--line-3); }
.cabc-mx th.cabc-tot { background: var(--surf-3); }

/* Coluna do mês: congelada à esquerda, senão a matriz perde a âncora ao rolar. */
.cabc-mx th.cabc-mes { position: sticky; left: 0; z-index: 3;
                       background: var(--surf); text-align: left;
                       color: var(--ink); font-weight: var(--bi-fw-semibold);
                       border-right: 1px solid var(--line); }
.cabc-mx thead th.cabc-mes { z-index: 4; background: var(--surf-2); }

/* Cabeçalho de coluna: o MESMO componente da Gerencial (`gc-bh__*`), que já
   empilha total · barra · bitola · código · unidade. Os tokens `--gc-*` são
   declarados lá no contêiner `.gc`, então aqui eles são apontados para os
   mesmos valores globais — apontar é o que evita duplicar a regra do
   componente (e ele deixaria de ser um só, que é o ponto). */
.cabc { --gc-ink: var(--ink); --gc-ink-2: var(--ink-2); --gc-ink-3: var(--ink-3);
        --gc-line: var(--line); --gc-panel-3: var(--surf-2);
        --gc-green: var(--bs-success); --gc-red: var(--bs-danger); }
.cabc-mx th.cabc-bitola { vertical-align: bottom; text-align: right; }
/* A barra da Gerencial cresce dos DOIS lados de uma linha de zero (saldo pode
   ser negativo). Aqui a medida é volume do ano: cresce só para cima, a partir
   da base — sem linha de zero, que não teria o que separar. */
.cabc-mx .gc-bh__bar { height: 1.6rem; margin: .1rem 0 .15rem; }
.cabc-mx .gc-bh__bar b { left: 30%; right: 30%; bottom: 0; }
.cabc-mx .gc-bh__num { color: var(--ink); font-size: .68rem; }
.cabc-mx .gc-bh--dn .gc-bh__num { color: var(--negative-text); }
.cabc-mx .gc-bh__lbl { font-size: .72rem; }
.cabc-mx .gc-bh__und { line-height: 1.2; }
/* Verde na Gerencial quer dizer "saldo positivo". Aqui a barra mede TAMANHO da
   coluna no ano — não há bom nem ruim —, então ela usa a mesma família azul da
   rampa de participação do corpo, e não uma cor com opinião. */
.cabc-mx .gc-bh__bar b { background: var(--acc-line); }
.cabc-mx .gc-bh--dn .gc-bh__bar b { background: var(--negative-text); }
/* O código tem 8 dígitos e é ele que dita a largura da coluna: sem apertar a
   fonte dele, as 12 bitolas empurram Faturamento/Compra/Margem/Meta para fora
   da janela (medido: 137 px de sobra). */
.cabc-mx .gc-bh__cod { font-size: .56rem; letter-spacing: -0.04em; }
.cabc-mx th, .cabc-mx td { padding: .24rem .22rem; }

.cabc-mx td.cabc-num { text-align: right; font-variant-numeric: tabular-nums; }
.cabc-mx td.cabc-zero { color: var(--ink-4); }
.cabc-mx td.cabc-sub { background: var(--surf-2); font-weight: var(--bi-fw-semibold); }
.cabc-share { display: block; font-size: .68rem; font-weight: 400; color: var(--ink-3); }

/* O hover NÃO pode pintar o fundo: apagaria justo a tinta da linha que o
   leitor está lendo. Vira anel. */
.cabc-mx tbody tr:hover td { box-shadow: inset 0 -1px 0 var(--line-3), inset 0 1px 0 var(--line-3); }
.cabc-mx tbody tr:hover th.cabc-mes { background: var(--surf-3); }
.cabc-linha-vazia td, .cabc-linha-vazia th { color: var(--ink-4); }

.cabc-mx tfoot th, .cabc-mx tfoot td { background: var(--surf-2); }
.cabc-mx tfoot tr.cabc-total th, .cabc-mx tfoot tr.cabc-total td {
  background: var(--surf-3); font-weight: var(--bi-fw-semibold); color: var(--ink); }
.cabc-mx tfoot th.cabc-mes { background: var(--surf-3); }

.cabc-ok { color: var(--positive-text, #1a7f4b); }
.cabc-abaixo { color: var(--negative-text); }

/* ── Mira (hover acende linha + coluna) ──────────────────────────────────── */
/* `biUtils.ligarMira` marca as células; aqui a coluna vira um par de trilhos
   verticais, pelo mesmo motivo do hover de linha logo acima: pintar o fundo
   apagaria a rampa de participação, que é o dado da célula. */
.cabc-mx td.bi-mira-coluna, .cabc-mx tfoot th.bi-mira-coluna {
  box-shadow: inset 1px 0 0 var(--acc-line), inset -1px 0 0 var(--acc-line); }
/* Cruzamento: os trilhos da coluna + o anel da linha, num box-shadow só —
   a propriedade não acumula entre regras, a mais específica vence inteira. */
.cabc-mx tbody tr:hover td.bi-mira-coluna {
  box-shadow: inset 1px 0 0 var(--acc-line), inset -1px 0 0 var(--acc-line),
              inset 0 -1px 0 var(--line-3), inset 0 1px 0 var(--line-3); }
/* Cabeçalho: o fundo é chapado, então a coluna mirada pode receber a marca
   cheia — é o que diz de qual bitola são os trilhos. */
.cabc-mx thead th.bi-mira-coluna { background: var(--acc-soft); color: var(--ink); }
.cabc-mx thead th.cabc-grupo.bi-mira-coluna,
.cabc-mx thead th.cabc-tot.bi-mira-coluna { background: var(--acc-soft); }

.cabc-legenda { font-size: var(--bi-fs-compact); color: var(--ink-3); }

/* ═══════════════════════════════════════════════════════════════════════════
   METAS POR VENDEDOR  —  /metas-vendedor/
   Quadro meta × realizado × atingimento por representante, em dois blocos
   (equipe interna e externos). Escopo de PÁGINA.
   ═══════════════════════════════════════════════════════════════════════════ */
.mvd-mes { flex: 0 0 auto; width: auto; min-width: 9rem; }
.mvd-ano { flex: 0 0 auto; width: auto; min-width: 5.5rem; }
.mvd-eixo { flex: 0 0 auto; width: auto; min-width: 10rem; }
.mvd-salvar { flex: 0 0 auto; }

/* A tela usa a janela inteira: o card estica e a grade ocupa o que sobra, em vez
   de deixar faixa branca embaixo quando o mês tem poucos vendedores. */
.mvd .card { display: flex; flex-direction: column; min-height: calc(100vh - 6.5rem); }
.mvd .card-body { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
.mvd-wrap { overflow: auto; flex: 1 1 auto; min-height: 0; }

.mvd-mx { width: 100%; border-collapse: separate; border-spacing: 0;
          font-size: var(--bi-fs-compact); }
.mvd-mx th, .mvd-mx td { padding: .3rem .5rem; white-space: nowrap;
                         border-bottom: 1px solid var(--line-2); }

.mvd-mx thead th { position: sticky; top: 0; z-index: 2; background: var(--surf-2);
                   color: var(--ink-2); font-weight: var(--bi-fw-semibold);
                   text-align: right; border-bottom: 1px solid var(--line); }
.mvd-mx thead tr:nth-child(2) th { top: 2.1rem; }
.mvd-mx th.mvd-eixo { text-align: center; background: var(--surf-3); color: var(--ink);
                      border-left: 1px solid var(--line-3); }

.mvd-mx th.mvd-nome { position: sticky; left: 0; z-index: 3; background: var(--surf);
                      text-align: left; color: var(--ink);
                      font-weight: var(--bi-fw-semibold);
                      border-right: 1px solid var(--line); }
.mvd-mx thead th.mvd-nome { z-index: 4; background: var(--surf-2); }

.mvd-mx td.mvd-num { text-align: right; font-variant-numeric: tabular-nums; }
.mvd-mx td.mvd-meta { padding: .15rem .25rem; }

/* Folha de cadastro (modo ano): doze colunas de digitação. O campo encolhe —
   com a largura do modo mês a grade não caberia na janela e a rolagem
   horizontal mataria a comparação entre meses, que é o ponto da folha. */
.mvd--ano .mvd-input { width: 4.4rem; }
.mvd-mx td.mvd-ano-total { background: var(--surf-2); font-weight: var(--bi-fw-semibold); }

/* Célula editável precisa PARECER editável mesmo vazia: sem borda o usuário lê
   a coluna Meta como espaço em branco e não descobre que ali se digita. */
.mvd-input { width: 6rem; text-align: right; font-variant-numeric: tabular-nums;
             border: 1px dashed var(--line-3); border-radius: var(--r-sm);
             background: var(--surf); color: var(--ink); padding: .15rem .35rem;
             font-size: var(--bi-fs-compact); }
.mvd-input:hover { border-style: solid; border-color: var(--bs-primary); }
.mvd-input:focus { border-color: var(--bs-primary); background: var(--surf);
                   outline: none; }
/* Meta digitada e ainda não gravada: o número na tela não é o do banco, e isso
   precisa ser visível — senão o usuário sai achando que salvou. */
.mvd-input--sujo { background: var(--warning-subtle); border-color: var(--warning-text); }

.mvd-mx tr.mvd-bloco th { background: var(--surf-3); color: var(--ink);
                          text-align: left; text-transform: uppercase;
                          letter-spacing: .04em; font-size: .7rem; }
.mvd-mx tr.mvd-subtotal th, .mvd-mx tr.mvd-subtotal td { background: var(--surf-2);
                                                         font-weight: var(--bi-fw-semibold); }
/* Agenda — seleção em lote na coluna de atrasados. A caixa fica FORA do botão
   da linha (botão dentro de botão não é HTML válido) e o item vira a régua que
   alinha os dois. A BARRA de ação não mora aqui: é `position-fixed` no rodapé
   da janela, mesma anatomia da savebar da Matriz de Acesso — dentro desta
   coluna ela empurrava a lista a cada clique.
   `center` e não `flex-start`: a caixa fica na altura do NOME, que é a
   primeira linha do rótulo, sem margem chutada. */
.ag-item { display: flex; align-items: center; gap: .5rem; }
.ag-item .ag-marcar { flex: 0 0 auto; margin: 0; }
.ag-item .ag-linha { flex: 1 1 auto; min-width: 0; }
/* Rodapé fixo cobriria a última linha da coluna, que rola por dentro. */
[data-pagina="crm-agenda"] .ag-atrasados { padding-bottom: 3.5rem; }

/* Pendentes de meta: quem tem acesso ao CRM e ainda não entrou no quadro. A
   seção fica DEPOIS do último subtotal e não soma em nada — o recuo e o texto
   apagado são o que impede alguém de ler estas linhas como parte do time
   medido. Zero não é resultado ruim aqui, é "ninguém digitou a meta ainda". */
.mvd-mx tr.mvd-bloco--pendente th { background: var(--surf-2); color: var(--ink-2);
                                    font-style: italic; text-transform: none;
                                    letter-spacing: 0; }
/* A linha pendente NÃO é apagada: o campo de meta dela é editável, e cinza
   lê como desabilitado — foi o que fez a gerente achar que não dava para
   digitar ali. Quem sinaliza o estado é a etiqueta "sem meta", não a tinta. */
.mvd-mx tr.mvd-pendente th, .mvd-mx tr.mvd-pendente td { color: inherit; }
.mvd-mx tr.mvd-pendente .mvd-nome { padding-left: var(--sp-4); }
.mvd-mx tfoot tr.mvd-total th, .mvd-mx tfoot tr.mvd-total td {
  position: sticky; bottom: 0; background: var(--surf-3);
  font-weight: var(--bi-fw-semibold); color: var(--ink);
  border-top: 1px solid var(--line-3); }

.mvd-vazio { color: var(--ink-3); text-align: center; padding: .75rem; }
.mvd-tag { margin-left: .35rem; padding: 0 .3rem; border-radius: var(--r-sm);
           background: var(--warning-subtle); color: var(--warning-text);
           font-size: .65rem; font-weight: 600; }

.mvd-ok { color: var(--positive-text, #1a7f4b); }
.mvd-abaixo { color: var(--negative-text); }
.mvd-status { font-size: var(--bi-fs-compact); color: var(--ink-3); }

/* ── Mira (hover acende linha + coluna) ──────────────────────────────────── */
/* Marcação de `biUtils.ligarMira`, a mesma da Gerencial e da Curva ABC. Aqui as
   células não têm tinta de dado própria, então a mira pode ser fundo — é o que
   mantém o olho na dupla vendedor × coluna numa grade de 12 colunas. */
.mvd-mx tbody tr.bi-mira-linha td, .mvd-mx tbody tr.bi-mira-linha th.mvd-nome {
  background: var(--surf-2); }
.mvd-mx tbody td.bi-mira-coluna { background: var(--surf-2); }
.mvd-mx tbody tr.bi-mira-linha td.bi-mira-coluna { background: var(--surf-3); }
.mvd-mx thead th.bi-mira-coluna { background: var(--acc-soft); color: var(--ink); }

/* Custo herdado de um mês anterior (mês sem importação): o número é estimativa,
   não medição, e a tela não pode deixar os dois com a mesma cara. */
.cabc-mx td.cabc-estimado { color: var(--ink-3); font-style: italic; }

/* Faixas de família no cabeçalho da Curva ABC — a planilha manual colore o
   cabeçalho por bloco (Fio verde, Cordoalha azul `4F81BD`, totais verde-oliva
   `9BBB59`), e é assim que o usuário lê a matriz há anos. Mesmos matizes, na
   luminosidade do tema claro do app: o verde puro (#00FF00) da planilha não
   sobrevive ao lado de texto. */
/* A família é IDENTIDADE (categórico); a célula de dado é MAGNITUDE
   (sequencial). Os dois não podem dividir o mesmo canal: com fundo pastel no
   cabeçalho e azuis de dado logo abaixo, a banda lia como mais um degrau da
   mesma escala (o `#d6e3f3` antigo caía exatamente entre as faixas 1 e 2 da
   rampa). Então a família desce para uma RÉGUA — 3px de borda — e o fundo do
   cabeçalho volta a ser neutro. */
.cabc-mx th.cabc-banda-1 { box-shadow: inset 0 -3px 0 #7fb872; }
.cabc-mx th.cabc-banda-2 { box-shadow: inset 0 -3px 0 #6d93cc; }
.cabc-mx th.cabc-banda-3 { box-shadow: inset 0 -3px 0 #9ab863; }
.cabc-mx th.cabc-banda-4 { box-shadow: inset 0 -3px 0 #b98fb4; }

/* Limite de família descendo o corpo inteiro: sem ele o agrupamento morre na
   primeira linha de dado e a varredura vertical perde a referência. */
.cabc-mx th.cabc-fim-familia, .cabc-mx td.cabc-fim-familia {
  border-right: 1px solid var(--line-3); }

/* Rampa sequencial de PARTICIPAÇÃO da bitola no mês, normalizada por LINHA —
   o total mensal varia de 1.072 t a 2.299 t, e uma escala global confundiria
   "mês grande" com "bitola dominante". Um hue só (o azul de gráfico do app),
   monotônica em luminosidade: em escala de cinza a leitura sobrevive.
   Faixa 0 (< 3%) fica SEM tinta de propósito — é o branco que faz o Pareto
   aparecer; pintar tudo mataria a leitura. */
.cabc-mx td.cabc-f1 { background: #e0e9fc; }
.cabc-mx td.cabc-f2 { background: #c2d3f9; }
.cabc-mx td.cabc-f3 { background: #a3bdf7; }
.cabc-mx td.cabc-f4 { background: #87a9f4; }
/* Em célula pintada o texto vai para `--ink`: `--ink-3` mede 2,07:1 sobre o
   degrau mais escuro e reprova AA. */
.cabc-mx td.cabc-f1, .cabc-mx td.cabc-f2,
.cabc-mx td.cabc-f3, .cabc-mx td.cabc-f4 { color: var(--ink); }

/* Devolução maior que venda: fora da rampa. Cor chapada e o sinal no número. */
.cabc-mx td.cabc-neg { background: var(--negative-subtle); color: var(--negative-text); }

/* Mês que ainda não aconteceu: meta visível, atingimento sem cor de direção. */
.cabc-mx td.cabc-futuro { color: var(--ink-4); }

/* Rodapé fixo: Total · Média · % no grupo · % do total precisam ficar
   co-visíveis com o dado. Sem isso, responder "quais são as bitolas A" custa
   descer 600 px, ler 14 percentuais, memorizar os três maiores e voltar.
   Mesmo padrão que a /metas-vendedor/ já usa. */
.cabc-mx tfoot th, .cabc-mx tfoot td { position: sticky; z-index: 2; }
.cabc-mx tfoot tr:nth-child(1) th, .cabc-mx tfoot tr:nth-child(1) td { bottom: 5.4rem; }
.cabc-mx tfoot tr:nth-child(2) th, .cabc-mx tfoot tr:nth-child(2) td { bottom: 3.6rem; }
.cabc-mx tfoot tr:nth-child(3) th, .cabc-mx tfoot tr:nth-child(3) td { bottom: 1.8rem; }
.cabc-mx tfoot tr:nth-child(4) th, .cabc-mx tfoot tr:nth-child(4) td { bottom: 0; }
.cabc-mx tfoot th.cabc-mes { z-index: 4; }

/* ==========================================================================
   CRM · PEDIDOS (`[data-pagina="crm-pedidos"]`)
   Fora do FCDS por decisão do dono (02/09/2026): linguagem própria, moderna
   e minimalista. Tudo escopado no seletor da página — nenhum token global,
   nenhum vazamento nas outras ~28 telas. Uma cor semântica só (alerta);
   "despachado" não ganha cor, ganha o ponto preenchido do trilho.

   A GRADE daqui (folha, chips, tabela, seta, filtros de coluna, vazio,
   rodapé, ponto de estágio) vale também para `/reportes/`, que usa o mesmo
   `crm/js/grade.js` desde o reporte #27 (15/09/2026): o dono tomou esta lista
   como a canônica. `:is()` pesa o mesmo que o seletor sozinho, então nada
   muda na cascata do Pedidos; dossiê, busca e colunas próprias ficam só aqui.
   ========================================================================== */
:is([data-pagina="crm-pedidos"], [data-pagina="reportes"]) {
  /* Paleta PRÓPRIA desta tela (decisão do dono, 03/09/2026: liberdade total
     com cor, sem reusar token nem elemento do FCDS). Nomes próprios de
     propósito — nada aqui deve ser confundido com os tokens globais, e nada
     daqui vaza: tudo vive sob este seletor.

     A cor não é enfeite: a rampa petróleo→verde acompanha a JORNADA do
     pedido, então a cor diz "quão longe isso foi" em vez de rotular
     categorias sem ordem. Âmbar e vermelho ficam para o que sai da jornada
     (travado, cancelado) e para o prazo vencido. */
  --pedido-papel: #ffffff;
  --pedido-papel-2: #f5f7f8;
  --pedido-tinta: #0d1117;
  --pedido-tinta-2: #59626e;
  --pedido-fio: #e3e6ea;
  --pedido-fio-forte: #b9c1ca;
  --pedido-petroleo: #0b5c66;
  --pedido-petroleo-2: #cfe3e5;
  --pedido-verde: #1c7a52;
  --pedido-ambar: #8a5a00;
  --pedido-vermelho: #a4241c;
  background: var(--pedido-papel);
  color: var(--pedido-tinta);
  /* A folha ocupa a janela inteira e SANGRA para fora do recuo do `.content`,
     em cima e embaixo. Sem isto sobrava o cinza do shell (`--bg`) nas duas
     pontas — duas cores de fundo na mesma tela, com costura no meio. Só na
     VERTICAL: sangrar na horizontal também joga a folha para baixo da barra
     lateral (medido: começava em 28px, e a lateral ocupa 48).
     As margens negativas usam as MESMAS variáveis do recuo que
     estão anulando, e o respiro interno volta como padding: assim o dia em
     que o shell mudar o recuo, isto acompanha sozinho, em vez de descolar. */
  margin: calc(var(--content-pad-y) * -1) 0 calc(var(--content-pad-b) * -1);
  padding: var(--content-pad-y) 0 var(--content-pad-b);
  min-height: calc(100vh - 52px);
  box-sizing: border-box;
}
/* Ponte: as regras desta seção nasceram com os nomes `--pd-*`. A paleta nova
   é a única fonte; estes cinco apenas apontam para ela, para não haver dois
   valores de verdade enquanto os seletores antigos existirem. */
:is([data-pagina="crm-pedidos"], [data-pagina="reportes"]) {
  --pd-tinta: var(--pedido-tinta);
  --pd-secundario: var(--pedido-tinta-2);
  --pd-fio: var(--pedido-fio);
  --pd-fundo: var(--pedido-papel);
  --pd-alerta: var(--pedido-vermelho);
}

/* Sem título aqui: a topbar já diz "Pedidos". Só o resumo, à direita. */
[data-pagina="crm-pedidos"] .pd-resumo {
  color: var(--pd-secundario); font-variant-numeric: tabular-nums;
}
/* O Bootstrap dá `width: 100%` a `.form-select`/`.form-control` — dentro de
   um flex container isso vira o próprio flex-basis, e cada select tenta
   tomar a LINHA INTEIRA (era o que empurrava "Todas as UF" de ponta a
   ponta). Largura pelo conteúdo: cada controle do lado do vendedor. */
[data-pagina="crm-pedidos"] .pd-periodo { display: flex; align-items: center; gap: .5rem; }
[data-pagina="crm-pedidos"] .pd-periodo #pd-periodo-livre { display: flex; gap: .5rem; }
/* O grid, em `table-layout: auto`: cada coluna toma só o que o conteúdo
   pede — os `width` abaixo são pistas mínimas para nº/uf/datas/valor, não
   uma partilha forçada de 100% (era o que abria o vão entre cliente e uf:
   `fixed` + `width:100%` estica a coluna sem largura própria para
   preencher a sobra, mesmo com nome curto). Sem `width:100%` na tabela: ela
   lê como uma linha só, não uma grade esticada até a borda. */
/* Piso e teto por coluna. Sem piso, a lista vazia esmaga tudo contra a borda
   (medido: Nº com 23px, SAIR ATÉ com 31px); sem teto, o cliente engolia
   metade da tela (1.102px) e o representante 346px. Os números saem da
   largura real do conteúdo — data cabe em 5,5rem, UF em 2,5rem. */
[data-pagina="crm-pedidos"] .pd-col-numero { min-width: 4.5rem; }
[data-pagina="crm-pedidos"] .pd-col-cliente { min-width: 12rem; }
[data-pagina="crm-pedidos"] .pd-col-uf { min-width: 3rem; }
[data-pagina="crm-pedidos"] .pd-col-estagio { min-width: 8rem; }
[data-pagina="crm-pedidos"] .pd-col-data { min-width: 6rem; }
[data-pagina="crm-pedidos"] .pd-col-nf { min-width: 5rem; }
[data-pagina="crm-pedidos"] .pd-col-valor { min-width: 7rem; }
[data-pagina="crm-pedidos"] .pd-col-representante { min-width: 8rem; max-width: 12rem; }
/* A seta de ordenação aparece SEMPRE: apagada na coluna inativa (diz "dá para
   ordenar por aqui"), cheia e em petróleo na ativa (diz "está ordenado por
   aqui, neste sentido"). Afordância que só aparece depois de usada não é
   afordância. */
[data-pagina="crm-pedidos"] .pd-col-numero { width: 4.5rem; font-variant-numeric: tabular-nums; }
[data-pagina="crm-pedidos"] .pd-col-uf { width: 2.75rem; }
[data-pagina="crm-pedidos"] .pd-col-estagio { width: 7rem; }
[data-pagina="crm-pedidos"] .pd-col-data { width: 5.5rem; font-variant-numeric: tabular-nums; }
[data-pagina="crm-pedidos"] .pd-col-nf { width: 4rem; }
[data-pagina="crm-pedidos"] .pd-col-representante { width: 10rem; }
[data-pagina="crm-pedidos"] .pd-col-valor {
  width: 7rem; text-align: right; font-variant-numeric: tabular-nums;
}
/* Teto, não largura fixa: nome curto fica curto (a linha "lê como uma linha
   só"), nome comprido trunca no `ellipsis` do `td` — nunca abre a coluna até
   empurrar as vizinhas para longe. */
[data-pagina="crm-pedidos"] .pd-col-cliente { font-weight: 600; max-width: 16rem; }
[data-pagina="crm-pedidos"] .pd-alerta { color: var(--pd-alerta); font-weight: 600; }

/* As seis colunas que vieram da /pedidos/ quando ela foi absorvida
   (10/09/2026). Mesma régua das outras: piso pela largura real do conteúdo,
   teto onde o texto do ERP é longo (descrição de transação e de condição de
   pagamento passam de 30 caracteres). */
[data-pagina="crm-pedidos"] .pd-col-codigo {
  width: 4.5rem; color: var(--pd-secundario); font-variant-numeric: tabular-nums;
}
[data-pagina="crm-pedidos"] .pd-col-segmento { max-width: 7rem; }
[data-pagina="crm-pedidos"] .pd-col-situacao { max-width: 8rem; }
[data-pagina="crm-pedidos"] .pd-col-transacao { max-width: 10rem; }
[data-pagina="crm-pedidos"] .pd-col-pagamento { max-width: 7rem; }
[data-pagina="crm-pedidos"] .pd-col-itens {
  width: 3.5rem; text-align: right; font-variant-numeric: tabular-nums;
}
/* Os dias de atraso ao lado da previsão — o badge que a /pedidos/ desenhava,
   agora com o número que o serviço calcula. */
[data-pagina="crm-pedidos"] .pd-atraso {
  color: var(--pd-alerta); font-weight: 600; font-variant-numeric: tabular-nums;
}
/* O dossiê (ADENDO item 6, 03/09/2026): mesma gramática do resto da tela —
   sem cartão, sem sombra, sem raio, sem ícone colorido por trilha. O trilho
   é a única peça gráfica; o resto é texto e um traço embaixo do link. */
/* O canvas usa a janela: eram 32rem (512 px) numa tela de 1440, com o pedido
   inteiro empilhado numa coluna só e faixa de branco à direita. Duas colunas
   ASSIMÉTRICAS (pedido do dono, 03/09/2026), porque as duas metades têm pesos
   diferentes: à esquerda a identidade do pedido, de tamanho previsível; à
   direita o que cresce sem limite — uma NOTA por bloco. */
/* Mais largo desde 03/09/2026: com as regiões ganhando superfície e
   respiro, 70rem espremia a coluna da identidade a ponto de "Four Importacao
   e Distribuicao Ltda" quebrar em duas linhas e a linha do tempo ler quatro
   palavras por linha. */
[data-pagina="crm-pedidos"] .pd-canvas { width: min(84rem, 96vw); }
[data-pagina="crm-pedidos"] .pd-dossie {
  display: grid; grid-template-columns: 1fr; gap: 1.5rem; align-items: start;
}
@media (min-width: 62rem) {
  [data-pagina="crm-pedidos"] .pd-dossie { grid-template-columns: 25rem 1fr; }
}
[data-pagina="crm-pedidos"] .pd-dossie__coluna { min-width: 0; }
[data-pagina="crm-pedidos"] .pd-canvas__cabecalho { border-bottom: 1px solid var(--pd-fio); }
/* `PEDIDO 21135 — CLIENTE` na barra de título (pedido do dono, 03/09/2026):
   o nome do cliente subiu da capa para cá. Caixa alta por `text-transform`,
   nunca reescrevendo o texto no JS — o dado segue legível para quem copia. */
[data-pagina="crm-pedidos"] .pd-canvas__titulo {
  font-size: 1.5rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .01em; line-height: 1.2; min-width: 0;
}
/* AS DUAS AÇÕES DO CABEÇALHO SÃO BOTÕES, com a mesma forma. Antes "Baixar
   tudo" era um <button> sem moldura ao lado de "Imprimir", que é um link
   sublinhado: duas coisas clicáveis, dois desenhos, e nenhuma parecia botão.
   Uma família de botão por tela, contornada em vez de preenchida — cinza
   cheio, nesta casa, lê como desabilitado. */
/* `.pd-doc` (a classe de link de documento) vem depois neste arquivo e
   sublinha; por isso os dois seletores citam as DUAS classes — sem isso o
   botão sai com o texto sublinhado dentro da moldura. */
[data-pagina="crm-pedidos"] .pd-doc.pd-canvas__enviar,
[data-pagina="crm-pedidos"] .pd-doc.pd-canvas__baixar,
[data-pagina="crm-pedidos"] .pd-doc.pd-canvas__reportar,
[data-pagina="crm-pedidos"] .pd-doc.pd-canvas__imprimir {
  display: inline-flex; align-items: center; min-height: 2.25rem;
  padding: 0 .85rem; border: 1px solid var(--pedido-fio-forte);
  border-radius: var(--r, .5rem); background: var(--surf);
  color: var(--pedido-tinta); font-size: .8125rem; font-weight: 600;
  white-space: nowrap; text-decoration: none; cursor: pointer;
}
[data-pagina="crm-pedidos"] .pd-doc.pd-canvas__enviar:hover,
[data-pagina="crm-pedidos"] .pd-doc.pd-canvas__baixar:hover,
[data-pagina="crm-pedidos"] .pd-doc.pd-canvas__imprimir:hover {
  border-color: var(--pedido-petroleo); color: var(--pedido-petroleo);
}
/* Reportar no cabeçalho do dossiê: o mesmo vermelho cheio do botão da barra
   (decisão do dono), para ser reconhecido como a MESMA ação. Tem de vir DEPOIS
   da regra compartilhada acima: mesma especificidade, e a que vem depois vence —
   antes dela, a cor e a borda eram sobrescritas e o botão saía igual ao Imprimir. */
[data-pagina="crm-pedidos"] .pd-doc.pd-canvas__reportar {
  background: var(--negative-text); border-color: var(--negative-text); color: #fff;
}
[data-pagina="crm-pedidos"] .pd-doc.pd-canvas__reportar:hover {
  background: var(--negative); border-color: var(--negative); color: #fff;
}
[data-pagina="crm-pedidos"] .pd-canvas__reportar:focus-visible {
  outline: 2px solid var(--negative-text); outline-offset: 2px;
}
[data-pagina="crm-pedidos"] .pd-canvas__baixar:focus-visible,
[data-pagina="crm-pedidos"] .pd-canvas__imprimir:focus-visible {
  outline: 2px solid var(--pedido-petroleo); outline-offset: 2px;
}
[data-pagina="crm-pedidos"] .pd-canvas__baixar[disabled] { opacity: .5; cursor: progress; }
/* No dedo, 36px é alvo pequeno demais. O piso de 44px vale para quem aponta
   com o dedo, não para quem tem mouse — no desktop o botão maior só rouba
   altura do cabeçalho. */
@media (pointer: coarse) {
  [data-pagina="crm-pedidos"] .pd-doc.pd-canvas__baixar,
  [data-pagina="crm-pedidos"] .pd-doc.pd-canvas__imprimir { min-height: 2.75rem; }
}
/* `margin-left: auto` empurra o primeiro dos dois para a direita; quando o
   botão do pacote não existe (pedido sem certificado), quem empurra é o
   Imprimir. Sem isso o Imprimir grudaria no título nos pedidos com pacote. */
/* O PRIMEIRO botão visível é quem empurra o grupo para a direita — quais
   existem varia por pedido (sem certificado não há "Baixar tudo"; sem
   documento não há "Enviar"). Cada um pede `margin-left: auto` e os
   seguintes ficam com o espaço fixo, então qualquer combinação alinha. */
[data-pagina="crm-pedidos"] .pd-canvas__enviar { margin-left: auto; }
[data-pagina="crm-pedidos"] .pd-canvas__baixar { margin-left: auto; }
[data-pagina="crm-pedidos"] .pd-canvas__enviar:not([hidden]) ~ .pd-canvas__baixar,
[data-pagina="crm-pedidos"] .pd-canvas__enviar:not([hidden]) ~ .pd-canvas__imprimir,
[data-pagina="crm-pedidos"] .pd-canvas__baixar:not([hidden]) ~ .pd-canvas__imprimir {
  margin-left: .5rem;
}
[data-pagina="crm-pedidos"] .pd-canvas__baixar:not([hidden]) ~ .pd-canvas__imprimir {
  margin-left: .5rem;
}
[data-pagina="crm-pedidos"] .pd-canvas__imprimir { margin-left: auto; margin-right: .75rem; }
/* NO TELEFONE O CABEÇALHO QUEBRA (medido a 390x844, pedido 20921 com os três
   botões): a linha não quebrava, o `<h2>` colapsava a zero pelo `min-width: 0`
   do desktop e os botões, `white-space: nowrap`, eram desenhados POR CIMA do
   título — 263px de cabeçalho, 31% da tela, com o nome do cliente ilegível
   debaixo do "Baixar tudo". Mesmo princípio do `#hst-voltar` do canvas de
   histórico: o botão é controle de tamanho fixo, quem quebra é o nome do
   cliente. Aqui o nome ganha a primeira linha inteira e os botões a segunda;
   os `margin-left: auto` são do desktop, onde tudo cabe numa linha só, e
   empurrariam cada botão para uma linha própria depois da quebra. */
@media (max-width: 575.98px) {
  [data-pagina="crm-pedidos"] .pd-canvas__cabecalho { flex-wrap: wrap; }
  /* O nome do pedido toma a primeira linha inteira; os controles vêm abaixo,
     na mesma ordem do desktop (enviar, baixar, imprimir, fechar). Tentei pôr o
     `×` ao lado do título: a 1,5rem em versal o nome sozinho já ocupa as duas
     linhas do cabeçalho, e o `×` acabava solto à esquerda, debaixo dele. */
  [data-pagina="crm-pedidos"] .pd-canvas__titulo { flex: 1 1 100%; }
  [data-pagina="crm-pedidos"] .pd-canvas__enviar,
  [data-pagina="crm-pedidos"] .pd-canvas__baixar,
  [data-pagina="crm-pedidos"] .pd-canvas__imprimir { margin-left: 0; }
}
/* O PAINEL DE ENVIO: mesma superfície branca das outras regiões, aberto
   dentro do dossiê — o canvas já é um painel sobre a lista, e um modal por
   cima seria a terceira camada. Duas colunas: à esquerda o que vai, à
   direita para quem e o que se escreve. */
[data-pagina="crm-pedidos"] .pd-envio {
  background: var(--surf); border: 1px solid var(--pedido-fio);
  border-radius: var(--r, .5rem); padding: 1.25rem 1.5rem; margin-bottom: 1.25rem;
}
[data-pagina="crm-pedidos"] .pd-envio__capa {
  display: flex; align-items: baseline; gap: 1rem;
  padding-bottom: .75rem; margin-bottom: 1rem;
  border-bottom: 1px solid var(--pedido-fio);
}
[data-pagina="crm-pedidos"] .pd-envio__capa .pd-canvas__titulo-secao { margin: 0; }
[data-pagina="crm-pedidos"] .pd-envio__fechar { margin-left: auto; }
[data-pagina="crm-pedidos"] .pd-envio__corpo {
  display: grid; grid-template-columns: 1fr; gap: 1.5rem;
}
@media (min-width: 52rem) {
  [data-pagina="crm-pedidos"] .pd-envio__corpo { grid-template-columns: 1fr 1fr; }
}
[data-pagina="crm-pedidos"] .pd-envio__grupo {
  font-size: .75rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .04em; color: var(--pd-secundario); margin: 1rem 0 .35rem;
}
[data-pagina="crm-pedidos"] .pd-envio__grupo:first-child { margin-top: 0; }
/* A linha inteira é o alvo do clique, não só a caixinha de 13px. */
[data-pagina="crm-pedidos"] .pd-envio__item {
  display: flex; align-items: center; gap: .6rem; min-height: 2.25rem;
  padding: .15rem .35rem; border-radius: .25rem; cursor: pointer;
  font-size: .875rem;
}
[data-pagina="crm-pedidos"] .pd-envio__item:hover { background: var(--surf-2); }
[data-pagina="crm-pedidos"] .pd-envio__item input { cursor: pointer; }
[data-pagina="crm-pedidos"] .pd-envio__rotulo { color: var(--pedido-tinta); }
[data-pagina="crm-pedidos"] .pd-envio__tamanho {
  margin-left: auto; font-size: .8125rem; color: var(--pd-secundario);
  font-variant-numeric: tabular-nums;
}
/* O estado do preparo mora na mesma coluna do tamanho: é a mesma pergunta
   ("quanto isso pesa, e já está pronto?"), e uma coluna a mais para dizer
   "pronto" seria largura gasta. */
[data-pagina="crm-pedidos"] .pd-envio__tamanho--pronto { color: var(--pedido-petroleo); }
[data-pagina="crm-pedidos"] .pd-envio__tamanho--recusado {
  color: var(--pd-alerta); white-space: normal; text-align: right;
}
/* O painel do pacote não tem a coluna de e-mail. A lista NÃO ocupa a largura
   toda por isso: o tamanho de cada documento é empurrado para a direita por
   `margin-left: auto`, e numa faixa de 1.300px ele acabava a um palmo do
   rótulo. Uma coluna da largura da do e-mail mantém os dois lados juntos. */
[data-pagina="crm-pedidos"] .pd-envio__corpo--pacote {
  grid-template-columns: minmax(0, 34rem);
}
[data-pagina="crm-pedidos"] .pd-envio__corpo--pacote .pd-envio__enviar {
  margin-top: 1rem;
}
[data-pagina="crm-pedidos"] .pd-envio__teto {
  margin: 1rem 0 0; font-size: .8125rem; color: var(--pd-secundario);
}
[data-pagina="crm-pedidos"] .pd-envio__campo {
  display: block; font-size: .75rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .04em; color: var(--pd-secundario); margin-bottom: .9rem;
}
[data-pagina="crm-pedidos"] .pd-envio__campo input,
[data-pagina="crm-pedidos"] .pd-envio__campo textarea {
  display: block; width: 100%; margin-top: .3rem; padding: .45rem .6rem;
  border: 1px solid var(--pedido-fio-forte); border-radius: var(--r, .5rem);
  font: inherit; font-size: .875rem; font-weight: 400; text-transform: none;
  letter-spacing: normal; color: var(--pedido-tinta); background: #fff;
}
[data-pagina="crm-pedidos"] .pd-envio__campo input:focus-visible,
[data-pagina="crm-pedidos"] .pd-envio__campo textarea:focus-visible {
  outline: 2px solid var(--pedido-petroleo); outline-offset: 1px;
}
/* O CAMPO "PARA" É UMA CAIXA DE ETIQUETAS (04/09/2026). O cadastro do cliente
   tem quatro campos de e-mail, cada um com mais de um endereço, e as pessoas
   ligadas a ele são várias — o campo de um endereço só descartava tudo isso.
   Todas nascem postas; tirar é um clique no `×`.

   A caixa imita um campo de texto (borda, raio, fundo branco) e a entrada
   livre mora DENTRO dela, sem borda própria: quem clica em qualquer ponto da
   caixa cai no lugar de digitar. O foco é desenhado na caixa, não na entrada,
   senão o anel apareceria no meio das etiquetas. */
/* A PRÉVIA DA GRADE DE BOLETOS (09/09/2026): o mesmo bloco que o cliente
   recebe, mostrado abaixo da mensagem para quem envia conferir antes. Ele já
   vem com estilo INLINE (é HTML de e-mail, que não enxerga folha de estilo),
   então aqui só se cuida de ele não empurrar a coluna do painel: tabela larga
   rola por dentro. */
[data-pagina="crm-pedidos"] .pd-envio__previa {
  overflow-x: auto; margin-bottom: .9rem;
}
[data-pagina="crm-pedidos"] .pd-envio__legenda { display: block; }
[data-pagina="crm-pedidos"] .pd-envio__tags {
  display: flex; flex-wrap: wrap; align-items: center; gap: .3rem;
  margin-top: .3rem; padding: .3rem .4rem; cursor: text;
  border: 1px solid var(--pedido-fio-forte); border-radius: var(--r, .5rem);
  background: #fff;
}
[data-pagina="crm-pedidos"] .pd-envio__tags:focus-within {
  outline: 2px solid var(--pedido-petroleo); outline-offset: 1px;
}
[data-pagina="crm-pedidos"] .pd-envio__tag {
  display: inline-flex; align-items: center; gap: .1rem;
  max-width: 100%; padding: .1rem .1rem .1rem .45rem;
  border-radius: var(--raio-chip); background: var(--surf-2);
  font-size: .8125rem; font-weight: 400; text-transform: none;
  letter-spacing: normal; color: var(--pedido-tinta);
}
[data-pagina="crm-pedidos"] .pd-envio__tag-texto {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
[data-pagina="crm-pedidos"] .pd-envio__tag-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.25rem; height: 1.25rem; padding: 0; border: 0; border-radius: 50%;
  background: none; color: var(--pd-secundario); font-size: 1rem; line-height: 1;
  cursor: pointer;
}
[data-pagina="crm-pedidos"] .pd-envio__tag-x:hover {
  background: var(--pedido-fio); color: var(--pedido-tinta);
}
/* A entrada livre não tem moldura: a moldura é a caixa. `min-width` para ela
   não sumir quando as etiquetas ocupam a linha, e `flex: 1` para tomar o
   resto da última linha — é ali que se digita o endereço que falta. */
[data-pagina="crm-pedidos"] .pd-envio__campo .pd-envio__entrada {
  flex: 1; min-width: 9rem; width: auto; margin: 0; padding: .15rem .2rem;
  border: 0; background: none;
}
[data-pagina="crm-pedidos"] .pd-envio__campo .pd-envio__entrada:focus-visible {
  outline: none;
}
[data-pagina="crm-pedidos"] .pd-envio__remetente {
  font-size: .8125rem; color: var(--pd-secundario); margin: 0 0 .5rem;
}
/* A assinatura aparece ANTES do envio: é ela que fecha o e-mail, e é aqui
   que se descobre que falta o telefone. Mesma decisão da tela de proposta. */
[data-pagina="crm-pedidos"] .pd-envio__assinatura {
  font-size: .8125rem; color: var(--pd-secundario);
  padding: .6rem .75rem; background: var(--surf-2);
  border-radius: var(--r, .5rem); margin-bottom: 1rem;
}
/* Os dois botões do painel citam `.pd-doc` no seletor pelo mesmo motivo dos
   do cabeçalho: aquela classe vem depois no arquivo e sublinha. */
[data-pagina="crm-pedidos"] .pd-doc.pd-envio__enviar,
[data-pagina="crm-pedidos"] .pd-doc.pd-envio__fechar {
  display: inline-flex; align-items: center; min-height: 2.25rem;
  padding: 0 .85rem; border: 1px solid var(--pedido-fio-forte);
  border-radius: var(--r, .5rem); background: var(--surf);
  color: var(--pedido-tinta); font-size: .8125rem; font-weight: 600;
  white-space: nowrap; text-decoration: none; cursor: pointer;
}
[data-pagina="crm-pedidos"] .pd-doc.pd-envio__enviar {
  border-color: var(--pedido-petroleo); color: var(--pedido-petroleo);
}
[data-pagina="crm-pedidos"] .pd-envio__enviar[disabled] { opacity: .5; cursor: progress; }
@media (pointer: coarse) {
  [data-pagina="crm-pedidos"] .pd-doc.pd-envio__enviar,
  [data-pagina="crm-pedidos"] .pd-doc.pd-envio__fechar { min-height: 2.75rem; }
}

/* A BARRA DO PACOTE: um fio que enche, não um cartão. Só aparece durante o
   download — o resto do tempo a tela não tem por que falar do assunto. */
[data-pagina="crm-pedidos"] .pd-baixar {
  display: flex; align-items: center; gap: .75rem; margin-bottom: 1.25rem;
}
[data-pagina="crm-pedidos"] .pd-baixar__trilho {
  flex: 1; height: 4px; border-radius: 2px; overflow: hidden;
  background: var(--pedido-fio);
}
[data-pagina="crm-pedidos"] .pd-baixar__feito {
  display: block; height: 100%; width: 0; background: var(--pedido-petroleo);
  transition: width .18s linear;
}
/* Enquanto o servidor monta o ZIP não há porcentagem que não seja invenção:
   a barra corre em vaivém para dizer "estou trabalhando", e só passa a
   medir quando os bytes começam a chegar. Quem pediu menos movimento na
   tela não vê o vaivém — vê o fio parado e o texto. */
[data-pagina="crm-pedidos"] .pd-baixar--indefinida .pd-baixar__feito {
  width: 35%; animation: pd-baixar-vaivem 1.1s ease-in-out infinite;
}
@keyframes pd-baixar-vaivem {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(285%); }
}
@media (prefers-reduced-motion: reduce) {
  [data-pagina="crm-pedidos"] .pd-baixar--indefinida .pd-baixar__feito {
    animation: none; width: 100%; opacity: .4;
  }
  [data-pagina="crm-pedidos"] .pd-baixar__feito { transition: none; }
}
/* O texto vem ANTES da barra: a frase é o que importa ("Emitindo o boleto
   27916-02 no Senior…", ou a recusa do ERP por extenso), e à direita ela era
   empurrada contra a borda e cortada. */
[data-pagina="crm-pedidos"] .pd-baixar__texto {
  font-size: .8125rem; color: var(--pedido-tinta); font-weight: 500;
  flex: 0 1 auto; min-width: 0;
}
[data-pagina="crm-pedidos"] .pd-canvas__capa {
  padding-bottom: 1rem; margin-bottom: 1rem; border-bottom: 1px solid var(--pd-fio);
}
[data-pagina="crm-pedidos"] .pd-canvas__cliente { font-weight: 600; margin: 0 0 .5rem; }
[data-pagina="crm-pedidos"] .pd-canvas__linha {
  display: flex; flex-wrap: wrap; gap: .1rem .75rem;
  color: var(--pd-secundario); font-size: .875rem;
}
[data-pagina="crm-pedidos"] .pd-canvas__bloqueio {
  color: var(--pd-alerta); font-weight: 600; margin: .5rem 0 0; font-size: .875rem;
}
/* O deslocamento (Task 11): editável na própria capa, mesma linha do "sair
   até" que ele recalcula — sem tela de configuração à parte. */
[data-pagina="crm-pedidos"] .pd-deslocamento { display: inline-flex; align-items: center; gap: .3rem; }
[data-pagina="crm-pedidos"] .pd-deslocamento__input {
  width: 3.5rem; padding: .1rem .3rem; border: 1px solid var(--pd-fio); border-radius: .25rem;
  font-size: .875rem; font-variant-numeric: tabular-nums; color: inherit; background: #fff;
}
[data-pagina="crm-pedidos"] .pd-deslocamento__input:disabled { opacity: .6; }
[data-pagina="crm-pedidos"] .pd-deslocamento__erro {
  color: var(--pd-alerta); font-size: .8125rem; margin: .5rem 0 0;
}
/* A previsão (Task 12): mesma capa, mesma gramática do deslocamento —
   editável onde é lida, confirmação antes de gravar porque esta grava no
   Senior. */
[data-pagina="crm-pedidos"] .pd-previsao { display: inline-flex; align-items: center; gap: .3rem; }
[data-pagina="crm-pedidos"] .pd-previsao__input {
  padding: .1rem .3rem; border: 1px solid var(--pd-fio); border-radius: .25rem;
  font-size: .875rem; font-variant-numeric: tabular-nums; color: inherit; background: #fff;
}
[data-pagina="crm-pedidos"] .pd-previsao__input:disabled { opacity: .6; }
[data-pagina="crm-pedidos"] .pd-previsao__erro {
  color: var(--pd-alerta); font-size: .8125rem; margin: .5rem 0 0;
}
[data-pagina="crm-pedidos"] .pd-canvas__secao { margin-bottom: 2rem; }
/* Todo título em caixa alta (pedido do dono, 03/09/2026), pelo CSS. */
[data-pagina="crm-pedidos"] .pd-canvas__titulo-secao {
  font-size: .8125rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .04em; color: var(--pd-secundario); margin: 0 0 .75rem;
}
/* Um bloco por NOTA: régua e espaço, não cartão com sombra — são muitos numa
   tela só, e caixa repetida achataria a diferença entre "identidade do
   pedido" (à esquerda) e "o que cada nota levou" (aqui). */
[data-pagina="crm-pedidos"] .pd-nota__titulo {
  font-size: .9375rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .03em; margin: 0; color: var(--pedido-tinta);
}
[data-pagina="crm-pedidos"] .pd-nota__meta {
  font-size: .8125rem; color: var(--pd-secundario);
  font-variant-numeric: tabular-nums;
}
[data-pagina="crm-pedidos"] .pd-nota__capa {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: .25rem .75rem;
  padding-bottom: .6rem; margin-bottom: .85rem;
  border-bottom: 1px solid var(--pd-fio);
}
/* REGIÕES, não uma folha corrida (reclamação do dono, 03/09/2026: "sem
   separações lógicas, layout pobre"). O corpo do canvas passou a ser o CHÃO
   cinza do app (`--surf-app`, o mesmo das outras telas) e cada região é uma
   superfície branca sobre ele: a cabeça, a coluna da identidade, cada nota.
   O olho separa por superfície, que é instantâneo, em vez de por fio fino,
   que exige procurar. Nenhuma superfície mora dentro de outra. */
[data-pagina="crm-pedidos"] .pd-canvas__corpo { background: var(--surf-app); }
[data-pagina="crm-pedidos"] .pd-dossie-resumo {
  background: var(--surf); border: 1px solid var(--pd-fio);
  border-radius: var(--r, .5rem); padding: 1.25rem 1.5rem;
  margin-bottom: 1.25rem;
}
[data-pagina="crm-pedidos"] .pd-dossie-resumo:empty { display: none; padding: 0; border: 0; }
[data-pagina="crm-pedidos"] .pd-cifras {
  display: flex; flex-wrap: wrap; gap: 1rem 3.5rem;
}
/* A FRASE que explica o estado, embaixo das cifras: as três dizem QUANTO, e
   ela diz EM QUE PÉ — a parte que o dono pediu explicada. Vem pronta do
   serviço. */
[data-pagina="crm-pedidos"] .pd-situacao {
  margin: .9rem 0 0; padding-top: .9rem; border-top: 1px solid var(--pd-fio);
  font-size: .875rem; color: var(--pd-secundario);
}
[data-pagina="crm-pedidos"] .pd-situacao--integral { color: var(--pedido-petroleo); }
[data-pagina="crm-pedidos"] .pd-cifra { display: flex; flex-direction: column; gap: .15rem; }
[data-pagina="crm-pedidos"] .pd-cifra__valor {
  font-size: 1.75rem; font-weight: 600; line-height: 1.1;
  letter-spacing: -.015em; font-variant-numeric: tabular-nums;
  color: var(--pedido-tinta);
}
[data-pagina="crm-pedidos"] .pd-cifra__rotulo {
  font-size: .75rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .04em; color: var(--pd-secundario);
}
/* Faturado por inteiro é a única boa notícia da cabeça, e leva o petróleo —
   o mesmo acento do ponto cumprido na jornada. Parcial fica em tinta comum
   (é o estado normal de um pedido vivo, não um alerta) e "nada faturado"
   recua para o secundário: não há o que comemorar nem o que corrigir. */
[data-pagina="crm-pedidos"] .pd-cifra--integral .pd-cifra__valor,
[data-pagina="crm-pedidos"] .pd-cifra--integral .pd-cifra__rotulo {
  color: var(--pedido-petroleo);
}
[data-pagina="crm-pedidos"] .pd-cifra--nenhum .pd-cifra__valor { color: var(--pd-secundario); }
[data-pagina="crm-pedidos"] .pd-nota__capa .pd-doc { margin-left: auto; }
/* Com DOIS downloads no cabeçalho (DANFE e XML), o `auto` só vale para o
   primeiro: no segundo ele abriria uma segunda vala e jogaria os dois para
   os cantos opostos. O segundo anda colado, a um respiro do primeiro. */
[data-pagina="crm-pedidos"] .pd-nota__capa .pd-doc + .pd-doc {
  margin-left: 1.1rem;
}
/* A DANFE é um DOWNLOAD, e download nesta tela é petróleo — a mesma cor e
   o mesmo peso do link de certificado dentro da grade
   (`.pd-docs-grade .pd-doc`, mais abaixo). Ela ficava em tinta comum só
   porque mora no cabeçalho da nota, FORA da grade, e caía na regra base do
   `.pd-doc` (defeito que o dono viu em 04/09/2026). O seletor cita `a`, e
   não a classe, para não pintar o `<span>` de nota sem DANFE: ausência
   continua cinza. */
[data-pagina="crm-pedidos"] .pd-nota__capa a.pd-doc {
  color: var(--pedido-petroleo); font-weight: 600;
}
/* O espaçamento e a superfície da nota moram no bloco "Notas e boletos",
   mais abaixo neste arquivo — é o que vence por ordem, e ter as duas metades
   em lugares diferentes foi o que fez a versão anterior se anular sozinha. */
/* O boleto é consequência da nota, não irmão do item: mesma grade, um
   degrau abaixo no peso e bem separada da lista de itens. O seletor tem de
   citar `.pd-rolagem` porque a grade de itens passou a morar dentro da caixa
   de rolagem — sem isso o `+` não alcança mais a grade de boletos, que é
   irmã da CAIXA, não da tabela. */
[data-pagina="crm-pedidos"] .pd-nota .pd-rolagem + .pd-docs-grade {
  margin-top: 1.75rem; font-size: .8125rem;
}
/* O certificado é uma PILHA de links, um por arquivo — o lote costuma ter
   mais de um papel, e enfileirá-los na horizontal estouraria a coluna. Nome
   longo corta com reticências; o nome inteiro e o tamanho ficam no `title`. */
[data-pagina="crm-pedidos"] .pd-cel-certificado {
  color: var(--pd-secundario); white-space: nowrap;
  max-width: 14rem;
}
[data-pagina="crm-pedidos"] .pd-doc--arquivo {
  display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis;
  font-weight: 500;
}
[data-pagina="crm-pedidos"] .pd-doc--arquivo + .pd-doc--arquivo { margin-top: .2rem; }
[data-pagina="crm-pedidos"] .pd-docs-grade thead th { text-transform: uppercase; }
[data-pagina="crm-pedidos"] .pd-canvas__vazio { color: var(--pd-secundario); font-size: .875rem; }

/* Os quatro blocos recolhíveis (itens/notas/títulos/certificados): `<details>`
   nativo, sem JS para abrir/fechar — o navegador já faz. */
[data-pagina="crm-pedidos"] .pd-bloco > summary { cursor: pointer; }
[data-pagina="crm-pedidos"] .pd-item-lista { list-style: none; padding: 0; margin: .5rem 0 0; }
[data-pagina="crm-pedidos"] .pd-item-linha {
  display: grid; grid-template-columns: 1fr auto auto; gap: .75rem;
  padding: .35rem 0; border-bottom: 1px solid var(--pd-fio); font-size: .875rem;
}
[data-pagina="crm-pedidos"] .pd-item-linha__quantidade,
[data-pagina="crm-pedidos"] .pd-item-linha__valor {
  color: var(--pd-secundario); text-align: right; white-space: nowrap;
}

/* O trilho: uma linha de pontos ligados por um filete de 1px. Vazio =
   contorno (`inset 0 0 0 1px`); cumprido = preenchido. Nada de cor por
   trilha — só a tinta principal, cumprido ou não. */
[data-pagina="crm-pedidos"] .pd-trilho { list-style: none; display: flex; padding: 0; margin: 0; }
[data-pagina="crm-pedidos"] .pd-parada {
  flex: 1; position: relative; padding-top: 1.25rem; font-size: .8125rem;
}
[data-pagina="crm-pedidos"] .pd-parada:not(:first-child)::before {
  content: ''; position: absolute; top: .3rem; left: -50%; width: 100%;
  height: 1px; background: var(--pd-fio);
}
[data-pagina="crm-pedidos"] .pd-ponto {
  position: absolute; top: 0; left: 0; width: 8px; height: 8px; border-radius: 50%;
  background: var(--pd-fundo); box-shadow: inset 0 0 0 1px var(--pd-fio);
}
[data-pagina="crm-pedidos"] .pd-parada--feita .pd-ponto {
  background: var(--pd-tinta); box-shadow: none;
}
[data-pagina="crm-pedidos"] .pd-parada__rotulo { display: block; font-weight: 600; }
[data-pagina="crm-pedidos"] .pd-parada__data,
[data-pagina="crm-pedidos"] .pd-parada__autor { display: block; color: var(--pd-secundario); }

/* O extrato: grid de três colunas, sem caixa nem ícone. */
[data-pagina="crm-pedidos"] .pd-extrato { list-style: none; padding: 0; margin: 0; }
[data-pagina="crm-pedidos"] .pd-evento {
  display: grid; grid-template-columns: auto 1fr auto; gap: .25rem .75rem;
  padding: .7rem 0; border-bottom: 1px solid var(--pd-fio); font-size: .875rem;
}
[data-pagina="crm-pedidos"] .pd-evento__quando {
  color: var(--pd-secundario); font-variant-numeric: tabular-nums; white-space: nowrap;
}
[data-pagina="crm-pedidos"] .pd-evento__autor { color: var(--pd-secundario); text-align: right; }
/* O log do Sênior guarda QUEBRA DE LINHA dentro do texto (`\r` entre
   "Pedido Liberado…", "Usuário de bloqueio:…", "Motivo do bloqueio:…"). O
   HTML engolia as quebras e as quatro frases viravam um parágrafo corrido.
   `pre-line` devolve a quebra e mantém a quebra automática do resto. */
[data-pagina="crm-pedidos"] .pd-evento__frase { white-space: pre-line; }

/* CAIXA DE ROLAGEM (pedido do dono, 03/09/2026): linha do tempo e lista de
   itens cresciam sem fim — um pedido de doze itens com histórico longo
   empurrava tudo para fora da janela e obrigava a rolar o dossiê inteiro
   para chegar aos boletos. Agora cada lista tem teto e rola por dentro; o
   teto é a JANELA, não um número fixo, para caber igual num notebook e num
   monitor de pé. O padding à direita reserva o lugar da barra de rolagem —
   sem ele o conteúdo dança quando a lista passa do teto. */
[data-pagina="crm-pedidos"] .pd-rolagem {
  max-height: min(30rem, 48vh); overflow-y: auto; padding-right: .5rem;
  overscroll-behavior: contain;
}
/* Cabeçalho grudado no topo da caixa: rolar cem lotes sem ver "PRODUTO |
   LOTE | QUANTIDADE" é ler número sem rótulo. Fundo opaco porque o cabeçalho
   passa POR CIMA das linhas que rolam. */
[data-pagina="crm-pedidos"] .pd-rolagem .pd-docs-grade thead th {
  position: sticky; top: 0; z-index: 1; background: #fff;
}

/* Documentos: uma LINHA por documento (revisão da Task 4, 03/09/2026 — a
   versão em parágrafo corrido escorria data/valor/motivo numa massa só).
   Link com traço embaixo — sem botão preenchido, sem
   raio. Ausente mostra o MOTIVO por extenso (ADENDO item 5), nunca um link
   morto. */
[data-pagina="crm-pedidos"] .pd-docs { list-style: none; padding: 0; margin: 0; font-size: .875rem; }
[data-pagina="crm-pedidos"] .pd-doc-linha {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem .75rem;
  padding: .35rem 0; border-bottom: 1px solid var(--pd-fio);
}
[data-pagina="crm-pedidos"] .pd-doc {
  color: var(--pd-tinta); text-decoration: underline; text-underline-offset: 2px;
}
[data-pagina="crm-pedidos"] .pd-doc--ausente { color: var(--pd-secundario); text-decoration: none; }
[data-pagina="crm-pedidos"] .pd-doc-linha__meta,
[data-pagina="crm-pedidos"] .pd-doc-linha__motivo { color: var(--pd-secundario); }

/* --------------------------------------------------------------------------
   ABAS · Pedidos | Notas fiscais (10/09/2026)
   Três telas viraram uma; a aba é o que separa os dois índices (pedido por
   numped, nota por empresa+filial+número+série). Mesma pílula dos estágios,
   um degrau acima em peso: é a troca de assunto, não de recorte.
   -------------------------------------------------------------------------- */
[data-pagina="crm-pedidos"] .pd-abas {
  display: flex; gap: .5rem; padding: .25rem 0 .75rem;
}
[data-pagina="crm-pedidos"] .pd-aba {
  background: none; border: 0; border-bottom: 2px solid transparent;
  padding: .25rem .1rem; color: var(--pd-secundario);
  font-size: .9375rem; cursor: pointer;
}
[data-pagina="crm-pedidos"] .pd-aba:hover { color: var(--pd-tinta); }
[data-pagina="crm-pedidos"] .pd-aba--ativa {
  color: var(--pd-tinta); font-weight: 600;
  border-bottom-color: var(--pedido-petroleo);
}

/* A grade de NOTAS reusa a folha, a tabela, o vazio e o rodapé da grade de
   pedidos — o que muda são quatro colunas próprias e o status do título.
   Nada de cartão novo: é a mesma tela. */
[data-pagina="crm-pedidos"] .nt-col-serie,
[data-pagina="crm-pedidos"] .nt-col-codigo { color: var(--pd-secundario); }
[data-pagina="crm-pedidos"] .nt-col-acoes { text-align: right; }
[data-pagina="crm-pedidos"] .nt-abrir {
  color: var(--pd-secundario); font-size: .8125rem;
}
[data-pagina="crm-pedidos"] .grade-linha:hover .nt-abrir { color: var(--pedido-petroleo); }
[data-pagina="crm-pedidos"] .nt-pedido {
  color: var(--pd-tinta); text-decoration: underline; text-underline-offset: 2px;
}
/* Nota sem pedido é a maioria (41% das notas de doze meses) — o rótulo diz o
   que ela é, em vez de deixar a célula vazia parecendo dado faltando. */
[data-pagina="crm-pedidos"] .nt-avulsa {
  color: var(--pd-secundario); font-size: .8125rem;
}
[data-pagina="crm-pedidos"] .nt-status { font-weight: 600; }
[data-pagina="crm-pedidos"] .nt-status--ve { color: var(--pedido-vermelho); }
[data-pagina="crm-pedidos"] .nt-status--ab { color: var(--pedido-ambar); }
[data-pagina="crm-pedidos"] .nt-status--ba { color: var(--pedido-verde); }
[data-pagina="crm-pedidos"] .nt-abertos {
  color: var(--pd-secundario); font-variant-numeric: tabular-nums;
}
[data-pagina="crm-pedidos"] .nt-mais {
  background: none; border: 0; border-bottom: 1px solid var(--pd-fio);
  color: var(--pd-tinta); padding: 0; cursor: pointer;
}

/* O detalhe da nota não tem folha de estilo própria: ele é o canvas do
   pedido (`.pd-canvas` & cia, mais abaixo). As regras do modal antigo saíram
   daqui em 11/09/2026 junto com o modal — estilo de componente que não existe
   é dívida que ninguém cobra e todos leem. */

/* O LINK DENTRO DA FICHA da capa — o pedido de origem da nota, a ponte de
   volta para a outra aba. Tinta do pedido e sublinhado discreto, a mesma
   gramática dos outros links do dossiê. */
[data-pagina="crm-pedidos"] .pd-ficha__link {
  color: var(--pedido-tinta); text-decoration: underline;
  text-underline-offset: 2px;
}
[data-pagina="crm-pedidos"] .pd-ficha__link + .pd-ficha__link { margin-left: .5rem; }


/* ==========================================================================
   CRM · PEDIDOS — segunda passada de desenho (03/09/2026)
   Decisões do dono nesta rodada: rótulo sempre capitalizado; cabeçalho não
   pode pesar menos que o dado; documentos em GRADE, não em texto solto;
   liberdade total com cor; e NADA do FCDS — nem token, nem elemento.
   Por isso os controles de filtro abaixo deixam de ser `.form-select` do
   Bootstrap e passam a ser desenhados aqui.
   ========================================================================== */

/* --- Controles de filtro: sem caixa, sem sombra, sem borda de formulário.
   `appearance:none` tira o widget do sistema; a seta é o chevron do app, em `::after`
   no invólucro, porque `<select>` não aceita pseudo-elemento. --- */
[data-pagina="crm-pedidos"] .pd-seletor { position: relative; display: inline-flex; }
[data-pagina="crm-pedidos"] .pd-seletor::after {
  content: '\f078'; font-family:'Font Awesome 6 Free'; font-weight:900; font-size: .625rem;
  position: absolute; right: .35rem; top: 50%; transform: translateY(-50%);
  color: var(--pedido-tinta-2); pointer-events: none;
}
/* O nome do cliente toma a sobra: o teto de 20rem existia para fechar um vão
   que sumiu quando a tabela deixou de esticar, e o que ele faz hoje é truncar
   nome com espaço livre à direita. */
[data-pagina="crm-pedidos"] .pd-col-cliente { max-width: none; width: 100%; }

/* --- Estágio: UM tom, preenchimento crescente (vazio -> meio -> cheio).
   A primeira versão usava seis matizes na rampa da jornada; o benchmark
   corrige: a convenção (Ant Design, replicada por Retool e Sentry) é no
   máximo cinco cores semânticas e cor SÓ quando o valor é acionável —
   estado normal fica neutro. Então o progresso vira densidade de um mesmo
   petróleo, e a cor fica reservada para exceção: travado, cancelado e
   prazo vencido. --- */
:is([data-pagina="crm-pedidos"], [data-pagina="reportes"]) .pd-estagio-marca {
  display: inline-block; width: .5rem; height: .5rem; border-radius: 50%;
  margin-right: .45rem; vertical-align: baseline;
  box-shadow: inset 0 0 0 1.25px var(--pedido-petroleo); background: transparent;
}
[data-pagina="crm-pedidos"] .pd-e-separado .pd-estagio-marca {
  background: linear-gradient(90deg, var(--pedido-petroleo) 50%, transparent 50%);
}
[data-pagina="crm-pedidos"] .pd-e-faturado_parcial .pd-estagio-marca {
  background: linear-gradient(90deg, var(--pedido-petroleo) 75%, transparent 75%);
}
[data-pagina="crm-pedidos"] .pd-e-faturado .pd-estagio-marca,
[data-pagina="crm-pedidos"] .pd-e-despachado_parcial .pd-estagio-marca,
[data-pagina="crm-pedidos"] .pd-e-despachado .pd-estagio-marca {
  background: var(--pedido-petroleo);
}
/* O despacho é o fim da jornada: ganha o anel externo, não outra cor. */
[data-pagina="crm-pedidos"] .pd-e-despachado .pd-estagio-marca {
  box-shadow: 0 0 0 2px var(--pedido-petroleo-2), inset 0 0 0 1.25px var(--pedido-petroleo);
}
/* Exceção — aqui a cor vale, porque pede ação. */
[data-pagina="crm-pedidos"] .pd-e-bloqueado .pd-estagio-marca {
  background: var(--pedido-ambar); box-shadow: inset 0 0 0 1.25px var(--pedido-ambar);
}
[data-pagina="crm-pedidos"] .pd-e-cancelado .pd-estagio-marca {
  background: var(--pedido-vermelho); box-shadow: inset 0 0 0 1.25px var(--pedido-vermelho);
}
[data-pagina="crm-pedidos"] .pd-e-bloqueado { color: var(--pedido-ambar); }
[data-pagina="crm-pedidos"] .pd-e-cancelado { color: var(--pedido-vermelho); }

/* Os blocos do dossiê são seções abertas, não acordeão — o benchmark é
   unânime: dentro de painel de detalhe, tudo aberto e rolando. */
[data-pagina="crm-pedidos"] .pd-bloco > .pd-canvas__titulo-secao { cursor: default; }

/* --- Documentos em grade (pedido do dono): mesma régua da grade principal —
   cabeçalho capitalizado em tinta, número à direita com `tabular-nums`, e o
   motivo da recusa numa COLUNA, não como frase pendurada embaixo. --- */
[data-pagina="crm-pedidos"] .pd-docs-grade {
  width: 100%; border-collapse: collapse; font-size: .875rem;
}
/* O RESPIRO das grades (pedido do dono, 03/09/2026): a linha apertada fazia
   doze itens lerem como um bloco de texto. O teto de rolagem, acima, é o que
   permite a linha mais alta sem a lista voltar a empurrar a tela. */
[data-pagina="crm-pedidos"] .pd-docs-grade thead th {
  text-align: left; font-weight: 600; font-size: .75rem;
  color: var(--pedido-tinta); padding: 0 .75rem .55rem 0;
  border-bottom: 1px solid var(--pedido-fio-forte);
}
[data-pagina="crm-pedidos"] .pd-docs-grade tbody td {
  padding: .65rem .75rem .65rem 0; border-bottom: 1px solid var(--pedido-fio);
  vertical-align: baseline;
}
/* O nome do DOCUMENTO nunca quebra em duas linhas: "27916-01" partido no
   hífen vira dois documentos aos olhos de quem varre. Vale para o link, não
   para a célula inteira: desde que a grade passou a listar ITENS
   (03/09/2026), a primeira coluna é a descrição do produto — "FOUR - FIO DE
   ACO NAO LIGADO RECOZIDO DUPLO TRANCADO BWG 18" sem quebra empurrava a
   tabela para fora do bloco e cortava a coluna de valor. */
[data-pagina="crm-pedidos"] .pd-docs-grade .pd-doc { white-space: nowrap; }
[data-pagina="crm-pedidos"] .pd-docs-grade { table-layout: auto; }
[data-pagina="crm-pedidos"] .pd-docs-grade tbody td:first-child:not(.pd-cel-codigo),
[data-pagina="crm-pedidos"] .pd-docs-grade tbody td.pd-cel-codigo + td { word-break: break-word; }
/* A FOLGA VAI PARA A PRIMEIRA COLUNA, nas duas grades — é o que faz item e
   boleto ocuparem a mesma largura (pedido do dono, 03/09/2026). Antes a folga
   era da coluna Situação (`width: 99%` nela), e a grade de boletos amontoava
   as quatro colunas na metade esquerda enquanto a de itens ia até a borda:
   dois objetos de larguras diferentes empilhados dentro da mesma nota. */
   Desde 10/09/2026 a grade de itens começa pelo CÓDIGO do produto, e a folga
   não pode ser dele: código é largura fixa. Ela passa para a coluna
   seguinte — a descrição —, endereçada pelo irmão adjacente para a grade de
   boletos (que não tem código) continuar com a folga na primeira. */
[data-pagina="crm-pedidos"] .pd-docs-grade thead th:first-child:not(.pd-cel-codigo),
[data-pagina="crm-pedidos"] .pd-docs-grade tbody td:first-child:not(.pd-cel-codigo),
[data-pagina="crm-pedidos"] .pd-docs-grade thead th.pd-cel-codigo + th,
[data-pagina="crm-pedidos"] .pd-docs-grade tbody td.pd-cel-codigo + td { width: 99%; }
[data-pagina="crm-pedidos"] .pd-doc-cel--data,
[data-pagina="crm-pedidos"] .pd-doc-cel--valor {
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
[data-pagina="crm-pedidos"] .pd-doc-cel--valor { text-align: right; }
[data-pagina="crm-pedidos"] .pd-doc-cel--situacao { color: var(--pedido-tinta-2); }
[data-pagina="crm-pedidos"] .pd-docs-grade .pd-doc { color: var(--pedido-petroleo); font-weight: 600; }
[data-pagina="crm-pedidos"] .pd-docs-grade .pd-doc--ausente {
  color: var(--pedido-tinta-2); font-weight: 400; text-decoration: none;
}

/* --- O trilho da jornada herda a mesma rampa: ponto cumprido em petróleo,
   pendente vazio com o fio por fora. --- */
[data-pagina="crm-pedidos"] .pd-parada--feita .pd-ponto { background: var(--pedido-petroleo); }
[data-pagina="crm-pedidos"] .pd-canvas__titulo-secao { color: var(--pedido-tinta); }

/* A GRADE CABE NA JANELA (pedido do dono, 15/09/2026, vendo a lista inteira
   de 100 pedidos esticar a página): as duas telas usam `content--altura-cheia`,
   e aqui a cadeia fecha até a `.grade`, que faz o resto (barra, cabeçalho e
   rodapé à vista; só as linhas rolam, nos dois eixos).
   A sangria de margem da folha branca sai: sob `altura-cheia` o `.content` já
   não tem recuo vertical para anular, e ela empurraria a tela 16px para baixo
   da topbar. */
.content--altura-cheia > .page:is([data-pagina="crm-pedidos"], [data-pagina="reportes"]) {
  margin: 0; min-height: 0; padding-top: var(--content-pad-y); padding-bottom: 0;
}
.content--altura-cheia > .page[data-pagina="crm-pedidos"] > section {
  flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
}
/* O valor é o que o olho procura numa lista de pedidos. */
[data-pagina="crm-pedidos"] .pd-col-valor { font-weight: 600; }


/* --- A FICHA do dossiê (pedido do dono, 03/09/2026): rótulo em cima, valor
   embaixo, em grade. Antes era uma frase corrida e quem procurava a condição
   de pagamento tinha de ler tudo. Grade que se adapta: quatro colunas em
   painel largo, duas em painel estreito. --- */
[data-pagina="crm-pedidos"] .pd-ficha {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: .75rem 1.25rem; margin: .75rem 0 0; padding: 0;
}
[data-pagina="crm-pedidos"] .pd-ficha__par { margin: 0; }
[data-pagina="crm-pedidos"] .pd-ficha__rotulo {
  font-size: .6875rem; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--pedido-tinta-2); margin: 0 0 .1rem;
}
[data-pagina="crm-pedidos"] .pd-ficha__valor {
  margin: 0; font-size: .9375rem; color: var(--pedido-tinta);
  font-variant-numeric: tabular-nums;
}
[data-pagina="crm-pedidos"] .pd-ficha__valor .pd-alerta { color: var(--pedido-vermelho); font-weight: 600; }

/* --- Notas e boletos: um bloco por NOTA, com os boletos dela dentro. É a
   hierarquia real do ERP (o título nasce da nota), e era o que faltava para
   parar de casar número por número na cabeça. --- */
/* Uma nota é UMA superfície branca sobre o chão cinza. Antes eram blocos
   separados por fio e espaço, e num pedido de três notas as seis grades liam
   como uma lista só — a "falta de separação lógica" que o dono apontou em
   03/09/2026. Agora cada nota tem começo e fim visíveis. */
[data-pagina="crm-pedidos"] .pd-nota {
  background: var(--surf); border: 1px solid var(--pedido-fio);
  border-radius: var(--r, .5rem); padding: 1.25rem 1.5rem;
  margin-bottom: 1.25rem;
}
/* A COLUNA DA IDENTIDADE tem as mesmas duas superfícies: a ficha com a
   jornada, e a linha do tempo. São coisas diferentes — o que o pedido É e o
   que aconteceu com ele — e estavam empilhadas sem nada entre elas. */
[data-pagina="crm-pedidos"] #pd-capa,
[data-pagina="crm-pedidos"] #pd-historico {
  background: var(--surf); border: 1px solid var(--pedido-fio);
  border-radius: var(--r, .5rem); padding: 1.25rem 1.25rem .5rem;
}
[data-pagina="crm-pedidos"] #pd-capa:empty,
[data-pagina="crm-pedidos"] #pd-historico:empty { display: none; }
[data-pagina="crm-pedidos"] #pd-historico { margin-top: 1.25rem; }
/* O boleto NÃO leva fundo próprio (o dono vetou a faixa cinza em
   03/09/2026): dentro de uma nota que já é superfície branca, um segundo
   fundo vira mancha. Ele se distingue por espaço e por corpo menor — a
   regra logo acima —, que é o suficiente para dizer que é consequência da
   nota, não irmão do item. */
[data-pagina="crm-pedidos"] .pd-nota__capa {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; padding-bottom: .4rem;
}
[data-pagina="crm-pedidos"] .pd-nota__numero {
  font-weight: 600; font-variant-numeric: tabular-nums;
}
[data-pagina="crm-pedidos"] .pd-nota .pd-docs-grade { margin-bottom: .35rem; }
[data-pagina="crm-pedidos"] .pd-nota .pd-docs-grade tbody tr:last-child td { border-bottom: 0; }
/* O código do lote não quebra: "250200701-1" partido no hífen vira dois lotes
   aos olhos de quem confere no galpão. */
[data-pagina="crm-pedidos"] .pd-cel-lote {
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
/* Código do produto e unidade de medida: largura do conteúdo, nunca da
   folga. O código fica em tinta secundária — quem lê a grade procura o nome
   do produto, e o código é a confirmação que ele consulta depois (é assim
   que a folha impressa do Senior o apresenta). */
[data-pagina="crm-pedidos"] .pd-cel-codigo {
  white-space: nowrap; font-variant-numeric: tabular-nums;
  color: var(--pedido-tinta-2); width: 1%;
}
[data-pagina="crm-pedidos"] .pd-cel-unidade {
  white-space: nowrap; color: var(--pedido-tinta-2); width: 1%;
}
/* ==========================================================================
   MALHA — mapa da operação, dores, POPs
   Escopo de página: tudo prefixado `.malha-`. Nenhum token global tocado.
   O canvas do grafo é a única superfície escura do app, de propósito: é
   superfície de grafo (padrão Obsidian), não "modo escuro" da página, e por
   isso tem tokens próprios em vez de reusar os do tema.
   ========================================================================== */

/* A régua de maturidade colore chip, anel do grafo e badge da ficha. Os tokens
   ficam nas RAÍZES das quatro telas, e não só em `.malha-app`: definidos apenas
   no mapa, o badge da ficha caía em `var()` indefinido e saía transparente. */
.malha-app,
.malha-ficha,
.malha-dores-tela,
.malha-base,
.malha-documento {
  --malha-canvas-fundo: #14181b;
  --malha-canvas-texto: #d7dde0;
  --malha-canvas-aresta: rgba(255, 255, 255, .16);
  --malha-canvas-aresta-fluxo: rgba(216, 153, 88, .55);
  --malha-canvas-aresta-apoio: rgba(255, 255, 255, .09);

  --malha-nao_mapeado: #6b7480;
  --malha-mapeado: #d0a72a;
  --malha-sop_criado: #5698d1;
  --malha-sop_implementado: #3fae7a;
  --malha-melhoria_continua: #33d3b3;
}

.malha-app {
  display: flex;
  flex-direction: column;
  gap: 10px;
  /* A tela usa a janela inteira: sem faixa branca sobrando no rodapé. O desconto
     é a topbar do shell mais o respiro do `.content`. */
  height: calc(100dvh - 118px);
  min-height: 480px;
}

/* --- barra do mapa --- */
.malha-barra {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

.malha-busca {
  position: relative;
  flex: 1 1 240px;
  max-width: 380px;
}

.malha-busca i {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: #8b8474;
  font-size: .8rem;
}

.malha-busca input {
  width: 100%;
  padding: 6px 10px 6px 30px;
  border: 1px solid #dee2e6;
  border-radius: 6px;
  font-size: .85rem;
  background: #fff;
}

.malha-legenda {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.malha-chip {
  border: 1px solid #dee2e6;
  background: #fff;
  border-radius: var(--raio-chip);
  padding: 3px 10px;
  font-size: .74rem;
  color: #495057;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.malha-chip::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--malha-nao_mapeado);
}

.malha-chip--mapeado::before { background: var(--malha-mapeado); }
.malha-chip--sop_criado::before { background: var(--malha-sop_criado); }
.malha-chip--sop_implementado::before { background: var(--malha-sop_implementado); }
.malha-chip--melhoria_continua::before { background: var(--malha-melhoria_continua); }

.malha-chip--ativo {
  border-color: #212529;
  color: #212529;
  font-weight: 600;
}

/* --- canvas --- */
.malha-canvas-wrap {
  position: relative;
  flex: 1 1 auto;
  min-height: 420px;
  border-radius: 10px;
  overflow: hidden;
  background: var(--malha-canvas-fundo);
}

#malhaGrafo {
  width: 100%;
  height: 100%;
  display: block;
}

.malha-aresta {
  stroke: var(--malha-canvas-aresta);
  stroke-width: 1;
}

.malha-aresta--fluxo {
  stroke: var(--malha-canvas-aresta-fluxo);
  stroke-width: 1.6;
}

.malha-aresta--apoio {
  stroke: var(--malha-canvas-aresta-apoio);
  stroke-dasharray: 3 4;
}

.malha-aresta--apagada { opacity: .12; }

.malha-seta { fill: var(--malha-canvas-aresta-fluxo); }

.malha-no { cursor: pointer; }

.malha-no text {
  fill: var(--malha-canvas-texto);
  font-size: 10.5px;
  pointer-events: none;
}

.malha-no--area text { font-size: 13px; }
.malha-no--raiz text { font-size: 10.5px; font-weight: 700; }

.malha-no circle {
  stroke: var(--malha-nao_mapeado);
  stroke-width: 3;
}

.malha-no--raiz circle { fill: #efe6d5; stroke: #b8532b; }

.malha-anel--mapeado { stroke: var(--malha-mapeado); }
.malha-anel--sop_criado { stroke: var(--malha-sop_criado); }
.malha-anel--sop_implementado { stroke: var(--malha-sop_implementado); }
.malha-anel--melhoria_continua { stroke: var(--malha-melhoria_continua); }

.malha-no--apagado { opacity: .18; }

.malha-no--selecionado circle {
  stroke-width: 5;
  filter: drop-shadow(0 0 6px rgba(255, 255, 255, .35));
}

.malha-resumo {
  position: absolute;
  left: 14px;
  bottom: 12px;
  display: flex;
  gap: 16px;
  font-size: .76rem;
  color: #d7dde0;
  background: rgba(20, 24, 27, .78);
  border: 1px solid rgba(255, 255, 255, .08);
  border-radius: 8px;
  padding: 6px 12px;
}

.malha-dica {
  position: absolute;
  right: 14px;
  bottom: 12px;
  margin: 0;
  max-width: 340px;
  text-align: right;
  font-size: .72rem;
  color: #7d8790;
}

/* --- ficha, dores, base --- */
.malha-secao {
  font-size: .95rem;
  font-weight: 600;
  color: #212529;
  margin: 0 0 10px;
}

.malha-contador {
  font-size: .75rem;
  color: #6c757d;
  font-weight: 400;
}

.malha-ficha__titulo {
  display: flex;
  align-items: center;
  gap: 12px;
}

.malha-ficha__titulo h1 {
  font-size: 1.25rem;
  margin: 0;
}

.malha-ficha__sub,
.malha-ficha__desc {
  color: #6c757d;
  font-size: .85rem;
  margin: 2px 0 0;
}

.malha-pino {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--malha-cor, #6c757d);
  flex: 0 0 auto;
}

.malha-status {
  margin-left: auto;
  border-radius: var(--raio-chip);
  padding: 3px 12px;
  font-size: .74rem;
  color: #fff;
  background: var(--malha-nao_mapeado);
}

.malha-status--mapeado { background: var(--malha-mapeado); }
.malha-status--sop_criado { background: var(--malha-sop_criado); }
.malha-status--sop_implementado { background: var(--malha-sop_implementado); }
.malha-status--melhoria_continua { background: var(--malha-melhoria_continua); }

.malha-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  margin: 14px 0 0;
}

.malha-meta dt {
  font-size: .7rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: #8b8474;
  font-weight: 600;
}

.malha-meta dd {
  margin: 2px 0 0;
  font-size: .85rem;
  color: #212529;
}

.malha-tag {
  display: inline-block;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  padding: 1px 6px;
  margin-right: 4px;
  font-size: .72rem;
  color: #495057;
}

.malha-dores,
.malha-docs,
.malha-timeline {
  list-style: none;
  margin: 0;
  padding: 0;
}

.malha-dor {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 0;
  border-top: 1px solid #f1f3f5;
}

.malha-dor p { margin: 0; font-size: .88rem; color: #212529; }
.malha-dor__corpo { flex: 1 1 auto; }

.malha-dor__meta {
  font-size: .74rem;
  color: #6c757d;
  margin-top: 3px !important;
}

.malha-dor--resolvida .malha-dor__corpo p { text-decoration: line-through; color: #adb5bd; }

.malha-sev {
  flex: 0 0 auto;
  border-radius: 4px;
  padding: 1px 7px;
  font-size: .7rem;
  color: #fff;
  background: #6c757d;
}

.malha-sev--alta { background: #c0392b; }
.malha-sev--media { background: #d0a72a; }
.malha-sev--baixa { background: #7f8c8d; }

.malha-vazio {
  color: #adb5bd;
  font-size: .84rem;
  padding: 10px 0;
}

.malha-form-dor textarea,
.malha-form-dor input,
.malha-form-dor select {
  border: 1px solid #dee2e6;
  border-radius: 6px;
  padding: 6px 9px;
  font-size: .84rem;
  width: 100%;
  background: #fff;
}

.malha-form-dor__linha {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 8px;
}

.malha-form-dor__linha > * { flex: 1 1 150px; }
.malha-form-dor__linha > button { flex: 0 0 auto; }

.malha-filtros {
  /* `.card` do Bootstrap já é flex-column; sem declarar a direção, a barra de
     filtro empilhava um campo por linha. */
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

.malha-filtros input,
.malha-filtros select {
  border: 1px solid #dee2e6;
  border-radius: 6px;
  padding: 6px 9px;
  font-size: .84rem;
  flex: 1 1 160px;
  background: #fff;
}

.malha-form-processo,
.malha-form-documento {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 12px;
}

.malha-form-processo label,
.malha-form-documento label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: .74rem;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: #8b8474;
  font-weight: 600;
}

.malha-form-processo input,
.malha-form-processo select,
.malha-form-processo textarea,
.malha-form-documento input,
.malha-form-documento select,
.malha-form-documento textarea {
  border: 1px solid #dee2e6;
  border-radius: 6px;
  padding: 6px 9px;
  font-size: .85rem;
  color: #212529;
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
  background: #fff;
}

.malha-form-processo__largo,
.malha-form-documento__largo { grid-column: 1 / -1; }

.malha-form-documento textarea { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

.malha-timeline li {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  padding: 6px 0;
  border-top: 1px solid #f1f3f5;
  font-size: .78rem;
  color: #495057;
}

.malha-timeline__data { color: #8b8474; }
.malha-timeline__tipo { font-weight: 600; }
.malha-timeline__nota { color: #6c757d; }

.malha-docs li {
  padding: 7px 0;
  border-top: 1px solid #f1f3f5;
  font-size: .88rem;
}

.malha-prosa { font-size: .9rem; color: #212529; line-height: 1.55; }
.malha-prosa h1, .malha-prosa h2, .malha-prosa h3 { font-size: 1rem; margin: 16px 0 6px; }
.malha-prosa ul, .malha-prosa ol { padding-left: 20px; }
.malha-prosa code { background: #f1f3f5; border-radius: 4px; padding: 1px 4px; }
.malha-prosa pre { background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 6px; padding: 10px; overflow-x: auto; }
.malha-prosa table { width: 100%; font-size: .84rem; border-collapse: collapse; }
.malha-prosa th, .malha-prosa td { border: 1px solid #dee2e6; padding: 5px 8px; }

/* ============================================================
   CRM · VENDEDORES E REPRESENTANTES  (/crm/representantes/)
   Uma tabela para varrer com o olho: 140 linhas de cadastro. Sem cartão por
   linha — cartão por linha viraria rolagem. A cor só aparece onde há trabalho
   a fazer: a conta desligada. A tela é CONSULTA; amarrar é em /crm/usuarios/.
   ============================================================ */
.rep-resumo { display: flex; flex-wrap: wrap; gap: 24px; align-items: baseline;
              margin-bottom: 14px; }
.rep-resumo__item { display: flex; flex-direction: column; gap: 2px; }
.rep-resumo__rotulo { font-size: .72rem; letter-spacing: .04em;
                      text-transform: uppercase; color: var(--crm-tinta-2); }
.rep-numero { font-size: 1.5rem; font-weight: 600; line-height: 1;
              font-variant-numeric: tabular-nums; color: var(--crm-tinta); }
.rep-numero--alerta { color: var(--crm-avi); }
.rep-numero--ok     { color: var(--crm-ok); }


.rep-filtros { margin-bottom: 12px; }
/* Flex num `<td>` tira a célula do layout de tabela: ela deixa de obedecer ao
   `align-middle` da linha e as pílulas sobem, desalinhadas do resto da linha.
   Por isso o flex mora num `<span>` DENTRO da célula, nunca na célula. */
.rep-segmentos { display: flex; flex-wrap: wrap; gap: 4px; }
/* O segmento é etiqueta de leitura, não estado: fica em cinza, e a cor da
   tela continua reservada para o que pede providência. */
.rep-seg { font-size: .7rem; letter-spacing: .03em; padding: 1px 6px;
           border-radius: 10px; background: #eaeeec; color: var(--crm-tinta-2); }
.rep-codigo { font-variant-numeric: tabular-nums; font-weight: 600; }
.rep-nome { display: block; font-weight: 600; }
.rep-tipo { display: block; font-size: .74rem; color: var(--crm-tinta-2); }
.rep-vinculo { margin-top: 3px; }
.rep-vinculo__nome { font-size: .82rem; }
.rep-vinculo__login { font-size: .74rem; color: var(--crm-tinta-2); }
.rep-vazio { color: var(--crm-tinta-2); }
.rep-desligada { font-size: .74rem; color: var(--crm-avi); }
/* Só o código preso a conta desligada ganha marca: sem vínculo é o estado
   NORMAL de 130 dos 140 ativos (escritório de representação não tem login
   aqui), e pintá-lo de falta apagaria a falta de verdade. */
.rep-linha--conta_inativa > td:first-child { box-shadow: inset 3px 0 var(--crm-avi); }

/* ===== REUNIÃO SEMANAL (rs-*) =====================================
   Tela da reunião de segunda (STEEL). Gabarito:
   `docs/redesign/mockups/reuniao-semanal-terminal-claro.html` — a variante C,
   aprovada pelo dono em 17/09/2026. NÃO EDITAR POR GOSTO: mude o mockup
   primeiro e depois meça a tela contra ele (mesmo trato de /despesas/nova/).

   Terminal claro: tema claro fixo, uma fonte (a do shell, tabular-nums), tinta
   + uma cor de estado. Sem cartão, moldura, raio ou sombra em repouso — o que
   separa as regiões é a faixa de título clara, o conteúdo branco e o fio de
   cabelo no vão. `--dnv-mark` é seleção, foco e link; `--dnv-risco` só o que
   pede ação, e o estado vem sempre do serviço. A tela é a janela: a página não
   rola, cada região rola por dentro e AVISA quantas linhas ficaram abaixo.

   A pele vem dos tokens `--dnv-*` da seção DESPESAS (a página entra na LISTA DE
   SELETORES deles, `custom.css` ~19700) — nenhum valor de cor é copiado para cá.
   O tamanho de tudo pende de `--rs-fs`, como o `html{font-size}` do gabarito.
   ================================================================== */
.rs-tela{--rs-fs:13px;
  /* fio de cabelo entre linhas de lista (mais claro que `--dnv-rule`) e os dois
     cinzas dos segmentos (entrada/saída, faturado/carteira). Escopo de página. */
  --rs-fio:#ECEEF1; --rs-seg-1:#2B323C; --rs-seg-3:#AAB1BA;
  background:var(--dnv-surface);color:var(--dnv-ink);font-family:var(--dnv-sans);font-size:var(--rs-fs);
  line-height:1.35;-webkit-font-smoothing:antialiased;overflow:hidden;color-scheme:light}
.rs-tela button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer;text-align:left}
.rs-tela :focus-visible{outline:2px solid var(--dnv-mark);outline-offset:1px}
.rs-tela .rs-d,.rs-tela .rs-cnv,.rs-tela .rs-val,.rs-tela .rs-dia b,.rs-tela .rs-caixatot b,
.rs-tela .rs-tb td,.rs-tela .rs-dev-dias{font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1,"lnum" 1}
.rs-tela .rs-mudo{color:var(--dnv-ink-3)}
.rs-tela .rs-risco{color:var(--dnv-risco)}
.rs-tela h2{margin:0}
/* a tela encosta na barra lateral e na borda direita da janela: quem dá o
   respiro é `.rs-app`, com o mesmo recuo do gabarito. */
.content--altura-cheia > .page.rs-tela{padding:0}
/* rótulos dos seletores do topo no vocabulário de /despesas/nova/ (`.dnv-k`):
   rótulo pequeno em versal, valor em 600. Só na barra desta tela. */
body:has(.rs-tela) #topbar .fdrop{font-size:10px;font-weight:600;letter-spacing:.11em;text-transform:uppercase;color:var(--ink-3)}
body:has(.rs-tela) #topbar .fdrop b{font-size:.875rem;letter-spacing:0;text-transform:none;font-weight:600}

/* ── estrutura: três faixas empilhadas, sem cartão ─────────────────────── */
.rs-tela .rs-app{flex:1 1 auto;min-height:0;min-width:0;display:flex;flex-direction:column;gap:25px;padding:14px 20px 12px}
.rs-tela .rs-l1{flex:0 0 auto;position:relative}
.rs-tela .rs-l2{flex:0 0 auto;position:relative;display:grid;grid-template-columns:minmax(0,1.5fr) minmax(0,1fr);gap:25px}
.rs-tela .rs-l3{flex:1 1 0;min-height:0;position:relative;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:25px}
.rs-tela .rs-bloco{position:relative;min-width:0;min-height:0;display:flex;flex-direction:column}
/* o fio de cabelo mora no VÃO, na metade dele — não é borda de cartão */
.rs-tela .rs-sep-t::before{content:"";position:absolute;top:-13px;left:0;right:0;height:1px;background:var(--dnv-rule)}
.rs-tela .rs-sep-l::before{content:"";position:absolute;left:-13px;top:0;bottom:0;width:1px;background:var(--dnv-rule)}
/* faixa de título clara + conteúdo branco: a separação sem cartão */
.rs-tela .rs-cab{flex:0 0 auto;display:flex;align-items:center;gap:8px;min-height:28px;margin-bottom:6px;
  padding:0 10px;background:var(--dnv-surface-3);white-space:nowrap}
.rs-tela .rs-cab h2{font-size:calc(var(--rs-fs)*.93);font-weight:700;letter-spacing:.02em}
.rs-tela .rs-cab-meta{margin-left:auto;display:flex;align-items:center;gap:14px;
  font-size:calc(var(--rs-fs)*.8);letter-spacing:.04em;text-transform:uppercase;color:var(--dnv-ink-2)}
.rs-tela .rs-cab-meta b{font-weight:600;color:var(--dnv-ink)}
.rs-tela .rs-corpo{flex:1 1 auto;min-height:0;display:flex;flex-direction:column}
.rs-tela .rs-corpo[hidden]{display:none}

/* ── gramática comum ──────────────────────────────────────────────────── */
.rs-tela .rs-rot{display:inline-flex;align-items:center;gap:6px;font-size:calc(var(--rs-fs)*.77);font-weight:500;
  letter-spacing:.04em;text-transform:uppercase;color:var(--dnv-ink-3);white-space:nowrap}
.rs-tela .rs-rot.rs-risco{color:var(--dnv-risco)}
/* o que abre gaveta tem sublinhado SEMPRE visível: a porta não se esconde até
   o ponteiro passar. Uma porta por registro — o valor é a porta. */
.rs-tela .rs-drill{cursor:pointer;text-decoration:underline;text-decoration-thickness:1px;
  text-decoration-color:var(--dnv-rule-2);text-underline-offset:3px}
.rs-tela .rs-drill:hover{text-decoration-color:var(--dnv-ink)}
.rs-tela .rs-link,.rs-tela .rs-acao,.rs-tela .rs-abrir{color:var(--dnv-mark);font-weight:500;white-space:nowrap;text-decoration:none}
.rs-tela .rs-link:hover,.rs-tela .rs-acao:hover,.rs-tela .rs-abrir:hover{text-decoration:underline}
.rs-tela .rs-acao{font-size:calc(var(--rs-fs)*.8);letter-spacing:.03em}
.rs-tela .rs-link[hidden],.rs-tela .rs-acao[hidden]{display:none}
.rs-tela .rs-frase{font-size:calc(var(--rs-fs)*.85);color:var(--dnv-ink-2);white-space:nowrap}
.rs-tela .rs-dir{margin-left:auto}
.rs-tela .rs-vazio{padding:8px 0;font-size:calc(var(--rs-fs)*.88);color:var(--dnv-ink-3)}
/* amostra da cor do segmento, do tamanho de uma letra */
.rs-tela .rs-am{display:inline-block;width:9px;height:9px;flex:none}
.rs-tela .rs-t1{background:var(--rs-seg-1)}
.rs-tela .rs-t2{background:repeating-linear-gradient(135deg,var(--rs-seg-1) 0 2px,var(--dnv-surface) 2px 4px)}
.rs-tela .rs-t3{background:var(--rs-seg-3)}
.rs-tela .rs-t4{background:repeating-linear-gradient(135deg,var(--rs-seg-3) 0 2px,var(--dnv-surface) 2px 4px)}
.rs-tela .rs-t5{background:repeating-linear-gradient(135deg,var(--dnv-risco) 0 1.5px,var(--dnv-surface) 1.5px 5px);
  box-shadow:inset 0 0 0 1px var(--dnv-risco)}
/* par de visões (Previsão/Fluxo, Pauta/Projetos): aba sublinhada, não pílula */
.rs-tela .rs-par{display:flex;gap:12px}
.rs-tela .rs-pr{font-size:calc(var(--rs-fs)*.8);font-weight:500;letter-spacing:.04em;color:var(--dnv-ink-3);
  padding:4px 0;border-bottom:2px solid transparent;white-space:nowrap}
.rs-tela .rs-pr:hover{color:var(--dnv-ink)}
.rs-tela .rs-pr.rs-on{color:var(--dnv-ink);border-bottom-color:var(--dnv-mark)}
.rs-tela .rs-par-titulo .rs-pr{font-size:calc(var(--rs-fs)*.93);font-weight:700;letter-spacing:.02em}
.rs-tela .rs-par-titulo .rs-pr b{margin-left:4px;font-weight:400;color:var(--dnv-ink-3)}
.rs-tela .rs-par-titulo .rs-pr b:empty{display:none}

/* ── a conta do mês: parcela + parcela + … = firme, e o que falta vender ── */
.rs-tela .rs-conta{display:flex;align-items:flex-start;justify-content:space-between;gap:6px;margin:0 0 10px}
.rs-tela .rs-pcl,.rs-tela .rs-res,.rs-tela .rs-vender{display:flex;flex-direction:column;gap:2px;min-width:0}
.rs-tela .rs-vender{padding-left:18px}
.rs-tela .rs-op{font-size:calc(var(--rs-fs)*1.2);color:var(--dnv-ink-3);padding-top:18px}
.rs-tela .rs-cnv{font-size:calc(var(--rs-fs)*1.55);font-weight:500;line-height:1.25;letter-spacing:-.01em;white-space:nowrap}
.rs-tela .rs-res .rs-cnv,.rs-tela .rs-vender .rs-cnv{font-size:calc(var(--rs-fs)*1.85);font-weight:700}
.rs-tela .rs-cns{font-size:calc(var(--rs-fs)*.82);color:var(--dnv-ink-2);white-space:nowrap}
/* a trilha é a mesma conta, em largura: cada pedaço já vem em % do serviço */
.rs-tela .rs-trilho{position:relative;height:10px;display:flex;background:var(--dnv-surface)}
.rs-tela .rs-sg{height:100%;display:block}
.rs-tela .rs-trilho-meta{position:absolute;top:-5px;bottom:-5px;width:2px;margin-left:-2px;background:var(--dnv-ink)}
.rs-tela .rs-trilho-meta b{position:absolute;right:4px;top:calc(100% + 3px);font-size:calc(var(--rs-fs)*.72);
  font-weight:500;letter-spacing:.04em;color:var(--dnv-ink-2);white-space:nowrap;font-variant-numeric:tabular-nums}

/* ── tabelas: a régua do gabarito ─────────────────────────────────────── */
.rs-tela .rs-tb{width:100%;border-collapse:collapse;font-size:calc(var(--rs-fs)*.96)}
.rs-tela .rs-tb th{font-size:calc(var(--rs-fs)*.74);font-weight:500;letter-spacing:.04em;color:var(--dnv-ink-2);
  text-align:right;padding:0 8px;height:20px;white-space:nowrap;vertical-align:bottom}
.rs-tela .rs-tb th:first-child,.rs-tela .rs-tb td:first-child{text-align:left;padding-left:0}
.rs-tela .rs-tb th:last-child,.rs-tela .rs-tb td:last-child{padding-right:0}
.rs-tela .rs-tb td{padding:0 8px;height:calc(var(--rs-fs)*1.78);text-align:right;white-space:nowrap;
  border-bottom:1px solid var(--rs-fio)}
.rs-tela .rs-tb .rs-d{text-align:right}
.rs-tela .rs-tb .rs-n{text-align:left}
.rs-tela .rs-tb .rs-pct{color:var(--dnv-ink-2)}
.rs-tela .rs-tb tbody tr:hover td{background:var(--dnv-surface-2)}
/* áreas: os grupos (Faturamento · Volume · Margem bruta) se separam por respiro,
   com um fio sob o rótulo que começa na 1ª coluna do grupo. */
.rs-tela .rs-tb-areas thead tr.rs-grupos th{color:var(--dnv-ink);font-weight:700;text-align:left;vertical-align:bottom}
.rs-tela .rs-tb-areas thead tr.rs-grupos th span{display:block;border-bottom:1px solid var(--dnv-rule-2);
  padding-bottom:2px;margin-right:6px}
.rs-tela .rs-tb-areas thead tr.rs-colunas th{border-bottom:1px solid var(--dnv-ink)}
.rs-tela .rs-tb-areas td.rs-vao,.rs-tela .rs-tb-areas th.rs-vao{padding:0 6px;width:14px}   /* o vão guarda o fio da linha: sem ele o filete da linha nasce picado */
.rs-tela .rs-tb-areas tfoot td{border-top:1px solid var(--dnv-ink);border-bottom:0;font-weight:700;
  height:calc(var(--rs-fs)*1.9)}
.rs-tela .rs-lapis{margin-left:3px;font-size:.7em;color:var(--dnv-ink-3)}
/* cabeçalho que ordena (dono, 17/09/2026): o rótulo é o próprio botão, sem
   moldura em repouso — a coluna ativa é a que mostra a seta. As duas colunas de
   VOLUME não ordenam (KG, RL e PC não formam um ranking), e por isso continuam
   `th` de texto: o que não é clicável não parece clicável. */
.rs-tela .rs-ord{all:unset;cursor:pointer;display:inline-flex;align-items:center;gap:3px;
  font:inherit;color:inherit;letter-spacing:inherit}
.rs-tela .rs-ord:hover{color:var(--dnv-mark)}
.rs-tela .rs-ord:focus-visible{outline:1px solid var(--dnv-mark);outline-offset:2px}
.rs-tela .rs-seta{font-size:.8em}
.rs-tela .rs-tb-areas thead tr.rs-colunas th.rs-ord-on{color:var(--dnv-ink)}
/* a célula editável se anuncia em repouso: sublinhado pontilhado, sem lápis por
   número (o lápis fica uma vez, no cabeçalho da coluna). */
.rs-tela .rs-lap{border-bottom:1px dashed var(--dnv-rule-3);cursor:text;padding-bottom:1px}
.rs-tela .rs-lap:hover{background:var(--dnv-mark-wash)}
.rs-tela .rs-area{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:inline-block;vertical-align:bottom}
.rs-tela .rs-add{color:var(--dnv-mark);font-size:calc(var(--rs-fs)*.8);letter-spacing:.04em}
.rs-tela .rs-add.rs-risco{color:var(--dnv-risco)}
.rs-tela .rs-add:hover{text-decoration:underline}
.rs-tela .rs-ed-wrap{display:inline-flex;flex-direction:column;align-items:flex-end}
.rs-tela .rs-ed{display:inline-flex;align-items:stretch;height:1.6rem;border:1px solid var(--dnv-mark);background:var(--dnv-surface)}
.rs-tela .rs-ed input{width:7.5em;min-width:0;border:0;outline:0;padding:0 .25rem;background:transparent;
  color:var(--dnv-ink);font:inherit;text-align:right}
.rs-tela .rs-ed .rs-ok,.rs-tela .rs-ed b{display:flex;align-items:center;padding:0 .5rem;background:var(--dnv-mark);
  color:var(--dnv-surface);font-size:calc(var(--rs-fs)*.75);font-weight:600;cursor:pointer}
.rs-tela .rs-ed-wrap .rs-erro{padding:2px 0 0;white-space:normal}

/* ── faturamento diário: o SVG é desenhado em pixel (não estica) ───────── */
.rs-tela .rs-graf{position:relative;flex:1 1 auto;min-height:110px;min-width:0}
.rs-tela .rs-graf svg{position:absolute;inset:0;overflow:visible}
.rs-tela .rs-graf text{font-family:inherit;font-size:10.5px;fill:var(--dnv-ink-3)}
.rs-tela .rs-graf .rs-g-forte{fill:var(--dnv-ink);font-weight:500}
.rs-tela .rs-graf .rs-graf-avender{fill:var(--dnv-risco);font-weight:500}
.rs-tela .rs-g-grade{stroke:var(--rs-fio)}
.rs-tela .rs-g-base{stroke:var(--dnv-rule-2)}
.rs-tela .rs-g-hoje{stroke:var(--dnv-rule-3);stroke-dasharray:2 3}
.rs-tela .rs-g-anterior{fill:none;stroke:var(--rs-seg-3);stroke-width:1.5}
.rs-tela .rs-g-meta{stroke:var(--dnv-ink);stroke-dasharray:1 3;stroke-width:1.3}
.rs-tela .rs-g-faturado-area{fill:#E4E7EB}
.rs-tela .rs-g-faturado{fill:none;stroke:var(--dnv-ink);stroke-width:2}
.rs-tela .rs-g-firme{fill:none;stroke:var(--dnv-ink);stroke-width:1.5;stroke-dasharray:5 3}
.rs-tela .rs-g-vao{stroke:var(--dnv-risco);stroke-width:3}
.rs-tela .rs-g-ponto{fill:var(--dnv-ink)}
.rs-tela .rs-g-mira{stroke:var(--dnv-mark)}
.rs-tela .rs-g-zona{fill:transparent}

/* ── dica (gráfico diário e dia do caixa): a de /despesas/nova/ ─────────── */
.rs-tela .rs-balao{position:fixed;z-index:70;pointer-events:none;display:flex;flex-direction:column;gap:2px;min-width:12rem;
  padding:8px 11px;background:var(--dnv-surface);border:1px solid var(--dnv-rule-2);box-shadow:0 10px 24px -12px rgba(0,0,0,.35);
  font-size:12px;color:var(--dnv-ink-2);white-space:nowrap}
.rs-tela .rs-balao[hidden]{display:none}
.rs-tela .rs-balao-k{margin-bottom:2px;font-size:10.5px;font-weight:600;letter-spacing:.06em;color:var(--dnv-ink-3)}
.rs-tela .rs-balao-l{display:flex;justify-content:space-between;gap:1rem}
.rs-tela .rs-balao-l b{font-weight:600;color:var(--dnv-ink);font-variant-numeric:tabular-nums}
.rs-tela .rs-balao-l b.rs-risco{color:var(--dnv-risco)}

/* ── inadimplência ────────────────────────────────────────────────────── */
/* cabeçalho de número grande, comum à inadimplência e ao Comex */
/* o cabeçalho quebra em vez de estourar a coluna: em 1366 a contagem de
   títulos não cabe ao lado do valor, e número cortado não é número. */
.rs-tela .rs-cab2{flex:0 0 auto;display:flex;flex-wrap:wrap;align-items:baseline;gap:0 10px;margin:4px 0 6px;min-width:0;white-space:nowrap}
.rs-tela .rs-val{font-size:calc(var(--rs-fs)*1.45);font-weight:500;letter-spacing:-.01em}
.rs-tela .rs-fxs{flex:0 0 auto;display:grid;grid-template-columns:auto minmax(30px,1fr) auto;column-gap:10px;
  align-items:center;font-size:calc(var(--rs-fs)*.9)}
.rs-tela .rs-fxs > *{height:calc(var(--rs-fs)*1.42);display:flex;align-items:center}
.rs-tela .rs-fxs .rs-d{justify-content:flex-end}
.rs-tela .rs-trk{height:6px;display:block;align-self:center;background:var(--dnv-surface-3)}
.rs-tela .rs-trk i{display:block;height:100%;background:var(--rs-seg-1)}
.rs-tela .rs-trk.rs-risco i{background:var(--dnv-risco)}
.rs-tela .rs-dev{flex:0 1 auto;min-height:0;overflow:hidden;margin-top:4px;display:grid;
  grid-template-columns:minmax(0,1fr) auto auto;column-gap:10px;align-items:center;font-size:calc(var(--rs-fs)*.88)}
.rs-tela .rs-dev .rs-rot{grid-column:1/-1;height:calc(var(--rs-fs)*1.4);display:flex;align-items:flex-end;padding-bottom:3px}
.rs-tela .rs-dev ol{display:contents;margin:0;padding:0;list-style:none}
.rs-tela .rs-dev li{display:contents}
.rs-tela .rs-dev li > *{height:calc(var(--rs-fs)*1.38);display:flex;align-items:center;border-bottom:1px solid var(--rs-fio)}
.rs-tela .rs-dev-nome{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block!important;
  line-height:calc(var(--rs-fs)*1.38)}
.rs-tela .rs-dev-dias{justify-content:flex-end;color:var(--dnv-ink-3);font-size:calc(var(--rs-fs)*.8);
  text-transform:uppercase;white-space:nowrap}
.rs-tela .rs-dev .rs-d{justify-content:flex-end;white-space:nowrap}

/* ── caixa do mês: calendário compacto, valor só na dica ───────────────── */
.rs-tela .rs-caixatot{flex:0 0 auto;display:grid;grid-template-columns:repeat(3,auto);justify-content:space-between;
  margin:4px 0 6px;gap:0 10px}
.rs-tela .rs-caixatot > span{display:flex;flex-direction:column;min-width:0}
.rs-tela .rs-caixatot .rs-dir{text-align:right;align-items:flex-end;margin-left:0}
.rs-tela .rs-caixatot b{font-size:calc(var(--rs-fs)*1.05);font-weight:500;white-space:nowrap}
.rs-tela .rs-cal{flex:1 1 auto;min-height:0;display:grid;grid-template-columns:repeat(7,minmax(0,1fr));
  grid-template-rows:auto;grid-auto-rows:minmax(0,1fr);column-gap:3px;row-gap:3px}
.rs-tela .rs-sem{font-size:calc(var(--rs-fs)*.7);font-weight:500;letter-spacing:.04em;color:var(--dnv-ink-3);padding-bottom:2px}
.rs-tela .rs-dia{position:relative;min-height:0;padding:2px 3px;border-top:1px solid var(--rs-fio);width:100%;
  display:flex;flex-direction:column;align-items:stretch}   /* flex, não block: `<button>` centra o miolo na vertical e o dia sairia do alto da célula */
.rs-tela span.rs-dia{cursor:default}
.rs-tela .rs-dia:hover{background:var(--dnv-surface-2)}
.rs-tela .rs-dia.rs-vazio{border-top:0}
.rs-tela .rs-dia b{display:block;font-size:calc(var(--rs-fs)*.74);font-weight:400;color:var(--dnv-ink-2);line-height:1}
.rs-tela .rs-dia.rs-fds b{color:var(--dnv-rule-3)}
/* dia negativo é MARCADO, sem valor escrito: o número mora na dica */
.rs-tela .rs-dia.rs-neg b{color:var(--dnv-risco);font-weight:500}
.rs-tela .rs-dia.rs-hoje{box-shadow:inset 0 2px 0 var(--dnv-mark)}
.rs-tela .rs-dia.rs-hoje b{color:var(--dnv-mark);font-weight:700}
.rs-tela .rs-fl{position:absolute;left:3px;right:3px;bottom:2px;top:14px;display:flex;align-items:flex-end;
  gap:2px;justify-content:flex-end}
.rs-tela .rs-fl i{width:5px;display:block;min-height:1px}
.rs-tela .rs-fl .rs-e{background:var(--rs-seg-1)}
.rs-tela .rs-fl .rs-s{background:var(--rs-seg-3)}
/* fonte parada: uma linha vermelha por cima e o conteúdo apagado — o número
   velho continua legível, mas não se confunde com o de agora. */
.rs-tela .rs-avisofrio{flex:0 0 auto;padding:2px 0 4px;font-size:calc(var(--rs-fs)*.85);font-weight:500;color:var(--dnv-risco);
  white-space:normal}
.rs-tela .rs-frio{opacity:.4}

/* ── comex em trânsito: o detalhe abre NA LINHA ────────────────────────── */
.rs-tela .rs-tb-proc th{position:sticky;top:0;z-index:1;background:var(--dnv-surface);
  font-size:calc(var(--rs-fs)*.72);height:18px;border-bottom:1px solid var(--dnv-ink);padding:0 0 0 8px}
.rs-tela .rs-tb-proc td{height:calc(var(--rs-fs)*1.6);padding:0 0 0 8px}
.rs-tela .rs-tb-proc tr.rs-linha{cursor:pointer}
.rs-tela .rs-tb-proc tr.rs-linha:hover td{background:var(--dnv-surface-2)}
.rs-tela .rs-seta{display:inline-block;width:12px;font-style:normal;color:var(--dnv-ink-3);transition:transform .15s ease-out}
.rs-tela .rs-tb-proc tr[aria-expanded="true"] .rs-seta{transform:rotate(90deg);color:var(--dnv-ink)}
.rs-tela .rs-tb-proc tr[aria-expanded="true"] td{border-bottom-color:transparent;font-weight:500}
.rs-tela .rs-quando{margin-left:6px;color:var(--dnv-ink-3);font-size:calc(var(--rs-fs)*.8)}
.rs-tela .rs-detalhe td{padding:0 0 8px;text-align:left;white-space:normal;border-bottom:1px solid var(--rs-fio);height:auto}
.rs-tela .rs-quadro{border:1px solid var(--dnv-rule);padding:8px 10px;font-size:calc(var(--rs-fs)*.84)}
.rs-tela .rs-quadro dl{display:grid;grid-template-columns:auto minmax(0,1fr);gap:2px 10px;margin:0 0 8px}
.rs-tela .rs-quadro dt{font-size:calc(var(--rs-fs)*.7);font-weight:500;letter-spacing:.04em;color:var(--dnv-ink-3);align-self:center}
.rs-tela .rs-quadro dd{margin:0}
.rs-tela .rs-itens{list-style:none;margin:2px 0 0;padding:0}
.rs-tela .rs-itens li{padding:4px 0;border-top:1px solid var(--rs-fio)}
.rs-tela .rs-it-num{display:flex;justify-content:space-between;gap:8px;margin-top:1px;color:var(--dnv-ink-2);
  font-variant-numeric:tabular-nums}
.rs-tela .rs-it-num b{color:var(--dnv-ink);font-weight:500}

/* ── pauta e projetos: um bloco, duas abas ─────────────────────────────── */
.rs-tela .rs-frm{flex:0 0 auto;display:flex;gap:6px;padding:4px 0 6px;border-bottom:1px solid var(--dnv-rule)}
.rs-tela .rs-frm[hidden]{display:none}
.rs-tela .rs-cmp{min-width:0;height:1.6rem;padding:0 6px;border:1px solid var(--dnv-rule-2);border-radius:0;
  background:var(--dnv-surface);color:var(--dnv-ink);font:inherit;font-size:calc(var(--rs-fs)*.9);appearance:none}
.rs-tela .rs-frm .rs-cmp{flex:1 1 auto}
.rs-tela .rs-cmp::placeholder{color:var(--dnv-ink-3);letter-spacing:.04em}
.rs-tela .rs-cmp:focus{outline:0;border-color:var(--dnv-mark)}
.rs-tela .rs-frm .rs-sel-pessoas{flex:0 0 9rem}
.rs-tela .rs-botao{display:inline-flex;align-items:center;justify-content:center;gap:.375rem;flex:none;
  height:1.6rem;padding:0 10px;border:0;border-radius:4px;background:var(--dnv-mark);color:var(--dnv-surface);
  font-size:calc(var(--rs-fs)*.8);font-weight:500;white-space:nowrap}
.rs-tela .rs-botao:hover{filter:brightness(1.12)}
.rs-tela .rs-erro{padding:2px 0;font-size:calc(var(--rs-fs)*.85);color:var(--dnv-risco)}
.rs-tela .rs-erro:empty{display:none}
.rs-tela .rs-tf,.rs-tela .rs-ft{display:grid;grid-template-columns:18px minmax(0,1fr) auto;gap:6px;
  align-items:start;padding:4px 0;border-bottom:1px solid var(--rs-fio);font-size:calc(var(--rs-fs)*.92)}
.rs-tela .rs-cxb,.rs-tela .rs-q{width:13px;height:13px;margin-top:2px;flex:none;
  border:1px solid var(--dnv-rule-3);background:var(--dnv-surface)}
.rs-tela .rs-cxb:hover{border-color:var(--dnv-mark)}
.rs-tela .rs-q.rs-ok,.rs-tela .rs-feito .rs-cxb{background:var(--dnv-mark);border-color:var(--dnv-mark)}
.rs-tela .rs-tt,.rs-tela .rs-ftt{min-width:0;overflow-wrap:anywhere}
.rs-tela .rs-feito .rs-tt,.rs-tela .rs-risc{color:var(--dnv-ink-3);text-decoration:line-through}
.rs-tela .rs-tt .rs-mudo{margin-left:4px;font-size:calc(var(--rs-fs)*.78)}
.rs-tela .rs-resp{font-size:calc(var(--rs-fs)*.78);font-weight:500;letter-spacing:.03em;color:var(--dnv-ink-2);
  padding-top:1px;white-space:nowrap}
.rs-tela .rs-resp.rs-risco{color:var(--dnv-risco)}
/* O ponto de pauta ganhou uma quarta coluna: o × que manda para a lixeira.
   Ele só aparece quando o cursor (ou o teclado) está na linha — gesto do
   To-Do: a linha fica limpa e a ação aparece onde a mão está. */
.rs-tela .rs-tf{grid-template-columns:18px minmax(0,1fr) auto 12px}
.rs-tela .rs-xr{width:12px;line-height:1;text-align:center;color:var(--dnv-ink-3);
  opacity:0;transition:opacity .12s}
.rs-tela .rs-tf:hover .rs-xr,.rs-tela .rs-tf:focus-within .rs-xr{opacity:1}
.rs-tela .rs-xr:hover{color:var(--dnv-risco)}
/* O título abre o detalhe: é botão, e o único sinal disso é o cursor — fio
   embaixo em dezesseis linhas viraria cerca. */
.rs-tela button.rs-tt,.rs-tela button.rs-ftt{width:100%}
.rs-tela button.rs-tt:hover,.rs-tela button.rs-ftt:hover{color:var(--dnv-mark)}
/* A oferta de DESFAZER, entre a recusa e a lista. */
.rs-tela .rs-desfeito{display:flex;align-items:center;gap:8px;
  font-size:calc(var(--rs-fs)*.85);color:var(--dnv-ink-2)}
.rs-tela .rs-desfeito:empty{display:none}
.rs-tela .rs-desfeito span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rs-tela .rs-desf{margin-left:auto;flex:none;font-size:calc(var(--rs-fs)*.78);font-weight:500;
  letter-spacing:.03em;color:var(--dnv-mark);text-decoration:underline}
.rs-tela .rs-pj{padding-bottom:6px}
.rs-tela .rs-pj-cab{display:flex;align-items:baseline;gap:10px;padding:4px 0 2px}
.rs-tela .rs-pj-cab .rs-t{font-weight:500;font-size:calc(var(--rs-fs)*.98)}
.rs-tela .rs-pj-prog{font-size:calc(var(--rs-fs)*.85);color:var(--dnv-ink-2);white-space:nowrap}
.rs-tela .rs-pj-cab .rs-abrir{margin-left:auto;font-size:calc(var(--rs-fs)*.8);letter-spacing:.03em}
.rs-tela .rs-prog{height:4px;margin:2px 0 6px;background:var(--dnv-surface-3)}
.rs-tela .rs-prog i{display:block;height:100%;background:var(--rs-seg-1)}
.rs-tela .rs-pj .rs-s{font-size:calc(var(--rs-fs)*.82);color:var(--dnv-ink-2)}
.rs-tela .rs-fn{display:flex;gap:8px;padding:6px 0 1px;font-size:calc(var(--rs-fs)*.74);font-weight:500;
  letter-spacing:.04em;text-transform:uppercase;color:var(--dnv-ink-2)}
.rs-tela .rs-fn span:first-child{flex:1;min-width:0}
.rs-tela #rs-pauta-minhas{flex:0 0 auto;padding-top:4px;font-size:calc(var(--rs-fs)*.78);letter-spacing:.04em}

/* ── rolagem por dentro: a pista avisa quantas linhas ficaram abaixo ───── */
.rs-tela .rs-rola{position:relative;flex:1 1 auto;min-height:0;overflow:auto;scrollbar-width:thin}
.rs-tela .rs-rola.rs-tem-mais{-webkit-mask-image:linear-gradient(#000 calc(100% - 18px),rgba(0,0,0,.25));
  mask-image:linear-gradient(#000 calc(100% - 18px),rgba(0,0,0,.25))}
.rs-tela .rs-mais{flex:0 0 auto;height:15px;line-height:15px;text-align:right;font-size:calc(var(--rs-fs)*.72);
  font-weight:500;letter-spacing:.04em;color:var(--dnv-ink-2)}
.rs-tela .rs-mais:empty{display:none}

/* ── janelas: cabeçalho comum aos três diálogos ───────────────────────── */
.rs-tela .rs-hd{flex:none;display:flex;flex-wrap:wrap;align-items:center;align-content:flex-start;gap:0 .5rem;min-height:2.25rem;padding:.25rem .75rem}
.rs-tela .rs-hd h2{margin:0;font-size:13px;line-height:1.75rem;font-weight:600;letter-spacing:.04em;color:var(--dnv-ink);white-space:nowrap}
.rs-tela .rs-hd > .rs-par{margin-left:auto}
.rs-tela .rs-botao-principal{font-weight:600}

/* ── estado de carga e falha ──────────────────────────────────────────── */
.rs-tela .rs-esqueleto{flex:1;min-height:0;display:flex;flex-direction:column;justify-content:center;gap:.625rem;padding:.75rem}
.rs-tela .rs-esqueleto i{display:block;height:10px;background:linear-gradient(100deg,var(--dnv-surface-3) 0 38%,var(--dnv-surface-2) 52%,var(--dnv-surface-3) 66% 100%);
  background-size:320% 100%;animation:rs-esqueleto 1.25s linear infinite}
.rs-tela .rs-esqueleto i:nth-child(2n){width:72%} .rs-tela .rs-esqueleto i:nth-child(3n){width:88%}
@keyframes rs-esqueleto{from{background-position:130% 0}to{background-position:-190% 0}}
@media (prefers-reduced-motion:reduce){.rs-tela .rs-esqueleto i{animation:none}}
.rs-tela .rs-falha{flex:1;min-height:0;display:flex;flex-direction:column;align-items:flex-start;justify-content:center;
  gap:.5rem;padding:.75rem;font-size:.8125rem;color:var(--dnv-ink-3)}
.rs-tela .rs-tentar{height:1.75rem;padding:0 .625rem;border:1px solid var(--dnv-rule-2);color:var(--dnv-ink);font-size:.8125rem}

/* ── diálogos: a única sombra da tela ─────────────────────────────────────
   `<dialog>` sobe para a top layer e continua herdando os tokens de `.rs-tela`
   por ser filho dela no DOM. */
.rs-tela .rs-dialog{width:100%;max-width:min(920px,92vw);max-height:86vh;overflow:auto;padding:0;border:1px solid var(--dnv-rule-2);
  border-radius:0;background:var(--dnv-surface);color:var(--dnv-ink);font:13.5px/1.45 var(--dnv-sans);
  box-shadow:0 12px 32px rgb(11 14 18/.16)}
.rs-tela .rs-dialog::backdrop{background:rgb(11 14 18/.32)}
.rs-tela .rs-dialog-largo{max-width:min(1400px,96vw)}
.rs-tela .rs-dialog .rs-hd{position:sticky;top:0;z-index:3;background:var(--dnv-surface);border-bottom:1px solid var(--dnv-rule)}
.rs-tela .rs-dialog .rs-hd h2{text-transform:uppercase;letter-spacing:.04em}
/* registros na grade da casa: a janela cabe na tela e só a grade rola por
   dentro; texto livre corta em reticências (texto inteiro no `title`) para a
   coluna de valor nunca sair da janela */
/* a gaveta da ÁREA prova três números (R$, volume e margem) e por isso leva dez
   colunas: a janela usa a largura do `rs-dialog-largo`, senão a coluna Valor sai
   dela. Mesmo teto do quadro de metas do ano, na mesma tela. */
.rs-tela .rs-dialog-registros{max-width:min(1400px,96vw)}
.rs-tela .rs-dialog-registros .grade{padding:0 .75rem .5rem;background:var(--dnv-surface)}
.rs-tela .rs-dialog-registros .grade .rs-reg-texto{max-width:18rem}
/* a gaveta da ÁREA é a mais larga: além do R$ ela prova volume e margem
   (quantidade, líquido, CMV, MB, MC). Quem cede largura é o texto livre —
   cliente e item já cortam em reticências, com o texto inteiro no `title`. */
.rs-tela #rs-registros-faturamento-grade .rs-reg-texto{max-width:12rem}
.rs-tela #rs-modal-registros-totais .rs-tot{justify-content:flex-start;flex-wrap:wrap;gap:.25rem 1.5rem;box-shadow:none;
  text-transform:uppercase;letter-spacing:.04em;font-size:12px}
.rs-tela #rs-modal-registros-totais .rs-rt{font-weight:500;color:var(--dnv-ink-3)}
.rs-tela #rs-modal-registros-totais .rs-rt b{margin-left:.25rem;font-size:13.5px;font-weight:600;letter-spacing:0;
  color:var(--dnv-ink);font-variant-numeric:tabular-nums}
.rs-tela #rs-modal-registros-totais .rs-esqueleto{padding:.5rem .75rem}
.rs-tela .rs-dialog .rs-tb th{top:2.5rem}
.rs-tela .rs-fechar{margin-left:auto;width:1.75rem;height:1.75rem;text-align:center!important;color:var(--dnv-ink-3)}
.rs-tela .rs-fechar:hover{color:var(--dnv-ink)}
.rs-tela .rs-dcorpo{display:flex;flex-direction:column;align-items:flex-start;gap:.5rem;padding:.75rem}
.rs-tela .rs-dialog-projeto{max-width:min(640px,92vw)}
.rs-tela .rs-dica{margin:0;font-size:12px;color:var(--dnv-ink-3)}
.rs-tela .rs-pj-campos{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,12rem) 9.5rem;gap:.5rem;width:100%}
.rs-tela .rs-rotulo{display:flex;flex-direction:column;gap:2px;margin:0;font-size:11px;font-weight:600;letter-spacing:.04em;
  text-transform:uppercase;color:var(--dnv-ink-2)}
.rs-tela .rs-rotulo .rs-cmp{font-weight:400;letter-spacing:0;text-transform:none}
.rs-tela #rs-projeto-fases{width:100%;display:flex;flex-direction:column;gap:.5rem}
.rs-tela #rs-projeto-fases:empty{display:none}
.rs-tela .rs-fase{display:flex;flex-direction:column;align-items:flex-start;gap:.375rem;padding:.5rem 0 .5rem .75rem;
  border-left:2px solid var(--dnv-rule-3)}
.rs-tela .rs-fase-cab,.rs-tela .rs-tarefa{display:flex;align-items:center;gap:.375rem;width:100%}
.rs-tela .rs-fase-nome{font-weight:600}
.rs-tela .rs-fase-nome,.rs-tela .rs-tarefa-titulo{flex:1 1 auto}
.rs-tela .rs-fase-tarefas{display:flex;flex-direction:column;gap:.375rem;width:100%;padding-left:.75rem}
.rs-tela .rs-fase-tarefas:empty{display:none}
.rs-tela .rs-fase .rs-tarefa-add{margin-left:.75rem}
.rs-tela .rs-tarefa .rs-sel-pessoas{flex:0 0 11rem}
/* O gatilho da escolha de responsáveis veste o mesmo campo da tela (`.rs-cmp`):
   quadrado, 1,75rem, régua da Reunião — e não a caixa arredondada do Bootstrap. */
.rs-tela .tf-pessoas .colfilter-multi__trigger{height:1.75rem;border-radius:0;
  border-color:var(--dnv-rule-2);background:var(--dnv-surface);color:var(--dnv-ink);font:.8125rem/1 var(--dnv-sans)}
.rs-tela .rs-acoes{display:flex;align-items:center;gap:.5rem;padding:.5rem .75rem;border-top:1px solid var(--dnv-rule)}
.rs-tela .rs-acoes .rs-erro{padding:0}
.rs-tela div.rs-tot{display:flex;justify-content:space-between;gap:.75rem;padding:.5rem .75rem;
  box-shadow:inset 0 1px 0 var(--dnv-rule-3);font-weight:600}
.rs-tela div.rs-tot .rs-v{font-variant-numeric:tabular-nums}
/* metas do ano: realizado e atingimento moram DENTRO da célula do mês, abaixo
   da meta — uma linha extra por área dobraria a altura da grade */
.rs-tela .rs-ano-legenda{margin:0;padding:.375rem .75rem;font-size:11px;letter-spacing:.04em;color:var(--dnv-ink-3)}
.rs-tela .rs-ano-legenda b{font-weight:600;color:var(--dnv-ink-2)}
.rs-tela .rs-anow{overflow-x:auto;padding:0 0 .5rem}
.rs-tela .rs-tbano td{vertical-align:top}
/* doze meses + área + ano cabem em 1366 sem rolar de lado: célula mais justa */
.rs-tela .rs-tbano th,.rs-tela .rs-tbano td{padding:.25rem .375rem;font-size:.8125rem}
.rs-tela .rs-dialog .rs-tbano th{top:0}   /* o contêiner que rola de lado é o `.rs-anow`, não o diálogo */
.rs-tela .rs-tbano b{display:block;font-weight:600;font-variant-numeric:tabular-nums}
.rs-tela .rs-tbano i{display:block;font-style:normal;font-size:.75rem;color:var(--dnv-ink-3);font-variant-numeric:tabular-nums}
.rs-tela .rs-tbano .rs-n i{text-transform:uppercase;letter-spacing:.04em}
.rs-tela .rs-tbano .rs-edit{cursor:pointer}
.rs-tela .rs-tbano .rs-edit:hover b{color:var(--dnv-mark)}
.rs-tela .rs-tbano .rs-err{color:var(--dnv-risco)}
/* as duas pontas presas enquanto o meio rola: o nome da área e o total do ano */
.rs-tela .rs-tbano th:first-child,.rs-tela .rs-tbano td:first-child{position:sticky;left:0;z-index:2;background:var(--dnv-surface);
  min-width:120px;max-width:170px;white-space:normal}
.rs-tela .rs-tbano thead th:first-child,.rs-tela .rs-tbano thead th:last-child{z-index:3}
.rs-tela .rs-tbano th:last-child,.rs-tela .rs-tbano td:last-child{position:sticky;right:0;z-index:2;background:var(--dnv-surface)}

/* o cabeçalho das janelas gruda no topo: fora da tela a `.rs-tb` não é sticky */
.rs-tela .rs-dialog .rs-tb th{position:sticky;z-index:1;background:var(--dnv-surface);text-transform:uppercase}
.rs-tela .rs-dialog .rs-tb td{white-space:nowrap}

/* ── 1600×900 ou maior: o gabarito cresce em bloco (mesma proporção) ───── */
@media (min-width:1600px) and (min-height:900px){
  .rs-tela{--rs-fs:14.5px}
  .rs-tela .rs-app{gap:33px;padding:20px 28px 16px}
  .rs-tela .rs-l2,.rs-tela .rs-l3{gap:33px}
  .rs-tela .rs-sep-t::before{top:-17px}
  .rs-tela .rs-sep-l::before{left:-17px}
  .rs-tela .rs-tb td{height:calc(var(--rs-fs)*2)}
  .rs-tela .rs-conta{margin:4px 0 14px}
}

/* ── até 1440px: as onze colunas das áreas cedem folga lateral ─────────── */
@media (max-width:1440px){
  .rs-tela .rs-tb th,.rs-tela .rs-tb td{padding-left:6px;padding-right:6px}
  .rs-tela .rs-tb-areas td.rs-vao,.rs-tela .rs-tb-areas th.rs-vao{padding:0 4px;width:10px}
  .rs-tela .rs-area{max-width:11rem}
}

/* ── ESTREITO (≤1100px) ou deitado (altura ≤500px): uma coluna e a página
   rola. Nesse tamanho a tela não é um terminal, é uma consulta. ────────── */
@media (max-width:1100px),(max-height:500px){
  .rs-tela{overflow:auto}
  .rs-tela .rs-app{overflow:auto;gap:18px}
  .rs-tela .rs-l2,.rs-tela .rs-l3{grid-template-columns:minmax(0,1fr);gap:18px}
  .rs-tela .rs-l3{flex:none}
  .rs-tela .rs-sep-l::before{display:none}
  .rs-tela .rs-conta{flex-wrap:wrap}
  .rs-tela .rs-graf{height:260px;flex:none}
  .rs-tela .rs-cal{grid-auto-rows:34px;flex:none}
  .rs-tela .rs-rola{flex:none;max-height:420px}
}

/* ═══ CRM · USUÁRIOS ══════════════════════════════════════════════════════
   Grade compacta no molde de /crm/pedidos/. As regras abaixo são CÓPIA
   deliberada (decisão do dono, 08/09/2026): com duas telas não dá para saber
   quais regras são do padrão e quais são do pedido. Promover a componente
   compartilhado quando aparecer a terceira cópia.
   Os chips não são cópia: reusam o `.cl-aba` das grades de clientes e
   negócios, e a página só entrou na lista de escopo daquele bloco.
   ============================================================ */
[data-pagina="crm-usuarios"] .us-tabela { table-layout: auto; }
/* Adensa por ESPAÇAMENTO, nunca por fonte menor: linha de 28-32px com a
   fonte intacta continua legível; fonte menor não. */
[data-pagina="crm-usuarios"] .us-tabela td,
[data-pagina="crm-usuarios"] .us-tabela th { padding: .1rem .5rem .1rem 0;
                                             font-size: .9375rem; }
[data-pagina="crm-usuarios"] .us-tabela thead th { position: sticky; top: 0;
                                                   z-index: 1; background: var(--surf); }
[data-pagina="crm-usuarios"] .us-filtros-col th { position: sticky; top: 1.6rem;
                                                  z-index: 3; background: var(--surf); }
/* O cabeçalho inteiro é o alvo de ordenar — botão que parece link dentro do
   <th>, não um ícone pequeno ao lado do rótulo. */
[data-pagina="crm-usuarios"] .us-ordenar {
  border: 0; background: none; padding: 0; color: inherit; font: inherit;
  font-weight: 600; text-align: left; cursor: pointer;
}
[data-pagina="crm-usuarios"] .us-seta { color: var(--crm-tinta-2); font-weight: 400; }
[data-pagina="crm-usuarios"] .us-nome { display: block; font-weight: 600; }
[data-pagina="crm-usuarios"] .us-login { display: block; font-size: .74rem;
                                         color: var(--crm-tinta-2); }
[data-pagina="crm-usuarios"] .us-codigo { font-variant-numeric: tabular-nums;
                                          font-weight: 600; margin-right: .35rem; }
[data-pagina="crm-usuarios"] .us-representante__nome { color: var(--crm-tinta-2); }
[data-pagina="crm-usuarios"] .us-num { text-align: right;
                                       font-variant-numeric: tabular-nums; }
[data-pagina="crm-usuarios"] .us-alerta { color: var(--crm-avi); font-size: .74rem; }
[data-pagina="crm-usuarios"] .us-select { width: auto; min-width: 6rem; }
[data-pagina="crm-usuarios"] .us-filtro-texto {
  width: 100%; min-width: 8rem; border: 1px solid var(--crm-borda);
  border-radius: 4px; padding: .1rem .35rem; font-size: .8125rem; font-weight: 400;
}

/* Transferir carteira (reporte #8): uma linha acima da grade, De · Para ·
   Transferir. A pergunta de confirmação toma o lugar do botão. */
[data-pagina="crm-usuarios"] .us-carteira__painel {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: .5rem 1rem;
}
[data-pagina="crm-usuarios"] .us-carteira__campo {
  display: flex; flex-direction: column; gap: .15rem; font-size: .8125rem;
  font-weight: 600; flex: 1 1 18rem; max-width: 34rem;
}
[data-pagina="crm-usuarios"] .us-carteira__confirma {
  display: flex; flex-wrap: wrap; align-items: center; gap: .5rem;
}
[data-pagina="crm-usuarios"] .us-carteira__pergunta { margin: 0; flex: 1 1 24rem; }

/* A GRADE É A TELA: ocupa a janela inteira. Medido em 08/09/2026, antes disto:
   o cartão terminava em 564px numa janela de 900 e sobravam 336px de chão
   cinza — 37% da tela vazia embaixo de uma lista que cresce toda semana.
   Mesmo padrão de `.page[data-pagina="forecast_comex"]`: a página vira coluna
   flex de altura fixa (52px é a topbar; não existe token para ela) e o cartão
   fica com a sobra, rolando por dentro com os dois cabeçalhos parados. */
.page[data-pagina="crm-usuarios"] {
  display: flex; flex-direction: column; gap: .5rem;
  height: calc(100dvh - 52px - var(--content-pad-y) - var(--content-pad-b));
}
/* O respiro entre chips, aviso, painel e cartão é o `gap` da coluna, e só
   ele. Medido em 15/09/2026: o aviso de sucesso começava no pixel em que os
   chips terminavam (0px), porque nenhuma faixa tinha margem em cima. Aviso
   vazio sai do fluxo — senão o `gap` dobrava entre chips e painel — e o
   alerta nasce `mb-0` no JS: a margem do Bootstrap é `!important` e somaria
   com o `gap`. */
.page[data-pagina="crm-usuarios"] > #us-aviso:empty { display: none; }
.page[data-pagina="crm-usuarios"] > .card { flex: 1; min-height: 0; }
.page[data-pagina="crm-usuarios"] > .card > .card-body {
  height: 100%; display: flex; flex-direction: column; min-height: 0;
}
/* O contêiner de rolagem é ESTE, e não a janela: é o que faz o `position:
   sticky` dos dois cabeçalhos grudar no topo da grade em vez de sumir com a
   página. */
.page[data-pagina="crm-usuarios"] .table-responsive-md {
  flex: 1; min-height: 0; overflow: auto;
}
[data-pagina="crm-usuarios"] .us-amarrar { display: flex; gap: .35rem;
                                           align-items: center; }
/* O chip de "representantes sem conta" CONTA e não recorta — nenhum deles é
   linha desta grade. Ele não é botão, então também não finge ser um. */
[data-pagina="crm-usuarios"] .cl-aba--informativa { cursor: default;
                                                    border-style: dashed; }

/* ═══ CRM · CLASSIFICAÇÃO ═════════════════════════════════════════════════
   Duas colunas: eixos à esquerda, opções do eixo selecionado à direita
   (item 24, dono 08/09/2026). A grade ocupa a janela inteira — mesmo padrão
   de `/crm/usuarios/` acima (medido lá: sobrava 37% de chão cinza sem isto).
   ============================================================ */
.page[data-pagina="crm-classificacao"] {
  display: flex; flex-direction: column;
  height: calc(100dvh - 52px - var(--content-pad-y) - var(--content-pad-b));
}
[data-pagina="crm-classificacao"] .cls-grade {
  display: grid; grid-template-columns: 280px 1fr; gap: 16px;
  flex: 1; min-height: 0;
}
[data-pagina="crm-classificacao"] .cls-coluna-eixos,
[data-pagina="crm-classificacao"] .cls-coluna-opcoes { min-height: 0; display: flex; flex-direction: column; }
[data-pagina="crm-classificacao"] .cls-coluna-eixos .card-body,
[data-pagina="crm-classificacao"] .cls-coluna-opcoes .card-body { flex: 1; min-height: 0; overflow: auto; }
[data-pagina="crm-classificacao"] .cls-titulo-coluna {
  font-size: .78rem; letter-spacing: .04em; text-transform: uppercase;
  color: var(--crm-tinta-2); margin-bottom: .5rem;
}
[data-pagina="crm-classificacao"] #cls-eixos { display: flex; flex-direction: column; gap: 2px; }
[data-pagina="crm-classificacao"] .cls-eixo {
  display: flex; justify-content: space-between; align-items: center; gap: .5rem;
  width: 100%; border: 0; background: none; padding: .5rem .6rem; border-radius: 6px;
  text-align: left; cursor: pointer; color: var(--crm-tinta);
}
[data-pagina="crm-classificacao"] .cls-eixo:hover { background: var(--surf-2); }
/* Eixo selecionado: fundo sólido, não borda — é o mesmo destaque de aba
   ativa que o resto do CRM usa (`.cl-aba--ativa`), sem introduzir um segundo
   vocabulário de "selecionado". */
[data-pagina="crm-classificacao"] .cls-eixo--ativo { background: var(--crm-borda); font-weight: 600; }
[data-pagina="crm-classificacao"] .cls-eixo__cadeado { margin-left: .35rem; color: var(--crm-tinta-2); }
[data-pagina="crm-classificacao"] .cls-eixo__conta {
  font-size: .78rem; color: var(--crm-tinta-2); font-variant-numeric: tabular-nums; white-space: nowrap;
}
[data-pagina="crm-classificacao"] .cls-nova-opcao { display: flex; gap: .4rem; margin-bottom: .75rem; }
[data-pagina="crm-classificacao"] .cls-tabela-opcoes td,
[data-pagina="crm-classificacao"] .cls-tabela-opcoes th { vertical-align: middle; }
/* Inativa fica NA MESMA lista, só apagada — esconder a linha esconderia
   exatamente a que o gerente precisa achar para reativar. */
[data-pagina="crm-classificacao"] .cls-opcao--inativa { color: var(--crm-tinta-2); }
[data-pagina="crm-classificacao"] .cls-opcao__uso { text-align: right; font-variant-numeric: tabular-nums; }
[data-pagina="crm-classificacao"] .cls-opcao__acoes { display: flex; gap: .35rem; justify-content: flex-end; }
[data-pagina="crm-classificacao"] .cls-situacao { font-size: .78rem; padding: 1px 8px; border-radius: 10px; }
[data-pagina="crm-classificacao"] .cls-situacao--ativa { background: #e6f4ea; color: var(--crm-ok); }
[data-pagina="crm-classificacao"] .cls-situacao--inativa { background: var(--surf-3); color: var(--crm-tinta-2); }

@media (max-width: 768px) {
  [data-pagina="crm-classificacao"] .cls-grade { grid-template-columns: 1fr; }
}

/* ==========================================================================
   CRM · Fita de variantes da proposta (tela do negócio)
   Um negócio pode ter propostas IRMÃS — a A e a B: recotar sem apagar a
   cotação anterior, ou partir o orçamento por família. A fita é a linha de
   abas acima do bloco de itens; ela só desenha as abas quando há mais de uma
   variante (quem decide é o backend, `_fita_de_variantes`), e as duas ações
   ficam sempre à mão porque é por elas que a segunda proposta nasce.
   ========================================================================== */
.crm-variantes { display: flex; flex-wrap: wrap; align-items: center;
  gap: .35rem; margin-bottom: .85rem;
  padding-bottom: .5rem; border-bottom: 1px solid var(--crm-borda); }
.crm-variante { display: inline-flex; flex-direction: column; align-items: flex-start;
  gap: .05rem; padding: .3rem .6rem; border-radius: 8px;
  background: var(--crm-superficie); border: 1px solid var(--crm-borda);
  color: var(--crm-tinta-2); cursor: pointer; text-align: left;
  transition: border-color .15s ease, background .15s ease, color .15s ease; }
.crm-variante:hover { border-color: var(--crm-borda-forte); color: var(--crm-tinta); }
/* A em foco é a que a tela está falando: borda no verde do funil e tinta
   cheia. Fundo continua branco — cinza aqui leria como desabilitada. */
.crm-variante--foco { border-color: var(--crm-tom-2); color: var(--crm-tinta);
  box-shadow: inset 0 0 0 1px var(--crm-tom-2); cursor: default; }
.crm-variante__nome { font-size: var(--bi-fs-compact); font-weight: 600; }
.crm-variante__estado { font-size: .6875rem; color: var(--crm-tinta-3); }
.crm-variante__acao { margin-left: .2rem; }
.crm-variantes__aviso { flex-basis: 100%; font-size: .6875rem;
  color: var(--crm-tinta-3); }

/* ===== E-MAIL MARKETING ===== */
/* Canvas de "Nova campanha" carrega assunto + remetente + corpo HTML +
   segmentação de listas — a largura padrão (22.5rem) espreme o textarea do
   corpo. Mesmo padrão de largura por classe do CRM (.crm-oc--larga etc.). */
[data-pagina="email-marketing"] .fem-canvas--larga { --bs-offcanvas-width: min(34rem, 96vw); }
/* Base de contatos é grade de dados (5 colunas, uma delas com form de edição
   inline) — a largura de formulário (34rem) fica cheia de scroll horizontal. */
[data-pagina="email-marketing"] .fem-canvas--xlarga { --bs-offcanvas-width: min(64rem, 96vw); }

/* A GRADE É A TELA (regra dura, mesmo padrão de .page[data-pagina="crm-usuarios"]):
   ocupa a janela inteira mesmo vazia — nunca só a altura do conteúdo. Os
   offcanvas são irmãos do .card dentro de .page, mas `position:fixed` do
   Bootstrap os tira do fluxo — não competem pela altura flex. */
.page[data-pagina="email-marketing"] {
  display: flex; flex-direction: column;
  height: calc(100dvh - 52px - var(--content-pad-y) - var(--content-pad-b));
}
.page[data-pagina="email-marketing"] > .card { flex: 1; min-height: 0; }
.page[data-pagina="email-marketing"] > .card > .card-body {
  height: 100%; display: flex; flex-direction: column; min-height: 0;
}
.page[data-pagina="email-marketing"] .table-responsive { flex: 1; min-height: 0; overflow: auto; }

/* ═══════════════════════════════════════════════════════════════════════════
   DESPESAS — VERSÃO NOVA (`/despesas/nova/`, em teste ao lado da atual)

   PORTE FIEL do mockup "Os Três Baldes" (`docs/redesign/mockups/
   despesas-tres-baldes.html`), aprovado pelo dono. As regras abaixo são as DO
   MOCKUP, valor por valor: nenhum tamanho, peso, cor, raio ou espaçamento foi
   reinterpretado. Não editar por gosto — mudança aqui é divergência do desenho
   aprovado; mude o mockup primeiro, que é o gabarito.

   O porte é MECÂNICO, feito por script (`scratchpad/portar_css.py`), e só faz
   três coisas:

     1. Toda classe `.foo` vira `.dnv-foo`. O mockup inventou 133 classes com
        nomes ultracurtos (`.k .n .cel .bt .dir .obs`), e `.grade` sozinha
        colide com 104 regras deste arquivo, que é lido por ~28 telas.
     2. Todo token vira `--dnv-*`. Seis dos 24 (`--ink`, `--ink-2/3/4`,
        `--sans`, `--mono`) já são nomes do `:root` daqui; prefixar só esses
        deixaria armadilha para o próximo token global. `DESIGN.md`: sequestrar
        nome global é proibido.
     3. Todo seletor nasce em `.page[data-pagina="despesas-nova"]`, e o
        `:root`/`html`/`body` do mockup viram esse mesmo seletor.

   O CABEÇALHO do mockup (`.trilho`: marca, Período, Segmento) NÃO está aqui.
   Ele é a L3 — o piloto do shell novo. Nesta aterrissagem o período e o
   segmento continuam vindo da barra de filtros do shell, já ligada ao
   `biFiltros`; desenhar os dois seria duplicar o controle.

   Logo abaixo, e separado de propósito, o único lugar onde o porte não é
   literal: o que o SHELL obriga a mudar.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── O PORTE, literal daqui para baixo ──────────────────────────────────── */
/* ════════════════════════════════════════════════════════════════
   Instrumento, não painel. Tinta + uma cor de estado. Cantos retos.
   Sem rolagem de página: os painéis rolam por dentro.
   ════════════════════════════════════════════════════════════════ */
/* Relatórios entra na LISTA DE SELETORES desta regra e não copia os 24 valores
   (seção RELATÓRIOS, no fim do arquivo): o dono pediu a mesma pele para o
   construtor (15/09/2026), e um segundo jogo de tokens com os mesmos números
   seriam duas verdades sobre a mesma cor. O alcance é o menor possível: só o
   CONSTRUTOR (`.rel-construtor`) e a barra que carrega o seletor dele — a
   LISTA divide a chave `relatorios` mas é a grade da casa e não lê nenhum
   `--dnv-*`. Nada mais da seção DESPESAS (porte literal do mockup aprovado) é
   tocado. A Reunião Semanal entra na mesma lista pelo mesmo motivo (dono,
   17/09/2026): mesma pele, uma verdade só sobre cada cor. */
.page[data-pagina="despesas-nova"], #topbar:has(.dnv-sel),
.page[data-pagina="relatorios"].rel-construtor, #topbar:has(.rel-sel),
.page[data-pagina="reuniao_semanal"],
.page[data-pagina="tarefas"], #topbar:has(.tf-busca){ --dnv-ground:#E9EBEE; --dnv-surface:#FFFFFF;  --dnv-surface-2:#F5F6F8;  --dnv-surface-3:#EEF0F3; --dnv-ink:#0B0E12;     --dnv-ink-2:#525A66;    --dnv-ink-3:#666E7A;      --dnv-ink-4:#666E7A; --dnv-rule:#D8DCE1;    --dnv-rule-2:#C2C8D0;   --dnv-rule-3:#9AA2AC; --dnv-mark:#1A3E7A;    --dnv-mark-wash:#E7EDF6; --dnv-risco:#9E1B10;   --dnv-risco-wash:#FBEDEB; --dnv-risco-rule:#E4B6B0; --dnv-risco-tinta:#FFFFFF; --dnv-wash:#DFE3E8; --dnv-graf:#3B5F96;    --dnv-graf-area:#CFDAEA;  --dnv-graf-area-2:#E4EBF4; --dnv-graf-eixo:#C6CDD6; --dnv-sans:var(--sans);   /* a fonte é a do shell (decisão do dono, 12/09) */ --dnv-mono:var(--dnv-sans); color-scheme:light; }
/* Tema escuro removido: o projeto tem tema claro fixo ("Tema claro é fixo.
   Não existe modo escuro neste produto." — PRODUCT.md). Eram dois blocos, o
   segundo cópia literal do primeiro. */
.page[data-pagina="despesas-nova"] *{ box-sizing:border-box }
.page[data-pagina="despesas-nova"]{ height:100% }
.page[data-pagina="despesas-nova"]{ margin:0; background:var(--dnv-ground); color:var(--dnv-ink); font-family:var(--dnv-sans); font-size:13.5px; line-height:1.45; -webkit-font-smoothing:antialiased; overflow:hidden; }
/* O filtro de coluna da casa (`colfilter-multi`) fica FORA desta limpeza: sem
   borda e sem fundo o gatilho virava três peças soltas na largura da coluna —
   funil à esquerda, "Todos" no meio, seta na ponta. `:where` mantém a
   especificidade da regra, então nenhum outro botão da tela muda. */
.page[data-pagina="despesas-nova"] button:not(:where(.colfilter-multi__trigger)){ font:inherit; color:inherit; background:none; border:none; padding:0; cursor:pointer; text-align:left }
.page[data-pagina="despesas-nova"] :focus-visible{ outline:2px solid var(--dnv-mark); outline-offset:1px }
@media (prefers-reduced-motion:reduce){
  .page[data-pagina="despesas-nova"] *{ transition:none!important }
}
.page[data-pagina="despesas-nova"] .dnv-n, .page[data-pagina="despesas-nova"] .dnv-faixa__v, .page[data-pagina="despesas-nova"] .dnv-total, .page[data-pagina="despesas-nova"] .dnv-comp__p, .page[data-pagina="despesas-nova"] .dnv-comp__a, .page[data-pagina="despesas-nova"] .dnv-risco__n, .page[data-pagina="despesas-nova"] .dnv-pux__v, .page[data-pagina="despesas-nova"] .dnv-cel, .page[data-pagina="despesas-nova"] .dnv-faixa__ref, .page[data-pagina="despesas-nova"] .dnv-faixa__d b, .page[data-pagina="despesas-nova"] .dnv-faixa__x{ font-variant-numeric:tabular-nums; font-feature-settings:"tnum" 1, "lnum" 1; }
.page[data-pagina="despesas-nova"] .dnv-k{ font-size:10px; letter-spacing:.11em; text-transform:uppercase; color:var(--dnv-ink-3); font-weight:600 }
.page[data-pagina="despesas-nova"] .dnv-sobe{ color:var(--dnv-risco) }
.page[data-pagina="despesas-nova"] .dnv-cai{ color:var(--dnv-ink-2) }
/* ── ESTRUTURA ─────────────────────────────────────────────────── */
.page[data-pagina="despesas-nova"] .dnv-app{ height:100dvh; display:grid; grid-template-rows:auto 1fr; grid-template-columns:352px 1fr; grid-template-areas:"trilho trilho" "lado palco"; background:var(--dnv-rule); gap:1px; }
/* ── TRILHO ────────────────────────────────────────────────────── */
.page[data-pagina="despesas-nova"] .dnv-busca{ font:inherit; font-size:12px; color:var(--dnv-ink); background:var(--dnv-surface-2); border:none; border-left:1px solid var(--dnv-rule); border-radius:0; padding:0 16px; height:100%; width:268px; }
.page[data-pagina="despesas-nova"] .dnv-busca::placeholder{ color:var(--dnv-ink-3) }
.page[data-pagina="despesas-nova"] .dnv-busca:focus{ background:var(--dnv-surface); outline-offset:-2px }
/* ── LADO: a leitura do período ────────────────────────────────── */
.page[data-pagina="despesas-nova"] .dnv-lado{ grid-area:lado; background:var(--dnv-surface); overflow-y:auto; display:flex; flex-direction:column; }
.page[data-pagina="despesas-nova"] .dnv-bloco{ padding:26px 24px }
.page[data-pagina="despesas-nova"] .dnv-nota{ padding:16px 24px 22px; margin:0; font-size:10.5px; color:var(--dnv-ink-4); line-height:1.5 }
.page[data-pagina="despesas-nova"] .dnv-total{ font-size:clamp(27px,2.9vw,37px); font-weight:600; letter-spacing:-.035em; line-height:1.05; margin:10px 0 0; white-space:nowrap }
.page[data-pagina="despesas-nova"] .dnv-total__sub{ margin:12px 0 0; font-size:12px; color:var(--dnv-ink-3); line-height:1.7 }
.page[data-pagina="despesas-nova"] .dnv-parcial{ display:inline-block; margin-left:2px; padding:1px 6px; font-size:10.5px; font-weight:600; color:var(--dnv-ink-2); background:var(--dnv-wash); }
.page[data-pagina="despesas-nova"] .dnv-livro{ margin:16px 0 0; font-size:12px; color:var(--dnv-ink-3) }
.page[data-pagina="despesas-nova"] .dnv-livro b{ color:var(--dnv-ink); font-weight:600 }
.page[data-pagina="despesas-nova"] .dnv-livro__x{ display:block; margin-top:6px; font-size:11px; color:var(--dnv-ink-4); line-height:1.55 }
.page[data-pagina="despesas-nova"] .dnv-trata__aviso{ margin:0; font-size:11.5px; color:var(--dnv-ink-2); line-height:1.5; padding-left:11px; border-left:2px solid var(--dnv-rule-3); }
/* comparação */
.page[data-pagina="despesas-nova"] .dnv-comp__n{ display:flex; align-items:baseline; gap:11px; margin-top:8px }
.page[data-pagina="despesas-nova"] .dnv-comp__p{ font-size:26px; font-weight:600; letter-spacing:-.03em }
.page[data-pagina="despesas-nova"] .dnv-comp__a{ font-size:13px; color:var(--dnv-ink-2) }
.page[data-pagina="despesas-nova"] .dnv-comp__b{ margin:10px 0 0; font-size:12px; color:var(--dnv-ink-3) }
.page[data-pagina="despesas-nova"] .dnv-comp__b b{ color:var(--dnv-ink-2); font-weight:600 }
/* suspeita */
.page[data-pagina="despesas-nova"] .dnv-risco{ display:block; width:100%; padding:12px 0 0; text-align:left }
.page[data-pagina="despesas-nova"] .dnv-risco:hover .dnv-risco__n{ text-decoration:underline }
.page[data-pagina="despesas-nova"] .dnv-risco__l{ display:flex; align-items:baseline; gap:11px }
.page[data-pagina="despesas-nova"] .dnv-risco__n{ font-size:26px; font-weight:600; color:var(--dnv-risco); letter-spacing:-.03em }
.page[data-pagina="despesas-nova"] .dnv-risco__v{ font-size:13px; color:var(--dnv-ink-3) }
.page[data-pagina="despesas-nova"] .dnv-risco__t{ margin:8px 0 0; font-size:11.5px; color:var(--dnv-ink-3) }
.page[data-pagina="despesas-nova"] .dnv-risco__t b{ color:var(--dnv-ink-2); font-weight:600 }
/* barras de composição da fila */
/* ── PALCO: os três baldes como painéis de expansão ────────────── */
/* Aviso de falha de render. Nasce escondido (só existe quando algo lançou) e
   fica no topo do palco, por cima da leitura anterior. */
.page[data-pagina="despesas-nova"] .dnv-falhou{ margin:0; padding:10px 16px; background:var(--dnv-risco-wash); border-bottom:1px solid var(--dnv-risco-rule); color:var(--dnv-risco); font-size:12.5px; font-weight:500; }
.page[data-pagina="despesas-nova"] .dnv-palco{ grid-area:palco; display:flex; flex-direction:column; gap:1px; overflow:hidden; background:var(--dnv-rule) }
.page[data-pagina="despesas-nova"] .dnv-pan{ background:var(--dnv-surface); display:flex; flex-direction:column; min-height:0; overflow:hidden }
/* Repartição da altura: as faixas fechadas crescem COM a tela até um teto (o
   gráfico de 12 meses cabia em 64px e agora respira), e o painel aberto fica
   com o resto. Antes o aberto comia tudo e sobravam 373px de branco sob uma
   tabela de 8 linhas numa tela de 1920; depois eu inverti e esmaguei o painel.
   O teto nas fechadas é o que equilibra. */
.page[data-pagina="despesas-nova"] .dnv-pan[data-aberto="1"]{ flex:0 1 auto; min-height:0 }
/* Só a faixa FECHADA estica — na aberta, `height:100%` fazia a faixa comer o
   painel inteiro e o miolo sobrava com 270px. */
.page[data-pagina="despesas-nova"] .dnv-pan[data-aberto="0"]{ flex:0 0 auto; height:clamp(118px, 15vh, 176px) }
.page[data-pagina="despesas-nova"] .dnv-pan[data-aberto="0"] .dnv-faixa{ height:100% }
/* NADA aberto (é o estado inicial, por ordem do dono): as três faixas dividem a
   altura em vez de ficarem no teto com 547px de vazio embaixo numa tela de 1920.
   O teto existe para equilibrar com um painel ABERTO ao lado; sem nenhum aberto
   ele só empurra a tela para um rodapé branco. O gráfico de 12 meses é quem
   ganha a folga — é a leitura que a faixa fechada existe para dar. */
/* `min-height` e não só `flex:1 1 0`: no celular o palco ROLA em vez de ter
   altura fixa, e a base flexível de 0 colapsava as três faixas para 0px. O piso
   é o mesmo teto de antes, então no estreito nada muda. */
.page[data-pagina="despesas-nova"] .dnv-palco:not(:has(.dnv-pan[data-aberto="1"])) .dnv-pan{ flex:1 1 auto; height:auto; max-height:none; min-height:clamp(118px, 15vh, 176px); }
/* ...e o preenchimento de sobra para de crescer, senão ele disputa a folga com
   as faixas e sobram 259px de branco justamente no estado inicial da tela. */
.page[data-pagina="despesas-nova"] .dnv-palco:not(:has(.dnv-pan[data-aberto="1"]))::after{ flex:0 0 auto }
/* O cinza é a cor do VÃO de 1px entre painéis, não um fundo. A sobra de altura
   ganha um preenchimento próprio em superfície — antes ela aparecia como uma
   faixa cinza de 78px colada no rodapé. Só funciona porque o painel aberto
   deixou de ser elástico: um `flex:1 1 0` roubaria esta folga de volta. */
.page[data-pagina="despesas-nova"] .dnv-palco::after{ content:""; flex:1 1 auto; min-height:0; background:var(--dnv-surface) }
.page[data-pagina="despesas-nova"] .dnv-pan:last-child .dnv-faixa{ padding-bottom:10px }
/* faixa fechada — sempre visível, densa */
.page[data-pagina="despesas-nova"] .dnv-faixa{ display:grid; align-items:center; gap:20px; width:100%; padding:0 18px 0 20px; height:106px; flex:0 0 auto; /* Toda coluna com minmax(0,…) para poder encolher: com larguras fixas a faixa media 780px numa caixa de 557 e a seta era desenhada FORA do painel de ~900px a ~1400px — some justamente o único sinal de que a faixa abre. */ grid-template-columns:minmax(0,172px) minmax(0,152px) minmax(0,128px) minmax(140px,1fr) minmax(0,62px) minmax(0,132px) 20px; border-left:3px solid transparent; }
.page[data-pagina="despesas-nova"] .dnv-faixa:hover{ background:var(--dnv-surface-2) }
.page[data-pagina="despesas-nova"] .dnv-pan[data-aberto="1"] .dnv-faixa{ border-left-color:var(--dnv-mark); background:var(--dnv-surface-2) }
.page[data-pagina="despesas-nova"] .dnv-faixa__nome{ font-size:14px; font-weight:600; letter-spacing:-.01em }
.page[data-pagina="despesas-nova"] .dnv-faixa__v{ font-size:21px; font-weight:600; letter-spacing:-.025em }
.page[data-pagina="despesas-nova"] .dnv-faixa__d{ font-size:12px; line-height:1.45 }
.page[data-pagina="despesas-nova"] .dnv-faixa__d b{ font-weight:600; font-size:14px; display:block; letter-spacing:-.015em }
.page[data-pagina="despesas-nova"] .dnv-faixa__d span{ color:var(--dnv-ink-3); font-size:11px }
.page[data-pagina="despesas-nova"] .dnv-faixa__g{ display:flex; flex-direction:column; gap:4px; min-width:0; height:100%; padding-block:14px; justify-content:center }
/* Sem teto: com os três baldes fechados a 1080px cada faixa tem ~340px e o gráfico
   parava em 150, deixando uma faixa branca em cima e embaixo. */
.page[data-pagina="despesas-nova"] .dnv-faixa__g-d{ display:block; flex:1 1 auto; min-height:56px }
.page[data-pagina="despesas-nova"] .dnv-faixa__g-d svg{ width:100%; height:100%; display:block }
.page[data-pagina="despesas-nova"] .dnv-faixa__x{ position:relative; height:13px; font-size:9.5px; color:var(--dnv-ink-4) }
.page[data-pagina="despesas-nova"] .dnv-faixa__x span{ position:absolute; top:0; transform:translateX(-50%); white-space:nowrap; padding-top:4px }
.page[data-pagina="despesas-nova"] .dnv-faixa__x span::before{ content:""; position:absolute; top:0; left:50%; width:1px; height:3px; background:var(--dnv-rule-2) }
.page[data-pagina="despesas-nova"] .dnv-faixa__x--mudo span{ color:transparent }
.page[data-pagina="despesas-nova"] .dnv-faixa__ref{ font-size:10.5px; color:var(--dnv-ink-3); white-space:nowrap; line-height:1.5 }
.page[data-pagina="despesas-nova"] .dnv-faixa__leg{ display:block; font-size:9px; color:var(--dnv-ink-4); white-space:normal; max-width:74px }
.page[data-pagina="despesas-nova"] .dnv-faixa__r{ font-size:11.5px; line-height:1.45 }
.page[data-pagina="despesas-nova"] .dnv-faixa__r b{ color:var(--dnv-risco); font-weight:600; font-family:var(--dnv-mono) }
.page[data-pagina="despesas-nova"] .dnv-faixa__r span{ color:var(--dnv-ink-3); display:block; font-size:11px }
.page[data-pagina="despesas-nova"] .dnv-faixa__r.dnv-limpo{ color:var(--dnv-ink-4) }
.page[data-pagina="despesas-nova"] .dnv-faixa__r.dnv-achou b{ color:var(--dnv-mark) }
.page[data-pagina="despesas-nova"] .dnv-faixa__r.dnv-achou span{ color:var(--dnv-ink-3) }
.page[data-pagina="despesas-nova"] .dnv-pux__mais{ margin:9px 0 0; font-size:11px; color:var(--dnv-ink-3) }
.page[data-pagina="despesas-nova"] .dnv-cursor{ font-size:12px; color:var(--dnv-ink-3); text-align:center; transition:transform .15s ease }
.page[data-pagina="despesas-nova"] .dnv-pan[data-aberto="1"] .dnv-cursor{ transform:rotate(90deg); color:var(--dnv-mark) }
/* miolo aberto */
/* A coluna da esquerda cede até 300px antes de a grade empilhar: fixa em 376px,
   o nome da conta ficava com 152px em 1281. */
.page[data-pagina="despesas-nova"] .dnv-miolo{ flex:1 1 auto; min-height:0; display:grid; grid-template-columns:clamp(300px, 26vw, 376px) 1fr; border-top:1px solid var(--dnv-rule); background:var(--dnv-rule); gap:1px }
.page[data-pagina="despesas-nova"] .dnv-miolo__e{ background:var(--dnv-surface-2); overflow-y:auto; padding:22px 24px 28px }
.page[data-pagina="despesas-nova"] .dnv-miolo__d{ background:var(--dnv-surface); overflow-y:auto; min-height:0; display:flex; flex-direction:column }
.page[data-pagina="despesas-nova"] .dnv-miolo__d > div{ display:flex; flex-direction:column; min-height:100% }
.page[data-pagina="despesas-nova"] .dnv-miolo__d table{ flex:0 0 auto }
.page[data-pagina="despesas-nova"] .dnv-miolo__d .dnv-pe{ margin-top:auto }
.page[data-pagina="despesas-nova"] .dnv-sec + .dnv-sec{ margin-top:26px; padding-top:22px; border-top:1px solid var(--dnv-rule) }
/* Coluna estreita (1281–1400px): o alternador desce inteiro em vez de os botões
   quebrarem em "Mês / anterior". */
.page[data-pagina="despesas-nova"] .dnv-sec__cab{ display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:11px; flex-wrap:wrap; row-gap:8px }
.page[data-pagina="despesas-nova"] .dnv-troca{ display:flex; border:1px solid var(--dnv-rule-2) }
.page[data-pagina="despesas-nova"] .dnv-troca button{ white-space:nowrap; padding:6px 10px; font-size:10.5px; color:var(--dnv-ink-3); letter-spacing:.03em }
.page[data-pagina="despesas-nova"] .dnv-troca button + button{ border-left:1px solid var(--dnv-rule-2) }
.page[data-pagina="despesas-nova"] .dnv-troca button[aria-pressed="true"]{ background:var(--dnv-ink); color:var(--dnv-surface); font-weight:600 }
.page[data-pagina="despesas-nova"] .dnv-troca button[disabled], .page[data-pagina="despesas-nova"] .dnv-troca button[aria-disabled="true"]{ opacity:.4; cursor:not-allowed }
.page[data-pagina="despesas-nova"] .dnv-pux{ display:flex; flex-direction:column }
.page[data-pagina="despesas-nova"] .dnv-pux__l{ display:grid; grid-template-columns:1fr auto; gap:12px; align-items:baseline; padding:7px 0 }
.page[data-pagina="despesas-nova"] .dnv-pux__l + .dnv-pux__l{ border-top:1px solid var(--dnv-rule) }
.page[data-pagina="despesas-nova"] .dnv-pux__t{ display:flex; align-items:baseline; gap:0; min-width:0; font-size:12.5px }
.page[data-pagina="despesas-nova"] .dnv-pux__t > .dnv-pux__n{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.page[data-pagina="despesas-nova"] .dnv-pux__t > .dnv-marca-t{ flex:none }
.page[data-pagina="despesas-nova"] .dnv-pux__c{ flex:none; font-size:11px; color:var(--dnv-ink-3); margin-right:8px; font-variant-numeric:tabular-nums }
.page[data-pagina="despesas-nova"] .dnv-pux__v{ font-size:12.5px; font-weight:600; white-space:nowrap; font-variant-numeric:tabular-nums }
.page[data-pagina="despesas-nova"] .dnv-marca-t{ display:inline-block; margin-left:7px; padding:0 5px; font-size:10px; font-weight:600; color:var(--dnv-ink-2); background:var(--dnv-wash); border-left:2px solid var(--dnv-rule-3); }
.page[data-pagina="despesas-nova"] .dnv-marca-t--r{ color:var(--dnv-risco); background:var(--dnv-risco-wash); border-left-color:var(--dnv-risco) }
/* veredito + tira de pontos (substituiu o medidor com cara de slider) */
.page[data-pagina="despesas-nova"] .dnv-vered{ margin:0 0 6px; font-size:13.5px; font-weight:600; line-height:1.4; color:var(--dnv-ink) }
.page[data-pagina="despesas-nova"] .dnv-vered__e{ margin:0 0 12px; font-size:12px; color:var(--dnv-ink-2); line-height:1.5 }
.page[data-pagina="despesas-nova"] .dnv-vered__e b{ color:var(--dnv-ink); font-weight:600 }
.page[data-pagina="despesas-nova"] .dnv-tira{ display:block; width:100%; height:auto; overflow:visible }
.page[data-pagina="despesas-nova"] .dnv-tira text{ font-family:var(--dnv-sans) }
.page[data-pagina="despesas-nova"] .dnv-tira__c{ margin:6px 0 0; font-size:10.5px; color:var(--dnv-ink-4); line-height:1.5 }
.page[data-pagina="despesas-nova"] .dnv-mudo{ font-size:12px; color:var(--dnv-ink-2); line-height:1.55; margin:0 }
.page[data-pagina="despesas-nova"] .dnv-mudo b{ color:var(--dnv-ink); font-weight:600 }
/* tabela de contas — larguras na própria tabela, não em dois grids paralelos */
.page[data-pagina="despesas-nova"] .dnv-grade{ width:100%; border-collapse:collapse; table-layout:fixed }
/* O gabarito não declara `<!doctype>` e roda em quirks mode, onde tabela NÃO
   herda `line-height`: as linhas foram aprovadas com `normal` (33px). Aqui, em
   modo padrão, herdavam 1.45 e cada linha saía 4px mais alta — oito contas, 32px
   a mais de grade. A medição achou; o olho não. */
.page[data-pagina="despesas-nova"] .dnv-grade, .page[data-pagina="despesas-nova"] .dnv-lanc__wrap table{ line-height:normal }
.page[data-pagina="despesas-nova"] .dnv-grade col.dnv-c-exp{ width:34px }
/* Os números são curtos ("31,1%", "+R$ 227.265", "R$ 1.283.515"); com 376px
   reservados para eles, o nome da conta ficava com 91px em 1280. */
.page[data-pagina="despesas-nova"] .dnv-grade col.dnv-c-pct{ width:92px }
.page[data-pagina="despesas-nova"] .dnv-grade col.dnv-c-delta{ width:108px }
.page[data-pagina="despesas-nova"] .dnv-grade col.dnv-c-val{ width:116px }
.page[data-pagina="despesas-nova"] .dnv-grade thead th{ position:sticky; top:0; z-index:2; background:var(--dnv-surface-3); padding:9px 14px; font-size:9.5px; letter-spacing:.1em; text-transform:uppercase; color:var(--dnv-ink-3); font-weight:600; border-bottom:1px solid var(--dnv-rule-2); white-space:nowrap; text-align:left; }
.page[data-pagina="despesas-nova"] .dnv-grade th.dnv-dir, .page[data-pagina="despesas-nova"] .dnv-grade td.dnv-dir{ text-align:right }
.page[data-pagina="despesas-nova"] .dnv-grade tbody th, .page[data-pagina="despesas-nova"] .dnv-grade tbody td{ padding:9px 14px; border-bottom:1px solid var(--dnv-rule); font-weight:400; text-align:left; }
.page[data-pagina="despesas-nova"] .dnv-grade tbody th{ font-size:12.5px; overflow:hidden }
.page[data-pagina="despesas-nova"] .dnv-linha{ border-left:2px solid transparent; cursor:pointer }
.page[data-pagina="despesas-nova"] .dnv-linha:hover{ background:var(--dnv-surface-2) }
.page[data-pagina="despesas-nova"] .dnv-linha--aberta{ background:var(--dnv-mark-wash) }
.page[data-pagina="despesas-nova"] .dnv-linha--aberta > *:first-child{ box-shadow:inset 2px 0 0 var(--dnv-mark) }
.page[data-pagina="despesas-nova"] .dnv-cel-exp{ padding-right:0!important; width:34px }
/* Código e nome em DUAS COLUNAS fixas. Em flex com quebra, o nome que não cabia
   ao lado do código descia inteiro para baixo dele: a coluna ficava torta (uns
   nomes em x=871, outros em x=827) e, cortado com reticências, "Custos de frete
   internaci…" não dizia que conta era. Agora o nome quebra DENTRO da coluna. */
.page[data-pagina="despesas-nova"] .dnv-cel-nome__in{ display:grid; grid-template-columns:44px minmax(0,1fr); align-items:baseline; row-gap:3px; min-width:0 }
.page[data-pagina="despesas-nova"] .dnv-conta__c{ font-size:11px; color:var(--dnv-ink-3); font-variant-numeric:tabular-nums }
/* O nome tem PISO e a etiqueta cede. Entre 1181 e 1280px o flex descontava tudo
   do nome — 0 a 8px de 97 — e a linha mostrava "1061" ao lado de "142 sob
   suspeita", sem dizer que conta era. A etiqueta é contexto; o nome é a
   identidade da linha, e identidade não cede primeiro. */
.page[data-pagina="despesas-nova"] .dnv-conta__n{ min-width:0; overflow-wrap:anywhere }
.page[data-pagina="despesas-nova"] .dnv-cel-nome__in > .dnv-conta__n:first-child{ grid-column:1/-1 }
/* A etiqueta cede DESCENDO, não encolhendo: espremida a 12px ela vira três
   pontinhos que não informam nada, e é justamente onde ela mais importa (é ela
   que diz QUAL conta concentra a suspeita — a faixa só diz o total do balde).
   Quebrar para a linha de baixo custa altura e preserva a leitura. */
.page[data-pagina="despesas-nova"] .dnv-cel-nome__in > .dnv-marca-t{ grid-column:2; justify-self:start; white-space:nowrap }
/* O `›` é 4×12px — a linha inteira reencaminha o clique, mas o alvo FOCÁVEL
   (e portanto o anel de foco do teclado) era esse retângulo de 48px². Padding
   negativo não muda o layout da célula e triplica a área. */
.page[data-pagina="despesas-nova"] .dnv-conta{ display:block; padding:10px 12px; margin:-10px -12px; line-height:1 }
.page[data-pagina="despesas-nova"] .dnv-cur{ display:inline-block; font-size:10px; color:var(--dnv-ink-3); transition:transform .15s ease }
.page[data-pagina="despesas-nova"] .dnv-conta[aria-expanded="true"] .dnv-cur{ transform:rotate(90deg); color:var(--dnv-mark) }
.page[data-pagina="despesas-nova"] .dnv-cel{ font-size:12px; color:var(--dnv-ink-2); font-variant-numeric:tabular-nums }
.page[data-pagina="despesas-nova"] .dnv-cel--v{ font-size:12.5px; color:var(--dnv-ink); font-weight:600 }
.page[data-pagina="despesas-nova"] .dnv-grade tfoot th, .page[data-pagina="despesas-nova"] .dnv-grade tfoot td{ padding:11px 14px; border-top:1px solid var(--dnv-rule-2); background:var(--dnv-surface-2); font-weight:600; font-size:12px; text-align:left; }
.page[data-pagina="despesas-nova"] .dnv-grade tfoot td.dnv-dir{ text-align:right }
.page[data-pagina="despesas-nova"] .dnv-grade tfoot{ position:sticky; bottom:0 }
/* lançamentos */
.page[data-pagina="despesas-nova"] .dnv-lanc{ background:var(--dnv-surface-2); padding:0!important }
.page[data-pagina="despesas-nova"] .dnv-lanc-linha[hidden]{ display:none }
.page[data-pagina="despesas-nova"] .dnv-lanc table{ width:100%; border-collapse:collapse; font-size:11.5px }
.page[data-pagina="despesas-nova"] .dnv-lanc th{ text-align:left; padding:6px 14px; font-size:9px; letter-spacing:.1em; text-transform:uppercase; color:var(--dnv-ink-3); font-weight:600; border-bottom:1px solid var(--dnv-rule); white-space:nowrap; }
.page[data-pagina="despesas-nova"] .dnv-lanc td{ padding:7px 14px; border-bottom:1px solid var(--dnv-rule); vertical-align:top }
/* A observação traz tokens sem espaço (chave de CT-e de 44 dígitos, `RCTR-C-…|RC-DC…`)
   e, com `table-layout:auto`, a coluna nunca ficava mais estreita que eles: entre
   1300 e 1700px a tabela passava da gaveta e o VALOR saía cortado à direita. Pelo
   mesmo motivo os rótulos do cabeçalho podem quebrar; a linha de filtros não muda. */
.page[data-pagina="despesas-nova"] .dnv-lanc td{ overflow-wrap:anywhere }
.page[data-pagina="despesas-nova"] .dnv-lanc thead tr:first-child th, .page[data-pagina="despesas-nova"] .dnv-lanc thead tr:first-child th *{ white-space:normal }
.page[data-pagina="despesas-nova"] .dnv-lanc .dnv-dir{ white-space:nowrap }
.page[data-pagina="despesas-nova"] .dnv-grade td.dnv-dir, .page[data-pagina="despesas-nova"] .dnv-grade th.dnv-dir{ white-space:nowrap }
.page[data-pagina="despesas-nova"] .dnv-lanc tr:last-child td{ border-bottom:none }
.page[data-pagina="despesas-nova"] .dnv-lanc .dnv-dir{ text-align:right }
.page[data-pagina="despesas-nova"] .dnv-lanc .dnv-obs{ color:var(--dnv-ink-2); max-width:300px }
.page[data-pagina="despesas-nova"] .dnv-lanc tr.dnv-viciada td{ background:var(--dnv-risco-wash) }
/* Lançamentos em BRANCO (dono, 15/09): o cinza da gaveta lia como bloco desligado.
   Escurecem o que está sob o mouse e o que está selecionado — caixa marcada ou
   painel de tratamento aberto. */
.page[data-pagina="despesas-nova"] .dnv-lanc tbody tr:not(.dnv-viciada):not(.dnv-trata) > td{ background:var(--dnv-surface) }
.page[data-pagina="despesas-nova"] .dnv-lanc tbody tr:not(.dnv-trata):is(:hover, :has([data-dnv-sel]:checked), :has([data-dnv-tratar][aria-expanded="true"])) > td{ background:var(--dnv-surface-3) }
.page[data-pagina="despesas-nova"] .dnv-lanc__nota{ margin:0; padding:11px 14px; font-size:11.5px; color:var(--dnv-ink-3) }
.page[data-pagina="despesas-nova"] .dnv-lanc__nota b{ color:var(--dnv-ink-2); font-weight:600 }
/* Sem suspeita a barra de lote vem vazia — e com 10px de respiro em cima e embaixo
   era uma faixa branca de 21px entre a conta aberta e o cabeçalho da gaveta. */
.page[data-pagina="despesas-nova"] .dnv-lote:empty{ display:none }
.page[data-pagina="despesas-nova"] .dnv-lote{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; padding:10px 14px; border-bottom:1px solid var(--dnv-rule); background:var(--dnv-surface); }
.page[data-pagina="despesas-nova"] .dnv-lote > *{ min-width:0 }
.page[data-pagina="despesas-nova"] .dnv-lote__f{ flex:0 1 auto; overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.page[data-pagina="despesas-nova"] .dnv-lote__f{ padding:4px 10px; font-size:11.5px; color:var(--dnv-ink-2); border:1px solid var(--dnv-rule-2); background:var(--dnv-surface); }
.page[data-pagina="despesas-nova"] .dnv-lote__f:hover{ border-color:var(--dnv-ink-3) }
.page[data-pagina="despesas-nova"] .dnv-lote__f[aria-pressed="true"]{ background:var(--dnv-ink); border-color:var(--dnv-ink); color:var(--dnv-ground); font-weight:600 }
.page[data-pagina="despesas-nova"] .dnv-lote__e{ flex:1 1 auto }
.page[data-pagina="despesas-nova"] .dnv-lote__n{ flex:1 0 100%; margin:0; font-size:10.5px; color:var(--dnv-ink-4); line-height:1.5 }
.page[data-pagina="despesas-nova"] .dnv-cel-sel{ width:36px }
/* O input tem 15px, mas o alvo de toque é o rótulo em volta: 15px de caixa
   num dedo é chute. O padding vira área clicável sem inchar o desenho. */
.page[data-pagina="despesas-nova"] .dnv-cel-sel label{ display:block; padding:10px; margin:-10px; cursor:pointer }
.page[data-pagina="despesas-nova"] .dnv-cel-sel input{ width:16px; height:16px; accent-color:var(--dnv-risco); cursor:pointer }
/* A ação principal da tela media 29×13px no desktop — abaixo de qualquer alvo
   razoável, e a regra de `(hover:none)` só a socorria em aparelho de toque.
   O padding cresce a área sem mudar a caixa da célula. */
.page[data-pagina="despesas-nova"] .dnv-tratar{ font-size:11px; font-weight:600; color:var(--dnv-risco); white-space:nowrap; border-bottom:1px solid currentColor; padding:6px 4px; }
.page[data-pagina="despesas-nova"] .dnv-tratado{ font-size:10.5px; color:var(--dnv-ink-3); white-space:nowrap }
/* tratamento na linha */
.page[data-pagina="despesas-nova"] .dnv-trata td{ background:var(--dnv-risco-wash)!important; padding:0!important; border-left:3px solid var(--dnv-risco) }
.page[data-pagina="despesas-nova"] .dnv-trata__in{ padding:14px 16px; display:flex; flex-direction:column; gap:11px }
.page[data-pagina="despesas-nova"] .dnv-trata__h{ display:flex; align-items:baseline; gap:12px; flex-wrap:wrap }
.page[data-pagina="despesas-nova"] .dnv-trata__h b{ font-size:12.5px; color:var(--dnv-risco) }
.page[data-pagina="despesas-nova"] .dnv-trata__h span{ font-size:11.5px; color:var(--dnv-ink-2) }
.page[data-pagina="despesas-nova"] .dnv-trata__h span b{ color:var(--dnv-ink); font-variant-numeric:tabular-nums }
.page[data-pagina="despesas-nova"] .dnv-trata__m{ margin:0; font-size:13px; line-height:1.6; color:var(--dnv-ink); max-width:68ch; background:var(--dnv-surface); border:1px solid var(--dnv-risco-rule); padding:11px 13px; }
.page[data-pagina="despesas-nova"] .dnv-trata__f{ display:flex; flex-wrap:wrap; gap:5px 22px; font-size:11px; color:var(--dnv-ink-2) }
.page[data-pagina="despesas-nova"] .dnv-trata__f b{ color:var(--dnv-ink); font-weight:600 }
.page[data-pagina="despesas-nova"] .dnv-trata__a{ display:flex; flex-wrap:wrap; gap:8px; align-items:center }
/* Confirmação de ação destrutiva e contraprova do falso positivo: a pergunta ou o
   formulário ocupa o lugar dos botões da barra (tratamento ou lote) enquanto
   existe; sem eles, os botões voltam. */
.page[data-pagina="despesas-nova"] :has(> .dnv-confirma, > .dnv-contraprova) > :not(.dnv-confirma, .dnv-contraprova){ display:none!important }
.page[data-pagina="despesas-nova"] .dnv-confirma{ flex:1 1 100%; display:flex; flex-wrap:wrap; gap:8px; align-items:center }
.page[data-pagina="despesas-nova"] .dnv-confirma__p{ flex:1 1 260px; margin:0; font-size:12.5px; font-weight:600; color:var(--dnv-ink); line-height:1.5 }
.page[data-pagina="despesas-nova"] .dnv-bt{ padding:6px 14px; font-size:12px; font-weight:500; border:1px solid var(--dnv-rule-3); background:var(--dnv-surface) }
.page[data-pagina="despesas-nova"] .dnv-bt em{ display:block; font-style:normal; font-size:10px; font-weight:400; opacity:.8; margin-top:1px; letter-spacing:.01em; }
.page[data-pagina="despesas-nova"] .dnv-bt:hover{ border-color:var(--dnv-ink-2) }
/* No escuro, #fff sobre o vermelho claro dava 2,92:1. A tinta do botão vem do
   tema: branco no claro, quase-preto no escuro. */
.page[data-pagina="despesas-nova"] .dnv-bt--f{ background:var(--dnv-risco); border-color:var(--dnv-risco); color:var(--dnv-risco-tinta); font-weight:600 }
.page[data-pagina="despesas-nova"] .dnv-bt--f:hover{ filter:brightness(1.1) }
.page[data-pagina="despesas-nova"] .dnv-cx-campo{ flex:1 1 260px; max-width:440px; display:block }
.page[data-pagina="despesas-nova"] .dnv-cx{ width:100%; border:1px solid var(--dnv-rule-2); background:var(--dnv-surface); color:var(--dnv-ink); padding:6px 10px; font:inherit; font-size:12px; }
.page[data-pagina="despesas-nova"] .dnv-trata__c{ margin:0; padding:9px 12px; background:var(--dnv-surface); border-left:2px solid var(--dnv-mark); font-size:12.5px; color:var(--dnv-ink); line-height:1.5; }
.page[data-pagina="despesas-nova"] .dnv-trata__c .dnv-k{ display:block; margin-bottom:3px }
/* Contraprova do falso positivo (15/09/2026): o formulário (marca e lote) e a
   exibição na marca fechada. O texto guarda as quebras de linha de quem escreveu. */
.page[data-pagina="despesas-nova"] .dnv-contraprova{ flex:1 1 100%; display:flex; flex-direction:column; gap:8px; max-width:640px }
.page[data-pagina="despesas-nova"] .dnv-contraprova__lote{ margin:0; font-size:12px; color:var(--dnv-ink-2) }
.page[data-pagina="despesas-nova"] .dnv-contraprova__lote:empty{ display:none }
.page[data-pagina="despesas-nova"] .dnv-contraprova__rotulo{ margin:0; font-size:12.5px; font-weight:600; color:var(--dnv-ink) }
.page[data-pagina="despesas-nova"] .dnv-contraprova__texto{ width:100%; border:1px solid var(--dnv-rule-2); background:var(--dnv-surface); color:var(--dnv-ink); padding:6px 10px; font:inherit; font-size:12px; line-height:1.5; resize:vertical }
.page[data-pagina="despesas-nova"] .dnv-contraprova__print, .page[data-pagina="despesas-nova"] .dnv-contraprova__escolhido, .page[data-pagina="despesas-nova"] .dnv-contraprova__botoes{ display:flex; flex-wrap:wrap; align-items:center; gap:8px }
.page[data-pagina="despesas-nova"] .dnv-contraprova__escolhido[hidden]{ display:none }
/* O input de arquivo é invisível e continua no Tab: o anel de foco vai no rótulo que o veste de botão. */
.page[data-pagina="despesas-nova"] .dnv-contraprova__anexar{ margin:0; cursor:pointer }
.page[data-pagina="despesas-nova"] .dnv-contraprova__anexar:has(:focus-visible){ outline:2px solid var(--dnv-mark); outline-offset:1px }
.page[data-pagina="despesas-nova"] .dnv-contraprova__dica{ font-size:11px; color:var(--dnv-ink-3) }
.page[data-pagina="despesas-nova"] .dnv-contraprova__escolhido img{ width:48px; height:48px; object-fit:cover; border:1px solid var(--dnv-rule-2) }
.page[data-pagina="despesas-nova"] .dnv-contraprova__nome{ max-width:24ch; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:11.5px; color:var(--dnv-ink-2) }
.page[data-pagina="despesas-nova"] .dnv-contraprova__erro{ margin:0; font-size:12px; font-weight:600; color:var(--dnv-risco) }
.page[data-pagina="despesas-nova"] .dnv-contraprova [data-dnv-enviar-contraprova]:disabled{ opacity:.4; cursor:not-allowed }
/* O do lote abre acima da tabela e não pode escondê-la: quem marca precisa ver o
   que está marcando. Rótulo e frase numa linha, print e botões numa fileira que
   quebra no estreito, miniatura menor. O da marca individual não muda. */
.page[data-pagina="despesas-nova"] .dnv-contraprova--lote{ gap:6px; max-width:none }
.page[data-pagina="despesas-nova"] .dnv-contraprova__cabeca{ display:flex; flex-wrap:wrap; align-items:baseline; gap:2px 10px }
.page[data-pagina="despesas-nova"] .dnv-contraprova--lote .dnv-contraprova__lote{ font-size:11.5px; color:var(--dnv-ink-3) }
.page[data-pagina="despesas-nova"] .dnv-contraprova__acoes{ display:flex; flex-wrap:wrap; align-items:center; gap:6px 16px }
.page[data-pagina="despesas-nova"] .dnv-contraprova__acoes .dnv-contraprova__botoes{ margin-left:auto }
.page[data-pagina="despesas-nova"] .dnv-contraprova--lote .dnv-contraprova__escolhido img{ width:28px; height:28px }
.page[data-pagina="despesas-nova"] .dnv-lote:has(> .dnv-contraprova--lote){ padding-block:6px }
/* Com o print já anexado, a dica de colar cumpriu o papel: sair dá à fileira os
   ~100px que a faziam quebrar em 1366. */
.page[data-pagina="despesas-nova"] .dnv-contraprova--lote .dnv-contraprova__print:has(.dnv-contraprova__escolhido:not([hidden])) .dnv-contraprova__dica{ display:none }
.page[data-pagina="despesas-nova"] .dnv-trata__contraprova-texto{ margin:0; max-width:68ch; white-space:pre-wrap }
.page[data-pagina="despesas-nova"] .dnv-trata__contraprova img{ display:block; margin-top:6px; max-width:160px; max-height:120px; border:1px solid var(--dnv-rule-2) }
.page[data-pagina="despesas-nova"] .visually-hidden{ position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; }
.page[data-pagina="despesas-nova"] .dnv-feito{ font-size:12px; color:var(--dnv-ink-2) }
.page[data-pagina="despesas-nova"] .dnv-feito b{ color:var(--dnv-ink) }
.page[data-pagina="despesas-nova"] .dnv-vazio{ padding:28px 14px; text-align:center; color:var(--dnv-ink-3); font-size:12px }
.page[data-pagina="despesas-nova"] .dnv-recorte-aviso{ margin:0; padding:10px 14px; background:var(--dnv-surface-2); border-bottom:1px solid var(--dnv-rule); font-size:11.5px; color:var(--dnv-ink-2); line-height:1.5; }
.page[data-pagina="despesas-nova"] .dnv-recorte-aviso b{ color:var(--dnv-ink); font-weight:600 }
.page[data-pagina="despesas-nova"] .dnv-bloco--fila{ border-left:2px solid var(--dnv-risco) }
.page[data-pagina="despesas-nova"] .dnv-risco__esc{ margin:10px 0 0; font-size:10.5px; color:var(--dnv-ink-4); line-height:1.5 }
.page[data-pagina="despesas-nova"] .dnv-risco__d{ display:block; margin-top:4px; color:var(--dnv-mark); font-weight:600 }
.page[data-pagina="despesas-nova"] .dnv-semdados{ background:var(--dnv-surface); flex:1; display:flex; align-items:center; justify-content:center; padding:40px 24px }
.page[data-pagina="despesas-nova"] .dnv-semdados__in{ max-width:60ch }
.page[data-pagina="despesas-nova"] .dnv-semdados h2{ margin:0 0 12px; font-size:16px; font-weight:600; letter-spacing:-.01em }
.page[data-pagina="despesas-nova"] .dnv-semdados p{ margin:0 0 12px; font-size:13px; color:var(--dnv-ink-2); line-height:1.65 }
.page[data-pagina="despesas-nova"] .dnv-semdados b{ color:var(--dnv-ink); font-weight:600 }
.page[data-pagina="despesas-nova"] .dnv-semdados ul{ margin:0 0 16px; padding-left:18px; font-size:13px; color:var(--dnv-ink-2); line-height:1.8 }
.page[data-pagina="despesas-nova"] .dnv-semdados code{ font-size:12px; background:var(--dnv-wash); padding:1px 5px; color:var(--dnv-ink-2) }
.page[data-pagina="despesas-nova"] .dnv-pe{ display:grid; align-items:center; gap:14px; padding:10px 14px; grid-template-columns:14px minmax(0,1fr) 96px 124px 132px; border-top:1px solid var(--dnv-rule-2); background:var(--dnv-surface-2); position:sticky; bottom:0; font-weight:600; font-size:12px; }
/* ── ESTREITO ──────────────────────────────────────────────────── */
@media (max-width:1400px){
  .page[data-pagina="despesas-nova"] .dnv-faixa{ grid-template-columns:minmax(0,168px) minmax(0,140px) minmax(0,120px) minmax(110px,1fr) minmax(0,54px) minmax(0,116px) 20px; gap:13px }
}
@media (max-width:1120px){
  .page[data-pagina="despesas-nova"] .dnv-faixa{ grid-template-columns:minmax(0,160px) minmax(0,132px) minmax(0,112px) minmax(0,126px) 20px; gap:12px }
  .page[data-pagina="despesas-nova"] .dnv-faixa__g, .page[data-pagina="despesas-nova"] .dnv-faixa__ref{ display:none }
}
/* Rótulos do eixo de 12 meses colidiam quando a faixa aperta — cinco marcas
   num eixo que encolhe. Some com as intercaladas antes de elas se empilharem:
   três marcas legíveis dizem mais que cinco sobrepostas. */
@media (max-width:1240px){
  .page[data-pagina="despesas-nova"] .dnv-faixa__x span:nth-child(even){ visibility:hidden }
}
/* Até 1280px, e não 1180: entre os dois a grade ao lado da coluna de 376px dava
   52 a 151px ao nome da conta, que quebrava em até 34 linhas. */
@media (max-width:1280px){
  .page[data-pagina="despesas-nova"] .dnv-miolo{ grid-template-columns:1fr }
  .page[data-pagina="despesas-nova"] .dnv-miolo__e{ max-height:240px }
}
/* A tabela de lançamentos pedia 774px e o painel direito só tem 550px em
   1280px — "Tratar", a única ação da tela, ficava em x=1462 num viewport de
   1280, e `body{overflow-x:hidden}` não deixava rolar. O resgate era uma
   rolagem lateral invisível dentro do painel. Medido fora da tela em 960,
   1024, 1280 e 1440px; cabia só em 1120, 1180, 1512 e 1920 — ou seja, as duas
   larguras de notebook mais comuns quebravam e um teste nas larguras canônicas
   dava falso OK. As colunas de contexto saem primeiro. */
@media (max-width:1500px){
  .page[data-pagina="despesas-nova"] .dnv-esc{ display:none }
}
/* Alvo de toque decidido pelo APARELHO, não pela largura: num tablet de 768px
   o dedo é o mesmo, e a regra de ≤760px não o alcançava — "Comentar" ficava
   com 28px de altura. */
@media (hover:none){
  .page[data-pagina="despesas-nova"] .dnv-bt, .page[data-pagina="despesas-nova"] .dnv-lote__f, .page[data-pagina="despesas-nova"] .dnv-tratar, .page[data-pagina="despesas-nova"] .dnv-tratado{ min-height:44px }
  .page[data-pagina="despesas-nova"] .dnv-bt{ display:inline-flex; flex-direction:column; justify-content:center }
  .page[data-pagina="despesas-nova"] .dnv-cel-sel label{ padding:12px; margin:-12px }
  .page[data-pagina="despesas-nova"] .dnv-busca{ min-height:44px }
  /* As linhas de "Maiores credores" e "Maiores variações" são botões (abrem os
     lançamentos) e tinham ~33px; o alternador de base, ~28px. */
  .page[data-pagina="despesas-nova"] .dnv-pux__l{ min-height:44px; align-content:center }
  .page[data-pagina="despesas-nova"] .dnv-troca button{ min-height:44px }
}
@media (max-width:760px){
  .page[data-pagina="despesas-nova"] .dnv-esc2{ display:none!important }
  /* `auto` deixava o conteúdo empurrar a tabela para 365px num contêiner de
     360 — 5px de transbordo. Fixed com a coluna de valor estreita, e o nome
     trunca, que é o que já faz no desktop.

     As larguras seguem a POSIÇÃO das células que sobram, não o nome da coluna:
     `.esc2{display:none}` tira as células de "% do balde" e "Δ na janela", mas
     NÃO tira os `<col>` — em `table-layout:fixed` as três células restantes
     (abrir, conta, valor) mapeiam para os `<col>` 1, 2 e 3. Antes, a de valor
     herdava `c-pct{width:0}`: a coluna de dinheiro nascia com 0px, o texto
     vazava para a direita e cada número começava no mesmo x — uma coluna de
     dinheiro desalinhada por dígito, num arquivo que usa `tabular-nums` de
     propósito. O `<th>Valor</th>` ficava fora de registro pelo mesmo motivo. */
  .page[data-pagina="despesas-nova"] .dnv-grade{ table-layout:fixed }
  .page[data-pagina="despesas-nova"] .dnv-grade col.dnv-c-exp{ width:30px }
  .page[data-pagina="despesas-nova"] .dnv-grade col.dnv-c-pct{ width:104px }
  /* 3ª posição = a célula de VALOR */
  .page[data-pagina="despesas-nova"] .dnv-grade col.dnv-c-delta, .page[data-pagina="despesas-nova"] .dnv-grade col.dnv-c-val{ width:0 }
  /* fora do fluxo visível */
  .page[data-pagina="despesas-nova"] .dnv-grade thead th, .page[data-pagina="despesas-nova"] .dnv-grade tbody th, .page[data-pagina="despesas-nova"] .dnv-grade tbody td, .page[data-pagina="despesas-nova"] .dnv-grade tfoot th, .page[data-pagina="despesas-nova"] .dnv-grade tfoot td{ padding:10px 12px }
  .page[data-pagina="despesas-nova"] .dnv-cel-nome{ font-size:13px }
  .page[data-pagina="despesas-nova"] .dnv-cel-nome__in{ grid-template-columns:40px minmax(0,1fr) }
  /* A grade de lançamentos não cabe e não rolava: "Tratar" ficava em x=666 num
     viewport de 390 e o código da conta se imprimia por cima do valor. Abaixo
     de 760px cada lançamento vira um cartão, com o alvo de toque inteiro. */
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap table{ display:block }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap thead{ display:none }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap tbody{ display:block }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap tbody tr{ display:grid; grid-template-columns:1fr auto; gap:2px 10px; padding:12px 14px; border-bottom:1px solid var(--dnv-rule); }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap tbody tr.dnv-trata{ display:block; padding:0 }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap td{ display:block; padding:0!important; border:none!important }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap td:nth-child(1){ grid-column:1; grid-row:1 }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap td:nth-child(2){ grid-column:2; font-size:11px; color:var(--dnv-ink-3) }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap td:nth-child(7){ grid-column:3; grid-row:1; text-align:right; font-weight:600 }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap tbody tr{ grid-template-columns:auto 1fr auto }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap td:nth-child(3){ grid-column:1/-1; font-size:13px; font-weight:600 }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap td:nth-child(4){ grid-column:1/-1; font-size:11.5px; color:var(--dnv-ink-2) }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap td:nth-child(5), .page[data-pagina="despesas-nova"] .dnv-lanc__wrap td:nth-child(6){ grid-column:auto; font-size:11px; color:var(--dnv-ink-3); }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap td:nth-child(8){ grid-column:1/-1; margin-top:8px }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap td:nth-child(8) .dnv-tratar, .page[data-pagina="despesas-nova"] .dnv-lanc__wrap td:nth-child(8) .dnv-tratado{ display:block; width:100%; min-height:44px; line-height:44px; text-align:center; border:1px solid var(--dnv-risco); border-bottom-width:1px; font-size:13px; }
  .page[data-pagina="despesas-nova"] .dnv-trata__in{ padding:12px 14px }
  .page[data-pagina="despesas-nova"] .dnv-trata__m{ font-size:13px }
  .page[data-pagina="despesas-nova"] .dnv-bt{ min-height:44px }
}
@media (max-width:900px){
  .page[data-pagina="despesas-nova"]{ overflow:auto }
  .page[data-pagina="despesas-nova"] .dnv-app{ height:auto; grid-template-columns:1fr; grid-template-areas:"trilho" "lado" "palco" }
  /* A busca ficava encolhida à direita com o placeholder cortado em
     "credor, d" — no telefone ela ganha a linha inteira. */
  .page[data-pagina="despesas-nova"] .dnv-busca{ width:100%; border-left:none; padding-block:10px }
  /* O cinza é a cor do vão entre painéis; empilhado, o vão vira o fundo da
     página inteira abaixo do último balde. */
  .page[data-pagina="despesas-nova"] .dnv-app{ background:var(--dnv-surface) }
  .page[data-pagina="despesas-nova"] .dnv-palco{ gap:1px; background:var(--dnv-rule) }
  .page[data-pagina="despesas-nova"] .dnv-pan[data-aberto="1"]{ flex:none }
  /* Empilhado, a faixa fechada não divide altura com ninguém: presa em
     clamp(118px,15vh,176px) ela cortava a variação (conteúdo de 175px em 127). */
  .page[data-pagina="despesas-nova"] .dnv-pan[data-aberto="0"]{ height:auto }
  .page[data-pagina="despesas-nova"] .dnv-miolo__d{ max-height:520px }
  /* A página já rola: a coluna da esquerda numa caixa de 240px com rolagem
     própria escondia "Maiores variações" atrás de um segundo rolar. */
  .page[data-pagina="despesas-nova"] .dnv-miolo__e{ max-height:none; overflow:visible }
  .page[data-pagina="despesas-nova"] .dnv-faixa{ grid-template-columns:1fr 30px; height:auto; padding-block:14px; gap:10px }
  .page[data-pagina="despesas-nova"] .dnv-faixa__v, .page[data-pagina="despesas-nova"] .dnv-faixa__d, .page[data-pagina="despesas-nova"] .dnv-faixa__g, .page[data-pagina="despesas-nova"] .dnv-faixa__ref{ grid-column:1/-1 }
  .page[data-pagina="despesas-nova"] .dnv-faixa__g{ height:40px }
}

/* ── PEÇAS QUE O GABARITO NÃO TEM, e por que existem ───────────────────────
   Duas, e as duas nasceram de defeito medido, não de gosto. */

/* O aviso de seleção vazia: sem segmento marcado a tela volta zerada, e zero
   por filtro é indistinguível de zero por falta de despesa. */
.page[data-pagina="despesas-nova"] .dnv-vazio-filtro{
  display:flex; align-items:center; justify-content:space-between; gap:16px;
  padding:10px 24px; background:var(--dnv-surface-2);
  border-bottom:1px solid var(--dnv-rule); font-size:12.5px; color:var(--dnv-ink-2);
}
.page[data-pagina="despesas-nova"] .dnv-bt{
  flex:none; padding:6px 14px; font-size:12px; font-weight:500;
  border:1px solid var(--dnv-rule-3); background:var(--dnv-surface); color:var(--dnv-ink);
}
.page[data-pagina="despesas-nova"] .dnv-bt:hover{ border-color:var(--dnv-ink-2); }
/* A variante cheia vem DEPOIS da regra base, de propósito: com a mesma
   especificidade, a `.dnv-bt` acima apagava o vermelho portado do gabarito e
   "Marcar tratada" nascia branco — igual a um botão desabilitado. */
.page[data-pagina="despesas-nova"] .dnv-bt--f{ background:var(--dnv-risco); border-color:var(--dnv-risco); color:var(--dnv-risco-tinta); font-weight:600 }
.page[data-pagina="despesas-nova"] .dnv-bt--f:hover{ filter:brightness(1.1) }

/* A gaveta rola por dentro. `/linhas/` devolve 50 lançamentos por página e o
   gabarito mostra uma amostra de 5: sem teto, o painel aberto ficava 3.130px
   mais alto que o desenho e a grade de contas sumia da tela. O teto preserva o
   acesso a todos eles — rola —, sem o painel engolir a página. */
.page[data-pagina="despesas-nova"] .dnv-lanc__wrap{
  max-height:min(52vh, 420px); overflow-y:auto;
}

/* O bloco da fila virou <a> (era um <button> que não fazia nada e prometia
   "Abrir a fila →"). Ancora leva sublinhado e cor do shell; aqui ele continua
   lendo como bloco, e só o call-to-action se comporta como link. */
.page[data-pagina="despesas-nova"] a.dnv-risco{ color:inherit; text-decoration:none; }
.page[data-pagina="despesas-nova"] a.dnv-risco:hover .dnv-risco__ir{ text-decoration:underline; }

/* ── ADAPTAÇÕES DE SHELL — no FIM da seção, e é de propósito ────────────────
   O mockup é um documento inteiro e manda na janela (`html,body{height:100%}`,
   `body{overflow:hidden}`, `.app{height:100dvh}`). Aqui ele é filho de
   `.content`, que já tem topbar acima e respiro em volta.

   Estas regras vêm DEPOIS do porte porque a especificidade é a mesma dos dois
   lados (`.page[data-pagina="despesas-nova"]`) e quem decide é a ordem de
   origem: postas antes, o `margin:0` e o `height:100%` que o porte herdou do
   `body` do mockup as apagavam em silêncio — a tela nascia 88px mais estreita
   e 76px mais alta que o desenho, e quem contou isso foi a medição, não o olho.

   Nenhuma muda o desenho: mudam de quem é a altura e onde fica a borda. */
/* A tela SANGRA até a borda do `.content` e ocupa a janela inteira abaixo da
   topbar, como o mockup ocupa a dele. A margem negativa devolve exatamente o
   respiro que o shell deu — os dois lados saem do mesmo token, então não há
   número mágico a envelhecer —, e por isso a altura desconta SÓ a topbar: com o
   padding anulado, descontá-lo de novo tirava 52px a mais e encurtava as três
   faixas em 27px cada. */
.page[data-pagina="despesas-nova"]{
  margin-inline:calc(-1 * var(--content-pad-x));
  margin-block:calc(-1 * var(--content-pad-y)) calc(-1 * var(--content-pad-b));
  width:auto;
  height:calc(100dvh - 52px);   /* 52px = `.topbar`, 3.25rem */
  display:flex; flex-direction:column;
  /* A `.page` global tem `padding-bottom:24px`, que é o respiro de uma página
     que ROLA. Esta não rola: o mockup vai até o pé da janela e quem rola são os
     painéis, por dentro. Os 24px saíam da altura dos três baldes. */
  padding:0;
}
/* ESTREITO: o gabarito empilha e a PÁGINA rola (`body{overflow:auto}`,
   `.app{height:auto}` em ≤900px). Travar a altura da janela aqui espremia o
   rail de 878px para 283px e escondia o resto atrás de uma rolagem interna que
   ninguém vê. A tela volta a ter a altura do seu conteúdo e rola inteira.

   E a margem negativa passa a copiar a EXPRESSÃO do respiro, não o token: em
   ≤767.98px o `.content` troca o padding por `max(0.5rem, env(safe-area-*))` e
   não mexe em `--content-pad-x`, então puxar 20px de cada lado estourava 12px
   para fora da tela — que o `overflow-x:clip` do shell corta em silêncio, em
   vez de deixar rolar. */
@media (max-width:900px){
  .page[data-pagina="despesas-nova"]{ height:auto; }
  .page[data-pagina="despesas-nova"] .dnv-app{ height:auto; }
}
@media (max-width:767.98px){
  .page[data-pagina="despesas-nova"]{
    margin-inline:calc(-1 * max(0.5rem, env(safe-area-inset-left)))
                  calc(-1 * max(0.5rem, env(safe-area-inset-right)));
    margin-block:-0.5rem calc(-1 * max(1.5rem, env(safe-area-inset-bottom)));
  }
}

/* O `.dnv-app` fica com o que sobrar depois do host de filtros (1px) e do aviso
   de seleção vazia — `height:100%` mediria a página inteira e estouraria 24px
   por baixo quando o aviso estivesse na tela. */
.page[data-pagina="despesas-nova"] .dnv-app{
  flex:1 1 auto; min-height:0;
  grid-template-rows:1fr; grid-template-areas:"lado palco";
}
@media (max-width:900px){
  .page[data-pagina="despesas-nova"] .dnv-app{ grid-template-areas:"lado" "palco"; }
}
/* O branco da folha parava na borda da `.page`: o padding do `.content` em
   volta (o cinza `--surface-app` do resto do app) continuava aparecendo como
   moldura, e o `.main` tem `min-height:calc(100vh - 52px)`, então sobrava uma
   faixa cinza no rodapé quando o conteúdo era mais curto que a janela. `:has()`
   já é usado pelo shell (`content--altura-cheia`); aqui ele só pinta quando é
   ESTA página — as outras 27 não enxergam. */
.content:has(> .page[data-pagina="despesas-nova"]){ background:#fff; }
.main:has(> .content > .page[data-pagina="despesas-nova"]){ background:#fff; }

/* ── TRILHO: o cabeçalho do gabarito, vestido na barra do shell ─────────────
   Porte dos seletores `.trilho .marca .sel .pop .atalho .campo .segl .busca` do
   mockup, valor por valor. Mora nos blocos que o `base_fcds.html` já expõe
   (`crumb`, `topbar_filters`, `topbar_actions`), então nenhuma outra tela muda:
   o escopo `#topbar:has(.dnv-sel)` só casa na barra que carrega estes seletores.

   O que NÃO é literal, e por quê: logo, menu, Reportar e sino continuam na
   barra. São o caminho para o resto do app e o mockup não desenha nada para
   eles — ficam à direita, com o formato de ícone. A barra lateral fica, e é ela
   que desloca o conteúdo 48px em relação ao desenho. */
#topbar:has(.dnv-sel){
  height:46px; padding:0 12px 0 16px; gap:0; align-items:stretch;
  background:var(--dnv-surface); border-bottom:1px solid var(--dnv-rule);
  font-family:var(--dnv-sans); color:var(--dnv-ink);
}
#topbar:has(.dnv-sel) > .logo, #topbar:has(.dnv-sel) > .menu, #topbar:has(.dnv-sel) > .fcds-help, #topbar:has(.dnv-sel) > .fcds-reportar,
#topbar:has(.dnv-sel) > .fcds-sino{ align-self:center }
#topbar:has(.dnv-sel) > .menu{ margin-right:6px }
#topbar:has(.dnv-sel) > .vr{ display:none }
#topbar:has(.dnv-sel) .dnv-sel :where(button){ font:inherit; color:inherit; background:none; border:none; padding:0; cursor:pointer; text-align:left }
#topbar:has(.dnv-sel) :focus-visible{ outline:2px solid var(--dnv-mark); outline-offset:1px }
#topbar:has(.dnv-sel) .dnv-k{ font-size:10px; letter-spacing:.11em; text-transform:uppercase; color:var(--dnv-ink-3); font-weight:600 }

/* .marca — é o próprio `.crumb` do shell (no celular ele é o gatilho da gaveta) */
#topbar:has(.dnv-sel) .crumb{ display:flex; align-items:center; gap:10px; padding:0 18px; border-right:1px solid var(--dnv-rule) }
#topbar:has(.dnv-sel) .crumb b{ font-size:14px; font-weight:600; letter-spacing:-.01em }
#topbar:has(.dnv-sel) .crumb b::after{ content:"Four Group"; margin-left:10px; font-size:11px; font-weight:400; letter-spacing:0; color:var(--dnv-ink-3) }

#topbar:has(.dnv-sel) .dnv-sel{ position:relative; display:flex }
#topbar:has(.dnv-sel) .dnv-sel__bt{ display:flex; align-items:center; gap:10px; padding:0 18px; height:100%; border-right:1px solid var(--dnv-rule); white-space:nowrap }
#topbar:has(.dnv-sel) .dnv-sel__bt:hover{ background:var(--dnv-surface-2) }
#topbar:has(.dnv-sel) .dnv-sel__bt[aria-expanded="true"]{ background:var(--dnv-surface-2); box-shadow:inset 0 -2px 0 var(--dnv-mark) }
#topbar:has(.dnv-sel) .dnv-sel__v{ font-size:12.5px; font-weight:600; color:var(--dnv-ink) }
/* O ícone de chevron do app, não o glifo "▾": a 10px ele quase sumia (dono, 15/09). Vira para cima com o popover aberto. */
#topbar:has(.dnv-sel) .dnv-sel__s{ flex:none; font-size:11px; color:var(--dnv-ink-2); transition:transform .15s }
#topbar:has(.dnv-sel) .dnv-sel__bt[aria-expanded="true"] .dnv-sel__s{ transform:rotate(180deg); color:var(--dnv-mark) }
#topbar:has(.dnv-sel) .dnv-pop{
  position:absolute; top:100%; left:0; z-index:60; background:var(--dnv-surface);
  border:1px solid var(--dnv-rule-2); box-shadow:0 14px 34px -14px rgba(0,0,0,.3);
  padding:18px 20px 16px; min-width:320px; font-size:13.5px; line-height:1.45; cursor:default;
}
#topbar:has(.dnv-sel) .dnv-pop--periodo{ width:min(520px, calc(100vw - 28px)) }
#topbar:has(.dnv-sel) .dnv-pop--seg{ width:min(340px, calc(100vw - 28px)) }
#topbar:has(.dnv-sel) .dnv-pop__cols{ display:grid; grid-template-columns:1fr 1fr; gap:26px }
#topbar:has(.dnv-sel) .dnv-pop__c .dnv-k{ margin:0 0 10px }
#topbar:has(.dnv-sel) .dnv-pop__nota{ margin:16px 0 0; padding-top:13px; border-top:1px solid var(--dnv-rule); font-size:11px; color:var(--dnv-ink-3); line-height:1.6 }
#topbar:has(.dnv-sel) .dnv-pop__nota b{ color:var(--dnv-ink-2); font-weight:600 }
#topbar:has(.dnv-sel) .dnv-pop__acoes{ display:flex; gap:16px; margin-bottom:12px }
#topbar:has(.dnv-sel) .dnv-pop__acoes:not(:has(button:not([hidden]))){ display:none }
#topbar:has(.dnv-sel) .dnv-pop__acoes button{ font-size:11.5px; color:var(--dnv-mark); font-weight:600; border-bottom:1px solid currentColor }
#topbar:has(.dnv-sel) .dnv-atalho{ display:flex; align-items:baseline; gap:9px; width:100%; padding:7px 0; font-size:12.5px; border-bottom:1px solid var(--dnv-rule) }
#topbar:has(.dnv-sel) .dnv-atalho:last-child{ border-bottom:none }
#topbar:has(.dnv-sel) .dnv-atalho:hover:not([disabled]){ color:var(--dnv-mark) }
#topbar:has(.dnv-sel) .dnv-atalho[aria-pressed="true"]{ font-weight:600; color:var(--dnv-mark) }
#topbar:has(.dnv-sel) .dnv-atalho[disabled]{ color:var(--dnv-ink-4); cursor:not-allowed }
#topbar:has(.dnv-sel) .dnv-atalho em{ font-style:normal; margin-left:auto; font-size:10.5px; color:var(--dnv-ink-4); font-weight:400 }
#topbar:has(.dnv-sel) .dnv-campo{ display:flex; align-items:center; justify-content:space-between; gap:10px; font-size:12px; color:var(--dnv-ink-2); margin-bottom:8px }
#topbar:has(.dnv-sel) .dnv-campo input{ font:inherit; font-size:12px; color:var(--dnv-ink); background:var(--dnv-surface-2); border:1px solid var(--dnv-rule-2); padding:5px 8px; width:148px }
#topbar:has(.dnv-sel) .dnv-campo__erro{ margin:8px 0 0; font-size:11.5px; color:var(--dnv-risco); min-height:1em }
#topbar:has(.dnv-sel) .dnv-bt{ padding:6px 14px; font-size:12px; font-weight:500; border:1px solid var(--dnv-rule-3); background:var(--dnv-surface) }
#topbar:has(.dnv-sel) .dnv-bt:hover{ border-color:var(--dnv-ink-2) }
#topbar:has(.dnv-sel) .dnv-bt--f{ background:var(--dnv-risco); border-color:var(--dnv-risco); color:var(--dnv-risco-tinta); font-weight:600 }
#topbar:has(.dnv-sel) .dnv-bt--f:hover{ filter:brightness(1.1) }
#topbar:has(.dnv-sel) .dnv-dt-aplicar{ margin-top:10px }
#topbar:has(.dnv-sel) .dnv-segl{ display:grid; grid-template-columns:16px 1fr auto; gap:10px; align-items:center; width:100%; padding:8px 0; font-size:12.5px; border-bottom:1px solid var(--dnv-rule) }
#topbar:has(.dnv-sel) .dnv-segl:last-of-type{ border-bottom:none }
#topbar:has(.dnv-sel) .dnv-segl:hover{ color:var(--dnv-mark) }
#topbar:has(.dnv-sel) .dnv-segl__c{ width:14px; height:14px; border:1px solid var(--dnv-rule-3); display:grid; place-items:center; font-size:10px; line-height:1; color:var(--dnv-surface) }
#topbar:has(.dnv-sel) .dnv-segl[aria-pressed="true"] .dnv-segl__c{ background:var(--dnv-mark); border-color:var(--dnv-mark) }
#topbar:has(.dnv-sel) .dnv-segl__v{ font-size:11px; color:var(--dnv-ink-4); font-variant-numeric:tabular-nums }
#topbar:has(.dnv-sel) .dnv-trilho__fim{ margin-left:auto; margin-right:10px; display:flex; align-items:center; gap:0 }
#topbar:has(.dnv-sel) .dnv-busca{
  font:inherit; font-size:12px; color:var(--dnv-ink); background:var(--dnv-surface-2);
  border:none; border-left:1px solid var(--dnv-rule); border-right:1px solid var(--dnv-rule); border-radius:0;
  padding:0 16px; height:100%; width:268px;
}
#topbar:has(.dnv-sel) .dnv-busca::placeholder{ color:var(--dnv-ink-3) }
#topbar:has(.dnv-sel) .dnv-busca:focus{ background:var(--dnv-surface); outline-offset:-2px }
/* Reportar vira ícone aqui — mantém o vermelho que o dono escolheu, mas cede a
   largura ao trilho, como já faz abaixo de 992px em todo o app. */
#topbar:has(.dnv-sel) .fcds-reportar{ width:2rem; padding:0; justify-content:center; margin-inline:6px }
#topbar:has(.dnv-sel) .fcds-reportar__t{ display:none }

/* ── A FAIXA EM CINCO CÉLULAS — divergência do gabarito, ordem do dono (14/09) ─
   O gabarito tem sete trilhas: nome, valor, variação, gráfico, média, suspeita,
   seta. As duas antes da seta roubavam ~250px do gráfico numa tela de 1920,
   enquanto sobrava branco sob o nome e o valor. A suspeita desce para baixo do
   nome do balde, a média para baixo do valor, e o gráfico vai até a seta. De
   quebra some a coluna que aparecia e sumia conforme houvesse suspeita — o
   gráfico deixa de mudar de largura com o dado. */
.page[data-pagina="despesas-nova"] .dnv-faixa{
  grid-template-columns:minmax(0,172px) minmax(0,152px) minmax(0,128px) minmax(140px,1fr) 20px;
}
.page[data-pagina="despesas-nova"] .dnv-faixa__id,
.page[data-pagina="despesas-nova"] .dnv-faixa__val{ display:flex; flex-direction:column; gap:3px; min-width:0 }
.page[data-pagina="despesas-nova"] .dnv-faixa__id .dnv-faixa__r span{ display:inline; margin-left:6px }
.page[data-pagina="despesas-nova"] .dnv-faixa__val .dnv-faixa__leg{ max-width:none }
@media (max-width:1400px){
  .page[data-pagina="despesas-nova"] .dnv-faixa{ grid-template-columns:minmax(0,168px) minmax(0,140px) minmax(0,120px) minmax(110px,1fr) 20px }
}
@media (max-width:1120px){
  .page[data-pagina="despesas-nova"] .dnv-faixa{ grid-template-columns:minmax(0,160px) minmax(0,132px) minmax(0,1fr) 20px }
  .page[data-pagina="despesas-nova"] .dnv-faixa__ref{ display:block }
}
@media (max-width:900px){
  .page[data-pagina="despesas-nova"] .dnv-faixa{ grid-template-columns:1fr 30px }
  .page[data-pagina="despesas-nova"] .dnv-faixa__val{ grid-column:1/-1 }
  /* A seta ao lado do nome, na primeira linha. Pela ordem natural ela caía
     sozinha numa quarta linha, embaixo da variação — o gabarito tem o mesmo
     defeito a 390px. */
  .page[data-pagina="despesas-nova"] .dnv-cursor{ grid-column:2; grid-row:1 }
}

/* ── A DICA DO GRÁFICO DE 12 MESES ─────────────────────────────────────────
   O gabarito tinha só o `<title>` nativo: aparece depois de ~1s com o mouse
   parado e não marca o ponto. A dica é imediata, com guia vertical e ponto no
   mês — tema claro, a mesma superfície dos popovers do trilho. */
.page[data-pagina="despesas-nova"] .dnv-faixa__g-d{ position:relative }
.page[data-pagina="despesas-nova"] .dnv-guia{
  position:absolute; top:0; bottom:0; width:0; border-left:1px dashed var(--dnv-ink-3); pointer-events:none;
}
.page[data-pagina="despesas-nova"] .dnv-ponto{
  position:absolute; width:9px; height:9px; margin:-4.5px 0 0 -4.5px; border-radius:50%;
  background:var(--dnv-graf); box-shadow:0 0 0 2px var(--dnv-surface); pointer-events:none;
}
.page[data-pagina="despesas-nova"] .dnv-dica{
  position:fixed; z-index:70; pointer-events:none; display:flex; flex-direction:column; gap:2px;
  padding:8px 11px; background:var(--dnv-surface); border:1px solid var(--dnv-rule-2);
  box-shadow:0 10px 24px -12px rgba(0,0,0,.35); font-size:11.5px; color:var(--dnv-ink-2); white-space:nowrap;
}
.page[data-pagina="despesas-nova"] .dnv-dica b{ font-size:15px; font-weight:600; color:var(--dnv-ink); letter-spacing:-.01em }
.page[data-pagina="despesas-nova"] .dnv-dica__k{ font-size:10.5px; color:var(--dnv-ink-3) }
.page[data-pagina="despesas-nova"] .dnv-dica__m{ font-size:11px; color:var(--dnv-ink-3) }

/* ── OS MESES EM TODOS OS GRÁFICOS — divergência do gabarito, ordem do dono ──
   O gabarito rotulava só a última faixa, de três em três. Agora cada faixa tem
   os 13 meses; o corte para os trimestrais é decidido pela largura do PRÓPRIO
   gráfico (container query), não da janela — a mesma janela dá gráficos de
   larguras diferentes conforme o rail e a barra lateral. */
.page[data-pagina="despesas-nova"] .dnv-faixa__g{ container-type:inline-size }
.page[data-pagina="despesas-nova"] .dnv-faixa__x span:nth-child(even){ visibility:visible }
@container (max-width:760px){
  .page[data-pagina="despesas-nova"] .dnv-faixa__x .dnv-x-meio{ color:transparent }
}

/* ── O CREDOR COMO CAMINHO (dono, 14/09) ───────────────────────────────────
   Cada um dos maiores credores abre os lançamentos dele no topo do palco. A
   linha continua lendo como lista; só ganha cursor, destaque ao passar e o
   estado "aberto" com a mesma marca azul das contas abertas. */
.page[data-pagina="despesas-nova"] .dnv-cred{ width:calc(100% + 12px); margin-inline:-6px; padding-inline:6px; cursor:pointer; text-align:left }
.page[data-pagina="despesas-nova"] .dnv-cred:hover .dnv-pux__n{ color:var(--dnv-mark) }
.page[data-pagina="despesas-nova"] .dnv-cred[aria-pressed="true"]{ box-shadow:inset 2px 0 0 var(--dnv-mark); background:var(--dnv-mark-wash) }
/* Não encolhe: com um balde aberto ao mesmo tempo, os dois painéis disputavam a
   altura e o do credor era espremido até sobrar só o cabeçalho — sem tabela e
   sem o carregamento. A tabela dele já tem teto e rola por dentro. */
.page[data-pagina="despesas-nova"] .dnv-pan.dnv-pan--credor[data-aberto]{ border-bottom:1px solid var(--dnv-rule); flex:0 0 auto }
.page[data-pagina="despesas-nova"] .dnv-credor__cab{
  display:flex; align-items:baseline; gap:14px; padding:14px 20px 12px;
  border-left:3px solid var(--dnv-mark); background:var(--dnv-surface-2);
}
.page[data-pagina="despesas-nova"] .dnv-credor__n{ font-size:14px; font-weight:600; letter-spacing:-.01em }
.page[data-pagina="despesas-nova"] .dnv-credor__v{ font-size:12px; color:var(--dnv-ink-2) }
.page[data-pagina="despesas-nova"] .dnv-credor__cab .dnv-bt{ margin-left:auto }
.page[data-pagina="despesas-nova"] .dnv-credor__corpo{ padding:0 }

/* O desenho OCUPA a sobra da faixa, não impõe a própria altura. O SVG estica na
   largura e, sem teto, a altura intrínseca (520×74 esticado a 926px = 132px)
   empurrava o bloco do gráfico para 177px dentro de uma faixa ABERTA de 106 —
   e o eixo, agora com os meses visíveis em toda faixa, caía 57px por cima da
   primeira linha da grade. Base flexível zero: quem manda é a faixa. */
.page[data-pagina="despesas-nova"] .dnv-faixa__g-d{ flex:1 1 0; min-height:0; overflow:hidden }
.page[data-pagina="despesas-nova"] .dnv-faixa__g{ min-height:0; max-height:100% }

/* ── CARREGANDO: um para a tela, um por pedido menor (dono, 14/09) ─────────
   Eram quatro logos girando juntos a cada troca de recorte, e nenhum sinal ao
   abrir uma conta, um credor, o painel de tratamento, buscar ou tratar. Agora:
   · a tela inteira — UM logo, sobre `#dnv-app` (período, segmento, 1ª carga);
   · gaveta de conta, de credor e painel de tratamento — o mesmo logo, pequeno,
     no lugar que está buscando;
   · busca — um fio correndo sob o campo enquanto o servidor procura;
   · ação na marca — o botão ocupado, com o mesmo fio;
   · contadores recalculando depois de tratar — os números esmaecem. */
.page[data-pagina="despesas-nova"] .dnv-carregando{ position:relative; min-height:96px }
.page[data-pagina="despesas-nova"] .dnv-trata__in .dnv-carregando{ min-height:64px }
.page[data-pagina="despesas-nova"] .dnv-carregando .logo-loader{ background:transparent }
@keyframes dnv-fio{ from{ background-position:-40% 0 } to{ background-position:140% 0 } }
#topbar:has(.dnv-sel) .dnv-trilho__fim{ position:relative }
#topbar:has(.dnv-sel) .dnv-trilho__fim:has(.dnv-busca[aria-busy="true"])::after,
.page[data-pagina="despesas-nova"] .dnv-bt[aria-busy="true"]::after,
.page[data-pagina="despesas-nova"] .dnv-lote__f[aria-busy="true"]::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:2px;
  background:linear-gradient(90deg, transparent, var(--dnv-mark), transparent) no-repeat;
  background-size:40% 100%; animation:dnv-fio 1s linear infinite;
}
.page[data-pagina="despesas-nova"] .dnv-bt[aria-busy="true"],
.page[data-pagina="despesas-nova"] .dnv-lote__f[aria-busy="true"]{ position:relative; cursor:progress }
.page[data-pagina="despesas-nova"] .dnv-app[aria-busy="true"] :is(.dnv-risco__n, .dnv-risco__v, .dnv-faixa__r, .dnv-cel-nome .dnv-marca-t--r){
  opacity:.45; transition:opacity .2s;
}
@media (prefers-reduced-motion:reduce){
  #topbar:has(.dnv-sel) .dnv-trilho__fim::after, .page[data-pagina="despesas-nova"] .dnv-bt::after{ animation:none }
}

/* ── GRADES QUE ORDENAM E FILTRAM (dono, 14/09) ────────────────────────────
   Cabeçalho vira botão; a seta aparece SEMPRE — apagada na coluna inativa (diz
   "dá para ordenar"), cheia na ativa (diz o sentido). Na gaveta de lançamentos,
   a segunda linha do cabeçalho traz os filtros de coluna da casa (colfilter-multi)
   e um filtro de texto; o rodapé diz quantos sobraram, de quantos, e quanto somam. */
.page[data-pagina="despesas-nova"] .dnv-ordenar{
  display:inline-flex; align-items:center; gap:5px; font:inherit; color:inherit;
  letter-spacing:inherit; text-transform:inherit; cursor:pointer; white-space:nowrap;
}
.page[data-pagina="despesas-nova"] th.dnv-dir .dnv-ordenar{ justify-content:flex-end; width:100% }
.page[data-pagina="despesas-nova"] .dnv-ordenar:hover{ color:var(--dnv-ink) }
.page[data-pagina="despesas-nova"] .dnv-seta{ font-size:10px; color:var(--dnv-rule-3); line-height:1 }
.page[data-pagina="despesas-nova"] .dnv-ordenar--ativa{ color:var(--dnv-ink) }
.page[data-pagina="despesas-nova"] .dnv-ordenar--ativa .dnv-seta{ color:var(--dnv-mark) }
.page[data-pagina="despesas-nova"] .dnv-lanc__filtros th{ padding-top:0; padding-bottom:6px; text-transform:none; letter-spacing:0; font-weight:400 }
.page[data-pagina="despesas-nova"] .dnv-lanc__texto{
  width:100%; font:inherit; font-size:11.5px; color:var(--dnv-ink); background:var(--dnv-surface);
  border:1px solid var(--dnv-rule-2); padding:3px 7px;
}
.page[data-pagina="despesas-nova"] .dnv-lanc__filtros .colfilter-multi__trigger{ font-size:11.5px }
/* A gaveta mora DENTRO da grade, e `.dnv-grade thead th` (sticky, z-index:2) vale
   também para o cabeçalho dela: a célula seguinte (Documento) era pintada por cima
   do painel aberto e cortava o canto dele. Quem tem o painel aberto sobe. */
.page[data-pagina="despesas-nova"] thead th:has(.colfilter-multi__panel:not([hidden])){ z-index:4 }
.page[data-pagina="despesas-nova"] .dnv-lanc__pe{
  display:flex; align-items:center; gap:14px; padding:9px 14px; font-size:11.5px; color:var(--dnv-ink-2);
  border-top:1px solid var(--dnv-rule); background:var(--dnv-surface-2); position:sticky; bottom:0;
}
.page[data-pagina="despesas-nova"] .dnv-lanc__pe b{ color:var(--dnv-ink); font-weight:600 }
.page[data-pagina="despesas-nova"] .dnv-lanc__limpar{ margin-left:auto; color:var(--dnv-mark); font-weight:600; border-bottom:1px solid currentColor }

/* UMA rolagem, não duas. Dentro da grade de contas, a gaveta rolava sozinha
   (420px de 5.954) dentro do painel que também rola (446 de 761): o rodapé da
   gaveta — com "Mostrar mais" — ficava fora das duas. Ali a gaveta cresce e quem
   rola é o painel; o rodapé dela gruda embaixo enquanto ela está na tela, e o
   "Total do balde" desgruda para os dois não se sobreporem. A gaveta do credor
   não mora num painel que rola, e mantém o teto próprio. */
.page[data-pagina="despesas-nova"] .dnv-grade .dnv-lanc__wrap{ max-height:none; overflow:visible }
.page[data-pagina="despesas-nova"] .dnv-grade:has(.dnv-lanc__wrap) tfoot{ position:static }

/* No telefone os lançamentos viram cartões e o <thead> sumia — levando junto a
   ordenação e os filtros. Ali ele vira uma barra acima dos cartões: os botões de
   ordenar numa linha que quebra, os filtros na seguinte. */
@media (max-width:760px){
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap thead{ display:block; background:var(--dnv-surface-2); border-bottom:1px solid var(--dnv-rule) }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap thead tr{ display:flex; flex-wrap:wrap; gap:6px 12px; padding:8px 14px }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap thead th{ display:block; padding:0 !important; border:none !important; background:none !important; position:static }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap thead th:empty,
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap thead th:has(> .visually-hidden){ display:none }
  .page[data-pagina="despesas-nova"] .dnv-lanc__filtros{ padding-top:0 !important }
  .page[data-pagina="despesas-nova"] .dnv-lanc__filtros th{ flex:1 1 140px }
  /* "Todos" sozinho não diz de QUAL coluna é o filtro quando o cabeçalho não
     está logo acima dele. */
  .page[data-pagina="despesas-nova"] .dnv-lanc__filtros th[data-dnv-rotulo]{ display:flex !important; align-items:center; gap:6px }
  .page[data-pagina="despesas-nova"] .dnv-lanc__filtros th[data-dnv-rotulo]::before{
    content:attr(data-dnv-rotulo); font-size:10px; letter-spacing:.08em; text-transform:uppercase; color:var(--dnv-ink-3); white-space:nowrap
  }
  .page[data-pagina="despesas-nova"] .dnv-lanc__wrap thead th.dnv-esc{ display:block }
  .page[data-pagina="despesas-nova"] .dnv-lanc__pe{ flex-wrap:wrap }
}

/* ── O RAIL CABE NA JANELA — divergência do gabarito, ordem do dono (14/09) ──
   Rolagem no rail só em caso extremo. Com 26px acima e abaixo de cada bloco, o
   rail de setembro media 934px numa janela de 860 (814 úteis) e rolava sem
   motivo. O respiro vira 14px; as frases que só repetiam regra da tela saíram
   (a explicação de lançado × contabilizado virou dica, "Os 6 maiores por valor"
   e o escopo da fila sumiram) e o rodapé é só o caminho de volta. */
.page[data-pagina="despesas-nova"] .dnv-bloco{ padding:14px 24px }
.page[data-pagina="despesas-nova"] .dnv-nota--pe{ padding:8px 24px 10px }

/* A barra encolheu de 52px para os 46px do desenho: quem se posiciona abaixo
   dela precisa saber. */
/* `--dnv-topo` é a altura MEDIDA da barra (o `despesas-nova.js` a publica com um
   ResizeObserver): no estreito o trilho empilha em quatro linhas, e um 46 fixo
   escondia o topo da barra lateral atrás dele. */
body:has(#topbar .dnv-sel) .side{ top:var(--dnv-topo, 46px); height:calc(100vh - var(--dnv-topo, 46px)) }
body:has(#topbar .dnv-sel) .scrim{ inset:var(--dnv-topo, 46px) 0 0 0 }
.main:has(> .content > .page[data-pagina="despesas-nova"]){ min-height:calc(100vh - 46px) }
.page[data-pagina="despesas-nova"]{ height:calc(100dvh - 46px) }
.page[data-pagina="despesas-nova"] .dnv-nota--pe{ margin-top:auto }
.page[data-pagina="despesas-nova"] .dnv-nota--pe a{ color:var(--dnv-ink-3); text-decoration:underline }
/* Reporte #33. O consolidado não abre: sem mão, sem fundo de hover. O mês da
   janela escolhida se lê no eixo; "Maiores variações" mostra valor e diferença. */
.page[data-pagina="despesas-nova"] .dnv-pan--consolidado .dnv-faixa{ cursor:default }
.page[data-pagina="despesas-nova"] .dnv-pan--consolidado .dnv-faixa:hover{ background:none }
.page[data-pagina="despesas-nova"] .dnv-faixa__x .dnv-x-dest{ z-index:1; color:var(--dnv-surface); background:var(--dnv-mark); font-weight:600; padding:2px 6px; margin-top:2px; border-radius:3px; line-height:1 }
.page[data-pagina="despesas-nova"] .dnv-faixa__x .dnv-x-dest::before{ display:none }
.page[data-pagina="despesas-nova"] .dnv-marca-mes{ position:absolute; width:11px; height:11px; margin:-5.5px 0 0 -5.5px; border-radius:50%; background:var(--dnv-mark); box-shadow:0 0 0 2.5px var(--dnv-surface); pointer-events:none }
.page[data-pagina="despesas-nova"] .dnv-pux__cab{ display:grid; grid-template-columns:minmax(0,1fr) auto; gap:12px; padding:0 0 5px; border-bottom:1px solid var(--dnv-rule); font-size:9.5px; letter-spacing:.1em; text-transform:uppercase; color:var(--dnv-ink-3); font-weight:600 }
.page[data-pagina="despesas-nova"] .dnv-pux--dupla :is(.dnv-pux__l, .dnv-pux__cab){ grid-template-columns:minmax(0,1fr) auto auto }
.page[data-pagina="despesas-nova"] .dnv-pux__a{ font-size:12.5px; white-space:nowrap; color:var(--dnv-ink-2); font-variant-numeric:tabular-nums }
.page[data-pagina="despesas-nova"] .dnv-pux__cab span{ text-align:right }

@media (hover:none){
  #topbar:has(.dnv-sel) .dnv-atalho, #topbar:has(.dnv-sel) .dnv-segl, #topbar:has(.dnv-sel) .dnv-bt{ min-height:44px }
  #topbar:has(.dnv-sel) .dnv-campo input, #topbar:has(.dnv-sel) .dnv-busca{ min-height:44px }
}
/* ESTREITO: o gabarito empilha o trilho — marca, Período, Segmento e a busca,
   cada um na sua linha. Aqui a primeira linha é a do shell (☰ + marca + ícones),
   e a barra deixa de ser grudada: com quatro linhas ela comeria meia tela. */
@media (max-width:900px){
  #topbar:has(.dnv-sel){ height:auto; flex-wrap:wrap; padding:0 }
  #topbar:has(.dnv-sel) > .crumb{ order:0; flex:1 1 auto; min-height:46px; border-right:none }
  #topbar:has(.dnv-sel) > .fcds-help, #topbar:has(.dnv-sel) > .fcds-reportar, #topbar:has(.dnv-sel) > .fcds-sino{ order:1 }
  #topbar:has(.dnv-sel) > .fcds-sino{ margin-right:12px }
  #topbar:has(.dnv-sel) > .dnv-sel{ order:2; flex:1 0 100%; position:relative; border-top:1px solid var(--dnv-rule) }
  #topbar:has(.dnv-sel) .dnv-sel__bt{ width:100%; min-height:46px; border-right:none }
  #topbar:has(.dnv-sel) .dnv-pop{ left:14px; right:14px; width:auto!important; min-width:0 }
  #topbar:has(.dnv-sel) .dnv-pop__cols{ grid-template-columns:1fr; gap:18px }
  #topbar:has(.dnv-sel) .dnv-campo input{ width:100% }
  #topbar:has(.dnv-sel) > .dnv-trilho__fim{ order:3; margin:0; flex:1 0 100%; border-top:1px solid var(--dnv-rule) }
  #topbar:has(.dnv-sel) .dnv-busca{ width:100%; border:none; padding-block:10px }
  .page[data-pagina="despesas-nova"]{ height:auto }
}
/* Sem barra lateral fixa (ela vira gaveta), a barra de quatro linhas deixa de ser
   grudada: no telefone ela comeria um quarto da tela o tempo todo. */
@media (max-width:767.98px){
  #topbar:has(.dnv-sel){ position:relative }
}


/* ==========================================================================
   TAXA DE FRETE — /taxa-frete/
   ==========================================================================
   PORTE FIEL do protótipo aprovado em 10/09/2026, decisão do dono: "o MOCKUP
   ERA MUITO SUPERIOR EM VÁRIOS ASPECTOS, implemente o mockup, pixel perfect".

   As regras abaixo são as DO PROTÓTIPO, valor por valor. A única mudança é
   mecânica: todo seletor nasce dentro de `.page[data-pagina="taxa_frete"]`,
   e o `:root`/`body` dele viraram esse mesmo seletor — o `custom.css` é lido
   por ~28 telas e token em `:root` vaza no app inteiro. Nenhum tamanho, peso,
   cor, raio ou espaçamento foi reinterpretado.

   Não editar por gosto: mudança aqui é divergência do desenho aprovado.
   ========================================================================== */
.page[data-pagina="taxa_frete"] {/* Neutro frio com viés de zinco — a cor do arame galvanizado, não cinza de framework.
     Recusa deliberada do creme+terracota: três direções de design chegaram nele, e é
     justamente o visual que hoje denuncia página gerada. *//* Uma cor só carrega quantidade de frete, e ela é azul-petróleo: profunda o
     bastante para a barra ter peso sobre o branco, dessaturada o bastante para não
     virar botão. Sem semáforo — a Four não tem meta de frete aprovada, e pintar
     faixa de bom e ruim inventaria um julgamento que ninguém fez. O tijolo entra
     só onde há defeito de dado (peso que não fecha), nunca como avaliação. */
  color-scheme: light;
  
  --zinco:#f1f3f6; --branco:#ffffff; --trilho-bg:#e6eaef;
  --linha:#dbe1e8; --linha-2:#eaeef2;
  --tinta:#16202b; --tinta-2:#48596a; --tinta-3:#76889a; --tinta-4:#a6b4c1;
  
  --frete:#1c5f8b; --frete-forte:#134a6e; --frete-fraco:#d3e4f0;
  --alerta:#9e3a2a;
  --sans:"Archivo",system-ui,-apple-system,"Segoe UI",sans-serif;
  --mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
}
.page[data-pagina="taxa_frete"], .page[data-pagina="taxa_frete"] * { box-sizing:border-box; }
.page[data-pagina="taxa_frete"] {
  margin:0; background:var(--zinco); color:var(--tinta);
  font-family:var(--sans); font-size:13.5px; line-height:1.45;
  -webkit-font-smoothing:antialiased;
}
.page[data-pagina="taxa_frete"] .txf-tela { max-width:1220px; margin:0 auto; padding:26px 20px 48px; }
.page[data-pagina="taxa_frete"] .txf-caps { font-size:10px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; }/* ── a frase ── */


.page[data-pagina="taxa_frete"] .txf-topo { display:flex; justify-content:space-between; align-items:flex-end; gap:32px; flex-wrap:wrap; margin-bottom:22px; }
.page[data-pagina="taxa_frete"] .txf-frase { margin:0; font-size:25px; font-weight:400; line-height:1.32; max-width:24ch; letter-spacing:-.01em; }
.page[data-pagina="taxa_frete"] .txf-frase b { font-weight:650; }
.page[data-pagina="taxa_frete"] .txf-heroi {
  font-family:var(--mono); font-size:58px; font-weight:600; color:var(--frete-forte);
  letter-spacing:-.03em; line-height:1; display:inline-block; vertical-align:-6px; margin:0 2px;
}
.page[data-pagina="taxa_frete"] .txf-ficha { text-align:right; display:flex; flex-direction:column; gap:3px; }
.page[data-pagina="taxa_frete"] .txf-ficha .txf-caps { color:var(--tinta-3); }
.page[data-pagina="taxa_frete"] .txf-ficha b { font-family:var(--mono); font-weight:500; font-size:14px; }
.page[data-pagina="taxa_frete"] .txf-rascunho {
  align-self:flex-start; border:1px dashed var(--linha); border-radius:99px;
  padding:4px 10px; color:var(--tinta-3);
}/* ── régua de meses ── */


.page[data-pagina="taxa_frete"] .txf-regua { margin-bottom:20px; }
.page[data-pagina="taxa_frete"] .txf-regua-topo { display:flex; justify-content:space-between; align-items:baseline; gap:20px; margin-bottom:2px; }
.page[data-pagina="taxa_frete"] .txf-regua-topo .txf-caps { color:var(--tinta-2); }
.page[data-pagina="taxa_frete"] .txf-legenda-ref {
  font-style:normal; font-weight:500; letter-spacing:.02em; text-transform:none;
  color:var(--tinta-3); margin-left:10px; font-size:11px;
}
.page[data-pagina="taxa_frete"] .txf-regua-topo p { margin:0; font-size:12px; color:var(--tinta-3); }
.page[data-pagina="taxa_frete"] .txf-moldura { overflow-x:auto; }
.page[data-pagina="taxa_frete"] .txf-moldura svg { display:block; width:100%; height:auto; }
.page[data-pagina="taxa_frete"] .txf-barra { fill:var(--frete); }
.page[data-pagina="taxa_frete"] .txf-barra-parcial { fill:var(--frete-fraco); }
.page[data-pagina="taxa_frete"] .txf-topo-aberto { stroke:var(--frete); stroke-width:1.5; stroke-dasharray:3 3; }
.page[data-pagina="taxa_frete"] .txf-aguardando { stroke:var(--tinta-4); stroke-width:2; }
.page[data-pagina="taxa_frete"] .txf-linha-base { stroke:var(--linha); stroke-width:1; }
.page[data-pagina="taxa_frete"] .txf-ref { stroke:var(--tinta-3); stroke-width:1; stroke-dasharray:4 4; }
.page[data-pagina="taxa_frete"] .txf-ref-rot.txf-fim { text-anchor:end; }
.page[data-pagina="taxa_frete"] .txf-ref-rot { font-family:var(--sans); font-size:9px; font-weight:700; letter-spacing:.07em; fill:var(--tinta-3); }
.page[data-pagina="taxa_frete"] .txf-num-mes { font-family:var(--mono); font-size:10px; font-weight:500; fill:var(--tinta-2); text-anchor:middle; }
.page[data-pagina="taxa_frete"] .txf-num-mes.txf-parcial { fill:var(--tinta-4); }
.page[data-pagina="taxa_frete"] .txf-mes-rot { font-family:var(--sans); font-size:9px; font-weight:600; letter-spacing:.06em; fill:var(--tinta-4); text-anchor:middle; }
.page[data-pagina="taxa_frete"] .txf-mes-rot.txf-destaque { fill:var(--tinta-2); }
.page[data-pagina="taxa_frete"] .txf-ano-rot { font-family:var(--sans); font-size:10px; font-weight:700; letter-spacing:.08em; fill:var(--tinta-2); text-anchor:middle; }/* ── navegador de profundidade ── */


.page[data-pagina="taxa_frete"] .txf-navegador {
  display:flex; align-items:stretch; gap:0; background:var(--branco);
  border:1px solid var(--linha); border-radius:12px; overflow:hidden; max-height:600px;
}
.page[data-pagina="taxa_frete"] .txf-navegador + .txf-navegador { margin-top:16px; }
.page[data-pagina="taxa_frete"] .txf-trilho {
  width:72px; flex:none; background:var(--trilho-bg); border-right:1px solid var(--linha);
  padding:14px 8px; display:flex; flex-direction:column; align-items:center; gap:10px;
  cursor:pointer; position:relative;
}
.page[data-pagina="taxa_frete"] .txf-trilho:hover { background:#dde4ec; }
.page[data-pagina="taxa_frete"] .txf-trilho::after {
  content:""; position:absolute; right:0; top:0; bottom:0; width:3px; background:var(--frete);
}
.page[data-pagina="taxa_frete"] .txf-trilho .txf-nivel {/* 'RECORTE' em 10px estourava os 58px do trilho */
  color:var(--tinta-3); font-size:8px; letter-spacing:.05em; text-align:center;
  line-height:1.2; 
}
.page[data-pagina="taxa_frete"] .txf-trilho .txf-escolha {/* break-all picotava "Arame Enfardamento" em "Enfar/damen/to"; quebra por
     palavra e três linhas no máximo. */
  font-family:var(--mono); font-size:11px; font-weight:600; text-align:center;
  
  overflow-wrap:anywhere; hyphens:none; line-height:1.25;
  display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden;
}
.page[data-pagina="taxa_frete"] .txf-trilho .txf-medida { font-family:var(--mono); font-size:11px; color:var(--frete-forte); font-weight:600; }
.page[data-pagina="taxa_frete"] .txf-coluna { flex:1 1 0; min-width:0; border-right:1px solid var(--linha); display:flex; flex-direction:column; }
.page[data-pagina="taxa_frete"] .txf-coluna:last-child { border-right:none; }
.page[data-pagina="taxa_frete"] .txf-coluna-cabeca { padding:13px 16px 10px; border-bottom:1px solid var(--linha-2); }
.page[data-pagina="taxa_frete"] .txf-coluna-cabeca .txf-caps { color:var(--tinta-3); display:block; margin-bottom:5px; }
.page[data-pagina="taxa_frete"] .txf-coluna-cabeca h2 { margin:0; font-size:16px; font-weight:600; letter-spacing:-.01em; }
.page[data-pagina="taxa_frete"] .txf-resumo { display:flex; gap:18px; flex-wrap:wrap; margin-top:8px; }
.page[data-pagina="taxa_frete"] .txf-resumo div { display:flex; flex-direction:column; }
.page[data-pagina="taxa_frete"] .txf-resumo .txf-caps { margin-bottom:1px; color:var(--tinta-4); }
.page[data-pagina="taxa_frete"] .txf-resumo b { font-family:var(--mono); font-size:13.5px; font-weight:600; }
.page[data-pagina="taxa_frete"] .txf-resumo b.txf-forte { color:var(--frete-forte); font-size:17px; }
.page[data-pagina="taxa_frete"] .txf-lista { list-style:none; margin:0; padding:6px 8px 12px; overflow-y:auto; flex:1; }
.page[data-pagina="taxa_frete"] .txf-linha {
  display:grid; grid-template-columns:1fr auto; align-items:center; gap:2px 10px;
  padding:7px 8px; border-radius:7px; cursor:pointer;
}
.page[data-pagina="taxa_frete"] .txf-linha:hover { background:var(--zinco); }
.page[data-pagina="taxa_frete"] .txf-linha.txf-escolhido { background:#e9f1f7; box-shadow:inset 2px 0 0 var(--frete); }
.page[data-pagina="taxa_frete"] .txf-linha .txf-rot { font-weight:650; font-size:13px; }
.page[data-pagina="taxa_frete"] .txf-linha .txf-ident { font-family:var(--mono); font-size:12.5px; font-weight:600; }
.page[data-pagina="taxa_frete"] .txf-linha .txf-val { font-family:var(--mono); font-size:13px; font-weight:600; text-align:right; }
.page[data-pagina="taxa_frete"] .txf-linha .txf-val.txf-fino { font-weight:500; color:var(--tinta-2); }
.page[data-pagina="taxa_frete"] .txf-linha .txf-sub { grid-column:1/-1; font-size:11.5px; color:var(--tinta-3); }
.page[data-pagina="taxa_frete"] .txf-linha.txf-bloco { grid-template-columns:1fr auto; }/* Estado: sigla, barra e percentual na MESMA faixa — em três alturas, 18 estados
   viravam uma coluna de rolagem infinita. */

.page[data-pagina="taxa_frete"] .txf-linha.txf-uf { grid-template-columns:30px 1fr auto; }
.page[data-pagina="taxa_frete"] .txf-linha.txf-uf .txf-regua-linha { grid-column:auto; height:7px; }
.page[data-pagina="taxa_frete"] .txf-linha.txf-uf .txf-sub { grid-column:2/-1; }
.page[data-pagina="taxa_frete"] .txf-regua-linha { grid-column:1/-1; background:var(--linha-2); border-radius:2px; height:5px; overflow:hidden; }
.page[data-pagina="taxa_frete"] .txf-regua-linha i { display:block; height:100%; background:var(--frete); border-radius:2px; }
.page[data-pagina="taxa_frete"] .txf-regua-linha.txf-fina { height:3px; }
.page[data-pagina="taxa_frete"] .txf-regua-linha.txf-fina i { background:var(--tinta-4); }
.page[data-pagina="taxa_frete"] .txf-linha .txf-sub b { font-weight:600; }
.page[data-pagina="taxa_frete"] .txf-deduzido, .page[data-pagina="taxa_frete"] .txf-suspeito {
  margin-left:7px; font-size:9.5px; font-weight:700; letter-spacing:.05em; text-transform:uppercase;
  border-radius:3px; padding:1px 5px;
}
.page[data-pagina="taxa_frete"] .txf-deduzido { color:var(--frete-forte); background:var(--frete-fraco); }
.page[data-pagina="taxa_frete"] .txf-suspeito { color:var(--alerta); background:#f6e7e3; cursor:help; }
.page[data-pagina="taxa_frete"] .txf-obs { font-family:var(--mono); font-size:11px; }
.page[data-pagina="taxa_frete"] .txf-pe-coluna {
  padding:10px 16px 14px; border-top:1px solid var(--linha-2); font-size:11.5px;
  color:var(--tinta-2); line-height:1.5;
}
.page[data-pagina="taxa_frete"] .txf-pe-coluna b { color:var(--tinta); }/* ── seletores dentro do trilho zero ── */


.page[data-pagina="taxa_frete"] .txf-coluna.txf-recorte .txf-lista { padding-top:10px; }
.page[data-pagina="taxa_frete"] .txf-grupo-rot { display:block; padding:10px 8px 4px; color:var(--tinta-4); }
.page[data-pagina="taxa_frete"] .txf-item {
  display:flex; align-items:center; gap:9px; padding:6px 8px; border-radius:7px; cursor:pointer; font-size:12.5px;
}
.page[data-pagina="taxa_frete"] .txf-item:hover { background:var(--zinco); }
.page[data-pagina="taxa_frete"] .txf-item .txf-marca {
  width:14px; height:14px; flex:none; border-radius:4px; border:1.5px solid var(--linha);
  background:var(--branco); display:grid; place-items:center; font-size:9px; color:var(--branco);
}
.page[data-pagina="taxa_frete"] .txf-item.txf-ligado .txf-marca { background:var(--frete); border-color:var(--frete); }
.page[data-pagina="taxa_frete"] .txf-item .txf-nome { flex:1; }
.page[data-pagina="taxa_frete"] .txf-item:not(.txf-ligado) .txf-nome { color:var(--tinta-4); }
.page[data-pagina="taxa_frete"] .txf-item .txf-medida { font-family:var(--mono); font-size:11.5px; color:var(--tinta-3); }

.page[data-pagina="taxa_frete"] .txf-explica { margin:14px 0 0; font-size:12.5px; color:var(--tinta-2); line-height:1.55; max-width:96ch; }
.page[data-pagina="taxa_frete"] .txf-explica b { color:var(--tinta); }
.page[data-pagina="taxa_frete"] .txf-rodape { margin-top:22px; font-size:11.5px; color:var(--tinta-3); line-height:1.55; max-width:110ch; }
.page[data-pagina="taxa_frete"] .txf-rodape b { color:var(--tinta-2); }
@media (prefers-reduced-motion:reduce) { .page[data-pagina="taxa_frete"], .page[data-pagina="taxa_frete"] * { transition:none !important; } }

/* ── protótipo clicável ── */


.page[data-pagina="taxa_frete"] .txf-linha { transition:background .12s ease; }
.page[data-pagina="taxa_frete"] .txf-linha:focus-visible, .page[data-pagina="taxa_frete"] .txf-trilho:focus-visible { outline:2px solid var(--frete); outline-offset:-2px; }
.page[data-pagina="taxa_frete"] .txf-coluna.txf-fantasma { opacity:.38; pointer-events:none; background:var(--zinco); }
.page[data-pagina="taxa_frete"] .txf-coluna.txf-fantasma h2 { font-size:14px; color:var(--tinta-3); }
.page[data-pagina="taxa_frete"] .txf-alternadores { display:flex; gap:10px; flex-wrap:wrap; margin-top:10px; }
.page[data-pagina="taxa_frete"] .txf-alternador { display:inline-flex; border:1px solid var(--linha); border-radius:8px; overflow:hidden; }
.page[data-pagina="taxa_frete"] .txf-alternador button {
  border:0; background:var(--branco); color:var(--tinta-2); font-family:inherit; font-size:11.5px;
  font-weight:600; padding:6px 11px; cursor:pointer; letter-spacing:.02em;
}
.page[data-pagina="taxa_frete"] .txf-alternador button + button { border-left:1px solid var(--linha); }
.page[data-pagina="taxa_frete"] .txf-alternador button.txf-on { background:var(--frete); color:#fff; }
.page[data-pagina="taxa_frete"] .txf-alternador button:not(.txf-on):hover { background:var(--zinco); }
.page[data-pagina="taxa_frete"] .txf-dica-uso {
  margin:0 0 12px; font-size:12.5px; color:var(--tinta-2); background:var(--branco);
  border:1px solid var(--linha); border-left:3px solid var(--frete);
  border-radius:8px; padding:10px 14px; line-height:1.55;
}
.page[data-pagina="taxa_frete"] .txf-dica-uso b { color:var(--tinta); }
.page[data-pagina="taxa_frete"] .txf-dica-uso kbd {
  font-family:var(--mono); font-size:11px; background:var(--zinco); border:1px solid var(--linha);
  border-radius:4px; padding:1px 5px;
  color:var(--tinta-2);
}
.page[data-pagina="taxa_frete"] #txf-migalha {
  font-family:var(--mono); font-size:11.5px; color:var(--tinta-3); margin:0 0 8px; min-height:17px;
}
.page[data-pagina="taxa_frete"] #txf-navegador { min-height:520px; }
.page[data-pagina="taxa_frete"] .txf-recorte-corpo { padding:10px 14px 14px; overflow-y:auto; flex:1; }
.page[data-pagina="taxa_frete"] .txf-recorte-corpo .txf-caps { display:block; color:var(--tinta-4); margin:12px 0 5px; }
.page[data-pagina="taxa_frete"] .txf-recorte-corpo .txf-caps:first-child { margin-top:0; }
.page[data-pagina="taxa_frete"] .txf-fecha-recorte {
  margin-top:12px; border:1px solid var(--linha); background:var(--branco); border-radius:8px;
  padding:6px 12px; font-family:inherit; font-size:11.5px; font-weight:600; color:var(--tinta-2); cursor:pointer;
}
.page[data-pagina="taxa_frete"] .txf-fecha-recorte:hover { background:var(--zinco); }/* ── o contrário na linha ── */


.page[data-pagina="taxa_frete"] .txf-contra {
  grid-column:1/-1; font-family:var(--mono); font-size:11px; color:var(--frete-forte);
  letter-spacing:.01em;
}
.page[data-pagina="taxa_frete"] .txf-linha.txf-escolhido .txf-contra { color:#0f3d5c; }/* Rótulo longo (nome de família) ocupa a faixa inteira e empurra a barra para
   baixo — em 30px ele escrevia por cima do gráfico. */



.page[data-pagina="taxa_frete"] .txf-linha.txf-uf.txf-longo { grid-template-columns:1fr auto; }
.page[data-pagina="taxa_frete"] .txf-linha.txf-uf.txf-longo .txf-regua-linha { grid-column:1/-1; margin-top:3px; }
.page[data-pagina="taxa_frete"] .txf-linha.txf-uf.txf-longo .txf-rot { font-size:13px; }
.page[data-pagina="taxa_frete"] .txf-linha.txf-uf.txf-longo .txf-sub { grid-column:1/-1; }
.page[data-pagina="taxa_frete"] .txf-linha .txf-rot { min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }/* ── régua clicável ── */



.page[data-pagina="taxa_frete"] .txf-mes .txf-alvo { fill:transparent; }
.page[data-pagina="taxa_frete"] .txf-mes.txf-clicavel { cursor:pointer; }
.page[data-pagina="taxa_frete"] .txf-mes.txf-clicavel:hover .txf-alvo { fill:rgba(28,95,139,.08); }
.page[data-pagina="taxa_frete"] .txf-mes.txf-clicavel:focus-visible .txf-alvo { fill:rgba(28,95,139,.15); outline:none; }
.page[data-pagina="taxa_frete"] .txf-mes.txf-apagado { opacity:.3; }
.page[data-pagina="taxa_frete"] .txf-mes.txf-selecionado .txf-barra { fill:var(--frete-forte); }
.page[data-pagina="taxa_frete"] .txf-mes.txf-selecionado .txf-num-mes { fill:var(--frete-forte); font-weight:600; }
.page[data-pagina="taxa_frete"] .txf-mes.txf-selecionado .txf-mes-rot { fill:var(--frete-forte); font-weight:700; }
.page[data-pagina="taxa_frete"] #txf-mes-escolhido {
  margin:0 0 8px; font-size:12.5px; color:var(--tinta-2);
}
.page[data-pagina="taxa_frete"] #txf-mes-escolhido:empty { display:none; }
.page[data-pagina="taxa_frete"] #txf-mes-escolhido b { color:var(--frete-forte); }
.page[data-pagina="taxa_frete"] #txf-limpar-mes {
  margin-left:8px; border:1px solid var(--linha); background:var(--branco); border-radius:7px;
  padding:3px 10px; font-family:inherit; font-size:11.5px; font-weight:600; color:var(--tinta-2); cursor:pointer;
}
.page[data-pagina="taxa_frete"] #txf-limpar-mes:hover { background:var(--zinco); border-color:var(--frete); }/* ── busca pelos dois lados ── */


.page[data-pagina="taxa_frete"] .txf-barra-busca { position:relative; margin:0 0 10px; max-width:520px; }
.page[data-pagina="taxa_frete"] #txf-busca {
  width:100%; font-family:var(--mono); font-size:13px; color:var(--tinta);
  background:var(--branco); border:1px solid var(--linha); border-radius:9px;
  padding:10px 13px 10px 38px;
}
.page[data-pagina="taxa_frete"] #txf-busca:focus { outline:none; border-color:var(--frete); box-shadow:0 0 0 3px var(--frete-fraco); }
.page[data-pagina="taxa_frete"] #txf-busca::placeholder { color:var(--tinta-4); font-family:var(--sans); }
.page[data-pagina="taxa_frete"] .txf-lupa {
  position:absolute; left:13px; top:50%; transform:translateY(-50%);
  width:14px; height:14px; border:1.8px solid var(--tinta-4); border-radius:50%;
}
.page[data-pagina="taxa_frete"] .txf-lupa::after {
  content:""; position:absolute; right:-5px; bottom:-3px; width:6px; height:1.8px;
  background:var(--tinta-4); transform:rotate(45deg);
}
.page[data-pagina="taxa_frete"] #txf-achados { list-style:none; margin:6px 0 0; padding:0; display:grid; gap:3px; }
.page[data-pagina="taxa_frete"] #txf-achados li {
  display:grid; grid-template-columns:auto auto 1fr; align-items:baseline; gap:10px;
  background:var(--branco); border:1px solid var(--linha); border-radius:8px;
  padding:8px 12px; cursor:pointer; font-size:12.5px;
}
.page[data-pagina="taxa_frete"] #txf-achados li:hover { border-color:var(--frete); background:#f5f9fc; }
.page[data-pagina="taxa_frete"] #txf-achados b { font-family:var(--mono); font-size:12.5px; }
.page[data-pagina="taxa_frete"] #txf-achados span:last-child { color:var(--tinta-3); }
.page[data-pagina="taxa_frete"] .txf-uf-achado {
  font-size:9.5px; font-weight:700; letter-spacing:.06em; color:var(--tinta-2);
  background:var(--zinco); border-radius:4px; padding:2px 6px;
}
.page[data-pagina="taxa_frete"] #txf-achados li.txf-vazio { cursor:default; color:var(--tinta-3); grid-template-columns:1fr; }
.page[data-pagina="taxa_frete"] #txf-achados li.txf-vazio:hover { border-color:var(--linha); background:var(--branco); }

/* ── acréscimos do redesenho de 10/09/2026 ──────────────────────────────────
   Vindos da leitura da /despesas/nova/, que o dono apontou como referência:
   recorte na topbar, constatação no lugar da instrução, e o drill ACIMA da
   evolução (o trabalho é investigar; a série é contexto do recorte). ────── */

/* O grupo de contas vive no `topbar_actions`, FORA da `.page` — não há como
   escopá-lo. O prefixo `txf-` continua exclusivo desta tela, então não vaza. */
.txf-recorte { display:inline-flex; border:1px solid var(--line-3); }
.txf-recorte__b {
  border:0; background:#fff; color:var(--ink-2); padding:5px 12px; cursor:pointer;
  font-size:.8rem; display:inline-flex; align-items:center; gap:6px;
  font-family:"Archivo",system-ui,sans-serif;
}
.txf-recorte__b + .txf-recorte__b { border-left:1px solid var(--line-3); }
.txf-recorte__b b { font-weight:600; }
.txf-recorte__b.txf-on { background:#134a6e; color:#fff; }
.txf-recorte__b:disabled { opacity:.4; cursor:not-allowed; }
.txf-recorte__b:not(.txf-on):not(:disabled):hover { background:#eef2f6; }

/* A constatação é UMA LINHA de texto entre o número e o drill. Sem moldura: o
   que a separa é o fio de cima e o respiro, como tudo mais nesta tela. */
.page[data-pagina="taxa_frete"] .txf-constatacao {
  margin:0 0 16px; padding:12px 0 0; border-top:1px solid var(--linha);
  font-size:13.5px; color:var(--tinta-2); line-height:1.5;
}
.page[data-pagina="taxa_frete"] .txf-constatacao b { color:var(--tinta); font-weight:650; }
.page[data-pagina="taxa_frete"] .txf-constatacao button {
  border:0; background:none; padding:0; margin-left:6px; font:inherit;
  font-weight:600; color:var(--frete); cursor:pointer; text-decoration:underline;
}
.page[data-pagina="taxa_frete"] .txf-constatacao button:hover { color:var(--frete-forte); }

/* Alternador vira ABA DE TEXTO sublinhada, não pílula preenchida — leitura da
   /despesas/nova/ ("Abrir por: Grupo · Segmento · Credor"). Pílula cinza lê como
   botão desabilitado, e são três grupos de alternador na mesma linha. */
.page[data-pagina="taxa_frete"] .txf-alternador { border:0; border-radius:0; gap:18px; }
.page[data-pagina="taxa_frete"] .txf-alternador button {
  background:none; border:0; border-bottom:2px solid transparent; padding:0 0 4px;
  font-size:11.5px; font-weight:600; letter-spacing:.03em; color:var(--tinta-4);
}
.page[data-pagina="taxa_frete"] .txf-alternador button + button { border-left:0; }
.page[data-pagina="taxa_frete"] .txf-alternador button.txf-on {
  background:none; color:var(--frete-forte); border-bottom-color:var(--frete);
}
.page[data-pagina="taxa_frete"] .txf-alternador button:not(.txf-on):hover {
  background:none; color:var(--tinta-2);
}
.page[data-pagina="taxa_frete"] .txf-alternadores { gap:26px; }

/* O total fecha a página sob fio grosso, como na /despesas/nova/. */
.page[data-pagina="taxa_frete"] .txf-total {
  display:flex; justify-content:space-between; align-items:baseline; gap:20px;
  border-top:2px solid var(--tinta); margin-top:18px; padding-top:10px;
}
.page[data-pagina="taxa_frete"] .txf-total-rot { font-size:11px; font-weight:700;
  letter-spacing:.09em; text-transform:uppercase; }
.page[data-pagina="taxa_frete"] .txf-total-sub { font-size:11.5px; color:var(--tinta-3); }
.page[data-pagina="taxa_frete"] .txf-total b { font-family:var(--mono); font-size:20px;
  font-weight:600; }

/* A evolução passa a fechar a página, não a abri-la. */
.page[data-pagina="taxa_frete"] .txf-regua { margin:22px 0 0; padding-top:14px;
  border-top:1px solid var(--linha); }

/* ── largura inteira, altura da janela (10/09/2026) ─────────────────────────
   Cobrança do dono: "não aproveita largura total da tela, ainda tem muita
   rolagem vertical, o drill precisa ser melhor espalhado". O protótipo nasceu
   como página de leitura — 1220px centrados, tudo empilhado e a página rolando.
   Aqui ele vira TELA DE TRABALHO: quatro faixas numa janela só, e quem rola é a
   lista dentro da coluna, nunca a página.

   O que saiu para caber: a migalha (o trilho já é o caminho, e dizia a mesma
   coisa duas vezes) e o rodapé de quatro linhas (a fonte foi para a
   constatação, que é onde o dono lê). ─────────────────────────────────────── */
.page[data-pagina="taxa_frete"] .txf-tela {
  max-width:none; margin:0; padding:0;
  height:calc(100dvh - 52px - var(--content-pad-y) - var(--content-pad-b));
  /* cabeça · famílias · evolução · drill — a evolução subiu para cima do drill
     em 10/09/2026, decisão do dono. Quem fica com toda a altura que sobra
     continua sendo o drill: é nele que se rola. */
  display:grid; grid-template-rows:auto auto auto minmax(0,1fr); gap:8px;
}

/* PLAIN, de novo e por escrito: nada de raio nesta tela ("eliminem botões com
   raio arredondado; pill redondo; o uso de cards, quero tu plain"). O porte do
   protótipo tinha trazido os raios de volta. */
.page[data-pagina="taxa_frete"] .txf-navegador,
.page[data-pagina="taxa_frete"] .txf-linha,
.page[data-pagina="taxa_frete"] .txf-item,
.page[data-pagina="taxa_frete"] .txf-regua-linha,
.page[data-pagina="taxa_frete"] .txf-regua-linha i,
.page[data-pagina="taxa_frete"] .txf-deduzido,
.page[data-pagina="taxa_frete"] .txf-suspeito,
.page[data-pagina="taxa_frete"] .txf-uf-achado,
.page[data-pagina="taxa_frete"] .txf-fecha-recorte,
.page[data-pagina="taxa_frete"] #txf-limpar-mes,
.page[data-pagina="taxa_frete"] #txf-busca,
.page[data-pagina="taxa_frete"] #txf-achados li { border-radius:0; }

/* ── faixa 1: o número, a ficha e a constatação ── */
.page[data-pagina="taxa_frete"] .txf-topo {
  display:grid; grid-template-columns:minmax(0,1fr) auto; align-items:end;
  gap:4px 28px; margin:0;
}
.page[data-pagina="taxa_frete"] .txf-frase { max-width:none; font-size:17px; line-height:1.3; }
.page[data-pagina="taxa_frete"] .txf-heroi { font-size:32px; vertical-align:-3px; }
.page[data-pagina="taxa_frete"] .txf-ficha {
  flex-direction:row; align-items:baseline; gap:26px; text-align:right;
}
.page[data-pagina="taxa_frete"] .txf-ficha > div { display:flex; flex-direction:column; gap:1px; }
.page[data-pagina="taxa_frete"] .txf-constatacao {
  grid-column:1/-1; margin:0; padding:5px 0 0; font-size:12.5px;
}

/* ── faixa 2: as famílias que entram na variação mensal ──────────────────────
   O seletor do recorte fica NO TOPO e manda na régua: marcar famílias troca o
   numerador para o frete amarrado às notas delas. Texto sublinhado, não pílula
   — pílula cinza lê como botão desabilitado. */
.page[data-pagina="taxa_frete"] .txf-faixa {
  display:flex; align-items:center; gap:8px 14px; padding:5px 0;
  border-top:1px solid var(--linha); border-bottom:1px solid var(--linha);
}
.page[data-pagina="taxa_frete"] .txf-faixa-rot { color:var(--tinta-3); flex:none; }
.page[data-pagina="taxa_frete"] .txf-familias {
  display:flex; flex-wrap:wrap; gap:2px 14px; flex:1; min-width:0;
  max-height:46px; overflow-y:auto;
}
.page[data-pagina="taxa_frete"] .txf-fam {
  border:0; background:none; padding:2px 0; font:inherit; font-size:12px;
  color:var(--tinta-4); cursor:pointer; border-bottom:2px solid transparent;
  white-space:nowrap;
}
.page[data-pagina="taxa_frete"] .txf-fam.txf-on { color:var(--tinta); border-bottom-color:var(--frete); }
.page[data-pagina="taxa_frete"] .txf-fam:hover { color:var(--tinta-2); }
.page[data-pagina="taxa_frete"] .txf-fam b {
  font-family:var(--mono); font-weight:600; font-size:11px; margin-left:5px; color:var(--frete-forte);
}
.page[data-pagina="taxa_frete"] .txf-fam:not(.txf-on) b { color:var(--tinta-4); }
.page[data-pagina="taxa_frete"] .txf-fam--todas { font-weight:700; }

/* A busca desce da própria faixa, sobre o conteúdo: campo largo de 520px em
   linha própria era 60px de altura para um campo que se usa uma vez por dia. */
.page[data-pagina="taxa_frete"] .txf-barra-busca { margin:0; flex:none; width:260px; }
.page[data-pagina="taxa_frete"] #txf-busca { padding:5px 10px 5px 30px; font-size:12px; }
.page[data-pagina="taxa_frete"] .txf-lupa { left:10px; width:12px; height:12px; }
.page[data-pagina="taxa_frete"] #txf-achados {
  position:absolute; z-index:6; top:calc(100% + 4px); left:0; right:0;
  max-height:52vh; overflow-y:auto; background:var(--branco); border:1px solid var(--linha);
}
.page[data-pagina="taxa_frete"] #txf-achados:empty { display:none; }
.page[data-pagina="taxa_frete"] #txf-achados li { border:0; border-bottom:1px solid var(--linha-2); }

/* ── faixa 3: o drill, que fica com TODA a altura que sobrar ── */
.page[data-pagina="taxa_frete"] #txf-navegador,
.page[data-pagina="taxa_frete"] .txf-navegador {
  min-height:0; max-height:none; height:100%; border-left:0; border-right:0;
}
.page[data-pagina="taxa_frete"] .txf-coluna { min-height:0; }
.page[data-pagina="taxa_frete"] .txf-coluna-cabeca { padding:9px 14px 8px; }
.page[data-pagina="taxa_frete"] .txf-coluna-cabeca h2 { font-size:14.5px; }
.page[data-pagina="taxa_frete"] .txf-resumo { gap:14px; margin-top:6px; }
.page[data-pagina="taxa_frete"] .txf-resumo b.txf-forte { font-size:15px; }
.page[data-pagina="taxa_frete"] .txf-lista { padding:4px 6px 8px; }
.page[data-pagina="taxa_frete"] .txf-linha { padding:5px 8px; }
.page[data-pagina="taxa_frete"] .txf-pe-coluna { padding:7px 14px 8px; font-size:11px; }
.page[data-pagina="taxa_frete"] .txf-trilho { width:64px; padding:10px 6px; }

/* ── faixa 3: a evolução, com o total na mesma linha do título ──────────────
   O total sob fio grosso ocupava uma faixa inteira só para ele. Aqui ele
   fecha a linha de cima da régua, que já estava com metade da largura vazia. */
.page[data-pagina="taxa_frete"] .txf-regua {
  margin:0; padding:2px 0 6px; border-top:0; border-bottom:1px solid var(--linha);
}
.page[data-pagina="taxa_frete"] .txf-regua-topo {
  display:flex; align-items:baseline; gap:6px 18px; flex-wrap:wrap; margin-bottom:0;
}
.page[data-pagina="taxa_frete"] .txf-regua-topo #txf-mes-escolhido { margin:0; flex:1; }
.page[data-pagina="taxa_frete"] .txf-total {
  border-top:0; margin:0 0 0 auto; padding:0; gap:10px;
}
.page[data-pagina="taxa_frete"] .txf-total b { font-size:16px; }
.page[data-pagina="taxa_frete"] .txf-moldura { overflow:hidden; }
/* O `.page` da casa fecha com 24px de padding embaixo, e era exatamente esse o
   resto de rolagem que sobrava depois da grade de altura de janela. */
.page[data-pagina="taxa_frete"] { padding-bottom:0; }
.page[data-pagina="taxa_frete"] .txf-tela { overflow:hidden; }

.page[data-pagina="taxa_frete"] .txf-fonte {
  display:block; margin-top:2px; font-style:normal; font-size:11px; color:var(--tinta-4);
}

/* Linha de rótulo longo (família, mês): o percentual sobe para a linha do NOME
   e a barra passa a ocupar a faixa inteira embaixo. Antes o número ficava à
   direita da BARRA, e cada linha comia 80px — seis famílias por tela numa
   coluna que cabe quinze. */
.page[data-pagina="taxa_frete"] .txf-linha.txf-uf.txf-longo { row-gap:2px; }
.page[data-pagina="taxa_frete"] .txf-linha.txf-uf.txf-longo .txf-rot { grid-column:1; grid-row:1; }
.page[data-pagina="taxa_frete"] .txf-linha.txf-uf.txf-longo .txf-val { grid-column:2; grid-row:1; }
.page[data-pagina="taxa_frete"] .txf-linha.txf-uf.txf-longo .txf-regua-linha {
  grid-column:1/-1; grid-row:2; margin-top:0;
}
.page[data-pagina="taxa_frete"] .txf-linha.txf-uf.txf-longo .txf-sub { grid-column:1/-1; grid-row:3; }

/* Fora da raiz, a coluna que já foi escolhida encolhe e a ÚLTIMA fica com a
   folga: uma lista de 3 estados não precisa de 800px, e a lista de CT-e sim. */
.page[data-pagina="taxa_frete"] .txf-coluna:not([data-eixo-raiz]):not(:last-of-type) {
  flex:0 0 clamp(260px, 24%, 400px);
}

/* ── o acerto visual de 11/09/2026 ("a tela tá feia") ───────────────────────
   Três coisas faziam a página parecer cheia e mal-arrumada: o número herói com
   a vírgula solta, a faixa de famílias quebrando em linha rasgada, e a linha do
   eixo gastando três alturas para dizer sigla, barra e percentual. ────────── */

/* O `letter-spacing:-.03em` do protótipo descolava a vírgula do 3,63% em
   IBM Plex Mono. Número é para ler, não para apertar. */
.page[data-pagina="taxa_frete"] .txf-heroi {
  letter-spacing:0; font-variant-numeric:tabular-nums; margin:0 4px;
}
.page[data-pagina="taxa_frete"] .txf-ficha b { font-variant-numeric:tabular-nums; }

/* A fonte volta para o FIM da constatação, na mesma linha: era a terceira
   linha de texto cinza seguida, e três linhas de prosa antes do primeiro
   número é o que fazia o topo parecer um parágrafo. */
.page[data-pagina="taxa_frete"] .txf-fonte {
  display:inline; margin-left:10px; font-size:11px; color:var(--tinta-4);
}

/* A faixa de famílias vira GRADE: colunas do mesmo tamanho, nomes alinhados uns
   sob os outros. Em `flex-wrap` os 21 nomes quebravam em linha rasgada — o
   olho não achava onde uma família terminava e a outra começava. */
.page[data-pagina="taxa_frete"] .txf-familias {
  display:grid; grid-template-columns:repeat(auto-fill, minmax(156px, 1fr));
  gap:1px 18px; align-content:start; max-height:66px; padding-right:2px;
  scrollbar-width:thin;
}
.page[data-pagina="taxa_frete"] .txf-fam {
  display:flex; align-items:baseline; gap:6px;
  font-size:11px; letter-spacing:.01em; padding:1px 0; min-width:0;
}
.page[data-pagina="taxa_frete"] .txf-fam > span {
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0;
}
.page[data-pagina="taxa_frete"] .txf-fam b { margin:0; flex:none; }
.page[data-pagina="taxa_frete"] .txf-fam--todas { grid-column:1; }

/* A linha do eixo cabe numa linha: rótulo · barra · percentual · faturado.
   Antes eram três alturas (nome+barra / percentual / "Faturado: R$ 3,8 M"), e a
   barra atravessava 800px como se fosse progresso de download. */
/* A barra fica com a folga (`1fr`): a coluna tem 800px e travar a barra em
   220px deixava 300px de branco no meio da linha. */
.page[data-pagina="taxa_frete"] .txf-linha.txf-faixa-linha,
.page[data-pagina="taxa_frete"] .txf-linha.txf-faixa-linha.txf-uf,
.page[data-pagina="taxa_frete"] .txf-linha.txf-faixa-linha.txf-uf.txf-longo {
  align-items:center; column-gap:14px; row-gap:0; padding:6px 8px;
  grid-template-columns:34px minmax(120px, 1fr) 62px 104px;
}
.page[data-pagina="taxa_frete"] .txf-linha.txf-faixa-linha.txf-uf.txf-longo {
  grid-template-columns:minmax(0, 180px) minmax(120px, 1fr) 62px 104px;
}
.page[data-pagina="taxa_frete"] .txf-linha.txf-faixa-linha .txf-rot,
.page[data-pagina="taxa_frete"] .txf-linha.txf-faixa-linha.txf-uf.txf-longo .txf-rot {
  grid-column:1; grid-row:1;
}
.page[data-pagina="taxa_frete"] .txf-linha.txf-faixa-linha .txf-regua-linha,
.page[data-pagina="taxa_frete"] .txf-linha.txf-faixa-linha.txf-uf .txf-regua-linha,
.page[data-pagina="taxa_frete"] .txf-linha.txf-faixa-linha.txf-uf.txf-longo .txf-regua-linha {
  grid-column:2; grid-row:1; margin:0; height:6px;
}
.page[data-pagina="taxa_frete"] .txf-linha.txf-faixa-linha .txf-val,
.page[data-pagina="taxa_frete"] .txf-linha.txf-faixa-linha.txf-uf.txf-longo .txf-val {
  grid-column:3; grid-row:1; font-size:12.5px;
}
.page[data-pagina="taxa_frete"] .txf-linha.txf-faixa-linha .txf-sub,
.page[data-pagina="taxa_frete"] .txf-linha.txf-faixa-linha.txf-uf .txf-sub,
.page[data-pagina="taxa_frete"] .txf-linha.txf-faixa-linha.txf-uf.txf-longo .txf-sub {
  grid-column:4; grid-row:1; text-align:right; font-family:var(--mono);
  font-size:11px; color:var(--tinta-3);
}

/* Sem a linha de caps repetindo o título, o cabeçalho da coluna encolhe. */
.page[data-pagina="taxa_frete"] .txf-coluna-cabeca .txf-caps:empty { display:none; }

/* A utilitária do Bootstrap entra na mesma regra, daqui — assim os templates
   e os módulos JS que escrevem `rounded-pill` não precisam ser caçados um a
   um, e o dia em que a casa quiser a pílula de volta é uma linha. */
.rounded-pill { border-radius: var(--raio-chip) !important; }

/* ══════════════════════════════════════════════════════════════════════════
   GRADE DA CASA — reto e sóbrio
   ══════════════════════════════════════════════════════════════════════════
   Reescrita do zero em 11/09/2026. A primeira tentativa empilhou quatro
   gramáticas (chip em pílula petróleo, botão azul do Bootstrap, pílula cinza
   do DataTables, caixa crua de fábrica), inventou um lugar novo para Copiar e
   Colunas, e arredondou tudo. O dono odiou, com razão: cada controle falava um
   sotaque, e a forma redonda dizia "botão" onde o elemento só rotula.

   Três regras, e nada fora delas:
     1. RETO — nenhum raio em lugar nenhum desta seção;
     2. SÓBRIO — só a paleta neutra do FCDS: papel branco, tinta #212529,
        secundária #495057, fio #dee2e6. Cor é para o estado da campanha, que
        é a única informação aqui que tem cor própria;
     3. NADA MUDA DE LUGAR — o `dom` do DataTables é o da casa, então Copiar,
        Colunas, busca e "por pág." ficam onde estão nas outras telas.

   A grade também deixou de morar num cartão: ela É a tela. O par
   `tbl-wrapper datatable` é o que o `esticarGradeUnica` do biUtils procura
   para medir a janela e esticar a lista até embaixo.                      */
.grade {
  --grade-papel: #ffffff;
  --grade-tinta: #212529;
  --grade-tinta-2: #495057;
  --grade-fio: #dee2e6;
  --grade-fio-forte: #adb5bd;
  --grade-realce: #f8f9fa;
}

/* ── chips de recorte ─────────────────────────────────────────────────────
   Retângulos encostados, como abas: a seleção é um retângulo cheio de tinta,
   não uma cor de marca. A contagem vem do SERVIDOR e descreve o recorte
   inteiro — a palavra é o comando, o número é a medida, daí os pesos. */
/* Sem fio embaixo: o respiro já separa os chips da barra, e o fio ali era a
   terceira linha horizontal em 100px de tela. */
.grade .grade-chips { display: flex; flex-wrap: wrap; padding: 0 0 .75rem; }
.grade .grade-chip {
  display: inline-flex; align-items: center; gap: .45rem;
  background: var(--grade-papel); border: 1px solid var(--grade-fio);
  margin-right: -1px; padding: .3rem .75rem;
  color: var(--grade-tinta-2); font-size: .8125rem; line-height: 1.4; cursor: pointer;
}
.grade .grade-chip:hover { background: var(--grade-realce); }
.grade .grade-chip:focus-visible { outline: 2px solid var(--grade-tinta); outline-offset: -1px; }
.grade .grade-chip__conta { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--grade-tinta); }
/* `:hover` junto: sem ele o chip recém-clicado, ainda sob o mouse, pegava o
   fundo claro do hover com a letra branca e sumia (dono, 15/09/2026). */
.grade .grade-chip--ativo,
.grade .grade-chip--ativo:hover {
  background: var(--grade-tinta); border-color: var(--grade-tinta); color: var(--grade-papel);
}
.grade .grade-chip--ativo .grade-chip__conta { color: var(--grade-papel); }

/* ── a barra do DataTables ────────────────────────────────────────────────
   Posição é a da casa; aqui só se apaga o arredondado e a cor de marca, para
   a barra falar a mesma língua da tabela logo abaixo. */
/* (1) A linha solta era o `border-bottom` que o `.datatable` da casa põe na
   barra. Aqui embaixo já vem o fio forte do cabeçalho da tabela: duas linhas
   a três pixels uma da outra leem como defeito, não como separação. */
.grade .datatable-toolbar { padding: .75rem 0; gap: .75rem; border-bottom: 0; }
/* "Limpar filtros": mesmo retângulo de fio dos botões da barra, com o nome por
   extenso; só existe na tela quando há filtro para limpar. */
.grade .grade-limpar-filtros {
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto;
  height: var(--grade-altura-campo); padding: 0 .75rem; white-space: nowrap;
  border: 1px solid var(--grade-fio); background: var(--grade-papel);
  color: var(--grade-tinta); font-size: .8125rem; cursor: pointer;
}
.grade .grade-limpar-filtros:hover { background: var(--grade-realce); }
/* Ação da própria tela na barra (o "Atualizar" das notas): o mesmo retângulo
   de fio, com texto. */
.grade .grade-acao {
  flex: 0 0 auto; height: var(--grade-altura-campo); padding: 0 .75rem;
  border: 1px solid var(--grade-fio); background: var(--grade-papel);
  color: var(--grade-tinta); font-size: .8125rem; cursor: pointer;
}
.grade .grade-acao:hover { background: var(--grade-realce); }
.grade .grade-acao:focus-visible { outline: 2px solid var(--grade-tinta); outline-offset: -1px; }
.grade .grade-limpar-filtros:focus-visible { outline: 2px solid var(--grade-tinta); outline-offset: -1px; }
/* Os chips moram na barra, à esquerda (o `grade.js` os leva para lá). */
.grade .datatable-toolbar__left { flex-wrap: wrap; min-width: 0; }
/* Período na barra e resumo no rodapé (o `pedidos.js` os leva): um campo a
   mais na fileira das ferramentas, com a mesma altura e o mesmo fio. */
[data-pagina="crm-pedidos"] .grade .pd-periodo { display: flex; align-items: center; gap: .5rem; flex: 0 0 auto; }
[data-pagina="crm-pedidos"] .grade .pd-periodo select,
[data-pagina="crm-pedidos"] .grade .pd-periodo input[type="date"] {
  width: auto; height: var(--grade-altura-campo); padding: 0 1.5rem 0 .4rem;
  border: 1px solid var(--grade-fio); background-color: var(--grade-papel);
  font-size: .8125rem; color: var(--grade-tinta);
}
[data-pagina="crm-pedidos"] .grade .pd-periodo input[type="date"] { padding-right: .4rem; }
/* O Cliente "tomava a sobra" (`width:100%`, sem teto) quando a lista cabia na
   folha; com 16 colunas e rolagem lateral, a sobra virava 500px e empurrava o
   Valor para fora da janela. */
[data-pagina="crm-pedidos"] .grade .pd-col-cliente { width: auto; max-width: 16rem; }
[data-pagina="crm-pedidos"] .grade .datatable-bottom .pd-resumo {
  margin-left: 1.25rem; font-size: .8125rem;
}
/* UMA linha, obrigatoriamente (dono, 15/09/2026): quem não cabe é a tela com
   atalho demais, e a correção é tirar chip, não quebrar a barra. */
.grade .datatable-toolbar { flex-wrap: nowrap; }
.grade .datatable-toolbar__left,
.grade .datatable-toolbar__right { flex-wrap: nowrap; white-space: nowrap; }
.grade .datatable-toolbar .grade-chips { flex-wrap: nowrap; }
.grade .datatable-toolbar .dt-buttons,
.grade .datatable-toolbar .grade-chip,
.grade .datatable-toolbar .dataTables_length { flex-wrap: nowrap; flex-shrink: 0; }
/* O grupo da direita não cede: o `.btn-group` dos botões quebra linha no
   mínimo de conteúdo, então o grupo encolhia abaixo da largura real e o
   Colunas vazava 7-9px pela borda a 1280. */
.grade .datatable-toolbar__right { margin-left: auto; flex-shrink: 0; }
/* Quem cede quando falta largura é a BUSCA (até 7rem), não a linha: chips,
   período e botões têm tamanho de palavra, o campo de busca não. */
.grade .datatable-toolbar__left { flex: 1 1 auto; }
.grade .datatable-toolbar .dataTables_filter { flex: 0 1 14rem; min-width: 7rem; }
.grade .datatable-toolbar .dataTables_filter label { display: flex; width: 100%; min-width: 0; margin: 0; }
/* `min-width: 0`: o `<input>` tem largura mínima nativa (~20 caracteres), que
   segurava o encolhimento e fazia a barra estourar a 1280. */
.grade .dataTables_wrapper .datatable-toolbar .dataTables_filter input { width: 100%; min-width: 0; margin: 0; }
.grade .datatable-toolbar .grade-chips { padding: 0; }
.grade .dt-buttons { gap: .5rem; }
.grade .dt-button,
.grade .dt-buttons .btn,
.grade .dt-buttons .pill {
  border-radius: 0 !important;
  border: 1px solid var(--grade-fio) !important;
  background: var(--grade-papel) !important;
  color: var(--grade-tinta) !important;
  padding: .3rem .75rem !important; margin: 0;
  font-size: .8125rem; font-weight: 400; box-shadow: none !important;
}
.grade .dt-button:hover,
.grade .dt-buttons .pill:hover { background: var(--grade-realce) !important; }
.grade .dt-button.dt-button-active,
.grade .dt-buttons .pill.active {
  background: var(--grade-tinta) !important; border-color: var(--grade-tinta) !important;
  color: var(--grade-papel) !important;
}
.grade .dt-button-collection {
  border-radius: 0; border: 1px solid var(--grade-fio);
  background: var(--grade-papel); box-shadow: 0 4px 14px rgba(33, 37, 41, .12); padding: .25rem;
}
.grade .dt-button-collection .dt-button { border: 0 !important; width: 100%; text-align: left; }

.grade .dataTables_filter input,
.grade .dataTables_length select {
  border-radius: 0; border: 1px solid var(--grade-fio);
  background: var(--grade-papel); color: var(--grade-tinta);
  padding: .3rem .5rem; font-size: .8125rem;
}
.grade .dataTables_filter input { width: 18rem; max-width: 100%; }
.grade .dataTables_filter input:focus,
.grade .dataTables_length select:focus { outline: none; border-color: var(--grade-fio-forte); }
.grade .dataTables_length select { font-variant-numeric: tabular-nums; }
.grade .dataTables_filter label,
.grade .dataTables_length label {
  color: var(--grade-tinta-2); font-size: .8125rem; margin: 0; gap: .4rem;
}

/* ── a tabela ─────────────────────────────────────────────────────────────
   Densidade por ESPAÇAMENTO, nunca por fonte menor: texto miúdo não é
   densidade, é perda de legibilidade. O cabeçalho ancora a coluna, então não
   pode pesar menos que o dado que nomeia. */
.grade .grade-tabela { border-collapse: collapse; width: 100%; font-size: .9375rem; margin: 0; }
/* O DataTables fecha a tabela sem rodapé com um fio escuro (`.no-footer`):
   linha solta embaixo da última linha, que o dono não quer. */
.grade table.dataTable.grade-tabela.no-footer { border-bottom: 0; }
.grade .grade-tabela thead th:first-child { padding-left: .6rem; }
.grade .grade-tabela thead th {
  position: sticky; top: 0; z-index: 2;
  text-align: left; font-weight: 600; text-transform: uppercase;
  color: var(--grade-tinta); font-size: .75rem; letter-spacing: .04em;
  padding: .35rem .75rem .35rem 0; white-space: nowrap;
  border-bottom: 1px solid var(--grade-fio-forte); background: var(--grade-papel);
}
.grade .grade-tabela thead tr.grade-filtros-col th {
  top: 1.85rem;
  text-transform: none; font-weight: 400; padding: .2rem .6rem .35rem 0;
  border-bottom: 1px solid var(--grade-fio-forte);
}
/* Um traço só ancora o cabeçalho, embaixo dos FILTROS. O fio entre rótulos e
   filtros cortava o cabeçalho ao meio e lia como linha voando (dono,
   15/09/2026). */
.grade .grade-tabela thead tr:first-child th { border-bottom: 0; }
.grade .grade-filtro-texto {
  width: 100%; min-width: 5rem; border-radius: 0;
  border: 1px solid var(--grade-fio); background: var(--grade-papel);
  padding: .12rem .35rem; font-size: .8125rem; color: var(--grade-tinta);
}
.grade .grade-filtro-texto:focus { outline: none; border-color: var(--grade-fio-forte); }

/* A seta aparece SEMPRE: apagada na coluna inativa diz "dá para ordenar por
   aqui"; cheia na ativa diz "está ordenado por aqui, neste sentido".
   Afordância que só aparece depois de usada não é afordância. A do DataTables
   é imagem de fundo — apagada, porque a nossa é texto e segue a cor. */
.grade .grade-tabela thead tr:first-child th { cursor: pointer; }
.grade .grade-tabela thead th.sorting,
.grade .grade-tabela thead th.sorting_asc,
.grade .grade-tabela thead th.sorting_desc { background-image: none !important; }
/* Caret cheio do Font Awesome, não seta de texto: a ↕ era "magrinha e feia"
   para o dono (15/09/2026), em todas as telas. */
/* O DataTables desenha o par ▲▼ com `::before`/`::after` em posição absoluta
   na borda direita da coluna e reserva 26px para ele: aqui o `::before` sai e
   o `::after` volta a correr junto do rótulo. */
.grade .grade-tabela thead tr:first-child th::before { content: none !important; }
.grade .grade-tabela thead tr:first-child th.sorting,
.grade .grade-tabela thead tr:first-child th.sorting_asc,
.grade .grade-tabela thead tr:first-child th.sorting_desc { padding-right: .75rem; }
.grade .grade-tabela thead tr:first-child th::after {
  content: '\f0dc'; font-family: 'Font Awesome 6 Free'; font-weight: 900;
  position: static; display: inline; line-height: inherit;
  margin-left: .35rem; font-size: .8125rem; color: var(--grade-tinta-2); opacity: .35;
}
.grade .grade-tabela thead tr:first-child th.sorting_asc::after { content: '\f0de'; color: var(--grade-tinta); opacity: 1; }
.grade .grade-tabela thead tr:first-child th.sorting_desc::after { content: '\f0dd'; color: var(--grade-tinta); opacity: 1; }
.grade .grade-tabela thead tr.grade-filtros-col th::after { content: none; }
/* Coluna que não ordena (ações, caixa de marcar) não ganha seta: sem isto a
   coluna "Ações" da separação mostrava um caret que não fazia nada. */
.grade .grade-tabela thead tr:first-child th.sorting_disabled::after { content: none; }

/* Sem fio vertical e sem zebra: a coluna já é separada pelo alinhamento, e
   cada linha de tinta a mais é ruído sobre o dado. Só o fio horizontal fica,
   no tom mais fraco que ainda separa. */
.grade .grade-tabela tbody tr {
  border-bottom: 1px solid var(--grade-fio); cursor: pointer;
  box-shadow: inset 2px 0 0 transparent;
}
/* Com coluna congelada a tabela passa a `border-collapse: separate` (exigência
   do `.stickcols`), e aí fio e sombra do `<tr>` não pintam: a divisão desce
   para a célula e o traço do cursor para a primeira célula. */
.grade table.stickcols.grade-tabela tbody tr { border-bottom: 0; }
.grade table.stickcols.grade-tabela tbody td { border-bottom: 1px solid var(--grade-fio); }
.grade table.stickcols.grade-tabela tbody td.dataTables_empty { border-bottom: 0; }
.grade table.stickcols.grade-tabela tbody tr:hover > td:first-child { box-shadow: inset 2px 0 0 var(--grade-tinta); }
/* Coluna congelada SEM fio na borda (dono, 15/09/2026: "tem uma linha de
   separação que não deveria existir, e o conteúdo toca a linha"). O divisor da
   casa (`::after` no td, `border-right` no th) sai; quem separa o painel preso
   do que rola por baixo é uma folga branca maior à direita da última coluna
   presa — o conteúdo que rola some atrás do papel, não atrás de um traço. */
.grade table.stickcols.grade-tabela td.stick--edge::after { content: none; }
.grade table.stickcols.grade-tabela th.stick--edge { border-right: 0; }
.grade table.stickcols.grade-tabela .stick--edge { padding-right: 1.5rem; }
/* A linha sob o cursor ganha um traço à ESQUERDA em vez de um banho de fundo:
   o banho embaça o texto que está em cima dele; o traço marca sem sujar. */
.grade .grade-tabela tbody tr:hover { box-shadow: inset 2px 0 0 var(--grade-tinta); }
.grade .grade-tabela tbody tr:focus-visible { outline: 2px solid var(--grade-tinta); outline-offset: -2px; }
.grade .grade-tabela tbody td {
  padding: .4rem .75rem .4rem 0; vertical-align: top;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.grade .grade-tabela tbody td:first-child { padding-left: .6rem; }
/* O corte do texto mora no invólucro, não no `<td>`: o Chrome ignora
   `max-width` numa célula de tabela automática, e a coluna abria até caber o
   nome inteiro (Cliente com 502px). O teto que a tela declara na célula chega
   aqui por herança. */
.grade .grade-tabela .grade-celula {
  max-width: inherit; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Número se compara de cima a baixo: à direita e com algarismo de largura
   fixa, senão a coluna dança a cada linha. */
.grade .grade-tabela .text-end { text-align: right; font-variant-numeric: tabular-nums; }
/* Teto, não largura fixa: assunto curto fica curto, comprido trunca no
   `ellipsis` — nunca abre a coluna até empurrar as vizinhas para longe. */
.grade .grade-col-larga { font-weight: 600; max-width: 26rem; }
/* O estado é a única informação da grade com cor própria, e ela tem ordem:
   rascunho é ausência, enviando é meio do caminho, concluída é fim. Retângulo
   de fio fino e letra na cor — o badge sólido gritava mais que o assunto. */

/* ── rodapé: contagem e páginas ───────────────────────────────────────── */
.grade .datatable-bottom { padding: .75rem 0; color: var(--grade-tinta-2); font-size: .8125rem; }
.grade .dataTables_info { font-variant-numeric: tabular-nums; }
/* Paginador: quadrados do mesmo tamanho para número e seta, sem caixa em
   volta. A página corrente é a ÚNICA coisa pintada; as setas são chevrons do
   Font Awesome (o `‹ ›` de texto era um fio quase invisível — dono,
   15/09/2026). No bootstrap5 do DataTables o elemento é
   `<li.page-item><a.page-link>`. */
.grade .dataTables_paginate .pagination { gap: .25rem; margin: 0; align-items: center; }
.grade .dataTables_paginate .page-item .page-link {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 2rem; height: 2rem; padding: 0 .5rem !important; margin: 0;
  border: 0 !important; box-shadow: none !important;
  background: transparent !important; color: var(--grade-tinta-2) !important;
  font-size: .875rem; font-variant-numeric: tabular-nums;
}
.grade .dataTables_paginate .page-item.previous .page-link,
.grade .dataTables_paginate .page-item.next .page-link {
  color: var(--grade-tinta) !important; font-size: .75rem;
}
.grade .dataTables_paginate .page-item:not(.active):not(.disabled) .page-link:hover {
  background: var(--grade-realce) !important; color: var(--grade-tinta) !important;
}
.grade .dataTables_paginate .page-item.active .page-link {
  background: var(--grade-tinta) !important; color: var(--grade-papel) !important;
  font-weight: 600;
}
.grade .dataTables_paginate .page-item.disabled .page-link {
  color: var(--grade-fio-forte) !important; background: transparent !important; cursor: default;
}

/* ── vazio ────────────────────────────────────────────────────────────────
   O bloco toma o lugar da grade (que fica `hidden`), e a notícia é dada UMA
   vez. Cabeçalho e filtros sobre nada são um esqueleto, e o dono leu isso
   como tela quebrada (03/09/2026). */
.grade .grade-vazio { padding: 4rem 1rem; text-align: center; border-top: 1px solid var(--grade-fio); }
.grade .grade-vazio__titulo { margin: 0; font-size: 1.0625rem; font-weight: 600; color: var(--grade-tinta); }
.grade .grade-vazio__dica { margin: .35rem 0 0; font-size: .875rem; color: var(--grade-tinta-2); }
.grade .grade-vazio__acao {
  margin-top: 1.25rem; border-radius: 0; border: 1px solid var(--grade-tinta);
  background: var(--grade-papel); padding: .35rem .9rem;
  font: inherit; font-size: .875rem; font-weight: 600; color: var(--grade-tinta); cursor: pointer;
}
.grade .grade-vazio__acao:hover { background: var(--grade-tinta); color: var(--grade-papel); }
/* Recorte vazio: a frase entra na linha única que o DataTables põe no corpo.
   `sticky` + `left:50%` a centra na parte VISÍVEL da folha, mesmo numa grade
   mais larga que a janela. */
.grade .grade-tabela tbody tr:has(> td.dataTables_empty) { cursor: default; box-shadow: none; border-bottom: 0; }
.grade .grade-tabela tbody td.dataTables_empty { padding: 0; white-space: normal; overflow: visible; text-align: left; }
.grade .grade-vazio--no-recorte {
  display: inline-block; position: sticky; left: 50%; transform: translateX(-50%);
  border-top: 0; padding: 3rem 1rem;
  /* Numa grade estreita (lista num cartão) a frase mais larga que a tabela
     saía pela esquerda: ela quebra linha dentro da metade do meio. */
  white-space: normal; max-width: 50%;
}

/* ── a grade É a tela ─────────────────────────────────────────────────────
   Três correções do dono em 11/09/2026, no mesmo lugar porque são o mesmo
   assunto — a grade não é um bloco DENTRO da página, ela é a página.

   1. Fundo branco de ponta a ponta. O gelo (`--bg`, #f6f7f9) é o cinza do
      shell aparecendo em volta; numa tela que é só tabela ele vira uma moldura
      sem função. A folha sangra na VERTICAL para cobrir o recuo do `.content`
      — só na vertical, porque sangrar na horizontal joga a folha para baixo da
      barra lateral.
   2. Altura da janela inteira, mesmo com oito linhas. Sem isto sobra uma faixa
      branca embaixo da última linha e a lista parece cortada no meio do nada.
      É `flex` puro, não medição em JS: o que se mede a cada `draw` descola no
      dia em que a barra muda de altura.
   3. O loader para de parecer cartão: sem raio e sem superfície própria, ele é
      só a marca sobre o branco que já está lá.                            */
[data-pagina="email-marketing"] {
  background: #fff;
  margin: calc(var(--content-pad-y) * -1) 0 calc(var(--content-pad-b) * -1);
  padding: var(--content-pad-y) 0 0;
  min-height: calc(100dvh - 52px);
  box-sizing: border-box;
  display: flex; flex-direction: column;
}
.content:has([data-pagina="email-marketing"]) { background: #fff; }

/* A cadeia inteira precisa ceder altura: basta um elo sem `min-height: 0`
   para o `flex: 1` do fim virar altura do conteúdo e a faixa voltar. */
.grade,
.grade .tbl-wrapper,
.grade .dataTables_wrapper {
  display: flex; flex-direction: column; flex: 1; min-height: 0;
}
.grade .datatable-scroll {
  flex: 1; min-height: 0; overflow: auto; max-height: none;
}
/* Sem fio em cima do rodapé: o dono quer a grade sem moldura e sem linha
   solta (15/09/2026). `margin-top:auto` é o que o empurra para o pé. */
.grade .datatable-bottom { margin-top: auto; justify-content: flex-start; gap: 1rem; }
/* Contagem (e resumo) à esquerda; "N por pág." e as páginas juntos à direita. */
.grade .datatable-bottom .dataTables_length { margin-left: auto; }
.grade .datatable-bottom .dataTables_length label { display: inline-flex; align-items: center; gap: .4rem; margin: 0; }
/* O mesmo combo do período: sem isto o `form-select-sm` do Bootstrap somava
   4px em cima e embaixo à altura de linha de 26px, e o número descia na caixa
   de 28px; e o `background` do campo apagava a seta do combo. */
.grade .dataTables_wrapper .datatable-bottom .dataTables_length select {
  appearance: auto; -webkit-appearance: auto;
  padding: 0 1.5rem 0 .4rem !important; line-height: normal;
  font-size: .8125rem !important; width: auto;
}
/* A casa põe `border-top` no rodapé do DataTables: era a segunda linha voando. */
.grade .dataTables_wrapper .datatable-bottom { border-top: 0; }

.grade .logo-loader {
  background: #fff; border-radius: 0;
}
.grade [data-bi-loading] { min-height: 0; }

/* ── grade embaixo de um painel ───────────────────────────────────────────
   Produtos e Previsão de caixa têm gráfico e cartões em cima e a grade
   embaixo. A grade NÃO mora num cartão (dono, 15/09/2026: sem moldura): a
   folha da página fica branca, os cartões de cima seguem com o fio deles, e o
   bloco da grade tem a altura da janela — rolando até ela, cabeçalho e rodapé
   ficam à vista e só as linhas rolam. */
.content:has(> .page[data-pagina="estoque2"]),
.content:has(> .page[data-pagina="previsao_caixa"]),
.content:has(> .page[data-pagina="separacao_faturamento"]),
.page[data-pagina="estoque2"],
.page[data-pagina="previsao_caixa"],
.page[data-pagina="separacao_faturamento"] { background: #fff; }
.page[data-pagina="previsao_caixa"] .pc-abas {
  display: flex; flex-direction: column; height: calc(100dvh - 52px); min-height: 420px;
}
.page[data-pagina="previsao_caixa"] .pc-abas > [data-tab-pane]:not([hidden]) {
  flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
}

/* ── grade em janela (`compacta`) ─────────────────────────────────────────
   Dentro de um modal a grade não estica: tem a altura do que mostra (10 por
   página), e só passa a rolar por dentro quando a lista não cabe na janela. */
.grade--compacta,
.grade--compacta .tbl-wrapper,
.grade--compacta .dataTables_wrapper { flex: none; }
.grade--compacta .datatable-scroll { flex: none; max-height: 60vh; }
.grade--compacta .datatable-bottom { margin-top: 0; }
/* Janela de inadimplência do faturamento: com o texto livre da observação
   solto, a tabela passava da largura da janela e os valores iam para fora. */
#modalbox-inadimplencia .grade .inad-col-nome { max-width: 11rem; }
#modalbox-inadimplencia .grade .inad-col-observacao { max-width: 9rem; }
/* Janela "ver registros" do cockpit: cliente e item de nota passam de 600px
   numa linha só; com teto, o valor fica dentro da janela. */
#modalbox-registros .grade .registros-col-texto { max-width: 20rem; }

/* ── linha expansível ─────────────────────────────────────────────────────
   A linha-filha é um painel da linha de cima, não outra linha de dados: sem
   listra, sem a barra de hover, com o fundo de realce da grade. */
.grade .grade-tabela tbody tr.grade-detalhe > td {
  padding: .75rem 1rem; background: var(--grade-realce);
  border-bottom: 1px solid var(--grade-fio); white-space: normal;
}
.grade .grade-tabela tbody tr.grade-detalhe:hover { box-shadow: none; }
.grade .grade-detalhe__espera { color: var(--grade-tinta-2); font-size: .8125rem; }

/* ── linha de total ───────────────────────────────────────────────────────
   Presa no pé da folha, como o cabeçalho no topo: o total fica à vista com a
   lista rolando. Fio forte em cima, o mesmo que ancora o cabeçalho. */
.grade .grade-tabela tfoot th {
  position: sticky; bottom: 0; z-index: 3;
  background: var(--grade-papel);
  border-top: 1px solid var(--grade-fio-forte); border-bottom: 0;
  font-weight: 600; color: var(--grade-tinta); white-space: nowrap;
}
.grade table.stickcols.grade-tabela tfoot th[class*="stick--"] { z-index: 6; }

/* ── correções de acabamento (dono, 11/09/2026, sobre print anotado) ──────
   1. Sobrava raio em três controles. Eles não vêm do meu CSS: o campo de
      busca e o de "por pág." são `.form-control` do Bootstrap, e o gatilho do
      `colfilter-multi` amarra o raio em `--bs-border-radius-sm` de propósito,
      para acompanhar os campos vizinhos. Dentro de `.grade` o vizinho é reto,
      então aqui o raio é zerado na origem — `!important` porque é exatamente
      contra essas amarras que ele precisa vencer.
   2. Os filtros tinham alturas diferentes: o campo de texto era um `<input>
      nu e o de lista um gatilho com ícone. Uma altura só, declarada num
      token, e os dois passam a cair na mesma linha de base.
   3. As etiquetas de estado eram contorno vazado em tom apagado. Viram
      PREENCHIDAS, com o texto centrado e largura mínima — numa coluna, o que
      se lê é o bloco de cor, e três blocos de larguras diferentes leem como
      três coisas diferentes.                                              */
.grade {
  --grade-altura-campo: 1.75rem;
}
.grade input,
.grade select,
.grade button,
.grade .page-link,
.grade .page-item,
.grade .colfilter-multi__trigger,
.grade .colfilter-multi__panel,
.grade .dt-button-collection {
  border-radius: 0 !important;
}
/* O interruptor é a exceção: reto ele deixa de ler como interruptor e vira
   uma caixa com uma bolinha dentro. */
.grade .form-switch .form-check-input { border-radius: 2em !important; }

/* Estado na célula: ponto + palavra, nunca pílula colorida (dono, requisito da
   grade global). Cor só para o que pede ação — o estado normal é neutro, como
   o estágio de Pedidos. Uma classe por tom; a tela mapeia a chave do serviço
   para o tom. */
.grade .grade-status { white-space: nowrap; }
.grade .grade-status::before {
  content: ''; display: inline-block; width: .5rem; height: .5rem; border-radius: 50%;
  margin-right: .45rem; vertical-align: baseline; background: var(--neutral);
}
.grade .grade-status--ok::before { background: var(--positive-text); }
.grade .grade-status--atencao { color: var(--warning-text); }
.grade .grade-status--atencao::before { background: var(--warning); }
.grade .grade-status--erro { color: var(--negative-text); }
.grade .grade-status--erro::before { background: var(--negative-text); }

/* Mesma altura, mesmo fio, mesma tipografia nos três controles da barra e nos
   dois da linha de filtros. */
.grade .dataTables_filter input,
.grade .dataTables_length input,
.grade .dataTables_length select,
.grade .grade-filtro-texto,
.grade .colfilter-multi__trigger {
  height: var(--grade-altura-campo); min-height: var(--grade-altura-campo);
  box-sizing: border-box; padding: 0 .4rem;
  border: 1px solid var(--grade-fio); background: var(--grade-papel);
  font-size: .8125rem; line-height: calc(var(--grade-altura-campo) - 2px);
  color: var(--grade-tinta);
}
.grade .dataTables_filter input:focus,
.grade .dataTables_length input:focus,
.grade .grade-filtro-texto:focus,
.grade .colfilter-multi__trigger:focus-visible {
  outline: none; border-color: var(--grade-fio-forte);
}
/* A casa pinta estes dois campos com pílula cinza e `!important` em
   `.dataTables_wrapper .dataTables_filter input` — mais específica que as
   regras acima, e era por isso que o raio e o fundo cinza sobreviviam. */
.grade .dataTables_wrapper .dataTables_filter input,
.grade .dataTables_wrapper .dataTables_length input,
.grade .dataTables_wrapper .dataTables_length select {
  border-radius: 0 !important; border: 1px solid var(--grade-fio) !important;
  background: var(--grade-papel) !important;
}
.grade .dataTables_wrapper .dataTables_filter input:focus,
.grade .dataTables_wrapper .dataTables_length input:focus,
.grade .dataTables_wrapper .dataTables_length select:focus { border-color: var(--grade-fio-forte) !important; }
.grade .dataTables_length input { width: 3.5rem; text-align: center; padding: 0; }
.grade .dataTables_filter input { width: 18rem; max-width: 100%; }
/* (2) O funil SOME. A linha inteira é de filtros — repetir um ícone de funil
   em cada coluna não informa nada, e espremido na altura do campo ele virava
   um losango sem forma, que foi lido como ícone quebrado. Fica o chevron,
   sozinho e no tamanho natural, que é o que diz "isto abre". */
.grade .colfilter-multi__ico { display: none; }
.grade .colfilter-multi__trigger > i {
  color: var(--grade-fio-forte); opacity: 1; font-size: .7rem; line-height: 1;
}
.grade .colfilter-multi__trigger > span {
  overflow: hidden; text-overflow: ellipsis;
}
.grade .colfilter-multi--ativo .colfilter-multi__trigger {
  border-color: var(--grade-tinta); color: var(--grade-tinta); font-weight: 600;
}

/* Etiqueta de estado: aqui SÓ a geometria — centrada e com largura mínima,
   porque numa coluna o que se lê é o bloco, e blocos de larguras diferentes
   leem como coisas diferentes. A COR vem dos modificadores canônicos do FCDS
   (`badge--primary`, `badge--neutro`, `badge--info`), que já resolvem esta
   semântica. Chumbar cor aqui foi como o mostarda #8a5a00 voltou: ele é
   exatamente o tom que o `custom.css` já tinha expulsado por ser "uma terceira
   família para dizer atenção". */
/* Etiqueta de estado: preenchida, centrada e de largura mínima — numa coluna
   o que se lê é o bloco, e blocos de larguras diferentes leem como coisas
   diferentes.

   A cor sai dos tokens da casa, nunca de hex escolhido na hora: foi assim que
   o mostarda `#8a5a00` voltou à tela depois de o `custom.css` já o ter
   expulsado por ser "uma terceira família para dizer atenção".

     concluída → `--positive-text`, o verde da casa. Decisão do dono em
                 11/09/2026, contra o que o `badge--neutro` recomenda — o
                 argumento de lá continua escrito, e ele olhou a tela real;
     enviando  → `--info-text`, família de informação. Em curso não é alerta,
                 e o âmbar era justamente o que lia como marrom;
     rascunho  → `--ink-2`, tinta neutra: nada aconteceu ainda.            */
[data-pagina="email-marketing"] .grade .grade-tabela .badge {
  justify-content: center; min-width: 6.25rem; line-height: 1.2;
  border: 0; color: #fff !important; font-weight: 600;
}
[data-pagina="email-marketing"] .grade .grade-estado--concluida { background: var(--positive-text) !important; }
[data-pagina="email-marketing"] .grade .grade-estado--enviando { background: var(--info-text) !important; }
[data-pagina="email-marketing"] .grade .grade-estado--rascunho { background: var(--ink-2) !important; }

/* ==========================================================================
   REPORTES — o botão do megafone (shell), o modal de reportar (shell) e a
   fila da triagem (`/reportes/`).

   Escopo em três níveis, de propósito:
     · `.fcds-reportar` é SHELL — vive na topbar de todas as telas, e por isso
       herda exatamente a forma do sino ao lado (mesma caixa, mesma borda,
       mesmo cinza). Dois botões vizinhos com gramáticas diferentes leem como
       dois sistemas;
     · `.reportar-*` é o modal, que também é shell, mas só existe aberto;
     · `[data-pagina="reportes"]` é a tela de triagem — escopo de página,
       livre.
   ========================================================================== */

/* ── o botão ───────────────────────────────────────────────────────────── */
/* Nasceu gêmeo cinza do sino e o dono leu a tela real: "ficou pouco visível"
   (11/09/2026). Três coisas mudaram, nessa ordem de importância:

     1. a PALAVRA. Ícone sozinho na topbar é charada — "Reportar" escrito é o
        que dispensa a pessoa de adivinhar. Some abaixo de 992px, onde não
        cabe, e aí o `aria-label` continua dizendo;
     2. a COR. Vermelho CHEIO, por ordem do dono no mesmo dia, depois de ver
        o contorno azul na tela: ele quer o botão achado sem procura. Fica
        registrado o argumento contra, para quem reabrir isto: vermelho é a
        família do NEGATIVO no sistema (perda, saída, abaixo do mínimo), e
        preenchido de vermelho fixo na topbar de 56 telas diz "há algo errado
        aqui" o tempo todo. O dono olhou a tela real e preferiu assim — como
        no verde de "concluída" da grade do e-mail marketing;
     3. o ÍCONE. Megafone é o que o botão FAZ com o reporte depois; exclamação
        é o que a pessoa SENTE na hora de clicar. */
.fcds-reportar{display:inline-flex;align-items:center;gap:.375rem;height:2rem;padding:0 .75rem;
  border:var(--bs-border-width) solid transparent;border-radius:var(--bs-border-radius-lg);
  background:var(--negative-text);color:#fff;font-size:.8125rem;font-weight:600;
  line-height:1;white-space:nowrap;cursor:pointer}
.fcds-reportar i{font-size:.9375rem}
/* `--negative` é o degrau mais claro da MESMA família, não um vermelho novo:
   hover que troca de matiz lê como outro botão. */
.fcds-reportar:hover{background:var(--negative);color:#fff}
.fcds-reportar:focus-visible{outline:2px solid var(--negative-text);outline-offset:2px}
.fcds-reportar[aria-busy="true"]{cursor:progress;opacity:.75}
@media (max-width:991.98px){
  .fcds-reportar{width:2rem;padding:0;justify-content:center}
  .fcds-reportar__t{display:none}
}

/* ── modal: tipo ───────────────────────────────────────────────────────── */
/* Bug e Melhoria como dois alvos grandes e não um `<select>`: são só dois, e
   a escolha é a primeira coisa que a pessoa faz. */
.reportar-tipos{display:flex;gap:.5rem;margin-bottom:1rem}
.reportar-tipo{flex:1 1 0;margin:0}
.reportar-tipo input{position:absolute;opacity:0;pointer-events:none}
.reportar-tipo span{display:flex;align-items:center;justify-content:center;gap:.375rem;
  padding:.5rem .75rem;border:var(--bs-border-width) solid var(--line-3);
  border-radius:var(--bs-border-radius);background:var(--surf);color:var(--ink-2);
  font-weight:600;cursor:pointer}
.reportar-tipo input:checked + span{border-color:var(--acc);background:var(--acc-soft);color:var(--acc-ink)}
.reportar-tipo input:focus-visible + span{outline:2px solid var(--acc);outline-offset:2px}

.reportar-rotulo{display:block;margin:0 0 .25rem;font-size:.8125rem;font-weight:600;color:var(--ink-2)}
.reportar-dica{align-self:center;font-size:.8125rem;color:var(--ink-3)}
.reportar-erro{margin:.75rem 0 0;font-size:.8125rem;color:var(--bs-danger)}
/* O erro que a tela mostrou, dito de volta à pessoa. Família de INFORMAÇÃO, não
   de alerta: aqui não está acontecendo nada de errado — está sendo avisado que
   uma prova já foi anexada. Vermelho aqui seria um segundo susto. */
/* Confirmação depois de enviar: verde de sucesso, na mesma gramática de faixa
   lateral da faixa de erro logo abaixo. */
.reportar-enviado{display:flex;align-items:flex-start;gap:.5rem;margin:0 0 1rem;
  padding:.625rem .75rem;border-left:3px solid var(--positive-text);
  background:var(--positive-subtle);font-size:.875rem;color:var(--ink)}
.reportar-enviado i{color:var(--positive-text);font-size:1.125rem;line-height:1.25rem}
.reportar-enviado span{display:block;color:var(--ink-2)}
.reportar-erro-app{display:flex;align-items:flex-start;gap:.375rem;margin:0 0 .75rem;
  padding:.375rem .5rem;border-left:3px solid var(--info-text);background:var(--surf-2);
  font-size:.8125rem;color:var(--ink-2)}

/* ── modal: anexos ─────────────────────────────────────────────────────── */
.reportar-anexos{display:flex;flex-wrap:wrap;gap:.5rem;margin:.75rem 0}
.reportar-anexos__vazio{margin:0;font-size:.8125rem;color:var(--ink-3)}
/* Miniatura grande e presa ao TOPO: a captura agora é a página inteira, e o
   topo é onde a pessoa reconhece a tela. */
.reportar-anexo{position:relative;margin:0;width:14rem}
.reportar-anexo img{display:block;width:100%;height:9rem;object-fit:cover;object-position:top;
  border:var(--bs-border-width) solid var(--line);border-radius:var(--bs-border-radius)}
.reportar-anexo figcaption{margin-top:.125rem;font-size:.6875rem;color:var(--ink-3)}
.reportar-anexo__x{position:absolute;top:.25rem;right:.25rem;width:1.25rem;height:1.25rem;
  display:flex;align-items:center;justify-content:center;padding:0;line-height:1;
  border:0;border-radius:var(--bs-border-radius-sm);background:rgba(0,0,0,.55);color:#fff;cursor:pointer}
.reportar-acoes{display:flex;flex-wrap:wrap;gap:.5rem;margin-top:.5rem}
/* "Editar captura" fica SOBRE a miniatura, no rodapé dela: é a única ação que só faz
   sentido com aquela imagem na frente, e um botão solto embaixo perderia a
   qual das cinco ele se refere. */
.reportar-anexo__marcar{position:absolute;left:0;right:0;bottom:1.125rem;
  padding:.125rem 0;border:0;line-height:1;
  background:rgba(0,0,0,.55);color:#fff;font-size:.6875rem;font-weight:600;cursor:pointer}
.reportar-anexo__marcar:hover{background:rgba(0,0,0,.75)}

/* ── modal: o marcador ─────────────────────────────────────────────────── */
.reportar-marcador{margin:.75rem 0;padding:.75rem;border:var(--bs-border-width) solid var(--line);
  border-radius:var(--bs-border-radius);background:var(--surf-2)}
.reportar-marcador__topo{position:sticky;top:-1rem;z-index:2;display:flex;flex-wrap:wrap;
  align-items:center;justify-content:space-between;gap:.5rem;margin:-.75rem -.75rem .5rem;
  padding:.75rem;background:var(--surf-2);border-bottom:var(--bs-border-width) solid var(--line);
  font-size:.8125rem;color:var(--ink-2)}
.reportar-marcador__topo span{display:block;color:var(--ink-3)}
/* Editando: o modal vira tela cheia e só o editor fica — sem o formulário, o
   mural e o rodapé disputando a altura com o print. */
.reportar-editando #reportar-form > :not(#reportar-marcador),
.reportar-editando #reportar-enviado,
.reportar-editando #reportar-mural,
.reportar-editando .modal-footer{display:none !important}
.reportar-editando .reportar-marcador{margin:0}
/* `crosshair` porque o gesto é desenhar, não clicar; `touch-action:none` porque
   sem ele o dedo ROLA a página em vez de desenhar o retângulo. */
.reportar-marcador__tela{display:block;max-width:100%;touch-action:none;cursor:crosshair;
  border:var(--bs-border-width) solid var(--line-3);background:var(--surf)}
.reportar-marcador__acoes{display:flex;flex-wrap:wrap;gap:.5rem}

/* ── modal: o mural da tela ────────────────────────────────────────────── */
.reportar-mural{margin-top:1.25rem;padding-top:1rem;border-top:var(--bs-border-width) solid var(--line)}
.reportar-mural__titulo{margin:0 0 .5rem;font-size:.8125rem;font-weight:700;color:var(--ink-2);
  text-transform:uppercase;letter-spacing:.04em}
.reportar-mural__lista{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.5rem}
.reportar-mural__vazio{font-size:.8125rem;color:var(--ink-3)}
.reportar-item{padding:.625rem .75rem;border:var(--bs-border-width) solid var(--line);
  border-radius:var(--bs-border-radius);background:var(--surf)}
/* O próprio reporte da pessoa marcado pela BORDA, não pelo fundo: fundo
   colorido numa lista de dez vira mancha, e aqui o destaque precisa apenas
   dizer "este é o seu". */
.reportar-item--meu{border-left:3px solid var(--acc)}
.reportar-item__topo{display:flex;flex-wrap:wrap;align-items:center;gap:.375rem;margin-bottom:.25rem}
.reportar-item__quem{margin-left:auto;font-size:.75rem;color:var(--ink-3)}
.reportar-item__texto{margin:0;font-size:.875rem;color:var(--ink);white-space:pre-wrap}
.reportar-item__nota{margin:.375rem 0 0;padding-left:.5rem;border-left:2px solid var(--line-3);
  font-size:.8125rem;color:var(--ink-2)}
.reportar-item__pe{display:flex;align-items:center;gap:.5rem;margin-top:.5rem}
.reportar-item__print img{width:3rem;height:2rem;object-fit:cover;
  border:var(--bs-border-width) solid var(--line);border-radius:var(--bs-border-radius-sm)}

.reportar-marca,.reportar-estado{display:inline-flex;align-items:center;padding:.0625rem .375rem;
  border-radius:var(--bs-border-radius-sm);font-size:.6875rem;font-weight:700;
  text-transform:uppercase;letter-spacing:.03em}
.reportar-marca--bug{background:var(--bs-danger);color:#fff}
.reportar-marca--melhoria{background:var(--acc);color:#fff}
.reportar-estado{background:var(--surf-3);color:var(--ink-2)}
.reportar-estado--andamento{background:var(--info-text);color:#fff}
.reportar-estado--deploy{background:var(--info-text);color:#fff}
.reportar-estado--fechado{background:var(--ink-2);color:#fff}

/* "+1": contorno, nunca cinza sólido — cinza cheio lê como desabilitado, e
   este é o botão que faz a fila se priorizar sozinha. */
/* Mural colaborativo (15/09/2026): gestos em texto, discretos ao lado do "+1",
   para não competir com o reporte; excluído vira uma linha recolhida, porque
   some da vista mas não do registro. */
.reportar-item__gestos{display:flex;flex-wrap:wrap;align-items:center;gap:.75rem;margin-left:auto}
.reportar-link{padding:0;border:0;background:none;font-size:.75rem;color:var(--acc-ink);cursor:pointer;margin:0}
.reportar-link:hover{text-decoration:underline}
.reportar-link--perigo{color:var(--negative-text)}
.reportar-item--excluido{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;
  background:var(--surf-2);border-style:dashed;font-size:.75rem;color:var(--ink-3)}
.reportar-item--excluido .reportar-link{margin-left:auto}
.reportar-edicao{display:flex;flex-direction:column;gap:.375rem}
.reportar-edicao__tipos{display:flex;gap:1rem;font-size:.8125rem}
.reportar-edicao__dica{margin:0;font-size:.75rem;color:var(--ink-3)}
.reportar-edicao__acoes{display:flex;gap:.5rem}
.reportar-historico{margin-top:.5rem;font-size:.75rem;color:var(--ink-2)}
.reportar-historico summary{cursor:pointer;color:var(--ink-3)}
.reportar-historico ul{margin:.375rem 0 0;padding-left:1rem}
.reportar-historico li{margin-bottom:.25rem}
.reportar-historico__antes{display:block;color:var(--ink-3);white-space:pre-wrap}
.reportar-mais{display:inline-flex;align-items:center;gap:.375rem;padding:.125rem .5rem;
  border:var(--bs-border-width) solid var(--line-3);border-radius:var(--bs-border-radius-sm);
  background:var(--surf);color:var(--ink-2);font-size:.75rem;font-weight:600;cursor:pointer}
.reportar-mais:hover:not(:disabled){border-color:var(--acc);color:var(--acc-ink)}
.reportar-mais.is-on{border-color:var(--acc);background:var(--acc-soft);color:var(--acc-ink)}
.reportar-mais:disabled{cursor:default;opacity:.75}

/* ── tela de triagem ───────────────────────────────────────────────────── */
/* A grade é a de /crm/pedidos/ (ver o cabeçalho de CRM · PEDIDOS). Aqui só o
   que é da fila: o ponto do status enche conforme a triagem anda — novo vazio,
   em andamento meio, fechado cheio —, num tom só, como o estágio do pedido.
   Excluído sai da jornada: ponto e texto apagados. */
/* A folha branca vai de borda a borda como a do Pedidos: o recuo lateral do
   `.content` sai e volta como respiro da própria página — senão sobra um
   filete cinza do shell dos dois lados. */
.content:has(> .page[data-pagina="reportes"]){padding-inline:0}
.content > .page[data-pagina="reportes"]{padding-inline:var(--content-pad-x)}
[data-pagina="reportes"] .rp-e-andamento .pd-estagio-marca{
  background:linear-gradient(90deg, var(--pedido-petroleo) 50%, transparent 50%)}
[data-pagina="reportes"] .rp-e-deploy .pd-estagio-marca{
  background:linear-gradient(90deg, var(--pedido-petroleo) 75%, transparent 75%)}
[data-pagina="reportes"] .rp-e-fechado .pd-estagio-marca{background:var(--pedido-petroleo)}
[data-pagina="reportes"] .rp-e-excluido{color:var(--pedido-tinta-2)}
[data-pagina="reportes"] .rp-e-excluido .pd-estagio-marca{box-shadow:inset 0 0 0 1.25px var(--pedido-fio-forte)}
/* "O que" fica com a sobra da linha e corta no fim; `max-width:0` é o que deixa
   a reticência agir numa tabela de largura automática. */
[data-pagina="reportes"] .rp-col-descricao{width:100%;max-width:0;min-width:16rem}
/* O invólucro da célula herda o teto da coluna (`max-width: inherit`, na
   GRADE DA CASA); aqui o teto é o `0` do truque acima, e herdado ele sumia com
   o texto inteiro (visto em produção, 15/09/2026). O corte já é do `td`. */
[data-pagina="reportes"] .rp-col-descricao .grade-celula{max-width:none}
.rp-excluido{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;margin-bottom:.75rem;
  padding:.5rem .625rem;border-left:3px solid var(--ink-3);background:var(--surf-2);font-size:.8125rem}
.rp-historico{margin:.25rem 0 .75rem;padding-left:1rem;font-size:.8125rem;color:var(--ink-2)}
.rp-historico li{margin-bottom:.25rem}
.rp-historico__antes{display:block;color:var(--ink-3);white-space:pre-wrap}
.rp-gestos--fim{margin-top:1rem;padding-top:.75rem;border-top:var(--bs-border-width) solid var(--line)}

.rp-painel__texto{margin:0 0 .25rem;font-size:.9375rem;color:var(--ink);white-space:pre-wrap}
.rp-painel__quem{margin:0 0 .75rem;font-size:.75rem;color:var(--ink-3)}
.rp-painel__nota{margin:.5rem 0 0;font-size:.8125rem;color:var(--ink-3)}
.rp-painel__print img{display:block;width:100%;margin-bottom:.75rem;
  border:var(--bs-border-width) solid var(--line);border-radius:var(--bs-border-radius)}
.rp-contexto{display:grid;grid-template-columns:auto 1fr;gap:.125rem .5rem;margin:0 0 1rem;
  font-size:.75rem}
.rp-contexto dt{color:var(--ink-3)}
.rp-contexto dd{margin:0;color:var(--ink-2);overflow-wrap:anywhere}
.rp-rotulo{display:block;margin:.75rem 0 .25rem;font-size:.8125rem;font-weight:600;color:var(--ink-2)}
.rp-gestos{display:flex;flex-wrap:wrap;gap:.5rem;align-items:center}

/* ═══ TAREFAS E PROJETOS ([data-pagina="tarefas"]) ═══════════════════════════
   /tarefas/ redesenhada em 17/09/2026 na pele TERMINAL CLARO — a mesma da
   Reunião Semanal e de /despesas/nova/ — com o vocabulário de interação do
   Microsoft To-Do. Gabarito: docs/redesign/mockups/tarefas-terminal-claro.html
   (variante A, aprovada pelo dono). Não mexer por gosto: mude o gabarito e
   depois meça a tela contra ele.

   A tela É a janela: `content--altura-cheia` no template dá a altura, e quem
   rola é o rail, a lista e o painel — nunca a página. Por isso toda a cadeia
   abaixo carrega `min-height:0` (sem ele o filho flex não encolhe e o rolo
   vaza para fora da janela).

   Os tokens são os `--dnv-*` já declarados na seção de despesas/reunião; esta
   tela só entra na lista de quem os recebe. Nenhuma cor nova. */

/* Recuo só à ESQUERDA: a barra lateral do shell se pinta até x=64 mas `.main`
   começa em x=48, então com `padding:0` os 16px iniciais do rail nascem ATRÁS
   dela (o "PROJETOS" virava "ROJETOS"). À direita não há recuo de propósito —
   é ali que o painel de detalhe encosta na janela. */
.page[data-pagina="tarefas"]{
  position:relative; padding:0 0 0 var(--content-pad-x) !important; overflow:hidden;
  background:var(--dnv-surface); color:var(--dnv-ink);
  font-size:13px; line-height:1.35; -webkit-font-smoothing:antialiased;
}
.page[data-pagina="tarefas"] *{ box-sizing:border-box }
/* O filtro de coluna da casa (`colfilter-multi`, usado pelo seletor de
   responsáveis) fica FORA da limpeza de botões: sem borda e sem fundo o
   gatilho vira três peças soltas. Mesmo `:where` da seção de despesas. */
.page[data-pagina="tarefas"] button:not(:where(.colfilter-multi__trigger)){
  font:inherit; color:inherit; background:none; border:0; padding:0; cursor:pointer; text-align:left;
}
.page[data-pagina="tarefas"] :focus-visible{ outline:2px solid var(--dnv-mark); outline-offset:1px }
.page[data-pagina="tarefas"] h1,
.page[data-pagina="tarefas"] h2,
.page[data-pagina="tarefas"] h3,
.page[data-pagina="tarefas"] h4{ margin:0 }
.page[data-pagina="tarefas"] .mudo{ color:var(--dnv-ink-3) }
.page[data-pagina="tarefas"] .risco{ color:var(--dnv-risco) }
.page[data-pagina="tarefas"] .tf-prazo,
.page[data-pagina="tarefas"] .tf-et-n{ font-variant-numeric:tabular-nums; font-feature-settings:"tnum" 1,"lnum" 1 }

/* ── a busca, na barra do shell ──────────────────────────────────────────── */
#topbar .tf-busca{ display:flex; align-items:center; gap:6px; min-width:0 }
#topbar .tf-busca input{
  width:220px; height:1.7rem; padding:0 7px; border:1px solid var(--dnv-rule-2);
  border-radius:0; background:var(--dnv-surface); color:var(--dnv-ink); font:inherit; font-size:13px;
}
#topbar .tf-busca input:focus{ outline:0; border-color:var(--dnv-mark) }
#topbar .tf-busca kbd{
  font:inherit; font-size:10px; font-weight:600; color:var(--dnv-ink-3);
  border:1px solid var(--dnv-rule); border-radius:0; padding:0 4px; background:none;
}

/* ── a folha: rail | centro | (painel cobre) ─────────────────────────────── */
.page[data-pagina="tarefas"] .tf{ flex:1 1 auto; min-height:0; min-width:0; display:flex }

/* ── rail: visões salvas, projetos com fases, pessoas ────────────────────── */
.page[data-pagina="tarefas"] .tf-rail{
  flex:0 0 218px; min-height:0; display:flex; flex-direction:column;
  background:var(--dnv-surface-2); border-right:1px solid var(--dnv-rule);
}
.page[data-pagina="tarefas"] .tf-rail__rolo{
  flex:1 1 auto; min-height:0; overflow:auto; overscroll-behavior:contain; padding:8px 0 4px;
}
.page[data-pagina="tarefas"] .tf-rail h2{
  padding:8px 12px 3px; font-size:9.6px; font-weight:700; letter-spacing:.09em;
  text-transform:uppercase; color:var(--dnv-ink-3);
}
.page[data-pagina="tarefas"] .tf-rail h2 + .tf-vis{ border-top:1px solid var(--dnv-rule) }
.page[data-pagina="tarefas"] .tf-vis{
  display:grid; grid-template-columns:14px minmax(0,1fr) auto; gap:8px; align-items:center;
  width:100%; padding:5px 12px; border-left:2px solid transparent;
}
.page[data-pagina="tarefas"] .tf-vis:hover{ background:var(--dnv-surface-3) }
.page[data-pagina="tarefas"] .tf-vis[aria-current="true"]{
  background:var(--dnv-surface); border-left-color:var(--dnv-ink); font-weight:500;
}
.page[data-pagina="tarefas"] .tf-vis .g{ color:var(--dnv-ink-3); font-size:12px; line-height:1; text-align:center }
.page[data-pagina="tarefas"] .tf-vis[aria-current="true"] .g{ color:var(--dnv-ink) }
.page[data-pagina="tarefas"] .tf-vis .n{
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:12.4px;
}
.page[data-pagina="tarefas"] .tf-vis .q{ font-variant-numeric:tabular-nums; font-size:11px; color:var(--dnv-ink-3) }
.page[data-pagina="tarefas"] .tf-vis .q.risco{ color:var(--dnv-risco); font-weight:600 }

/* projeto no rail: nome + progresso DO SERVIDOR + fases dobráveis */
.page[data-pagina="tarefas"] .tf-pj{ border-top:1px solid var(--dnv-rule) }
.page[data-pagina="tarefas"] .tf-pj:first-of-type{ border-top:0 }
.page[data-pagina="tarefas"] .tf-pj__cab{
  display:grid; grid-template-columns:14px minmax(0,1fr) auto; gap:8px; align-items:center;
  width:100%; padding:6px 12px 2px; border-left:2px solid transparent;
}
.page[data-pagina="tarefas"] .tf-pj[data-atual] .tf-pj__cab{
  background:var(--dnv-surface); border-left-color:var(--dnv-ink);
}
.page[data-pagina="tarefas"] .tf-pj__cab:hover{ background:var(--dnv-surface-3) }
.page[data-pagina="tarefas"] .tf-pj__cab .ca{
  width:14px; text-align:center; font-size:9px; color:var(--dnv-ink-3);
  transition:transform .12s; display:inline-block;
}
.page[data-pagina="tarefas"] .tf-pj[data-aberto] .tf-pj__cab .ca{ transform:rotate(90deg) }
.page[data-pagina="tarefas"] .tf-pj__cab .n{
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  font-size:12.4px; font-weight:500;
}
.page[data-pagina="tarefas"] .tf-pj__cab .q{ font-variant-numeric:tabular-nums; font-size:11px; color:var(--dnv-ink-3) }
.page[data-pagina="tarefas"] .tf-pj__prog{ height:3px; margin:0 12px 5px 34px; background:var(--dnv-surface-3) }
.page[data-pagina="tarefas"] .tf-pj__prog i{ display:block; height:100%; background:var(--rs-seg-1,#2B323C) }
.page[data-pagina="tarefas"] .tf-pj__fases[hidden]{ display:none }
.page[data-pagina="tarefas"] .tf-fase{
  display:grid; grid-template-columns:minmax(0,1fr) auto; gap:8px; align-items:center;
  width:100%; padding:3px 12px 3px 34px; border-left:2px solid transparent;
  font-size:11.7px; color:var(--dnv-ink-2);
}
.page[data-pagina="tarefas"] .tf-fase:hover{ background:var(--dnv-surface-3) }
.page[data-pagina="tarefas"] .tf-fase[aria-current="true"]{
  background:var(--dnv-surface); border-left-color:var(--dnv-ink); color:var(--dnv-ink); font-weight:500;
}
.page[data-pagina="tarefas"] .tf-fase .n{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.page[data-pagina="tarefas"] .tf-fase .q{ font-variant-numeric:tabular-nums; font-size:10.7px; color:var(--dnv-ink-3) }
.page[data-pagina="tarefas"] .tf-fase-nova{
  display:block; width:calc(100% - 46px); margin:2px 12px 4px 34px; height:1.5rem; padding:0 5px;
  border:1px solid transparent; border-radius:0; background:none; color:var(--dnv-ink);
  font:inherit; font-size:11.7px;
}
.page[data-pagina="tarefas"] .tf-fase-nova:hover{ border-color:var(--dnv-rule) }
.page[data-pagina="tarefas"] .tf-fase-nova:focus{ outline:0; border-color:var(--dnv-mark); background:var(--dnv-surface) }
.page[data-pagina="tarefas"] .tf-rail__pe{ flex:0 0 auto; border-top:1px solid var(--dnv-rule); padding:6px 12px }
.page[data-pagina="tarefas"] .tf-rail__pe button{ font-size:11px; color:var(--dnv-mark); font-weight:500 }
.page[data-pagina="tarefas"] .tf-rail__pe button:hover{ text-decoration:underline }

/* ── centro ──────────────────────────────────────────────────────────────── */
.page[data-pagina="tarefas"] .tf-centro{
  flex:1 1 auto; min-width:0; min-height:0; display:flex; flex-direction:column; padding:12px 18px 10px;
}
/* A LISTA tem largura máxima, e as duas razões são medidas: linha de 1.650px
   é longa demais para o olho varrer do título (à esquerda) até o prazo (à
   direita); e, como o painel COBRE a folha, a régua faz a faixa da direita da
   linha (etapas · responsáveis · prazo) cair fora do painel a partir de
   ~1.600px de janela. É a geometria do próprio To-Do. */
.page[data-pagina="tarefas"] .tf-centro > .tf-cab,
.page[data-pagina="tarefas"] .tf-centro > .tf-barra,
.page[data-pagina="tarefas"] .tf-centro > .tf-novo,
.page[data-pagina="tarefas"] .tf-centro > .tf-rolo{ max-width:1180px }

.page[data-pagina="tarefas"] .tf-cab{ flex:0 0 auto; display:flex; align-items:baseline; gap:12px; flex-wrap:wrap }
.page[data-pagina="tarefas"] .tf-cab h2{ font-size:1.0625rem; font-weight:600; letter-spacing:-.01em }
.page[data-pagina="tarefas"] .tf-cab__titulo{
  font:inherit; font-size:1.0625rem; font-weight:600; letter-spacing:-.01em; color:var(--dnv-ink);
  background:none; border:0; border-bottom:1px solid transparent; padding:1px 0; min-width:12rem;
}
.page[data-pagina="tarefas"] .tf-cab__titulo:hover{ border-bottom-color:var(--dnv-rule) }
.page[data-pagina="tarefas"] .tf-cab__titulo:focus{ outline:0; border-bottom-color:var(--dnv-mark) }
.page[data-pagina="tarefas"] .tf-cab__situacao{
  height:1.5rem; border:1px solid var(--dnv-rule-2); border-radius:0; background:var(--dnv-surface);
  color:var(--dnv-ink-2); font:inherit; font-size:11.7px; padding:0 4px;
}
.page[data-pagina="tarefas"] .tf-cab .sub{
  font-size:11px; color:var(--dnv-ink-3); font-variant-numeric:tabular-nums;
}
.page[data-pagina="tarefas"] .tf-cab .sub b{ font-weight:600; color:var(--dnv-ink-2) }
.page[data-pagina="tarefas"] .tf-cab .sub .risco{ font-weight:600 }
.page[data-pagina="tarefas"] .tf-cab__fim{ margin-left:auto; display:flex; align-items:center; gap:4px }

/* alternância LISTA | QUADRO: um par, o ativo sublinhado em tinta */
.page[data-pagina="tarefas"] .tf-par{ display:inline-flex; gap:12px; margin-right:6px }
.page[data-pagina="tarefas"] .tf-pr{
  font-size:10.4px; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  color:var(--dnv-ink-3); padding:1px 0 2px; border-bottom:2px solid transparent;
}
.page[data-pagina="tarefas"] .tf-pr[aria-pressed="true"]{ color:var(--dnv-ink); border-bottom-color:var(--dnv-ink) }

.page[data-pagina="tarefas"] .tf-erro[hidden]{ display:none }
.page[data-pagina="tarefas"] .tf-erro{
  margin-top:6px; padding:5px 8px; border:1px solid var(--dnv-risco-rule);
  background:var(--dnv-risco-wash); color:var(--dnv-risco); font-size:12px;
}

/* barra agrupar / ordenar */
.page[data-pagina="tarefas"] .tf-barra{
  flex:0 0 auto; display:flex; align-items:center; gap:16px; flex-wrap:wrap;
  padding:7px 0 6px; margin-top:6px;
  border-top:1px solid var(--dnv-rule); border-bottom:1px solid var(--dnv-rule);
}
.page[data-pagina="tarefas"] .tf-sel{ display:inline-flex; align-items:center; gap:6px }
.page[data-pagina="tarefas"] .tf-sel > span{
  font-size:9.6px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; color:var(--dnv-ink-3);
}
.page[data-pagina="tarefas"] .tf-sel select{
  height:1.55rem; padding:0 4px 0 5px; border:1px solid var(--dnv-rule-2); border-radius:0;
  background:var(--dnv-surface); color:var(--dnv-ink); font:inherit; font-size:11.7px;
}
.page[data-pagina="tarefas"] .tf-sel select:focus{ outline:0; border-color:var(--dnv-mark) }
.page[data-pagina="tarefas"] .tf-barra__fim{ margin-left:auto; display:flex; align-items:center; gap:14px }
.page[data-pagina="tarefas"] .tf-marca{
  display:inline-flex; align-items:center; gap:5px; font-size:11px; color:var(--dnv-ink-2); margin:0;
}
.page[data-pagina="tarefas"] .tf-marca input{ accent-color:var(--dnv-mark); margin:0 }

/* a linha "+ nova tarefa": o To-Do põe no TOPO, e é onde o olho já está */
.page[data-pagina="tarefas"] .tf-novo{
  flex:0 0 auto; display:flex; align-items:center; gap:6px; padding:7px 0 6px;
  border-bottom:1px solid var(--dnv-rule);
}
.page[data-pagina="tarefas"] .tf-novo .sinal{
  width:15px; text-align:center; color:var(--dnv-ink-3); font-size:15px; line-height:1;
}
.page[data-pagina="tarefas"] .tf-cmp{
  min-width:0; height:1.7rem; padding:0 7px; border:1px solid var(--dnv-rule-2); border-radius:0;
  background:var(--dnv-surface); color:var(--dnv-ink); font:inherit;
}
.page[data-pagina="tarefas"] .tf-novo .tf-cmp{ flex:1 1 auto; border-color:transparent; padding-left:0 }
.page[data-pagina="tarefas"] .tf-novo .tf-cmp:hover{ border-color:var(--dnv-rule); padding-left:7px }
.page[data-pagina="tarefas"] .tf-novo .tf-cmp:focus{ outline:0; border-color:var(--dnv-mark); padding-left:7px }
.page[data-pagina="tarefas"] .tf-cmp::placeholder{ color:var(--dnv-ink-3) }
.page[data-pagina="tarefas"] .tf-estado{
  flex:0 0 auto; font-size:9.6px; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  color:var(--dnv-ink-3); white-space:nowrap;
}
.page[data-pagina="tarefas"] .tf-estado.risco{
  color:var(--dnv-risco); text-transform:none; letter-spacing:0; font-weight:400; font-size:11.5px;
}

/* ── LISTA ───────────────────────────────────────────────────────────────── */
.page[data-pagina="tarefas"] .tf-rolo{ flex:1 1 auto; min-height:0; overflow:auto; overscroll-behavior:contain }
.page[data-pagina="tarefas"] .tf-grupo-cab{
  display:flex; align-items:center; gap:7px; width:100%; padding:9px 2px 3px;
  font-size:9.9px; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  color:var(--dnv-ink-2); border-bottom:1px solid var(--dnv-rule);
}
.page[data-pagina="tarefas"] .tf-grupo:first-child .tf-grupo-cab{ padding-top:4px }
.page[data-pagina="tarefas"] .tf-grupo-cab .ca{
  width:9px; text-align:center; font-size:9px; color:var(--dnv-ink-3); transition:transform .12s; display:inline-block;
}
.page[data-pagina="tarefas"] .tf-grupo[data-aberto] .tf-grupo-cab .ca{ transform:rotate(90deg) }
.page[data-pagina="tarefas"] .tf-grupo-cab .n{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.page[data-pagina="tarefas"] .tf-grupo-cab b{
  margin-left:auto; font-weight:600; color:var(--dnv-ink-3); font-variant-numeric:tabular-nums;
}
.page[data-pagina="tarefas"] .tf-grupo-corpo[hidden]{ display:none }

/* A LINHA: [○] título / meta … etapas  responsáveis  prazo  ⋯ */
.page[data-pagina="tarefas"] .tf-li{
  display:grid; grid-template-columns:16px minmax(0,1fr) auto; gap:8px; align-items:start;
  padding:5px 4px 5px 2px; border-bottom:1px solid var(--rs-fio,#ECEEF1); cursor:pointer; position:relative;
}
.page[data-pagina="tarefas"] .tf-li:hover{ background:var(--dnv-surface-2) }
.page[data-pagina="tarefas"] .tf-li[aria-selected="true"]{ background:var(--dnv-mark-wash) }
.page[data-pagina="tarefas"] .tf-li.arrastando{ opacity:.35 }
.page[data-pagina="tarefas"] .tf-li.alvo{ box-shadow:inset 0 2px 0 0 var(--dnv-mark) }

/* o círculo: o único canto redondo desta tela, e é controle, não moldura */
.page[data-pagina="tarefas"] .tf-cx{
  width:15px; height:15px; margin-top:1px; border:1px solid var(--dnv-ink-3); border-radius:50%;
  flex:none; position:relative; background:none; transition:background-color .12s, border-color .12s;
}
.page[data-pagina="tarefas"] .tf-cx::before{ content:""; position:absolute; inset:-6px -7px }
.page[data-pagina="tarefas"] .tf-cx:hover{ border-color:var(--dnv-mark) }
.page[data-pagina="tarefas"] .tf-cx::after{
  content:""; position:absolute; left:4px; top:1px; width:4px; height:8px;
  border:solid #fff; border-width:0 1.5px 1.5px 0; transform:rotate(42deg); opacity:0;
}
.page[data-pagina="tarefas"] .tf-li.feito .tf-cx,
.page[data-pagina="tarefas"] .tf-detalhe--feito .tf-cx{ background:var(--dnv-mark); border-color:var(--dnv-mark) }
.page[data-pagina="tarefas"] .tf-li.feito .tf-cx::after{ opacity:1 }

.page[data-pagina="tarefas"] .tf-corpo{ min-width:0 }
.page[data-pagina="tarefas"] .tf-tt{ display:block; min-width:0; overflow-wrap:anywhere }
.page[data-pagina="tarefas"] .tf-li.feito .tf-tt{ color:var(--dnv-ink-3); text-decoration:line-through }
.page[data-pagina="tarefas"] .tf-meta{
  display:flex; align-items:center; flex-wrap:wrap; gap:0 4px; margin-top:1px;
  font-size:9.6px; font-weight:600; letter-spacing:.06em; text-transform:uppercase; color:var(--dnv-ink-3);
}
.page[data-pagina="tarefas"] .tf-meta s{ text-decoration:none; color:var(--dnv-rule-2); padding:0 2px }
.page[data-pagina="tarefas"] .tf-meta .tf-bloq{ color:var(--dnv-risco) }

/* a direita da linha: etapas, responsáveis, prazo, menu */
.page[data-pagina="tarefas"] .tf-dir{ display:flex; align-items:center; gap:9px; padding-top:1px; white-space:nowrap }
.page[data-pagina="tarefas"] .tf-et-n{ font-size:10.4px; font-weight:600; color:var(--dnv-ink-2) }
.page[data-pagina="tarefas"] .tf-et-n i{
  display:inline-block; width:22px; height:3px; margin-left:4px; vertical-align:2px; background:var(--dnv-surface-3);
}
.page[data-pagina="tarefas"] .tf-et-n i b{ display:block; height:100%; background:var(--rs-seg-1,#2B323C) }
/* Primeiro nome, não iniciais (decisão do dono): quem é dono se lê sem passar
   o mouse. Teto de 13rem para um bando de responsáveis não empurrar o prazo. */
.page[data-pagina="tarefas"] .tf-resp{
  max-width:13rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
  font-size:11px; color:var(--dnv-ink-2);
}
.page[data-pagina="tarefas"] .tf-prazo{
  font-size:11px; font-weight:600; color:var(--dnv-ink-2); min-width:34px; text-align:right;
}
.page[data-pagina="tarefas"] .tf-prazo.tf-prazo--atrasado{ color:var(--dnv-risco) }
.page[data-pagina="tarefas"] .tf-prazo.tf-prazo--hoje{ color:var(--dnv-ink); border-bottom:2px solid var(--dnv-ink) }
.page[data-pagina="tarefas"] .tf-mm{
  width:18px; height:18px; line-height:16px; text-align:center; color:var(--dnv-rule-2); font-size:15px;
}
.page[data-pagina="tarefas"] .tf-li:hover .tf-mm,
.page[data-pagina="tarefas"] .tf-li[aria-selected="true"] .tf-mm,
.page[data-pagina="tarefas"] .tf-mm:focus-visible{ color:var(--dnv-ink-3) }
.page[data-pagina="tarefas"] .tf-mm:hover{ color:var(--dnv-ink) }

/* DESFAZER: some sozinho em 6 s. Concluir e excluir não perguntam (dono). */
.page[data-pagina="tarefas"] .tf-desf{
  display:inline-flex; align-items:center; gap:6px; margin-left:8px;
  font-size:9.6px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; color:var(--dnv-mark);
}
.page[data-pagina="tarefas"] .tf-desf:hover{ text-decoration:underline }
.page[data-pagina="tarefas"] .tf-desfeito{
  display:flex; align-items:center; gap:8px; padding:6px 4px 6px 2px;
  border-bottom:1px solid var(--rs-fio,#ECEEF1); background:var(--dnv-mark-wash); font-size:12px;
}

/* pergunta inline (excluir de vez, só dentro da lixeira): no lugar da linha,
   foco em CANCELAR. Nenhuma caixa do navegador nesta tela. */
.page[data-pagina="tarefas"] .tf-perg{
  display:flex; align-items:center; gap:8px; flex-wrap:wrap; padding:6px 4px 6px 2px;
  border-bottom:1px solid var(--rs-fio,#ECEEF1); background:var(--dnv-risco-wash);
}
.page[data-pagina="tarefas"] .tf-perg p{ margin:0; flex:1 1 100%; font-size:11.7px }
.page[data-pagina="tarefas"] .tf-perg p b{ font-weight:500 }
.page[data-pagina="tarefas"] .tf-bt{
  padding:2px 9px; border:1px solid var(--dnv-rule-2); background:var(--dnv-surface);
  font-size:10.1px; font-weight:600; letter-spacing:.09em; text-transform:uppercase; color:var(--dnv-ink-2);
}
.page[data-pagina="tarefas"] .tf-bt:hover{ border-color:var(--dnv-ink); color:var(--dnv-ink) }
.page[data-pagina="tarefas"] .tf-bt--principal{ background:var(--dnv-ink); border-color:var(--dnv-ink); color:#fff }
.page[data-pagina="tarefas"] .tf-bt--risco{ background:var(--dnv-risco); border-color:var(--dnv-risco); color:#fff }
.page[data-pagina="tarefas"] .tf-bt--risco:hover{ color:#fff }
.page[data-pagina="tarefas"] .tf-bt[disabled]{ opacity:.55; cursor:default }

/* a lixeira: o que saiu, por quem e quando */
.page[data-pagina="tarefas"] .tf-li--lixo{ grid-template-columns:minmax(0,1fr) auto; cursor:default }
.page[data-pagina="tarefas"] .tf-li--lixo:hover{ background:none }
.page[data-pagina="tarefas"] .tf-li--lixo .tf-dir{ gap:6px }

/* menu de contexto da linha (⋯) */
.page[data-pagina="tarefas"] .tf-menu{
  position:fixed; z-index:20; min-width:220px; background:var(--dnv-surface);
  border:1px solid var(--dnv-rule-2); padding:3px 0;
}
.page[data-pagina="tarefas"] .tf-menu[hidden]{ display:none }
.page[data-pagina="tarefas"] .tf-menu button{
  display:flex; align-items:center; gap:8px; width:100%; padding:4px 11px; font-size:12px; white-space:nowrap;
}
.page[data-pagina="tarefas"] .tf-menu button:hover{ background:var(--dnv-surface-2) }
.page[data-pagina="tarefas"] .tf-menu button .g{ width:13px; color:var(--dnv-ink-3); text-align:center }
.page[data-pagina="tarefas"] .tf-menu button.risco{ color:var(--dnv-risco) }
.page[data-pagina="tarefas"] .tf-menu hr{ margin:3px 0; border:0; border-top:1px solid var(--dnv-rule) }

/* vazio por visão: convite, não lamento */
.page[data-pagina="tarefas"] .tf-vazio{ padding:26px 2px; max-width:58ch }
.page[data-pagina="tarefas"] .tf-vazio b{ display:block; font-size:13.7px; font-weight:500; margin-bottom:3px }
.page[data-pagina="tarefas"] .tf-vazio p{ margin:0 0 9px; color:var(--dnv-ink-3) }

/* ── QUADRO ──────────────────────────────────────────────────────────────── */
.page[data-pagina="tarefas"] .tf-quadro{
  flex:1 1 auto; min-height:0; min-width:0; display:grid; grid-template-columns:repeat(4, minmax(0,1fr)); gap:0;
}
/* Com o painel aberto o quadro NÃO reflui: vira faixa rolável, e a coluna que
   ficou sob o painel continua alcançável. */
body[data-painel-tarefa] .page[data-pagina="tarefas"] .tf-quadro{
  overflow-x:auto; overscroll-behavior-x:contain; grid-template-columns:repeat(4, minmax(230px,1fr));
}
.page[data-pagina="tarefas"] .tf-qcol{
  min-width:0; min-height:0; display:flex; flex-direction:column;
  border-left:1px solid var(--dnv-rule); padding:0 10px;
}
.page[data-pagina="tarefas"] .tf-qcol:first-child{ border-left:0; padding-left:0 }
.page[data-pagina="tarefas"] .tf-qcol:last-child{ padding-right:0 }
.page[data-pagina="tarefas"] .tf-qcol__cab{
  flex:0 0 auto; display:flex; align-items:center; gap:7px; padding:6px 8px; margin:8px 0 0;
  background:var(--dnv-surface-2);
}
.page[data-pagina="tarefas"] .tf-qcol__cab h3{
  font-size:10.4px; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
}
.page[data-pagina="tarefas"] .tf-qcol__cab b{
  margin-left:auto; font-weight:600; color:var(--dnv-ink-3); font-variant-numeric:tabular-nums;
}
.page[data-pagina="tarefas"] .tf-qcol[data-coluna="bloqueado"] .tf-qcol__cab h3{ color:var(--dnv-risco) }
.page[data-pagina="tarefas"] .tf-qcol__rolo{
  flex:1 1 auto; min-height:0; overflow:auto; overscroll-behavior:contain; padding-top:2px;
}
.page[data-pagina="tarefas"] .tf-qcol.alvo .tf-qcol__rolo{ background:var(--dnv-mark-wash) }
.page[data-pagina="tarefas"] .tf-qcol .tf-li{ grid-template-columns:16px minmax(0,1fr) }
.page[data-pagina="tarefas"] .tf-qcol .tf-dir{ grid-column:2; padding-top:3px }
.page[data-pagina="tarefas"] .tf-qcol__vazio{ padding:10px 2px; font-size:11.4px; color:var(--dnv-ink-3) }
.page[data-pagina="tarefas"] .tf-raia{ border-top:1px solid var(--dnv-rule) }
.page[data-pagina="tarefas"] .tf-raia:first-child{ border-top:0 }
.page[data-pagina="tarefas"] .tf-raia__cab{
  display:flex; align-items:center; gap:7px; padding:7px 0 3px;
  font-size:9.9px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; color:var(--dnv-ink-2);
}
.page[data-pagina="tarefas"] .tf-raia__cab b{
  margin-left:auto; font-weight:600; color:var(--dnv-ink-3); font-variant-numeric:tabular-nums;
}

/* ── faixa de atalhos, rodapé da tela ────────────────────────────────────── */
.page[data-pagina="tarefas"] .tf-pe{
  flex:0 0 auto; display:flex; align-items:center; gap:14px; padding-top:6px; margin-top:6px;
  border-top:1px solid var(--dnv-rule);
  font-size:9.6px; font-weight:600; letter-spacing:.07em; text-transform:uppercase; color:var(--dnv-ink-3);
}
.page[data-pagina="tarefas"] .tf-pe kbd{
  font:inherit; font-size:9.6px; border:1px solid var(--dnv-rule-2); border-radius:0; background:none;
  padding:0 4px; color:var(--dnv-ink-2); margin-right:3px;
}
.page[data-pagina="tarefas"] .tf-pe .fim{ margin-left:auto; text-align:right }

/* ── O PAINEL DE DETALHE — COBRE a folha (decisão do dono, 17/09/2026) ───── */
.page[data-pagina="tarefas"] .tf-scrim{
  position:absolute; inset:0; z-index:25; background:rgba(11,14,18,.18);
  opacity:0; visibility:hidden; transition:opacity .16s, visibility .16s;
}
.page[data-pagina="tarefas"] .tf-scrim[data-aberto]{ opacity:1; visibility:visible }
.page[data-pagina="tarefas"] .tf-painel{
  position:absolute; top:0; right:0; bottom:0; width:clamp(340px, 27vw, 430px); z-index:30;
  display:flex; flex-direction:column; min-height:0;
  background:var(--dnv-surface); border-left:1px solid var(--dnv-rule-2);
  box-shadow:-1px 0 0 0 rgba(11,14,18,.05);
  transform:translateX(100%); visibility:hidden;
  transition:transform .18s cubic-bezier(.22,1,.36,1), visibility .18s;
}
.page[data-pagina="tarefas"] .tf-painel[data-aberto]{ transform:none; visibility:visible }
.page[data-pagina="tarefas"] .tf-det__hd{
  flex:0 0 auto; display:flex; align-items:center; gap:8px; padding:7px 12px;
  background:var(--dnv-surface-2); border-bottom:1px solid var(--dnv-rule);
}
.page[data-pagina="tarefas"] .tf-det__hd h2{
  font-size:10.1px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; color:var(--dnv-ink-3);
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.page[data-pagina="tarefas"] .tf-det__hd .x{
  margin-left:auto; width:22px; height:22px; text-align:center; line-height:20px; font-size:15px;
  color:var(--dnv-ink-3); flex:none;
}
.page[data-pagina="tarefas"] .tf-det__hd .x:hover{ color:var(--dnv-ink) }
.page[data-pagina="tarefas"] .tf-det__corpo{ flex:1 1 auto; min-height:0; overflow:auto; padding:12px 14px 16px }

/* ── O PAINEL DE TAREFAS NA REUNIÃO SEMANAL (17/09/2026) ──────────────────
   A Reunião Semanal abre o MESMO painel (`_tarefas_detalhe.html` +
   `tarefas-detalhe.js`). Como toda a pele acima está escopada em
   `.page[data-pagina="tarefas"] .tf-…`, o hospedeiro na Reunião carrega essa
   chave só para os seletores casarem — e estas quatro linhas desmancham o que
   ele herdaria de FOLHA (fundo, recuo, posição): ali ele é uma moldura
   transparente colada na janela, que não captura clique nenhum enquanto o
   painel está fechado. Zero mudança nos seletores de `/tarefas/`. */
.page[data-pagina="tarefas"].rs-tarefas-host{
  position:fixed; inset:0; z-index:1040; padding:0 !important;
  background:none; pointer-events:none;
}
.rs-tarefas-host .tf-scrim,
.rs-tarefas-host .tf-painel{ position:fixed; pointer-events:auto }

/* o corpo do painel (desenhado por tarefas-detalhe.js) */
.page[data-pagina="tarefas"] .tf-detalhe__banner[hidden]{ display:none }
.page[data-pagina="tarefas"] .tf-detalhe__banner{
  margin-bottom:8px; padding:5px 8px; border:1px solid var(--dnv-risco-rule);
  background:var(--dnv-risco-wash); color:var(--dnv-risco); font-size:12px;
}
.page[data-pagina="tarefas"] .tf-detalhe__titulo-linha{ display:flex; align-items:flex-start; gap:9px }
.page[data-pagina="tarefas"] .tf-detalhe__titulo{
  flex:1 1 auto; min-width:0; font:inherit; font-size:1.0625rem; font-weight:500; letter-spacing:-.01em;
  color:var(--dnv-ink); background:none; border:0; border-bottom:1px solid transparent; padding:1px 0;
}
.page[data-pagina="tarefas"] .tf-detalhe__titulo:hover{ border-bottom-color:var(--dnv-rule) }
.page[data-pagina="tarefas"] .tf-detalhe__titulo:focus{ outline:0; border-bottom-color:var(--dnv-mark) }
.page[data-pagina="tarefas"] .tf-detalhe__confirmacao{
  font-size:9.6px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; color:var(--dnv-mark);
}
.page[data-pagina="tarefas"] .tf-detalhe__confirmacao[hidden]{ display:none }
.page[data-pagina="tarefas"] .tf-detalhe__erro{ font-size:11.5px; color:var(--dnv-risco) }
.page[data-pagina="tarefas"] .tf-detalhe__erro[hidden]{ display:none }
.page[data-pagina="tarefas"] .tf-detalhe__meta{
  display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:9px 14px; margin-top:11px;
}
.page[data-pagina="tarefas"] .tf-detalhe__campo{ display:flex; flex-direction:column; gap:2px; min-width:0; margin:0 }
.page[data-pagina="tarefas"] .tf-detalhe__campo[data-campo="responsaveis"],
.page[data-pagina="tarefas"] .tf-detalhe__campo[data-campo="prazo"]{ grid-column:1 / -1 }
.page[data-pagina="tarefas"] .tf-detalhe__rotulo{
  font-size:9.3px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; color:var(--dnv-ink-3);
}
.page[data-pagina="tarefas"] .tf-detalhe__campo select,
.page[data-pagina="tarefas"] .tf-detalhe__campo input{
  height:1.7rem; border:1px solid var(--dnv-rule-2); border-radius:0; background:var(--dnv-surface);
  color:var(--dnv-ink); font:inherit; padding:0 5px;
}
.page[data-pagina="tarefas"] .tf-detalhe__campo select:focus,
.page[data-pagina="tarefas"] .tf-detalhe__campo input:focus{ outline:0; border-color:var(--dnv-mark) }
/* atalhos de prazo: Hoje / Amanhã / Próxima semana / Sem prazo */
.page[data-pagina="tarefas"] .tf-prazo-at{ display:flex; align-items:center; gap:5px; flex-wrap:wrap; margin-top:3px }
.page[data-pagina="tarefas"] .tf-at{
  padding:1px 7px; border:1px solid var(--dnv-rule); background:var(--dnv-surface);
  font-size:9.9px; font-weight:600; letter-spacing:.07em; text-transform:uppercase; color:var(--dnv-ink-2);
}
.page[data-pagina="tarefas"] .tf-at:hover{ border-color:var(--dnv-ink); color:var(--dnv-ink) }
.page[data-pagina="tarefas"] .tf-at.limpa{ color:var(--dnv-risco) }
.page[data-pagina="tarefas"] .tf-detalhe__bloqueio{
  margin-top:9px; padding:5px 8px; border:1px solid var(--dnv-risco-rule);
  background:var(--dnv-risco-wash); color:var(--dnv-risco); font-size:11.7px;
}
.page[data-pagina="tarefas"] .tf-detalhe__secao{ margin-top:15px }
.page[data-pagina="tarefas"] .tf-detalhe__secao-titulo,
.page[data-pagina="tarefas"] .tf-detalhe__secao > .tf-detalhe__rotulo{
  display:flex; align-items:center; gap:8px; font-size:9.9px; font-weight:700; letter-spacing:.09em;
  text-transform:uppercase; color:var(--dnv-ink-2); padding-bottom:3px;
  border-bottom:1px solid var(--dnv-rule); margin:0;
}
.page[data-pagina="tarefas"] .tf-detalhe__contagem{
  margin-left:auto; font-weight:600; color:var(--dnv-ink-3); font-variant-numeric:tabular-nums;
}
.page[data-pagina="tarefas"] .tf-detalhe__descricao,
.page[data-pagina="tarefas"] .tf-detalhe__comentario-novo{
  width:100%; margin-top:7px; padding:6px 7px; border:1px solid var(--dnv-rule-2); border-radius:0;
  background:var(--dnv-surface); color:var(--dnv-ink); font:inherit; resize:vertical;
}
.page[data-pagina="tarefas"] .tf-detalhe__descricao:focus,
.page[data-pagina="tarefas"] .tf-detalhe__comentario-novo:focus{ outline:0; border-color:var(--dnv-mark) }
.page[data-pagina="tarefas"] .tf-detalhe__acoes{ display:flex; align-items:center; gap:8px; margin-top:6px }
.page[data-pagina="tarefas"] .tf-detalhe__checklist-item{
  display:grid; grid-template-columns:15px minmax(0,1fr) 16px; gap:7px; align-items:start; padding:3px 0;
}
.page[data-pagina="tarefas"] .tf-detalhe__checklist-item input{ margin:2px 0 0; accent-color:var(--dnv-mark) }
.page[data-pagina="tarefas"] .tf-detalhe__checklist-item label{
  min-width:0; overflow-wrap:anywhere; font-size:12px; cursor:pointer; margin:0;
}
.page[data-pagina="tarefas"] .tf-detalhe__remover{
  width:16px; text-align:center; color:var(--dnv-ink-3); font-size:14px; line-height:1;
}
.page[data-pagina="tarefas"] .tf-detalhe__remover:hover{ color:var(--dnv-risco) }
.page[data-pagina="tarefas"] .tf-detalhe__checklist-add{
  width:100%; margin-top:6px; height:1.7rem; padding:0 7px; border:1px solid var(--dnv-rule-2);
  border-radius:0; background:var(--dnv-surface); color:var(--dnv-ink); font:inherit;
}
.page[data-pagina="tarefas"] .tf-detalhe__checklist-add:focus{ outline:0; border-color:var(--dnv-mark) }
.page[data-pagina="tarefas"] .tf-detalhe__dependencias{ list-style:none; margin:7px 0 0; padding:0 }
.page[data-pagina="tarefas"] .tf-detalhe__dependencia{
  display:flex; align-items:center; gap:7px; padding:3px 0; font-size:12px;
}
.page[data-pagina="tarefas"] .tf-detalhe__dependencia .tf-detalhe__remover{ margin-left:auto }
.page[data-pagina="tarefas"] .tf-detalhe__secao select{
  width:100%; margin-top:6px; height:1.7rem; border:1px solid var(--dnv-rule-2); border-radius:0;
  background:var(--dnv-surface); color:var(--dnv-ink); font:inherit;
}
.page[data-pagina="tarefas"] .tf-detalhe__anexo-arquivo,
.page[data-pagina="tarefas"] .tf-detalhe__anexo-imagem{
  display:flex; align-items:center; gap:7px; padding:3px 0; margin:0; font-size:12px;
}
.page[data-pagina="tarefas"] .tf-detalhe__anexo-imagem{ flex-wrap:wrap }
.page[data-pagina="tarefas"] .tf-detalhe__anexo-imagem img{ max-width:100%; height:auto; border:1px solid var(--dnv-rule) }
.page[data-pagina="tarefas"] .tf-detalhe__anexo-tamanho{ color:var(--dnv-ink-3); font-size:10.7px }
.page[data-pagina="tarefas"] .tf-detalhe__anexo-arquivo .tf-detalhe__remover,
.page[data-pagina="tarefas"] .tf-detalhe__anexo-imagem .tf-detalhe__remover{ margin-left:auto }
.page[data-pagina="tarefas"] .tf-detalhe__recusas{ margin-top:5px; font-size:11.5px; color:var(--dnv-risco) }
.page[data-pagina="tarefas"] .tf-detalhe__dropzone{
  margin-top:8px; padding:11px 9px; border:1px dashed var(--dnv-rule-2); text-align:center;
  font-size:11px; color:var(--dnv-ink-3);
}
.page[data-pagina="tarefas"] .tf-detalhe__anexo-rotulo{ color:var(--dnv-mark); cursor:pointer; margin:0 }
.page[data-pagina="tarefas"] .tf-detalhe__comentarios{ list-style:none; margin:0; padding:0 }
.page[data-pagina="tarefas"] .tf-detalhe__comentario{
  display:flex; gap:7px; padding:5px 0; border-bottom:1px solid var(--rs-fio,#ECEEF1); font-size:12px;
}
.page[data-pagina="tarefas"] .tf-detalhe__comentario-corpo{ min-width:0 }
.page[data-pagina="tarefas"] .tf-detalhe__comentario-cabeca{ display:flex; gap:7px; align-items:baseline }
.page[data-pagina="tarefas"] .tf-detalhe__comentario-autor,
.page[data-pagina="tarefas"] .tf-detalhe__comentario-quando{
  font-size:9.6px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; color:var(--dnv-ink-3);
}
.page[data-pagina="tarefas"] .tf-detalhe__comentario-texto{ margin:1px 0 0; overflow-wrap:anywhere }
.page[data-pagina="tarefas"] .tf-avatar{
  display:inline-flex; align-items:center; justify-content:center; flex:none;
  width:19px; height:19px; border-radius:50%; background:var(--dnv-surface-3); color:var(--dnv-ink-2);
  font-size:9.4px; font-weight:700;
}
.page[data-pagina="tarefas"] .tf-detalhe__historico{ margin-top:15px }
.page[data-pagina="tarefas"] .tf-detalhe__historico summary{
  font-size:9.9px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; color:var(--dnv-ink-2);
  padding-bottom:3px; border-bottom:1px solid var(--dnv-rule); cursor:pointer;
}
.page[data-pagina="tarefas"] .tf-detalhe__historico ul{
  margin:7px 0 0; padding-left:15px; font-size:11.4px; color:var(--dnv-ink-2);
}
.page[data-pagina="tarefas"] .tf-detalhe__rodape{
  display:flex; align-items:center; gap:8px; margin-top:16px; padding-top:7px;
  border-top:1px solid var(--dnv-rule);
}
.page[data-pagina="tarefas"] .tf-detalhe__criada{ font-size:10.4px; color:var(--dnv-ink-3) }
.page[data-pagina="tarefas"] .tf-detalhe__rodape .tf-bt{ margin-left:auto }
.page[data-pagina="tarefas"] .tf-vazio.tf-vazio--linha,
.page[data-pagina="tarefas"] li.tf-vazio{ padding:5px 0; font-size:11.7px; color:var(--dnv-ink-3); list-style:none }

/* o multiselect da casa dentro do painel */
.page[data-pagina="tarefas"] .tf-pessoas .colfilter-multi__trigger{
  height:1.7rem; border-radius:0; border:1px solid var(--dnv-rule-2); background:var(--dnv-surface);
}

/* esqueleto de carga */
.page[data-pagina="tarefas"] .tf-esqueleto__linha{
  height:9px; margin:8px 0; background:var(--dnv-surface-3); animation:tf-pulso 1.1s ease-in-out infinite;
}
.page[data-pagina="tarefas"] .tf-esqueleto__linha--curta{ width:62% }
@keyframes tf-pulso{ 50%{ opacity:.45 } }

/* ── novo projeto: o <dialog> nativo, vestido ────────────────────────────── */
.page[data-pagina="tarefas"] .tf-dialogo{
  border:1px solid var(--dnv-rule-2); border-radius:0; padding:14px 16px; min-width:min(420px, 92vw);
  background:var(--dnv-surface); color:var(--dnv-ink); font:inherit; font-size:13px;
}
.page[data-pagina="tarefas"] .tf-dialogo::backdrop{ background:rgba(11,14,18,.18) }
.page[data-pagina="tarefas"] .tf-dialogo h2{
  font-size:10.1px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; color:var(--dnv-ink-3);
  padding-bottom:4px; border-bottom:1px solid var(--dnv-rule); margin-bottom:10px;
}
.page[data-pagina="tarefas"] .tf-dialogo .tf-campo{ display:flex; flex-direction:column; gap:2px; margin-bottom:9px }
.page[data-pagina="tarefas"] .tf-dialogo .tf-campo > span{
  font-size:9.3px; font-weight:700; letter-spacing:.09em; text-transform:uppercase; color:var(--dnv-ink-3);
}
.page[data-pagina="tarefas"] .tf-dialogo input,
.page[data-pagina="tarefas"] .tf-dialogo select{
  height:1.7rem; padding:0 5px; border:1px solid var(--dnv-rule-2); border-radius:0;
  background:var(--dnv-surface); color:var(--dnv-ink); font:inherit;
}
.page[data-pagina="tarefas"] .tf-dialogo input:focus,
.page[data-pagina="tarefas"] .tf-dialogo select:focus{ outline:0; border-color:var(--dnv-mark) }
.page[data-pagina="tarefas"] .tf-dialogo__fase{ display:flex; align-items:center; gap:6px; margin-bottom:4px }
.page[data-pagina="tarefas"] .tf-dialogo__fase input{ flex:1 1 auto }
.page[data-pagina="tarefas"] .tf-dialogo__fase .rm{ color:var(--dnv-ink-3); font-size:14px; line-height:1; width:16px; text-align:center }
.page[data-pagina="tarefas"] .tf-dialogo__fase .rm:hover{ color:var(--dnv-risco) }
.page[data-pagina="tarefas"] .tf-dialogo__erro{ margin:6px 0 0; font-size:11.5px; color:var(--dnv-risco) }
.page[data-pagina="tarefas"] .tf-dialogo__erro[hidden]{ display:none }
.page[data-pagina="tarefas"] .tf-dialogo__acoes{ display:flex; justify-content:flex-end; gap:8px; margin-top:12px }

@media (prefers-reduced-motion:reduce){
  .page[data-pagina="tarefas"] .tf-painel,
  .page[data-pagina="tarefas"] .tf-scrim,
  .page[data-pagina="tarefas"] .tf-cx,
  .page[data-pagina="tarefas"] .ca{ transition:none }
  .page[data-pagina="tarefas"] .tf-esqueleto__linha{ animation:none }
}

/* ═══════════════════════════════════════════════════════════════════════════
   RELATÓRIOS (`/relatorios/`, `/relatorios/novo/`, `/relatorios/<id>/`)

   Duas telas na mesma chave: a LISTA do que está salvo (a grade da casa, sem
   nada de novo além do que a situação "excluído" pede) e o CONSTRUTOR, que o
   dono mandou vestir com a pele de `/despesas/nova/` (15/09/2026):
   "instrumento, não painel" — tinta, uma cor de estado, cantos retos, painéis
   separados por vão de 1px, rótulo pequeno, e a barra do shell vestida pelos
   blocos que o `base_fcds.html` já expõe.

   Os tokens são os MESMOS (`--dnv-*`): a regra que os define, lá em cima,
   ganhou `.page[data-pagina="relatorios"]` e `#topbar:has(.rel-sel)` na lista
   de seletores. Aqui não se declara nem se copia valor de token nenhum — só se
   usa. As classes novas levam o prefixo `rel-`.
   ═══════════════════════════════════════════════════════════════════════════ */

/* A folha é branca até a borda do `.content`, nas duas telas — o cinza do shell
   em volta leria como moldura, e o `.main` tem `min-height`, então sobraria uma
   faixa cinza no rodapé. Mesmo `:has()` de `/despesas/nova/`: só pinta quando é
   ESTA página. */
.content:has(> .page[data-pagina="relatorios"]){ background:#fff; }
.main:has(> .content > .page[data-pagina="relatorios"]){ background:#fff; }

/* ── A LISTA ───────────────────────────────────────────────────────────────
   A grade da casa faz o resto (barra numa linha só, chips, busca, Copiar,
   Colunas). Só duas coisas são desta tela. */
/* Sem "por página" e sem paginação: a lista de relatórios salvos vem inteira
   (é o padrão da grade para tela que não é janela) e quem rola é a caixa da
   lista, esticada até o pé da janela. */
.rel-lista .dataTables_length,
.rel-lista .dataTables_paginate{ display:none; }
/* A grade É a tela: ocupa a janela inteira mesmo com duas linhas (memória
   `tela-usa-janela-inteira`). A altura vem do gancho do shell
   (`content--altura-cheia`, declarado no template); daqui para baixo é só
   repassá-la — quem rola é a caixa da lista, não a página. */
.rel-lista{ display:flex; flex-direction:column; min-height:0; }
.rel-lista .grade,
.rel-lista .dataTables_wrapper{ flex:1 1 auto; min-height:0; display:flex; flex-direction:column; }
.rel-lista .datatable-scroll{ flex:1 1 auto; min-height:0; }
/* O excluído fica na lista, apagado, e não abre: o construtor busca a definição
   num endpoint que responde 404 a quem foi excluído. Quem o traz de volta é o
   Restaurar da própria linha. */
.rel-lista .rel-linha--excluida{ color:var(--ink-3); cursor:default; }
.rel-lista .rel-linha--excluida .grade-acao{ color:var(--ink); }

/* ── O CONSTRUTOR: lado × palco ────────────────────────────────────────────
   A tela ocupa a janela inteira abaixo da topbar e NÃO rola: quem rola é o
   lado (por dentro) e a grade do resultado. A margem negativa devolve
   exatamente o respiro que o shell deu, pelo mesmo token dos dois lados — por
   isso a altura desconta só a topbar. */
.rel-construtor *{ box-sizing:border-box; }
.rel-construtor{
  margin-inline:calc(-1 * var(--content-pad-x));
  margin-block:calc(-1 * var(--content-pad-y)) calc(-1 * var(--content-pad-b));
  width:auto; padding:0;
  /* A barra DESTA tela tem 46px (`#topbar:has(.rel-sel)`), não os 52px do
     shell: com 52 sobravam 6px de faixa morta no pé da janela — o que a
     memória `tela-usa-janela-inteira` proíbe. O token é o mesmo de
     `/despesas/nova/`; o 46px é só o piso enquanto ninguém mediu. Quando o
     `construtor.js` (8b) publicar `--dnv-topo` com um ResizeObserver (como o
     `despesas-nova.js` faz), o trilho empilhado no estreito passa a caber
     sozinho. */
  height:calc(100dvh - var(--dnv-topo, 46px));
  display:flex; flex-direction:column; overflow:hidden;
  background:var(--dnv-ground); color:var(--dnv-ink);
  font-family:var(--dnv-sans); font-size:13.5px; line-height:1.45;
  -webkit-font-smoothing:antialiased;
}
/* Quem se posiciona abaixo da barra precisa saber que ela encolheu: a barra
   lateral nascia em 52px e deixava 6px do fundo da página aparecendo por cima
   dela, e o `.main` continuava com um piso de 52px — a mesma faixa morta, agora
   embaixo. */
body:has(#topbar .rel-sel) .side{
  top:var(--dnv-topo, 46px); height:calc(100vh - var(--dnv-topo, 46px));
}
body:has(#topbar .rel-sel) .scrim{ inset:var(--dnv-topo, 46px) 0 0 0; }
.main:has(> .content > .page[data-pagina="relatorios"].rel-construtor){
  min-height:calc(100vh - 46px);
}
.rel-construtor button{
  font:inherit; color:inherit; background:none; border:none;
  padding:0; cursor:pointer; text-align:left;
}
.rel-construtor :focus-visible{ outline:2px solid var(--dnv-mark); outline-offset:1px; }
/* O rótulo pequeno vale nos dois lugares em que a tela fala: o trilho e os
   blocos do lado. Escopado nos dois — classe nova não vira regra global. */
.rel-construtor .rel-k, #topbar:has(.rel-sel) .rel-k{
  font-size:10px; letter-spacing:.11em; text-transform:uppercase;
  color:var(--dnv-ink-3); font-weight:600;
}

/* O vão de 1px entre lado e palco é o FUNDO da grade aparecendo, não uma
   borda: é o que separa os painéis no desenho do dono. */
.rel-construtor .rel-app{
  flex:1 1 auto; min-height:0;
  display:grid; grid-template-columns:352px 1fr; grid-template-areas:"lado palco";
  background:var(--dnv-rule); gap:1px;
}
.rel-construtor .rel-lado{
  grid-area:lado; background:var(--dnv-surface);
  display:flex; flex-direction:column; overflow-y:auto;
}
.rel-construtor .rel-bloco{ padding:22px 24px; }
.rel-construtor .rel-bloco + .rel-bloco{ border-top:1px solid var(--dnv-rule); }
.rel-construtor .rel-palco{
  grid-area:palco; background:var(--dnv-surface);
  display:flex; flex-direction:column; min-height:0; overflow:hidden;
}
/* O topo do palco é a LEITURA do que está montado: a frase-resumo do filtro e
   a contagem ao vivo. Fica sempre visível — é o que responde "o que eu pedi?". */
.rel-construtor .rel-topo{ padding:16px 20px; border-bottom:1px solid var(--dnv-rule); }
.rel-construtor .rel-frase{ margin:0; font-size:13.5px; color:var(--dnv-ink); }
.rel-construtor .rel-contagem{
  margin:6px 0 0; font-size:12px; color:var(--dnv-ink-3);
  font-variant-numeric:tabular-nums; font-feature-settings:"tnum" 1, "lnum" 1;
}
.rel-construtor .rel-recado{
  margin:10px 0 0; padding:8px 12px; font-size:12px;
  background:var(--dnv-mark-wash); color:var(--dnv-ink-2);
}
.rel-construtor .rel-resultado{ flex:1 1 auto; min-height:0; overflow:auto; }
.rel-construtor .rel-pe{
  margin:0; padding:10px 20px; border-top:1px solid var(--dnv-rule);
  font-size:10.5px; color:var(--dnv-ink-4);
}
/* ESTREITO: empilha e a PÁGINA volta a rolar — travar a altura da janela aqui
   espremeria o lado e esconderia o resto atrás de uma rolagem que ninguém vê.
   A margem copia a EXPRESSÃO do respiro (o `.content` troca o padding em
   ≤767.98px e não mexe no token), senão sobra o que o shell corta em silêncio. */
@media (max-width:900px){
  .rel-construtor{ height:auto; overflow:visible; }
  .rel-construtor .rel-app{ grid-template-columns:1fr; grid-template-areas:"lado" "palco"; }
  .rel-construtor .rel-lado{ overflow-y:visible; }
}
@media (max-width:767.98px){
  .rel-construtor{
    margin-inline:calc(-1 * max(0.5rem, env(safe-area-inset-left)))
                  calc(-1 * max(0.5rem, env(safe-area-inset-right)));
    margin-block:-0.5rem calc(-1 * max(1.5rem, env(safe-area-inset-bottom)));
  }
}

/* ── O TRILHO: o cabeçalho do construtor, vestido na barra do shell ────────
   Mora nos blocos que o `base_fcds.html` já expõe (`crumb`, `topbar_filters`,
   `topbar_actions`), então nenhuma outra tela muda: `#topbar:has(.rel-sel)` só
   casa na barra que carrega o seletor de Base. Logo, menu, Reportar e sino
   continuam onde o shell os põe — são o caminho para o resto do app. */
#topbar:has(.rel-sel){
  height:46px; padding:0 12px 0 16px; gap:0; align-items:stretch;
  background:var(--dnv-surface); border-bottom:1px solid var(--dnv-rule);
  font-family:var(--dnv-sans); color:var(--dnv-ink);
}
#topbar:has(.rel-sel) > .logo, #topbar:has(.rel-sel) > .menu,
#topbar:has(.rel-sel) > .fcds-reportar, #topbar:has(.rel-sel) > .fcds-sino{ align-self:center; }
#topbar:has(.rel-sel) > .menu{ margin-right:6px; }
#topbar:has(.rel-sel) > .vr{ display:none; }
/* Só os botões DESTA tela perdem a pele de botão. Sem o escopo, o Reportar e o
   sino — que o shell põe na barra e nenhuma tela pode remover — saíam com a
   pintura arrancada. */
#topbar:has(.rel-sel) :where(.rel-sel, .rel-nome, .rel-acoes) :where(button){
  font:inherit; color:inherit; background:none; border:none;
  padding:0; cursor:pointer; text-align:left;
}
#topbar:has(.rel-sel) :focus-visible{ outline:2px solid var(--dnv-mark); outline-offset:1px; }
#topbar:has(.rel-sel) .crumb{
  display:flex; align-items:center; gap:10px; padding:0 18px;
  border-right:1px solid var(--dnv-rule);
}
#topbar:has(.rel-sel) .crumb b{ font-size:14px; font-weight:600; letter-spacing:-.01em; }

/* O NOME do relatório é um campo, não um rótulo: renomear é o gesto mais comum
   da tela e não merece uma janela. Nasce sem moldura e ganha fio ao receber o
   cursor — moldura em repouso seria a terceira caixa da barra. */
/* O campo CRESCE com a barra: em 1920 sobra espaço, e um nome longo preso em
   240px era cortado no meio da palavra sem nem reticências. `min-width:0` é o
   que deixa um item flex encolher abaixo do conteúdo — sem ele o campo empurra
   as ações para fora. O nome inteiro fica no `title` (posto pelo JS). */
#topbar:has(.rel-sel) .rel-nome{ display:flex; align-items:center; gap:10px; padding:0 18px;
  border-right:1px solid var(--dnv-rule); flex:1 1 auto; min-width:0; }
#topbar:has(.rel-sel) .rel-nome__campo{
  font:inherit; font-size:12.5px; font-weight:600; color:var(--dnv-ink);
  background:none; border:none; border-radius:0; padding:2px 4px;
  flex:1 1 auto; min-width:8rem; max-width:34rem; text-overflow:ellipsis;
}
#topbar:has(.rel-sel) .rel-nome__campo::placeholder{ color:var(--dnv-ink-3); font-weight:400; }
#topbar:has(.rel-sel) .rel-nome__campo:hover{ background:var(--dnv-surface-2); }
#topbar:has(.rel-sel) .rel-nome__campo:focus{ background:var(--dnv-surface-2); outline-offset:-2px; }

/* O seletor de BASE: mesmo gesto do Período/Segmento de `/despesas/nova/` —
   um botão que abre um popover, com a escolha em cima do rótulo pequeno. */
#topbar:has(.rel-sel) .rel-sel{ position:relative; display:flex; }
#topbar:has(.rel-sel) .rel-sel__bt{
  display:flex; align-items:center; gap:10px; padding:0 18px; height:100%;
  border-right:1px solid var(--dnv-rule); white-space:nowrap;
}
#topbar:has(.rel-sel) .rel-sel__bt:hover{ background:var(--dnv-surface-2); }
#topbar:has(.rel-sel) .rel-sel__bt[aria-expanded="true"]{
  background:var(--dnv-surface-2); box-shadow:inset 0 -2px 0 var(--dnv-mark);
}
#topbar:has(.rel-sel) .rel-sel__v{ font-size:12.5px; font-weight:600; color:var(--dnv-ink); }
#topbar:has(.rel-sel) .rel-sel__s{ flex:none; font-size:11px; color:var(--dnv-ink-2); transition:transform .15s; }
#topbar:has(.rel-sel) .rel-sel__bt[aria-expanded="true"] .rel-sel__s{ transform:rotate(180deg); color:var(--dnv-mark); }
#topbar:has(.rel-sel) .rel-pop{
  position:absolute; top:100%; left:0; z-index:60; background:var(--dnv-surface);
  border:1px solid var(--dnv-rule-2); box-shadow:0 14px 34px -14px rgba(0,0,0,.3);
  padding:14px 16px; min-width:320px; font-size:13.5px; line-height:1.45; cursor:default;
}

/* AS AÇÕES, à direita. Gerar é a única cheia: consulta livre pode custar, então
   o resultado só sai quando alguém manda. Cinza cheio está fora — cinza lê como
   desabilitado (memória `botao-cinza-parece-desabilitado`). */
#topbar:has(.rel-sel) .rel-acoes{ display:flex; align-items:center; gap:8px; padding:0 4px 0 14px; }
#topbar:has(.rel-sel) .rel-bt{
  display:inline-flex; align-items:center; height:28px; padding:0 12px;
  font-size:12px; border:1px solid var(--dnv-rule-3);
  background:var(--dnv-surface); color:var(--dnv-ink);
}
#topbar:has(.rel-sel) .rel-bt:hover{ border-color:var(--dnv-ink-2); }
#topbar:has(.rel-sel) .rel-bt--f{
  background:var(--dnv-mark); border-color:var(--dnv-mark);
  color:#fff; font-weight:600;
}
#topbar:has(.rel-sel) .rel-bt--f:hover{ filter:brightness(1.12); }
/* Gerar/Salvar `disabled` quando falta escolher a unidade da grandeza (Task 5,
   contrato de 16/09/2026) — a recusa por escrito é o `title`, isto é só o
   afogado visual: sem ele os dois liam como se estivessem prontos. */
#topbar:has(.rel-sel) .rel-bt:disabled{ opacity:.5; cursor:default; }
#topbar:has(.rel-sel) .rel-bt:disabled:hover{ border-color:var(--dnv-rule-3); filter:none; }

/* ── O LADO: os três blocos do construtor ─────────────────────────────────
   Tudo aqui é controle, e controle é tinta: caixa de 1px, canto reto, nada de
   sombra nem de pílula. O que separa um bloco do outro já é o fio do painel. */
.rel-construtor .rel-campo{
  font:inherit; font-size:12.5px; color:var(--dnv-ink);
  background:var(--dnv-surface); border:1px solid var(--dnv-rule-2);
  border-radius:0; padding:3px 6px; max-width:100%;
}
.rel-construtor .rel-campo--curto{ width:6.5rem; }
.rel-construtor .rel-campo--lista{ min-width:10rem; }
.rel-construtor .rel-mini{
  font-size:11.5px; color:var(--dnv-ink-2); border:1px solid transparent;
  padding:2px 7px; white-space:nowrap;
}
.rel-construtor .rel-mini:hover{ border-color:var(--dnv-rule-2); background:var(--dnv-surface-2); }
.rel-construtor .rel-mini--perigo{ color:var(--dnv-risco); }
.rel-construtor .rel-nada{ margin:4px 0; font-size:11.5px; color:var(--dnv-ink-3); }
.rel-construtor .rel-fila{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; }
.rel-construtor .rel-marca{
  display:inline-flex; align-items:center; gap:6px; font-size:12.5px; margin:0;
}

/* A ÁRVORE. O aninhamento se lê pelo fio à esquerda, não por moldura (memória
   `grade-minimalista-sem-moldura`): um grupo dentro do outro é um recuo e um
   traço, não uma caixa dentro de outra caixa. */
.rel-construtor .rel-grupo--aninhado{
  margin:6px 0 6px 2px; padding-left:10px; border-left:2px solid var(--dnv-rule);
}
.rel-construtor .rel-grupo__topo{ display:flex; align-items:center; gap:6px; }
.rel-construtor .rel-conector{
  font-size:10px; letter-spacing:.11em; font-weight:700; color:var(--dnv-mark);
  border:1px solid var(--dnv-rule-2); padding:1px 8px;
}
.rel-construtor .rel-conector:hover{ background:var(--dnv-mark-wash); }
.rel-construtor .rel-item{
  display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin:6px 0;
}
.rel-construtor .rel-item--relacao{ display:block; }
.rel-construtor .rel-relacao{ font-size:12.5px; }
.rel-construtor .rel-agregado{
  display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin:6px 0 0 12px;
}
.rel-construtor .rel-valor-agregado{ display:flex; align-items:center; gap:6px; }
.rel-construtor .rel-e{ font-size:11.5px; color:var(--dnv-ink-3); }
.rel-construtor .rel-add{ display:flex; flex-wrap:wrap; align-items:center; gap:6px; margin-top:8px; }

/* COLUNAS: uma linha por coluna, com a ordem no próprio item (subir/descer).
   Arrastar ficaria bonito e seria inacessível pelo teclado. */
.rel-construtor .rel-col{ padding:4px 0; border-bottom:1px solid var(--dnv-rule); }
.rel-construtor .rel-col__topo{ gap:4px; }
.rel-construtor .rel-col__nome{ flex:1 1 auto; font-size:12.5px; }
/* A coluna AGREGADA se edita no lugar (relação, função, campo, rótulo e o
   subfiltro inteiro), e por isso ganha corpo: mesmo recuo com fio da árvore,
   para ler como "isto está dentro daquela coluna". */
.rel-construtor .rel-col__agregado{
  margin:6px 0 2px 2px; padding-left:10px; border-left:2px solid var(--dnv-rule);
  display:flex; flex-direction:column; gap:6px;
}
.rel-construtor .rel-col__agregado .rel-grupo--aninhado{ margin-left:0; }

/* AGRUPAR E TOTALIZAR: a coluna à esquerda, a função de total à direita. Só
   aparecem as funções que o servidor aceita para aquela coluna. */
.rel-construtor .rel-agr{
  display:flex; align-items:center; justify-content:space-between; gap:8px;
  padding:4px 0; border-bottom:1px solid var(--dnv-rule);
}
.rel-construtor .rel-agr input:disabled + span{ color:var(--dnv-ink-3); }

/* O RECADO do palco carrega pergunta (duplicata, exclusão) e histórico. */
.rel-construtor .rel-recado .rel-mini{ border-color:var(--dnv-rule-2); background:var(--dnv-surface); }
.rel-construtor .rel-historico{ margin:6px 0 0; padding-left:16px; }

/* O POPOVER da Base: uma entidade por linha; a atual fica marcada. */
#topbar:has(.rel-sel) .rel-opcoes-base{ display:flex; flex-direction:column; max-height:60vh; overflow:auto; }
#topbar:has(.rel-sel) .rel-opcao-base{ padding:5px 8px; font-size:13px; }
#topbar:has(.rel-sel) .rel-opcao-base:hover{ background:var(--dnv-surface-2); }
#topbar:has(.rel-sel) .rel-opcao-base[aria-current="true"]{ font-weight:600; box-shadow:inset 2px 0 0 var(--dnv-mark); }
#topbar:has(.rel-sel) .rel-confirma{
  margin-top:10px; padding-top:10px; border-top:1px solid var(--dnv-rule); font-size:12.5px;
}
#topbar:has(.rel-sel) .rel-confirma .rel-mini{
  font-size:11.5px; border:1px solid var(--dnv-rule-2); padding:2px 8px; margin-left:6px;
}
#topbar:has(.rel-sel) .rel-confirma .rel-mini--perigo{ color:var(--dnv-risco); }

/* ── O RESULTADO: a grade da casa dentro do palco ──────────────────────── */
/* A grade ocupa a altura toda do palco e rola por dentro (mesma escolha da
   lista): quem rola é a caixa, não a página. */
.rel-construtor .rel-resultado .grade,
.rel-construtor .rel-resultado .dataTables_wrapper{
  display:flex; flex-direction:column; min-height:0; height:100%;
}
.rel-construtor .rel-resultado .datatable-scroll{ flex:1 1 auto; min-height:0; }
/* O CABEÇALHO DE GRUPO. Rótulo, quantidade e subtotais vêm PRONTOS do
   servidor (`envelope.grupos`) — aqui é só onde eles pousam. */
.rel-construtor .rel-grupo-linha > td{
  background:var(--dnv-surface-2); border-top:1px solid var(--dnv-rule-2);
  padding:5px 10px; font-size:12px;
}
.rel-construtor .rel-grupo-linha__conta{
  margin-left:8px; color:var(--dnv-ink-3);
  font-variant-numeric:tabular-nums; font-feature-settings:"tnum" 1, "lnum" 1;
}
.rel-construtor .rel-grupo-linha__total{
  margin-left:14px; color:var(--dnv-ink-2);
  font-variant-numeric:tabular-nums; font-feature-settings:"tnum" 1, "lnum" 1;
}
/* O palco antes do primeiro Gerar: uma frase, não uma folha em branco. */
.rel-construtor .rel-palco-vazio{ margin:0; padding:22px 20px; font-size:12.5px; color:var(--dnv-ink-3); }
/* Sem resultado não há "Gerado às": o fio do rodapé sozinho seria uma faixa morta. */
.rel-construtor .rel-pe:empty{ display:none; }
/* ── Cobertura de Representantes: o quadro do canal na grade da casa ──────
   Teto nas duas colunas de texto. Sem ele o nome de uma cooperativa (80
   caracteres) abria a coluna até empurrar "Última venda" para fora da grade,
   e quem chegava na página 2 só via metade da linha. Teto, não largura fixa:
   nome curto fica curto, comprido corta na reticência do `.grade-celula`. */
[data-pagina="cobertura_representantes"] .grade .cr-col-nome{width:100%;max-width:0;min-width:14rem}
/* O invólucro herda o teto da coluna (`max-width:inherit` na grade da casa), e
   aqui o teto é o `0` do truque acima: herdado, ele sumiria com o texto. Quem
   corta é o `td` (mesmo caso de `.rp-col-descricao`). */
[data-pagina="cobertura_representantes"] .grade .cr-col-nome .grade-celula{max-width:none}
[data-pagina="cobertura_representantes"] .grade .cr-col-carteira{max-width:15rem}
