/* =============================================================================
   Canvas de fluxo — Cardexa Captura
   Passada visual · design · 29/08/2026

   Substitui integralmente o flow-builder.css anterior. Nenhuma cor nova: tudo sai
   dos tokens do cardexa.css. Nenhuma lib. Nenhum hook data-cxfb-* removido.

   O QUE MUDOU DE PREMISSA
   -----------------------
   1. A tela é um DOCUMENTO NARRATIVO, não um formulário. Os marcos (envelope,
      VEREDITO, fechamento) passam a ser os elementos mais pesados da espinha; os
      cartões, que se repetem, passam a ser o tecido. Antes era o contrário.

   2. Zona pintada. Captura tem fundo (--cx-subtle) e trilho tracejado: alguém está
      preenchendo. Análise fica no branco do cartão com trilho sólido: a máquina está
      rodando. Isso é o que faz "captura → análise → veredito → captura → análise"
      ser legível de relance em vez de uma lista de doze cartões iguais.

   3. Trilho com uma fonte de verdade só. --cxfb-pad e --cxfb-rail-x definem a
      geometria; --cxfb-rail-offset posiciona qualquer nó sobre o trilho. Mexer no
      respiro responsivo é mexer em duas variáveis.

   4. BUG CORRIGIDO: o arquivo antigo furava o trilho com var(--cx-page, #f8fafc).
      --cx-page NÃO EXISTE no cardexa.css (o token é --cx-surface), então o fallback
      #f8fafc valia sempre. Na demo passava porque o body é #f8fafc; em produção o
      componente vive em modal branco e a página é #ECEFF1 — os quadrados de "furo"
      apareceriam na cor errada nos dois casos. Agora existe --cxfb-canvas, que
      declara a cor de fundo real do lugar onde o canvas foi montado.

   5. Todos os fallbacks Tailwind saíram (#64748b, #94a3b8, #f1f5f9, #0f172a,
      #dcfce7, #166534, #e2e8f0…). Os tokens existem; os fallbacks só divergiam do
      design system em silêncio. Regra de ouro do cardexa.css: use o token.

   6. rem → px. O resto do dashboard é px; .72rem/.7rem/.95rem faziam o componente
      escalar com o root e caíam fora da escala do handoff.

   DEPENDE DE PATCH NO flow-builder.js (ver HANDOFF-CSS.md, 3 trechos):
      .cxfb-card--pulled / --puller   momento do magnetismo
      .cxfb-card--refused             recusa da selfie na 1ª parte
      [data-cxfb-final-only]          desacopla o CSS do enum do campo
   Sem o patch nada quebra: as regras ficam dormentes.
   ============================================================================= */

/* -----------------------------------------------------------------------------
   0 · Escopo e geometria
   -------------------------------------------------------------------------- */
.cxfb {
    display: grid;
    gap: var(--cx-s4);

    /* Fundo real de onde o canvas está montado. Os nós do trilho furam a linha com
       esta cor. Em modal e em card fica branco (o padrão). Montado direto sobre a
       página, o host declara: style="--cxfb-canvas: var(--cx-surface)". */
    --cxfb-canvas: var(--cx-card);

    /* Trilho: um lugar só para mudar o respiro. */
    --cxfb-pad: 44px;      /* recuo do conteúdo da espinha */
    --cxfb-rail-x: 15px;   /* centro do trilho, a partir da borda da espinha */
    --cxfb-node: 26px;     /* diâmetro do nó de marco */
    --cxfb-rail-offset: calc(var(--cxfb-rail-x) - var(--cxfb-pad) - 1px);
    --cxfb-node-offset: calc(var(--cxfb-rail-x) - var(--cxfb-pad) - (var(--cxfb-node) / 2));

    /* Elevação do arrastar. Mesma família rgba(11,16,32) das sombras do handoff:
       entre --cx-shadow-lift e --cx-shadow-modal, que é onde falta um degrau. */
    --cxfb-shadow-drag: 0 16px 34px rgba(11, 16, 32, .17), 0 3px 8px rgba(11, 16, 32, .10);
}

/* -----------------------------------------------------------------------------
   1 · Paleta de blocos
   -------------------------------------------------------------------------- */
.cxfb__palette {
    padding: var(--cx-s3) 18px 18px;
    background: var(--cx-subtle);
    border: 1px solid var(--cx-divider);
    border-radius: var(--cx-r-card);
}

.cxfb__kicker {
    font-family: var(--cx-mono);
    font-size: 10px;
    line-height: 14px;
    font-weight: 500;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--cx-ink-3);
    margin-bottom: var(--cx-s2);
}
.cxfb__kicker-hint {
    font-family: var(--cx-sans);
    font-size: 12px;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
}

.cxfb__palette-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(212px, 1fr));
    gap: var(--cx-s1);
}

/* Bloco: objeto que se pega. Ícone em tile de container, nome, tipo, e o "+" que
   fecha o gesto à direita. */
