// Reembolso → Calendário de Reembolso · gráficos (spec 2026-07-30).
// Três blocos: série de duas faixas, barras FE×UP e motivos.
//
// PREFIXO `rcc` em TODOS os identificadores de topo: os .jsx dividem um único escopo
// de script (Babel standalone) e colisão de nome derruba o app inteiro em silêncio.
//
// Paleta validada com o validador da skill dataviz (light, superfície #fff):
// #3B82F6 + #FD7119 -> ALL CHECKS PASS, CVD ΔE 30,3 (protan). var(--fenix-blue)
// (#303880) REPROVOU a banda de luminosidade como preenchimento (L 0,377) e
// var(--fenix-navy) reprovou também o piso de croma (lê como cinza) — por isso o
// lado esquerdo é #3B82F6, que já é cor de produção no projeto (Clickbank, LD_COLORS).
const RCC_A = '#3B82F6';   // 1ª janela
const RCC_B = '#FD7119';   // 2ª janela
const RCC_TAXA = '#FD7119';
const RCC_VOL = '#9AA3B5';

// Índices da série cobertos por uma janela (para a faixa sombreada). Compara ISO como
// string — 'YYYY-MM-DD' ordena lexicograficamente igual à data.
const rccFaixa = (serie, lado) => {
  if (!lado || !serie.length) return null;
  const d0 = String(lado.start).slice(0, 10), d1 = String(lado.end).slice(0, 10);
  let i0 = -1, i1 = -1;
  serie.forEach((p, i) => {
    if (p.bucket >= d0 && p.bucket <= d1) { if (i0 < 0) i0 = i; i1 = i; }
  });
  return i0 < 0 ? null : { i0, i1 };
};

// 'T12:00:00' força parse LOCAL (date-only vira UTC midnight e em BRT o eixo X
// rotularia o dia anterior) — mesma regra do Leads.jsx.
const rccDia = (iso) => {
  const d = new Date(iso + 'T12:00:00');
  return String(d.getDate()).padStart(2, '0') + '/' + String(d.getMonth() + 1).padStart(2, '0');
};
const RCC_WD = ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'];
const rccDiaLongo = (iso) => {
  const d = new Date(iso + 'T12:00:00');
  return `${RCC_WD[d.getDay()]} ${rccDia(iso)}`;
};

// Série de DUAS FAIXAS com eixo X compartilhado: taxa (%) em cima, volume (n) embaixo.
// Nunca eixo duplo — escalas incompatíveis pedem dois gráficos, não dois eixos.
const RccSerie = ({ serie = [], lados, onHoverDay }) => {
  const [ref, w] = useWidth();
  const [hover, setHover] = React.useState(null);
  if (!serie.length) return <div style={rccx.vazio}>Sem dado nos últimos 30 dias.</div>;

  const H_TAXA = 132, H_VOL = 46, PAD_L = 54, PAD_R = 16, PAD_T = 12, GAP = 10, PAD_B = 26;
  const H = PAD_T + H_TAXA + GAP + H_VOL + PAD_B;
  const cw = Math.max(w, 360);
  const innerW = cw - PAD_L - PAD_R;
  const taxas = serie.map(p => p.taxa || 0);
  const vols = serie.map(p => p.refunds || 0);
  const maxTaxa = Math.max(...taxas, 1) * 1.2;
  const maxVol = Math.max(...vols, 1);
  const x = i => PAD_L + (serie.length <= 1 ? 0 : innerW * i / (serie.length - 1));
  const yT = v => PAD_T + H_TAXA * (1 - v / maxTaxa);
  const baseT = PAD_T + H_TAXA;
  const topV = baseT + GAP;
  const baseV = topV + H_VOL;
  const bw = Math.max(2, innerW / serie.length * 0.55);

  const linha = serie.map((p, i) => (i ? 'L' : 'M') + x(i).toFixed(1) + ' ' + yT(taxas[i]).toFixed(1)).join(' ');
  const area = `M ${PAD_L} ${baseT} ` +
    serie.map((p, i) => 'L' + x(i).toFixed(1) + ' ' + yT(taxas[i]).toFixed(1)).join(' ') +
    ` L ${x(serie.length - 1).toFixed(1)} ${baseT} Z`;
  const ticks = [0, 0.5, 1].map(f => f * maxTaxa);
  const lblStep = Math.max(1, Math.ceil(serie.length / 10));

  const faixaA = rccFaixa(serie, lados && lados.a);
  const faixaB = rccFaixa(serie, lados && lados.b);
  const faixa = (f, cor) => f && (
    <rect x={x(f.i0) - bw / 2} y={PAD_T} width={Math.max(bw, x(f.i1) - x(f.i0) + bw)}
      height={baseV - PAD_T} fill={cor} opacity="0.10" />
  );

  const p = hover != null ? serie[hover] : null;
  return (
    <div style={rccx.card}>
      <div style={rccx.cardHead}>
        <div>
          <div style={rccx.eye}>Últimos 30 dias</div>
          <div style={rccx.cardTitle}>Taxa de refund e volume por dia</div>
        </div>
        <div style={rccx.legenda}>
          {lados && ['a', 'b'].map(k => (
            <span key={k} style={rccx.legItem}>
              <span style={{ ...rccx.legSw, background: k === 'a' ? RCC_A : RCC_B, opacity: .35 }} />
              {lados[k].label}
            </span>
          ))}
        </div>
      </div>
      <div ref={ref} style={{ width: '100%', position: 'relative' }}>
        <svg width={cw} height={H} style={{ display: 'block' }} onMouseLeave={() => setHover(null)}>
          <defs>
            <linearGradient id="rccTaxaFill" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0%" stopColor={RCC_TAXA} stopOpacity="0.22" />
              <stop offset="100%" stopColor={RCC_TAXA} stopOpacity="0" />
            </linearGradient>
          </defs>
          {faixa(faixaA, RCC_A)}
          {faixa(faixaB, RCC_B)}
          {ticks.map((v, i) => (
            <g key={i}>
              <line x1={PAD_L} y1={yT(v)} x2={cw - PAD_R} y2={yT(v)} stroke="#DEE2EA"
                strokeWidth="1" strokeDasharray={i === 0 ? '0' : '3 4'} />
              <text x={PAD_L - 10} y={yT(v) + 4} textAnchor="end" fontFamily="var(--font-num)"
                fontSize="10.5" fill="#9AA3B5">{PCT(v)}</text>
            </g>
          ))}
          <path d={area} fill="url(#rccTaxaFill)" />
          <path d={linha} fill="none" stroke={RCC_TAXA} strokeWidth="2.5"
            strokeLinecap="round" strokeLinejoin="round" />
          <line x1={PAD_L} y1={baseV} x2={cw - PAD_R} y2={baseV} stroke="#DEE2EA" strokeWidth="1" />
          <text x={PAD_L - 10} y={topV + 10} textAnchor="end" fontFamily="var(--font-num)"
            fontSize="10.5" fill="#9AA3B5">{NUM(maxVol)}</text>
          {serie.map((s, i) => (
            <rect key={'v' + i} x={x(i) - bw / 2} y={baseV - H_VOL * (vols[i] / maxVol)}
              width={bw} height={H_VOL * (vols[i] / maxVol)} rx="2"
              fill={hover === i ? RCC_TAXA : RCC_VOL} opacity={hover === i ? 1 : .55} />
          ))}
          {hover != null && (
            <line x1={x(hover)} y1={PAD_T} x2={x(hover)} y2={baseV} stroke={RCC_TAXA}
              strokeWidth="1" strokeDasharray="3 3" opacity="0.6" />
          )}
          {serie.map((s, i) => (
            <g key={'h' + i} onMouseEnter={() => { setHover(i); onHoverDay && onHoverDay(s); }}
              style={{ cursor: 'pointer' }}>
              <rect x={x(i) - innerW / serie.length / 2} y={PAD_T}
                width={Math.max(6, innerW / serie.length)} height={baseV - PAD_T} fill="transparent" />
              <circle cx={x(i)} cy={yT(taxas[i])} r={hover === i ? 5 : 3} fill="#fff"
                stroke={RCC_TAXA} strokeWidth="2.5" />
            </g>
          ))}
          {serie.map((s, i) => (i % lblStep === 0 &&
            <text key={'x' + i} x={x(i)} y={H - 8} textAnchor="middle" fontFamily="var(--font-num)"
              fontSize="10.5" fill="#9AA3B5">{rccDia(s.bucket)}</text>
          ))}
        </svg>
        {p && (
          <div style={{ ...rccx.tip, left: Math.min(Math.max(x(hover) - 110, 8), Math.max(cw - 236, 8)),
            top: Math.max(yT(taxas[hover]) - 8, 4) }}>
            <div style={rccx.tipTitle}>{rccDiaLongo(p.bucket)}</div>
            <div style={rccx.tipLinha}>
              <span>taxa</span><b className="fenix-num">{PCT(p.taxa)}</b>
            </div>
            <div style={rccx.tipLinha}>
              <span>reemb+cgbk</span><b className="fenix-num">{NUM(p.refunds)} · {USD(p.amount)}</b>
            </div>
            <div style={rccx.tipSect}>Quem moveu o dia</div>
            {(p.topProdutos || []).map(t => (
              <div key={t.name} style={rccx.tipLinha}>
                <span style={rccx.tipNome}>{t.name}</span>
                <b className="fenix-num">
                  {NUM(t.refunds)}
                  <span style={{ color: t.deltaVs7d > 0 ? '#F3A6A0' : t.deltaVs7d < 0 ? '#5FD6A0' : '#7E92AE',
                    marginLeft: 6 }}>
                    {t.deltaVs7d > 0 ? '▲' : t.deltaVs7d < 0 ? '▼' : '—'}
                    {Math.abs(t.deltaVs7d).toFixed(1)}
                  </span>
                </b>
              </div>
            ))}
            {(p.topProdutos || []).length > 0 && (
              <div style={rccx.tipNota}>variação vs. a média do próprio produto nos 7 dias anteriores</div>
            )}
          </div>
        )}
      </div>
    </div>
  );
};