.cxfb-block {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-rows: auto auto;
    align-items: center;
    gap: 1px var(--cx-s2);
    text-align: left;
    padding: 10px var(--cx-s2);
    background: var(--cx-card);
    border: 1px solid var(--cx-border);
    border-radius: var(--cx-r-btn);
    box-shadow: var(--cx-shadow-card);
    cursor: pointer;
    transition: border-color .14s ease, box-shadow .14s ease, transform .14s ease;
}
.cxfb-block__ico {
    grid-row: span 2;
    width: 34px;
    height: 34px;
    border-radius: var(--cx-r-field);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--cx-container);
    color: var(--cx-primary);
    font-size: 20px;
    transition: background .14s ease, color .14s ease;
}
/* Nome quebra em duas linhas em vez de cortar: "Credilink Cadastral" e
   "DataValid (Serpro)" viravam "Credilink Ca…" na largura de modal. */
.cxfb-block__name {
    grid-column: 2;
    font-size: 13px;
    line-height: 17px;
    font-weight: 600;
    color: var(--cx-ink);
    overflow-wrap: anywhere;
}
.cxfb-block__type {
    grid-column: 2;
    font-size: 12px;
    line-height: 16px;
    color: var(--cx-ink-3);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cxfb-block__add {
    grid-row: span 2;
    font-size: 20px;
    color: var(--cx-border-2);
    transition: color .14s ease;
}

.cxfb-block:hover:not(:disabled) {
    border-color: var(--cx-primary);
    box-shadow: var(--cx-shadow-lift);
    transform: translateY(-1px);
}
.cxfb-block:hover:not(:disabled) .cxfb-block__ico { background: var(--cx-primary); color: #fff; }
.cxfb-block:hover:not(:disabled) .cxfb-block__add { color: var(--cx-primary); }
.cxfb-block:active:not(:disabled) { transform: translateY(0); box-shadow: var(--cx-shadow-card); }

/* Já no fluxo: reestilizado, não apagado. opacity:.45 embaçava o nome junto e
   deixava a paleta suja — quem já entrou precisa ficar LEGÍVEL e claramente fora
   de alcance. */
.cxfb-block--used {
    background: var(--cx-subtle);
    border-color: var(--cx-divider);
    border-style: dashed;
    box-shadow: none;
    cursor: default;
}
.cxfb-block--used .cxfb-block__ico { background: var(--cx-success-bg); color: var(--cx-success-fg); }
.cxfb-block--used .cxfb-block__name { color: var(--cx-ink-3); font-weight: 500; }
.cxfb-block--used .cxfb-block__type { color: var(--cx-ink-4); }
.cxfb-block--used .cxfb-block__add { color: var(--cx-success); }

/* Faltava no arquivo antigo: paletteHtml() emite .cxfb__empty e não havia regra. */
.cxfb__empty {
    padding: 18px;
    border: 1px dashed var(--cx-border-2);
    border-radius: var(--cx-r-btn);
    background: var(--cx-card);
    font-size: 13px;
    color: var(--cx-ink-3);
    text-align: center;
}

/* -----------------------------------------------------------------------------
   2 · Espinha e trilho
   -------------------------------------------------------------------------- */
.cxfb__spine {
    position: relative;
    display: grid;
    gap: 0;
    padding-left: var(--cxfb-pad);
}
/* Trilho base: sólido. As zonas de captura o cobrem com tracejado. */
.cxfb__spine::before {
    content: "";
    position: absolute;
    left: calc(var(--cxfb-rail-x) - 1px);
    top: 14px;
    bottom: 14px;
    width: 2px;
    background: var(--cx-border);
    border-radius: 1px;
}

/* ── Nó de marco: conta a linha em vez de furá-la ────────────────────────────
   Miolo na cor do canvas com anel de 2px: o trilho passa por trás e o nó lê como
   conta enfiada no fio. */
.cxfb__marker > .cx-i,
.cxfb__pause > .cx-i,
.cxfb-esteira__head > .cx-i {
    position: absolute;
    left: var(--cxfb-node-offset);
    top: 50%;
    transform: translateY(-50%);
    width: var(--cxfb-node);
    height: var(--cxfb-node);
    border-radius: var(--cx-r-pill);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 16px;
    background: var(--cxfb-canvas);
    box-shadow: 0 0 0 2px var(--cxfb-canvas);
    color: var(--cx-ink-3);
}

/* ── Marco de sistema (envelope enviado, fechamento enviado, início, fim) ────
   Mono porque é o sistema falando, e um fio à direita que atravessa a largura:
   é o divisor da narrativa. O fio usa order:1 para caber entre o texto e a nota
   auxiliar, que quebra para a linha de baixo (order:2). */
.cxfb__marker {
    position: relative;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0 var(--cx-s2);
    padding: var(--cx-s3) 0;
    font-family: var(--cx-mono);
    font-size: 11px;
    line-height: 16px;
    color: var(--cx-ink-2);
}
.cxfb__marker::after {
    content: "";
    order: 1;
    flex: 1 0 24px;
    height: 1px;
    background: var(--cx-divider);
}
.cxfb__marker > .cx-i {
    background: var(--cx-hatch);
    box-shadow: 0 0 0 2px var(--cxfb-canvas);
    color: var(--cx-ink-2);
}
.cxfb__marker em { font-style: italic; color: var(--cx-ink-3); }

/* Abre e fecha a jornada: nó da marca. */
.cxfb__marker--start > .cx-i,
.cxfb__marker--end > .cx-i {
    background: var(--cx-container);
    color: var(--cx-primary);
}
.cxfb__marker--start,
.cxfb__marker--end {
    font-family: var(--cx-sans);
    font-size: 12px;
    font-weight: 600;
    color: var(--cx-ink-2);
}

.cxfb__pause-note {
    order: 2;
    flex-basis: 100%;
    font-family: var(--cx-sans);
    font-size: 12px;
    line-height: 17px;
    color: var(--cx-ink-3);
    padding-top: 5px;
}

/* -----------------------------------------------------------------------------
   3 · VEREDITO — a comporta
   Único bloco deep no meio da espinha, e de propósito: é a fronteira de custo da
   tela. Acima dele nada de biometria foi pago; abaixo, foi. O handoff reserva o
   neon para uso SOBRE deep, e este é o lugar dele.
   -------------------------------------------------------------------------- */
.cxfb__pause {
    position: relative;
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--cx-s2);
    margin: var(--cx-s2) 0;
    padding: var(--cx-s3) 20px;
    border-radius: var(--cx-r-btn);
    background: var(--cx-deep);
    color: var(--cx-on-deep);
    font-size: 13px;
    line-height: 20px;
    text-wrap: pretty;
    box-shadow: var(--cx-shadow-lift);
}
/* Fio de neon no topo: a costura entre as duas fases. */
.cxfb__pause::before {
    content: "";
    position: absolute;
    left: 20px;
    right: 20px;
    top: 0;
    height: 2px;
    background: var(--cx-neon);
    border-radius: 0 0 2px 2px;
    opacity: .55;
}
.cxfb__pause > .cx-i {
    background: var(--cx-deep-3);
    box-shadow: 0 0 0 2px var(--cxfb-canvas);
    color: var(--cx-neon);
}

/* -----------------------------------------------------------------------------
   4 · Seções de fase
   -------------------------------------------------------------------------- */
.cxfb__phase {
    position: relative;
    padding: var(--cx-s1) 0;
}
.cxfb__phase-head {
    display: flex;
    align-items: baseline;
    gap: var(--cx-s1);
    margin: 0 0 10px;
    font-family: var(--cx-mono);
    font-size: 10px;
    line-height: 14px;
    font-weight: 500;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--cx-ink-3);
}
.cxfb__phase-count {
    font-family: var(--cx-mono);
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
    color: var(--cx-ink-4);
    margin-left: auto;
}
.cxfb__list {
    display: grid;
    gap: var(--cx-s1);
    border-radius: var(--cx-r-field);
    transition: outline-color .16s ease, background .16s ease;
    outline: 1.5px dashed transparent;
    outline-offset: 7px;
}