// Cabeçalho compartilhado dos blocos: título + seletor de granularidade do drill.
// Desde a reforma de 30/jul cada bloco tem o SEU estado `detalhe` — um estado
// compartilhado fazia o toggle de um bloco trocar os outros (bug reportado).
const RccHead = ({ eye, titulo, detalhe, setDetalhe }) => (
  <div style={rccx.cardHead}>
    <div>
      <div style={rccx.eye}>{eye}</div>
      <div style={rccx.cardTitle}>{titulo}</div>
    </div>
    <div style={rccx.detalheWrap}>
      <span style={rccx.detalheLbl}>Detalhar por</span>
      <Segmented value={detalhe} onChange={setDetalhe}
        options={[{ key: 'funil', label: 'Funil' }, { key: 'etapa', label: 'Etapa' }]} />
    </div>
  </div>
);

const rccQuebra = (item, detalhe) => (detalhe === 'etapa' ? item.porEtapa : item.porFunil) || [];

// Cor POR ENTIDADE, idêntica nos DOIS donuts de um par (regra dataviz: a cor segue
// a entidade, nunca o rank dentro de cada donut). "Sem motivo informado" é cinza
// neutro deliberado, fora da paleta categórica. DONUT_PALETTE vem do KpiParts.jsx
// (escopo Babel compartilhado — mesmo precedente do LD_COLORS no LeadsEconomics).
const rccCorMap = (labels) => {
  const map = {};
  let i = 0;
  labels.forEach(l => {
    map[l] = l === 'Sem motivo informado'
      ? 'var(--gray-400)' : DONUT_PALETTE[i++ % DONUT_PALETTE.length];
  });
  return map;
};

// Tabela compacta da quebra (funil/etapa). NÃO estica 100% (feedback 30/jul: nada
// espremido na ponta do bloco): colunas com largura natural, agrupadas à esquerda.
// Hover padrão de linha (rodada 2, 31/jul): indigo wash da marca — vivo e
// semanticamente livre (não colide com verde/âmbar/vermelho nem com a seleção laranja).
const rccRowHover = {
  onMouseEnter: (e) => { e.currentTarget.style.background = 'var(--fenix-blue-100)'; },
  onMouseLeave: (e) => { e.currentTarget.style.background = 'transparent'; },
};

// `contagem` = colunas de vendas/reemb+cgbk/taxa (bloco 3); sem ela, shares e Δ (bloco 4).
const RccQuebraTabela = ({ item, detalhe, lados, contagem }) => {
  const linhas = rccQuebra(item, detalhe);
  return (
    <table style={rccx.subTabela}>
      <thead><tr>
        {[detalhe === 'etapa' ? 'Etapa' : 'Funil',
          ...(contagem
            ? [`Vendas ${lados.a.label}`, `Vendas ${lados.b.label}`, 'Reemb+CGBK', 'Taxa']
            : [lados.a.label, lados.b.label, 'Δ'])].map((h, i) => (
          <th key={h} style={{ ...rccx.subTh, textAlign: i ? 'right' : 'left' }}>{h}</th>
        ))}
      </tr></thead>
      <tbody>
        {linhas.map(q => contagem ? (
          <tr key={q.key} {...rccRowHover}>
            <td style={rccx.subTd}>{q.label}</td>
            <td style={rccx.subTdNum} className="fenix-num">{NUM(q.vendasA)}</td>
            <td style={rccx.subTdNum} className="fenix-num">{NUM(q.vendasB)}</td>
            <td style={rccx.subTdNum} className="fenix-num">
              {NUM(q.refundsA)}{' '}
              <span style={{ color: q.refundsB > q.refundsA ? 'var(--negative)'
                   : q.refundsB < q.refundsA ? 'var(--positive)' : 'var(--fg-4)' }}>
                → {NUM(q.refundsB)}</span>
            </td>
            <td style={rccx.subTdNum} className="fenix-num">
              {PCT(q.taxaA)} → <b style={{ color: refundHealth(q.taxaB).color }}>{PCT(q.taxaB)}</b>
            </td>
          </tr>
        ) : (
          <tr key={q.key} {...rccRowHover}>
            <td style={rccx.subTd}>{q.label}</td>
            <td style={rccx.subTdNum} className="fenix-num">{PCT(q.pctA)}</td>
            <td style={rccx.subTdNum} className="fenix-num">{PCT(q.pctB)}</td>
            <td style={{ ...rccx.subTdNum,
              color: q.deltaPp > 0 ? 'var(--negative)'
                   : q.deltaPp < 0 ? 'var(--positive)' : 'var(--fg-4)' }}
              className="fenix-num">
              {q.deltaPp > 0 ? '+' : ''}{q.deltaPp.toFixed(1).replace('.', ',')}
            </td>
          </tr>
        ))}
        {linhas.length === 0 && (
          <tr><td colSpan={contagem ? 5 : 4} style={rccx.subVazio}>Sem quebra nesta janela.</td></tr>
        )}
      </tbody>
    </table>
  );
};

// Barra 100% empilhada FE|UP de UMA janela — +50% de altura (20→30px) e anotações
// AO LADO das barras, não na borda do bloco (feedback 30/jul). O rótulo direto
// dentro do segmento é obrigatório (o laranja fica abaixo de 3:1 contra o branco).
const RccBarraFeUp = ({ lado, d }) => {
  if (!d || (d.feRefunds + d.upRefunds) === 0) {
    return (
      <div style={rccx.feupLinha}>
        <span style={rccx.feupData}>{lado}</span>
        <span style={rccx.feupVazio}>sem reemb+cgbk nesta janela</span>
      </div>
    );
  }
  const tot = d.feRefunds + d.upRefunds;
  const fePct = d.feRefunds / tot * 100;
  return (
    <div style={rccx.feupLinha}>
      <span style={rccx.feupData}>{lado}</span>
      <div style={rccx.feupTrack}>
        <div style={{ ...rccx.feupSeg, width: fePct + '%', background: 'var(--fenix-navy)',
          color: '#F6E9E0' }}>
          {fePct >= 18 && `FE ${NUM(d.feRefunds)} (${Math.round(fePct)}%)`}
        </div>
        <div style={{ ...rccx.feupSeg, width: (100 - fePct) + '%',
          background: 'var(--fenix-orange)', color: '#fff' }}>
          {(100 - fePct) >= 18 && `UP ${NUM(d.upRefunds)} (${Math.round(100 - fePct)}%)`}
        </div>
      </div>
      <span style={rccx.feupAnota} className="fenix-num"
        title="Peso do upsell nas VENDAS da janela — o denominador que falta na leitura ingênua">
        UP nas vendas {d.upPctVendas == null ? '—' : PCT(d.upPctVendas)}
      </span>
      <span style={{ ...rccx.feupAnota, fontWeight: 700,
        color: (d.upIndex == null || d.upIndex === 0) ? 'var(--fg-4)'
             : d.upIndex > 0 ? 'var(--negative)' : 'var(--positive)' }}
        title="Diferença entre o peso do upsell nos reemb+cgbk e nas vendas. Positivo = o upsell reembolsa acima do que vende.">
        {d.upIndex == null ? '—'
          : d.upIndex > 0 ? `UP reembolsa mais (+${d.upIndex.toFixed(1)} pp)`
          : d.upIndex < 0 ? `UP reembolsa menos (${d.upIndex.toFixed(1)} pp)`
          : 'proporcional'}
      </span>
    </div>
  );
};