/* ── Zona de captura: o app coletando ───────────────────────────────────────
   Fundo + trilho tracejado. A análise fica no branco com trilho sólido. É essa
   alternância que dá o ritmo da jornada. */
.cxfb__phase.cxfb-capture {
    background: var(--cx-subtle);
    border: 1px solid var(--cx-divider);
    border-radius: var(--cx-r-btn);
    padding: var(--cx-s2) 14px 14px;
    margin: 10px 0;
}
.cxfb-capture::before {
    content: "";
    position: absolute;
    left: var(--cxfb-rail-offset);
    top: -11px;
    bottom: -11px;
    width: 2px;
    background: repeating-linear-gradient(
        var(--cx-border-2) 0 4px,
        var(--cxfb-canvas) 4px 9px
    );
}
.cxfb-capture > .cxfb__phase-head { color: var(--cx-ink-2); }

.cxfb__dropzone {
    border: 1.5px dashed var(--cx-border-2);
    border-radius: var(--cx-r-btn);
    padding: var(--cx-s3);
    text-align: center;
    font-size: 12px;
    color: var(--cx-ink-3);
    background: var(--cx-card);
    transition: border-color .16s ease, background .16s ease, color .16s ease;
}

/* -----------------------------------------------------------------------------
   5 · Cartão de etapa
   -------------------------------------------------------------------------- */
.cxfb-card {
    position: relative;
    background: var(--cx-card);
    border: 1px solid var(--cx-border);
    border-radius: var(--cx-r-btn);
    box-shadow: var(--cx-shadow-card);
    transition: border-color .14s ease, box-shadow .14s ease, transform .14s ease, opacity .14s ease;
}
/* Trilho de acento como pseudo, não como border-left: border-left mudava a largura
   do conteúdo e as duas famílias (condicional / execução) brigavam pela mesma
   propriedade. Agora são canais separados. */
.cxfb-card::before {
    content: "";
    position: absolute;
    left: 0;
    top: 10px;
    bottom: 10px;
    width: 3px;
    border-radius: 0 3px 3px 0;
    background: transparent;
    transition: background .14s ease;
}
.cxfb-card:hover { border-color: var(--cx-border-2); box-shadow: var(--cx-shadow-lift); }
.cxfb-card--open {
    border-color: var(--cx-primary);
    box-shadow: var(--cx-shadow-lift);
}

/* Condicionada: trilho TRACEJADO — "nem sempre roda". */
.cxfb-card--cond::before {
    background: repeating-linear-gradient(
        var(--cx-info) 0 5px,
        transparent 5px 9px
    );
}

/* justify-content só age na linha que SOBRA quando o cabeçalho quebra: na linha
   cheia o __id (flex-grow) já consumiu a folga. É o que mantém "configurar /
   remover" alinhados à direita quando os chips ocupam a primeira linha inteira —
   sem margin-left:auto, que venceria o flex-grow e esmagaria o nome. */
.cxfb-card__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: var(--cx-s1) 10px;
    padding: 10px var(--cx-s2) 10px 14px;
    cursor: pointer;
}
.cxfb-card__n {
    flex: none;
    width: 22px;
    height: 22px;
    border-radius: var(--cx-r-pill);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--cx-deep);
    color: #fff;
    font-family: var(--cx-mono);
    font-size: 11px;
    font-weight: 600;
}
.cxfb-card__ico { flex: none; font-size: 20px; color: var(--cx-primary); }
.cxfb-card__id {
    display: grid;
    line-height: 1.3;
    flex: 1 1 140px;
    min-width: 0;
}
.cxfb-card__name {
    font-size: 14px;
    font-weight: 600;
    color: var(--cx-ink);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cxfb-card__type { font-size: 12px; color: var(--cx-ink-3); }
.cxfb-card__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
    justify-content: flex-end;
    flex: 0 1 auto;
    min-width: 0;
}
.cxfb-card__head > .cx-act { order: 5; flex: none; }
.cxfb-card__head > .cx-grip {
    flex: none;
    font-size: 20px;
    color: var(--cx-border-2);
    transition: color .14s ease;
}
.cxfb-card:hover > .cxfb-card__head > .cx-grip { color: var(--cx-ink-3); }

.cxfb-card__body {
    border-top: 1px solid var(--cx-divider);
    padding: 14px;
    background: var(--cx-subtle);
    border-radius: 0 0 var(--cx-r-btn) var(--cx-r-btn);
}
.cxfb-card__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(196px, 1fr));
    gap: var(--cx-s2);
}
.cxfb-field { display: grid; gap: 5px; align-content: start; min-width: 0; }
.cxfb-field--wide { grid-column: 1 / -1; }
.cxfb-field > label {
    font-size: 12px;
    line-height: 16px;
    font-weight: 600;
    color: var(--cx-ink-2);
}
.cxfb-note {
    font-size: 12px;
    line-height: 17px;
    color: var(--cx-ink-3);
    text-wrap: pretty;
}

/* Subseções do corpo. "Quando esta etapa roda" e "O que reprova aqui" são as duas
   perguntas do cartão: viram blocos com cara de bloco, não campos soltos. */
.cxfb-when,
.cxfb-rules {
    margin-top: 2px;
    padding: var(--cx-s2);
    border: 1px solid var(--cx-divider);
    border-radius: var(--cx-r-field);
    background: var(--cx-card);
}
.cxfb-when > label,
.cxfb-rules > label {
    margin-bottom: var(--cx-s1);
    color: var(--cx-ink);
}
.cxfb-when .cxfb-card__grid { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }

/* -----------------------------------------------------------------------------
   6 · Cartão de campo de captura
   Um campo é mais leve que uma consulta paga: raio menor, tipo menor, sem número
   de ordem. Antes tinha o mesmo peso de um cartão de serviço e superdimensionava.
   -------------------------------------------------------------------------- */
.cxfb-card--capture {
    border-radius: var(--cx-r-field);
    box-shadow: none;
}
.cxfb-card--capture::before { background: var(--cx-border-2); }
.cxfb-card--capture .cxfb-card__head { padding: var(--cx-s1) 10px var(--cx-s1) var(--cx-s2); }
.cxfb-card--capture .cxfb-card__ico { font-size: 18px; color: var(--cx-ink-3); }
.cxfb-card--capture .cxfb-card__name { font-size: 13px; }
.cxfb-card--capture .cxfb-card__type { font-size: 11px; }
.cxfb-card--capture .cxfb-card__body {
    border-radius: 0 0 var(--cx-r-field) var(--cx-r-field);
    padding: 10px var(--cx-s2);
}
/* Imagem é insumo de OCR/biometria: tile levemente destacado do campo digitado. */
.cxfb-capture__fields { display: flex; flex-wrap: wrap; gap: 4px; }

/* -----------------------------------------------------------------------------
   7 · Chips — três níveis
   Antes eram todos a mesma pílula cinza, então "cache 12h" gritava igual a
   "reprovou, para". Agora: estado (peso), configuração (silêncio), alerta (cor).
   -------------------------------------------------------------------------- */
.cxfb-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px var(--cx-s1);
    border-radius: var(--cx-r-pill);
    font-size: 11px;
    line-height: 16px;
    font-weight: 500;
    white-space: nowrap;
    background: var(--cx-surface);
    color: var(--cx-ink-3);
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
}
.cxfb-chip .cx-i { font-size: 13px; flex: none; }