// Bloco 3 (reforma 30/jul): DOIS donuts — um por janela — com fatias = PRODUTOS
// (reemb+cgbk). A legenda traz as VENDAS junto (visíveis sem clicar). Clique num
// produto abre o funil dele: barras FE|UP gordas + quebra por funil/etapa — o
// padrão TopProductsFunnel da página de afiliado.
const RccFeUp = ({ produtos = [], lados, detalhe, setDetalhe }) => {
  const [sel, setSel] = React.useState(null);
  const cores = rccCorMap(produtos.map(p => p.label));
  const p = produtos.find(x => x.key === sel) || null;
  const donut = (k) => {
    const K = k.toUpperCase();
    const segs = produtos.map(x => ({
      label: x.label, value: x['refunds' + K], color: cores[x.label], meta: x }));
    const total = segs.reduce((s, x) => s + (x.value || 0), 0);
    return (
      <div key={k}>
        <div style={rccx.janelaTag}>
          <span style={{ ...rccx.legSw, background: k === 'a' ? RCC_A : RCC_B }} />
          {lados[k].label}
        </div>
        <HoverDonut segments={segs} centerValue={NUM(total)} centerLabel="reemb+cgbk"
          legendValue={a => a.meta
            ? `${NUM(a.value)} · ${NUM(a.meta['vendas' + K] || 0)} vendas` : NUM(a.value)}
          caption={a => a.meta
            ? `${a.label} · ${NUM(a.value)} reemb+cgbk em ${NUM(a.meta['vendas' + K] || 0)} vendas`
            : `${a.label} · ${NUM(a.value)} reemb+cgbk`}
          onSlice={a => a.meta && setSel(a.meta.key)}
          hint="clique num produto para abrir o funil dele" />
      </div>
    );
  };
  return (
    <div style={rccx.card}>
      <RccHead eye="Bloco 3" titulo="Onde o refund nasce · por produto"
        detalhe={detalhe} setDetalhe={setDetalhe} />
      {produtos.length === 0
        ? <div style={rccx.vazio}>Sem produto nesta janela.</div>
        : <div style={rccx.doisDonuts}>{donut('a')}{donut('b')}</div>}
      {p && (
        <div style={rccx.detCard}>
          <div style={rccx.detTopo}>
            <span style={rccx.detNome}>
              <span style={{ ...rccx.legSw, background: cores[p.label] }} />{p.label}
            </span>
            <button style={rccx.detFechar} onClick={() => setSel(null)}>fechar ×</button>
          </div>
          {['a', 'b'].map(k => {
            const K = k.toUpperCase();
            return (
              <React.Fragment key={k}>
                <div style={rccx.detInfo} className="fenix-num">
                  {lados[k].label} · {NUM(p['vendas' + K])} vendas ·{' '}
                  {NUM(p['refunds' + K])} reemb+cgbk · taxa{' '}
                  <b style={{ color: refundHealth(p['taxa' + K]).color }}>{PCT(p['taxa' + K])}</b>
                </div>
                <RccBarraFeUp lado={lados[k].label} d={p.feUp && p.feUp[k]} />
              </React.Fragment>
            );
          })}
          <RccQuebraTabela item={p} detalhe={detalhe} lados={lados} contagem />
        </div>
      )}
      <div style={rccx.nota}>
        Fatia = reemb+cgbk do produto na janela (produto sem devolução não vira fatia);
        a legenda mostra as vendas junto. Cor de cada produto é a MESMA nos dois donuts.
        No funil aberto: FE navy · UP laranja.
      </div>
    </div>
  );
};

// Reembolsos por CANAL — só volume: o banco NÃO tem motivo para Tauk/Salesbound/
// Logicall (o chargebackReasonCode da Tauk está 98% vazio; o comparativo por motivo
// do Addendum trimestral foi classificação manual, fora do banco).
const RccParceiros = ({ parceiros = [], lados }) => {
  const max = parceiros.reduce((m, p) => Math.max(m, p.refundsA, p.refundsB), 1);
  return (
    <div style={rccx.parcWrap}>
      <div style={rccx.parcTitulo}>Reembolsos por canal</div>
      <div style={rccx.parcGrid}>
        {parceiros.map(p => (
          <div key={p.key} style={rccx.parcBloco}>
            <span style={rccx.parcNome}>{p.label}</span>
            {['a', 'b'].map(k => {
              const K = k.toUpperCase();
              return (
                <div key={k} style={rccx.parcLinha}>
                  <span style={rccx.parcData}>
                    <span style={{ ...rccx.legSw, background: k === 'a' ? RCC_A : RCC_B }} />
                    {lados[k].label}
                  </span>
                  <div style={rccx.parcTrack}>
                    <div style={{ width: Math.max(1, p['refunds' + K] / max * 100) + '%',
                      height: '100%', background: k === 'a' ? RCC_A : RCC_B,
                      borderRadius: '0 3px 3px 0' }} />
                  </div>
                  <span style={rccx.parcVal} className="fenix-num">
                    {NUM(p['refunds' + K])} · {USDk(p['amount' + K])}
                  </span>
                </div>
              );
            })}
          </div>
        ))}
      </div>
      <div style={rccx.notaCurta}>
        Só volume: nenhuma plataforma de recuperação grava MOTIVO no banco (o
        comparativo por motivo do relatório trimestral foi classificação manual).
        BuyGoods = os totais desta página; parceiros com janela pela data do pedido.
      </div>
    </div>
  );
};