/* Configuração: o mais silencioso possível sem sumir. */
.cxfb-chip--cond {
    background: var(--cx-info-bg);
    color: var(--cx-info-fg);
    max-width: 280px;
}
/* Alerta: cor de aviso e peso — "esta consulta é paga e não decide nada". */
.cxfb-chip--warn { background: var(--cx-warning-bg); color: var(--cx-warning-fg); font-weight: 600; }
/* Estado terminal do cartão. */
.cxfb-chip--stop { background: var(--cx-error-bg); color: var(--cx-error-fg); font-weight: 600; }
/* Contagem de checagens: deep, porque é o que efetivamente decide. */
.cxfb-chip--rules {
    background: var(--cx-deep);
    color: #fff;
    font-family: var(--cx-mono);
    font-weight: 500;
}
.cxfb-chip--btn {
    border: none;
    cursor: pointer;
    font: inherit;
    transition: background .12s ease, color .12s ease;
}
.cxfb-chip--btn:hover { background: var(--cx-container); color: var(--cx-primary); }

/* -----------------------------------------------------------------------------
   8 · Regras da esteira
   -------------------------------------------------------------------------- */
.cxfb-rule {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    padding: var(--cx-s1) 10px;
    margin-top: 6px;
    border-radius: var(--cx-r-field);
    background: var(--cx-card);
    border: 1px solid var(--cx-divider);
    transition: border-color .12s ease;
}
.cxfb-rule:hover { border-color: var(--cx-border); }
.cxfb-rule__ico { flex: none; font-size: 17px; color: var(--cx-ink-4); }
.cxfb-rule__main { display: grid; gap: 1px; line-height: 1.3; min-width: 0; flex: 1 1 200px; }
.cxfb-rule__name {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    font-size: 13px;
    font-weight: 600;
    color: var(--cx-ink);
}
.cxfb-rule__chain {
    font-size: 12px;
    line-height: 17px;
    color: var(--cx-ink-3);
    font-style: italic;
}
.cxfb-rule__val,
.cxfb-rule__dec {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: none;
    font-size: 12px;
    color: var(--cx-ink-3);
}
.cxfb-rule__val .cx-input {
    width: 96px;
    padding: 5px var(--cx-s1);
    font-family: var(--cx-mono);
    font-size: 12px;
}
/* A seta do .cx-select do DS mora em "right 10px center" com 18px: menos de 32px de
   padding à direita encavala o texto no ícone. */
.cxfb-rule__dec .cx-select {
    padding: 5px 32px 5px var(--cx-s1);
    font-size: 12px;
    background-size: 16px;
}
.cxfb-rule-add { margin-top: var(--cx-s1); }
.cxfb-rule-add .cx-select { max-width: 360px; font-size: 13px; }

/* -----------------------------------------------------------------------------
   9 · Painéis recolhíveis — corte antecipado e decisão da esteira
   -------------------------------------------------------------------------- */
.cxfb-esteira {
    position: relative;
    margin-top: var(--cx-s1);
    background: var(--cx-card);
    border: 1px solid var(--cx-border);
    border-radius: var(--cx-r-btn);
    box-shadow: var(--cx-shadow-card);
    transition: border-color .14s ease, box-shadow .14s ease;
}
.cxfb-esteira:hover { border-color: var(--cx-border-2); }
.cxfb-esteira--open { border-color: var(--cx-primary); box-shadow: var(--cx-shadow-lift); }
.cxfb-esteira__head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--cx-s1) 10px;
    padding: var(--cx-s2) 14px;
    cursor: pointer;
}
.cxfb-esteira__title {
    font-size: 14px;
    font-weight: 600;
    color: var(--cx-ink);
    flex: 1 1 200px;
    min-width: 0;
    text-wrap: pretty;
}
.cxfb-esteira__head .cx-act { flex: none; margin-left: auto; }
.cxfb-esteira__body {
    border-top: 1px solid var(--cx-divider);
    padding: 14px;
    background: var(--cx-subtle);
    border-radius: 0 0 var(--cx-r-btn) var(--cx-r-btn);
}
.cxfb-esteira__group { margin-top: var(--cx-s3); }
.cxfb-esteira__group:first-of-type { margin-top: 0; }
.cxfb-esteira__group-title {
    font-family: var(--cx-mono);
    font-size: 10px;
    letter-spacing: .12em;
    text-transform: uppercase;
    font-weight: 500;
    color: var(--cx-ink-3);
    margin-bottom: 6px;
}

/* Corte antecipado: barra antes de pagar. Nó em cor de erro porque é o que ele faz. */
.cxfb-gate { margin: 0 0 var(--cx-s1); }
.cxfb-gate .cxfb-esteira__head > .cx-i {
    background: var(--cx-error-bg);
    color: var(--cx-error-fg);
}

.cxfb-banner {
    display: flex;
    align-items: flex-start;
    gap: var(--cx-s1);
    padding: 10px var(--cx-s2);
    border-radius: var(--cx-r-field);
    margin-bottom: var(--cx-s1);
    background: var(--cx-warning-bg);
    border: 1px solid var(--cx-warning);
    color: var(--cx-warning-fg);
    font-size: 12px;
    line-height: 17px;
    font-weight: 600;
    text-wrap: pretty;
}

/* -----------------------------------------------------------------------------
   10 · Magnetismo — o sistema trabalhando por você
   O aviso saiu de "barra verde no topo" para a linguagem teal do DS: isto não é
   "sucesso" (verde é desfecho), é "o sistema mexeu no seu fluxo". O par
   --pulled / --puller acende OS DOIS cartões envolvidos ao mesmo tempo, para a
   relação de causa (Face Match ⟷ Selfie) ser vista, não deduzida.
   -------------------------------------------------------------------------- */