// Bloco 4 (reforma 30/jul): DOIS donuts — um por janela — com fatias = MOTIVOS.
// O share fecha 100% sobre os REEMB+CGBK da janela (nunca sobre vendas): as fatias
// somam exatamente o total do centro — é a resposta visual ao "fecha 100% de quê?".
const RccMotivos = ({ motivos = [], lados, kpis = {}, parceiros, detalhe, setDetalhe }) => {
  const [sel, setSel] = React.useState(null);
  const cores = rccCorMap(motivos.map(m => m.label));
  const m = motivos.find(x => x.key === sel) || null;
  const kpi = (k) => {
    const K = k.toUpperCase();
    return (
      <div style={rccx.motKpi}>
        <div style={rccx.janelaTag}>
          <span style={{ ...rccx.legSw, background: k === 'a' ? RCC_A : RCC_B }} />
          {lados[k].label}
        </div>
        <div style={rccx.motKpiLinha} className="fenix-num">
          <span>{NUM(kpis['vendas' + K] || 0)}<i style={rccx.motKpiSub}> vendas</i></span>
          <span>{NUM(kpis['refunds' + K] || 0)}<i style={rccx.motKpiSub}> reemb+cgbk</i></span>
          <span style={{ color: refundHealth(kpis['taxa' + K] || 0).color, fontWeight: 700 }}>
            {PCT(kpis['taxa' + K] || 0)}<i style={rccx.motKpiSub}> taxa</i></span>
        </div>
      </div>
    );
  };
  const donut = (k) => {
    const K = k.toUpperCase();
    const segs = motivos.map(x => ({ label: x.label, value: x['n' + K],
      color: cores[x.label], meta: x }));
    const total = segs.reduce((s, x) => s + (x.value || 0), 0);
    return (
      <HoverDonut segments={segs} centerValue={NUM(total)} centerLabel="reemb+cgbk"
        legendValue={a => a.meta
          ? `${NUM(a.value)} · ${PCT(a.meta['pct' + K] || 0)}` : NUM(a.value)}
        caption={a => a.meta
          ? `${a.label} · ${NUM(a.value)} de ${NUM(total)} reemb+cgbk (${PCT(a.meta['pct' + K] || 0)})`
          : `${a.label} · ${NUM(a.value)} de ${NUM(total)} reemb+cgbk`}
        onSlice={a => a.meta && setSel(a.meta.key)}
        hint="clique num motivo para abrir a quebra" />
    );
  };
  return (
    <div style={rccx.card}>
      <RccHead eye="Bloco 4" titulo="Motivos do reembolso · buygoods"
        detalhe={detalhe} setDetalhe={setDetalhe} />
      {parceiros && parceiros.length > 0 && <RccParceiros parceiros={parceiros} lados={lados} />}
      {motivos.length === 0
        ? <div style={rccx.vazio}>Sem reemb+cgbk nesta janela.</div>
        : (
          <div style={rccx.doisDonuts}>
            <div>{kpi('a')}{donut('a')}</div>
            <div>{kpi('b')}{donut('b')}</div>
          </div>
        )}
      {m && (
        <div style={rccx.detCard}>
          <div style={rccx.detTopo}>
            <span style={rccx.detNome}>
              <span style={{ ...rccx.legSw, background: cores[m.label] }} />{m.label}
            </span>
            <span style={{ ...rccx.detDelta,
              color: m.deltaPp > 0 ? 'var(--negative)'
                   : m.deltaPp < 0 ? 'var(--positive)' : 'var(--fg-4)' }} className="fenix-num">
              {m.deltaPp > 0 ? '▲ +' : m.deltaPp < 0 ? '▼ ' : '— '}
              {Math.abs(m.deltaPp).toFixed(1).replace('.', ',')} pp
            </span>
            <button style={rccx.detFechar} onClick={() => setSel(null)}>fechar ×</button>
          </div>
          <div style={rccx.detInfo} className="fenix-num">
            {lados.a.label}: {NUM(m.nA)} ({PCT(m.pctA)}) · {lados.b.label}: {NUM(m.nB)} ({PCT(m.pctB)})
          </div>
          <RccQuebraTabela item={m} detalhe={detalhe} lados={lados} />
        </div>
      )}
      <div style={rccx.nota}>
        As fatias fecham 100% sobre os <b>reemb+cgbk da janela</b> (o total do centro) —
        nunca sobre vendas; cancelamentos ficam fora da métrica (decisão 30/jul).
        "Sem motivo informado" em cinza: chargeback formal nunca traz motivo, e só a
        buygoods grava motivo (~60% das linhas). Na quebra aberta, o denominador é o
        funil (ou a etapa): "que fatia dos reemb+cgbk deste funil carrega este motivo".
      </div>
    </div>
  );
};