.cxfb-notice {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: var(--cx-s2) var(--cx-s3);
    border-radius: var(--cx-r-btn);
    background: var(--cx-container);
    border: 1px solid var(--cx-primary);
    color: var(--cx-primary);
    font-size: 13px;
    line-height: 19px;
    font-weight: 500;
    text-wrap: pretty;
    animation: cxfb-notice-in .32s cubic-bezier(.2, .8, .2, 1) both;
}
.cxfb-notice .cx-i { flex: none; font-size: 19px; }
@keyframes cxfb-notice-in {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: none; }
}

/* O campo puxado entra na seção certa: desce, assenta e pisca um anel. */
.cxfb-card--pulled { animation: cxfb-pulled .44s cubic-bezier(.2, .8, .2, 1) both; z-index: 1; }
@keyframes cxfb-pulled {
    0%   { opacity: 0; transform: translateY(-10px) scale(.97); }
    55%  { opacity: 1; }
    100% { opacity: 1; transform: none; }
}
.cxfb-card--pulled::after,
.cxfb-card--puller::after {
    content: "";
    position: absolute;
    inset: -3px;
    border-radius: calc(var(--cx-r-btn) + 2px);
    border: 2px solid var(--cx-primary);
    pointer-events: none;
    animation: cxfb-ring 1.6s ease-out both;
}
.cxfb-card--capture.cxfb-card--pulled::after { border-radius: calc(var(--cx-r-field) + 2px); }
@keyframes cxfb-ring {
    0%, 55% { opacity: 1; }
    100%    { opacity: 0; }
}
/* Quem puxou fica marcado junto, mais discreto: a causa. */
.cxfb-card--puller::after { border-color: var(--cx-border-2); }

/* -----------------------------------------------------------------------------
   11 · Arrastar
   Quase tudo aqui é CSS puro em cima do que o JS JÁ faz (a classe .cx-dragging).
   O :has() no container lê QUEM está sendo arrastado — o prefixo "field-" do
   data-cx-sort-item — e acende só os destinos válidos. Zero JS novo.
   -------------------------------------------------------------------------- */
.cxfb-card[draggable="true"] .cx-grip { cursor: grab; }
.cxfb-card[draggable="true"] .cx-grip:active { cursor: grabbing; }

/* O que está na mão: levanta, inclina de leve e continua LEGÍVEL. opacity:.5
   escondia justamente o que a pessoa está olhando. */
.cxfb-card.cx-dragging {
    opacity: .95;
    transform: scale(.985) rotate(-.4deg);
    border-color: var(--cx-primary);
    box-shadow: var(--cxfb-shadow-drag);
}
.cxfb-card.cx-dragging::before { background: var(--cx-primary); }

/* Enquanto existe arraste, o canvas inteiro entra em modo "escolha o lugar". */
.cxfb:has(.cx-dragging) .cxfb-card:not(.cx-dragging) { opacity: .72; }
.cxfb:has(.cx-dragging) .cxfb__palette { opacity: .5; }

/* Destinos válidos: etapa acende lista de etapa; campo acende lista de campo. */
.cxfb:has(.cx-dragging[data-cx-sort-item^="field-"]) [data-cxfb-field-list],
.cxfb:has(.cx-dragging[data-cx-sort-item]:not([data-cx-sort-item^="field-"])) [data-cxfb-list] {
    outline-color: var(--cx-primary);
    background: var(--cx-row-hover);
}
.cxfb:has(.cx-dragging[data-cx-sort-item^="field-"]) [data-cxfb-field-list] .cxfb__dropzone,
.cxfb:has(.cx-dragging[data-cx-sort-item]:not([data-cx-sort-item^="field-"])) [data-cxfb-list] .cxfb__dropzone {
    border-color: var(--cx-primary);
    background: var(--cx-container);
    color: var(--cx-primary);
    font-weight: 600;
}

/* Destino RECUSADO, anunciado ANTES da tentativa: pegar a selfie pinta a 1ª parte
   de erro na hora. Prevenir o erro vale mais que reclamar depois dele — o shake
   fica como reforço para quem insistir (ver .cxfb-card--refused).
   [data-cxfb-final-only] vem do patch do JS; o seletor field-10 é a rede de
   segurança enquanto o patch não entrar (10 = Selfie em CaptureFieldType). */
.cxfb:has(.cx-dragging[data-cxfb-final-only]) [data-cxfb-field-list="1"],
.cxfb:has(.cx-dragging[data-cx-sort-item="field-10"]) [data-cxfb-field-list="1"] {
    outline-color: var(--cx-error);
    outline-style: solid;
    background: var(--cx-error-field);
    cursor: no-drop;
}
.cxfb:has(.cx-dragging[data-cxfb-final-only]) [data-cxfb-field-list="1"] .cxfb__dropzone,
.cxfb:has(.cx-dragging[data-cx-sort-item="field-10"]) [data-cxfb-field-list="1"] .cxfb__dropzone {
    border-color: var(--cx-error);
    background: var(--cx-error-bg);
    color: var(--cx-error-fg);
}

/* Recusa insistida: o cartão nega com o corpo. */
.cxfb-card--refused { animation: cxfb-refuse .3s ease both; }
@keyframes cxfb-refuse {
    0%, 100% { transform: translateX(0) scale(.985); }
    20%      { transform: translateX(-5px) scale(.985); }
    45%      { transform: translateX(4px) scale(.985); }
    70%      { transform: translateX(-2px) scale(.985); }
}

/* O DIVISOR REAGINDO: cruzar o VEREDITO com um cartão muda a fase dele, e cruzar
   com um campo muda quando o app o pede. Durante o arraste a comporta pulsa e
   levanta o fio de neon — ela é a consequência do gesto. */
.cxfb:has(.cx-dragging) .cxfb__pause {
    animation: cxfb-gate-pulse 1.5s ease-in-out infinite;
}
.cxfb:has(.cx-dragging) .cxfb__pause::before { opacity: 1; height: 3px; }
@keyframes cxfb-gate-pulse {
    0%, 100% { box-shadow: var(--cx-shadow-lift); }
    50%      { box-shadow: var(--cx-shadow-lift), 0 0 0 3px var(--cx-container); }
}

/* -----------------------------------------------------------------------------
   12 · Execução — a mesma tela, no segundo momento
   Geometria IDÊNTICA à edição: mesmos tamanhos, mesmo trilho, mesmo respiro. Só a
   tinta muda. Nada de opacity no cartão inteiro: a etapa pulada é INFORMAÇÃO, e
   embaçar tudo apagava justamente o chip de estado e o motivo, que é o que se quer
   ler. Só a configuração recua.
   -------------------------------------------------------------------------- */
.cxfb-context {
    display: flex;
    flex-wrap: wrap;
    gap: var(--cx-s2) var(--cx-s5);
    padding: var(--cx-s2) 18px;
    background: var(--cx-deep);
    color: #fff;
    border-radius: var(--cx-r-btn);
}
.cxfb-context__item { display: grid; gap: 2px; line-height: 1.3; min-width: 0; }
.cxfb-context__item > span {
    font-family: var(--cx-mono);
    font-size: 10px;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--cx-on-deep-2);
}
.cxfb-context__item > strong {
    font-family: var(--cx-mono);
    font-size: 13px;
    font-weight: 600;
    color: #fff;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cxfb-exec { font-weight: 600; }
.cxfb-exec--passed  { background: var(--cx-success-bg); color: var(--cx-success-fg); }
.cxfb-exec--failed  { background: var(--cx-error-bg);   color: var(--cx-error-fg); }
.cxfb-exec--manual  { background: var(--cx-warning-bg); color: var(--cx-warning-fg); }
.cxfb-exec--skipped { background: var(--cx-surface);    color: var(--cx-ink-3); }
.cxfb-exec--pending { background: var(--cx-info-bg);    color: var(--cx-info-fg); }

/* Trilho do cartão = o que aconteceu. Sólido, para não confundir com o tracejado
   da condicionalidade (que continua legível no chip). */
.cxfb-card--xpassed::before  { background: var(--cx-success); }
.cxfb-card--xfailed::before  { background: var(--cx-error); }
.cxfb-card--xmanual::before  { background: var(--cx-warning); }
.cxfb-card--xpending::before { background: var(--cx-info); }
.cxfb-card--xskipped::before { background: var(--cx-border-2); }

.cxfb-card--xfailed { border-color: var(--cx-error-bg); }
.cxfb-card--xmanual { border-color: var(--cx-warning-bg); }
.cxfb-card--xskipped { background: var(--cx-subtle); }
/* Pulada: recua a configuração, preserva estado, nome e motivo. */
.cxfb-card--xskipped .cxfb-card__ico { color: var(--cx-ink-4); }
.cxfb-card--xskipped .cxfb-card__n { background: var(--cx-border-2); color: var(--cx-ink-2); }
.cxfb-card--xskipped .cxfb-card__chips > .cxfb-chip:not(.cxfb-exec) { opacity: .6; }

/* Desfecho: contrapeso do VEREDITO. A história tem duas âncoras, uma em cada ponta. */
.cxfb-outcome {
    display: flex;
    align-items: center;
    gap: var(--cx-s2) var(--cx-s3);
    flex-wrap: wrap;
    margin-top: var(--cx-s2);
    padding: var(--cx-s3) 20px;
    border-radius: var(--cx-r-btn);
    font-weight: 600;
    box-shadow: var(--cx-shadow-card);
}
.cxfb-outcome > .cx-i { font-size: 24px; flex: none; }
.cxfb-outcome--ok {
    background: var(--cx-success-bg);
    color: var(--cx-success-fg);
    border: 1px solid var(--cx-success);
}
.cxfb-outcome--err {
    background: var(--cx-error-bg);
    color: var(--cx-error-fg);
    border: 1px solid var(--cx-error);
}
.cxfb-outcome--warn {
    background: var(--cx-warning-bg);
    color: var(--cx-warning-fg);
    border: 1px solid var(--cx-warning);
}
.cxfb-outcome__result { font-size: 17px; line-height: 24px; letter-spacing: -.01em; }
.cxfb-outcome__amount {
    margin-left: auto;
    font-family: var(--cx-mono);
    font-size: 15px;
    font-weight: 600;
    flex: none;
}
.cxfb-outcome__when {
    font-family: var(--cx-mono);
    font-weight: 400;
    font-size: 11px;
    opacity: .85;
    flex: none;
}

/* Leitura não arrasta: sem grip, sem cursor de mão no que não abre. */
.cxfb-capture .cxfb-card__head { cursor: default; }

/* -----------------------------------------------------------------------------
   13 · Responsivo — alvo até 1024px (notebook)
   -------------------------------------------------------------------------- */
@media (max-width: 1024px) {
    .cxfb {
        --cxfb-pad: 34px;
        --cxfb-rail-x: 12px;
        --cxfb-node: 22px;
    }
    .cxfb__marker > .cx-i,
    .cxfb__pause > .cx-i,
    .cxfb-esteira__head > .cx-i { font-size: 14px; }
    .cxfb__palette-grid { grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); }
    .cxfb-card__grid { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
}

/* Abaixo de 900 os chips descem para a própria linha em vez de desaparecer — o
   arquivo antigo fazia display:none e levava embora o chip de EXECUÇÃO, que é a
   única coisa que não se pode perder na visão da proposta. */
@media (max-width: 900px) {
    .cxfb-card__chips {
        order: 9;
        flex-basis: 100%;
        justify-content: flex-start;
        padding-top: var(--cx-s1);
        border-top: 1px dashed var(--cx-divider);
    }
    .cxfb-chip--cond { max-width: 100%; }
    .cxfb-rule__val .cx-input { width: 80px; }
}

@media (max-width: 720px) {
    .cxfb { --cxfb-pad: 26px; --cxfb-rail-x: 10px; --cxfb-node: 20px; }
    .cxfb__palette-grid { grid-template-columns: 1fr 1fr; }
    .cxfb-card__grid,
    .cxfb-when .cxfb-card__grid { grid-template-columns: 1fr; }
    .cxfb-outcome__amount { margin-left: 0; }
}

/* -----------------------------------------------------------------------------
   14 · Movimento reduzido e impressão
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    .cxfb *,
    .cxfb *::before,
    .cxfb *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
    .cxfb-card.cx-dragging { transform: none; }
    /* O realce do magnetismo não pode sumir junto com a animação: sem movimento,
       o anel fica estático por conta do próprio border. */
    .cxfb-card--pulled::after,
    .cxfb-card--puller::after { opacity: 1; }
}