const rccx = {
  card: { background: '#fff', border: '1px solid var(--border-1)', borderRadius: 'var(--r-lg)',
    boxShadow: 'var(--shadow-sm)', padding: '16px 20px 10px', marginBottom: 16 },
  cardHead: { display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between',
    gap: 16, marginBottom: 8, flexWrap: 'wrap' },
  eye: { font: 'var(--text-label)', letterSpacing: '.05em', textTransform: 'uppercase', color: 'var(--fg-3)' },
  cardTitle: { font: 'var(--text-h3)', color: 'var(--fg-1)', marginTop: 4 },
  legenda: { display: 'flex', gap: 14, alignItems: 'center' },
  legItem: { display: 'inline-flex', alignItems: 'center', gap: 6,
    font: '600 11.5px/1 var(--font-sans)', color: 'var(--fg-2)' },
  legSw: { width: 11, height: 11, borderRadius: 3, flex: 'none' },
  vazio: { padding: '40px 0', textAlign: 'center', font: 'var(--text-body-sm)', color: 'var(--fg-4)' },
  tip: { position: 'absolute', width: 228, background: 'var(--fenix-navy)', borderRadius: 'var(--r-md)',
    padding: '11px 13px', boxShadow: 'var(--shadow-lg)', zIndex: 20, pointerEvents: 'none' },
  tipTitle: { font: '700 12.5px/1.2 var(--font-sans)', color: '#FFA866', marginBottom: 7 },
  tipLinha: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10,
    padding: '3px 0', font: '500 11.5px/1.3 var(--font-sans)', color: '#C3D0E2' },
  tipNome: { flex: 1, minWidth: 0, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' },
  tipSect: { font: '700 9.5px/1 var(--font-sans)', letterSpacing: '.08em', textTransform: 'uppercase',
    color: '#FFA866', margin: '9px 0 4px' },
  tipNota: { font: 'italic 10px/1.35 var(--font-sans)', color: '#7E92AE', marginTop: 6 },

  detalheWrap: { display: 'inline-flex', alignItems: 'center', gap: 9 },
  detalheLbl: { font: '600 11.5px/1 var(--font-sans)', color: 'var(--fg-3)' },

  // Par de donuts (um por janela) + rótulo de janela
  doisDonuts: { display: 'grid', gridTemplateColumns: 'repeat(2,minmax(0,1fr))', gap: 22,
    padding: '6px 2px 2px' },
  janelaTag: { display: 'inline-flex', alignItems: 'center', gap: 7,
    font: '800 12px/1 var(--font-num)', letterSpacing: '.04em', color: 'var(--fg-2)',
    marginBottom: 8 },

  // Painel de detalhe (produto ou motivo clicado)
  detCard: { background: 'var(--bg-sunken)', border: '1px solid var(--border-1)',
    borderRadius: 'var(--r-md)', padding: '14px 16px', margin: '12px 0 4px' },
  detTopo: { display: 'flex', alignItems: 'center', gap: 12, marginBottom: 6 },
  detNome: { flex: 1, display: 'inline-flex', alignItems: 'center', gap: 8,
    font: '700 14px/1.2 var(--font-sans)', color: 'var(--fg-1)' },
  detDelta: { font: '700 12px/1 var(--font-num)', whiteSpace: 'nowrap' },
  detFechar: { border: 0, background: 'transparent', color: 'var(--fg-3)',
    font: '600 11.5px/1 var(--font-sans)', cursor: 'pointer', padding: '4px 6px' },
  detInfo: { font: '600 12px/1.5 var(--font-num)', color: 'var(--fg-2)',
    margin: '8px 0 2px', fontVariantNumeric: 'tabular-nums' },

  // Barras FE|UP gordas (+50%, feedback 30/jul) com anotações ao lado
  feupLinha: { display: 'flex', alignItems: 'center', gap: 12, padding: '7px 0',
    flexWrap: 'wrap' },
  feupData: { font: '600 11px/1 var(--font-num)', color: 'var(--fg-3)', width: 84, flex: 'none' },
  feupTrack: { flex: '1 1 260px', minWidth: 220, height: 30, display: 'flex', gap: 2,
    overflow: 'hidden' },
  feupSeg: { height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center',
    font: '700 11px/1 var(--font-sans)', whiteSpace: 'nowrap', overflow: 'hidden',
    borderRadius: 4, transition: 'width .3s var(--ease)' },
  feupVazio: { flex: 1, font: 'var(--text-body-sm)', color: 'var(--fg-4)' },
  feupAnota: { font: '600 11px/1.4 var(--font-num)', color: 'var(--fg-2)',
    whiteSpace: 'nowrap', cursor: 'help' },

  // Parceiros (Reembolsos por canal)
  parcWrap: { background: 'var(--bg-sunken)', border: '1px solid var(--border-1)',
    borderRadius: 'var(--r-md)', padding: '12px 16px', marginBottom: 14 },
  parcTitulo: { font: '700 10.5px/1 var(--font-sans)', letterSpacing: '.06em',
    textTransform: 'uppercase', color: 'var(--fg-3)', marginBottom: 10 },
  parcGrid: { display: 'grid', gridTemplateColumns: 'repeat(2,minmax(0,1fr))',
    gap: '10px 26px' },
  parcBloco: { minWidth: 0 },
  parcNome: { display: 'block', font: '700 12.5px/1 var(--font-sans)', color: 'var(--fg-1)',
    marginBottom: 5 },
  parcLinha: { display: 'flex', alignItems: 'center', gap: 8, padding: '2px 0' },
  parcData: { display: 'inline-flex', alignItems: 'center', gap: 5, width: 86, flex: 'none',
    font: '600 10.5px/1 var(--font-num)', color: 'var(--fg-3)' },
  parcTrack: { flex: 1, minWidth: 70, height: 12, background: 'var(--gray-100)',
    borderRadius: 3 },
  parcVal: { font: '700 11px/1 var(--font-num)', color: 'var(--fg-1)', whiteSpace: 'nowrap',
    fontVariantNumeric: 'tabular-nums' },
  notaCurta: { font: '500 10.5px/1.5 var(--font-sans)', color: 'var(--fg-4)', marginTop: 8 },

  // KPIs por janela do bloco de motivos
  motKpi: { marginBottom: 10 },
  motKpiLinha: { display: 'flex', gap: 18, flexWrap: 'wrap',
    font: '700 13px/1.3 var(--font-num)', color: 'var(--fg-1)',
    fontVariantNumeric: 'tabular-nums' },
  motKpiSub: { font: '600 10px/1 var(--font-sans)', color: 'var(--fg-4)', fontStyle: 'normal' },

  // Tabela compacta da quebra — NÃO estica 100% (nada espremido na ponta do bloco)
  subTabela: { borderCollapse: 'collapse', margin: '10px 0 2px', width: 'auto' },
  subTh: { font: '700 9.5px/1 var(--font-sans)', letterSpacing: '.04em', textTransform: 'uppercase',
    color: 'var(--fg-4)', padding: '7px 16px 7px 0', borderBottom: '1px solid var(--border-1)',
    whiteSpace: 'nowrap' },
  subTd: { padding: '7px 26px 7px 0', borderBottom: '1px solid var(--border-1)',
    font: '600 12px/1.2 var(--font-sans)', color: 'var(--fg-2)', whiteSpace: 'nowrap' },
  subTdNum: { padding: '7px 26px 7px 0', borderBottom: '1px solid var(--border-1)',
    textAlign: 'right', whiteSpace: 'nowrap', font: 'var(--text-body-sm)', color: 'var(--fg-1)',
    fontFamily: 'var(--font-num)', fontVariantNumeric: 'tabular-nums' },
  subVazio: { padding: '12px 0', font: 'var(--text-body-sm)', color: 'var(--fg-4)' },
  nota: { font: '500 11px/1.6 var(--font-sans)', color: 'var(--fg-4)', padding: '12px 2px 4px' },
};

Object.assign(window, { RccSerie, RccFeUp, RccMotivos, RccParceiros, RccHead, RCC_A, RCC_B });