@media print {
    .cxfb__palette { display: none; }
    .cxfb-card,
    .cxfb-esteira { box-shadow: none; break-inside: avoid; }
    .cxfb__pause,
    .cxfb-context { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}

/* Seções da proposta editáveis no marco (fase 6.9 — toggle direto no fluxo). */
.cxfb-sections { flex-wrap: wrap; row-gap: 4px; }
.cxfb-sections__item { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; font-weight: 600; }
.cxfb-sections__max { display: inline-flex; align-items: center; gap: 4px; }
.cxfb-sections__max .cx-input { padding: 2px 6px; }

/* Histórico novo (30/08): timeline de versões + canvas com diff. */
.hist-layout { display: grid; grid-template-columns: 180px 1fr; gap: 16px; align-items: start; }
.hist-timeline { display: grid; gap: 6px; position: sticky; top: 0; }
.hist-ver { display: block; text-align: left; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--cx-border); background: var(--cx-card); cursor: pointer; }
.hist-ver.is-active { border-color: var(--cx-primary); box-shadow: var(--cx-shadow-lift); }
.hist-canvas { min-width: 0; }
.hist-diff { border: 1px solid var(--cx-border); border-left: 3px solid var(--cx-info-fg); border-radius: 10px; padding: 10px 14px; margin-bottom: 12px; background: var(--cx-card); }
.hist-diff__item { font-size: 13px; padding: 3px 0; }
@media (max-width: 820px) { .hist-layout { grid-template-columns: 1fr; } .hist-timeline { position: static; display: flex; flex-wrap: wrap; } }

/* ── Replay da proposta (30/08/2026) ─────────────────────────────────────────── */
.cxfb-replay-hide { opacity: 0; transform: translateY(12px); }
.cxfb-replay-in { transition: opacity .35s ease, transform .35s ease; opacity: 1; transform: none; }
.cxfb-replay-pulse { box-shadow: 0 0 0 3px var(--cx-brand, #0aa07c); border-radius: 10px; transition: box-shadow .25s; }
.cxfb-replay-clock {
    position: sticky; top: 8px; z-index: 5; float: right;
    background: var(--cx-deep, #0e2a23); color: #fff; border-radius: 999px;
    padding: 6px 14px; font-size: 13px; box-shadow: 0 2px 10px rgba(0,0,0,.25);
}
.cxfb-replay-clock span { font-weight: 700; font-variant-numeric: tabular-nums; }
.cxfb-replay-clock em { font-style: normal; opacity: .75; font-size: 11px; }

/* Botão de resultado da etapa (visão do cliente no portal, 31/08/2026): "analisar…"
   ganha peso quando a etapa está parada esperando um humano. */
.cx-act--attn { color: var(--cx-warning-fg); font-weight: 600; }
