// -------------------------------------------------------------------------
// EDITOR EM USO
//
// Destino: /lp/components/middle.jsx
// Protótipo: lab/protos/editor-em-uso.html · Ficha: refs/editor-em-uso/ficha.md
// GERADO por tools/portar.py — edite o protótipo e rode de novo.
//
// Ícones: use `II` (window.Icon), já aliasado no topo de middle.jsx.
// Tudo vive numa IIFE porque os arquivos de /lp/components/ dividem o
// mesmo escopo global — nomes soltos colidem entre si.
// -------------------------------------------------------------------------

(function () {
  // Em produção este arquivo entra em middle.jsx, onde o alias já é `II`.
  const II = window.Icon;

  // Olho de "Ver prévia" não existe no set — inline, como o boleto no hero.jsx.
  const IconeOlho = (p) => (
    <svg width={p.size || 12} height={p.size || 12} viewBox="0 0 24 24" fill="none" stroke="currentColor"
         strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <path d="M2 12s3.6-7 10-7 10 7 10 7-3.6 7-10 7-10-7-10-7z"/><circle cx="12" cy="12" r="3"/>
    </svg>
  );

  // Categorias da Biblioteca de blocos, com as contagens reais do editor.
  const CATEGORIAS = [
    { n:'Conversão & gatilhos', q:11, cor:'#f59e0b', bg:'#fffbeb', ic:<II.Zap size={14}/> },
    { n:'Diferenciais únicos',  q:12, cor:'#e11d48', bg:'#fff1f2', ic:<II.Star size={14}/> },
    { n:'Confiança',            q:5,  cor:'#16a34a', bg:'#f0fdf4', ic:<II.ShieldCheck size={14}/> },
    { n:'Personalizar',         q:6,  cor:'#7c3aed', bg:'#f5f3ff', ic:<II.Sparkles size={14}/> },
  ];

  // Os 5 essenciais, com os textos exatos do app.
  const ESSENCIAIS = [
    { n:'Cabeçalho da loja',    d:'Logo + selo de segurança.',                        ic:<II.Layers size={13}/> },
    { n:'Identificação',        d:'CPF/CNPJ, nome, e-mail e telefone.',               ic:<II.User size={13}/> },
    { n:'Endereço',             d:'CEP, rua, número, bairro, cidade.',                ic:<II.Truck size={13}/> },
    { n:'Métodos de pagamento', d:'PIX, cartão, boleto. Ordem configurável no tema.', ic:<II.CreditCard size={13}/> },
    { n:'Resumo do pedido',     d:'Itens, frete e total. Atualiza ao mudar pagamento.',ic:<II.PackageCheck size={13}/> },
  ];

  // Os 11 de "Conversão & gatilhos" — nomes e descrições reais.
  const BLOCOS_CONVERSAO = [
    { n:'Express Checkout',     d:'Apple Pay, Google Pay e 1-clique no topo.',            ic:<II.Zap size={13}/> },
    { n:'Escassez',             d:'Apenas X unidades restantes!',                          ic:<II.AlertTriangle size={13}/> },
    { n:'Contador de urgência', d:'Timer regressivo para promoções limitadas.',            ic:<II.Timer size={13}/> },
    { n:'Prova social ao vivo', d:'Toast: Maria de SP comprou há 3 min.',                  ic:<II.Users size={13}/> },
    { n:'Barra de frete grátis',d:'Faltam R$ 50 para frete grátis (com progresso).',       ic:<II.Truck size={13}/> },
    { n:'Cupom desbloqueável',  d:'Campo de cupom com animação ao aplicar.',               ic:<II.Tag size={13}/> },
    { n:'Oferta ao sair',       d:'Quando o cliente tenta sair, abre um pop-up com cupom.',ic:<II.Sparkles size={13}/> },
    { n:'Roleta de brindes',    d:'Roleta gamificada: o cliente gira e ganha um cupom.',   ic:<II.CircleDot size={13}/> },
    { n:'Barra de estoque',     d:'Visualiza % do estoque já vendido.',                    ic:<II.PieChart size={13}/> },
    { n:'Avaliações inline',    d:'Estrelas + número de avaliações.',                      ic:<II.Star size={13}/> },
    { n:'Comparativo de preço', d:'Você economiza R$ X vs o concorrente.',                 ic:<II.Percent size={13}/> },
  ];
  const ARRASTADO = 4; // Barra de frete grátis

  // Templates por nicho — vêm ANTES dos presets no painel real.
  const NICHOS = [
    { n:'Moda Feminina',   a:'#f43f5e', b:'#111827', bg:'#fff1f2' },
    { n:'Moda Masculina',  a:'#1e3a8a', b:'#111827', bg:'#eff6ff' },
    { n:'Pet',             a:'#16a34a', b:'#111827', bg:'#f0fdf4' },
    { n:'Ferramentas',     a:'#111827', b:'#111827', bg:'#fff' },
    { n:'Acessórios',      a:'#7c3aed', b:'#111827', bg:'#f5f3ff' },
    { n:'Vestuário Geral', a:'#111827', b:'#111827', bg:'#fff' },
  ];

  const PRESETS = [
    { n:'Violeta (padrão)', a:'#7c3aed', b:'#111827' },
    { n:'Minimalista',      a:'#111827', b:'#111827' },
    { n:'Premium',          a:'#7c3aed', b:'#111827', bg:'#f5f3ff' },
    { n:'Noturno',          a:'#a78bfa', b:'#ffffff', escuro:true },
    { n:'Esmeralda',        a:'#16a34a', b:'#111827', bg:'#f0fdf4' },
    { n:'Coral',            a:'#f43f5e', b:'#111827', bg:'#fff1f2' },
  ];
  const PRESET_ALVO = 3; // Noturno

  // 0 repouso · 1 cursor→categoria · 2 clique abre a lista · 3 cursor→bloco
  // 4 pega · 5 arrasta até a lousa · 6 zona destaca · 7 solta e o bloco assenta
  // 8 cursor→preset · 9 clique · 10 re-tematiza + "Salvo" · 11 hold
  const DUR = [700, 750, 550, 700, 420, 1000, 450, 900, 850, 420, 1100, 1500];
  const FIM = 10;
  const PRESSIONA_EM = { 2: 60, 4: 60, 9: 60 };
  const DUR_PRESS = 150;

  // A CÂMERA. `k` é a escala, `a` é o alvo a enquadrar (o mesmo ref que o cursor
  // visita), `d` a duração da viagem. `a: null` = plano geral, k volta pra 1.
  // O ritmo copia o do vídeo do Corvex: entra, fecha, ABRE pra caber o arrasto
  // inteiro, fecha no clímax, e abre de vez quando o checkout troca de cara.
  const CAM = [
    { k: 1.00, a: null,       d:  900 },  // 0  plano geral
    { k: 1.30, a: 'categoria', d:  900 }, // 1  cursor indo pra categoria
    { k: 1.30, a: 'categoria', d:  900 }, // 2  a lista abre
    { k: 1.45, a: 'bloco',     d:  800 }, // 3  desce até o bloco
    { k: 1.45, a: 'bloco',     d:  800 }, // 4  pega
    { k: 1.12, a: 'zona',      d:  900 }, // 5  abre: a viagem precisa das duas pontas
    { k: 1.35, a: 'zona',      d:  700 }, // 6  fecha na zona de solta
    { k: 1.55, a: 'inserido',  d:  800 }, // 7  clímax: o bloco assentando
    { k: 1.40, a: 'preset',    d:  900 }, // 8  sobe até o preset
    { k: 1.40, a: 'preset',    d:  900 }, // 9  clica
    { k: 1.00, a: null,        d: 1200 }, // 10 ABRE — o re-tema tem que ser visto inteiro
    { k: 1.00, a: null,        d: 1200 }, // 11 hold
  ];

  function useReduced() {
    const [r, setR] = React.useState(false);
    React.useEffect(() => {
      if (!window.matchMedia) return;
      const mq = window.matchMedia('(prefers-reduced-motion: reduce)');
      setR(mq.matches);
      const on = (e) => setR(e.matches);
      mq.addEventListener ? mq.addEventListener('change', on) : mq.addListener(on);
      return () => { mq.removeEventListener ? mq.removeEventListener('change', on) : mq.removeListener(on); };
    }, []);
    return r;
  }

  function Cursor({ x, y, visivel, apertado, arrastando }) {
    return (
      <div className="pointer-events-none absolute left-0 top-0 z-50 will-change-transform"
        style={{ transform:`translate(${x}px, ${y}px)`, opacity: visivel ? 1 : 0,
                 transition:'transform .6s cubic-bezier(.2,.7,.2,1), opacity .3s ease' }}>
        <div className="origin-top-left will-change-transform"
             style={{ transform:`scale(${apertado ? 0.8 : 1})`, transition:'transform .16s cubic-bezier(.2,.7,.2,1)' }}>
          <svg width="20" height="24" viewBox="0 0 22 26" fill="none">
            <path d="M2 2l16 10.5-7 1.3L7.6 22 2 2z" fill="#1a1233" stroke="#fff" strokeWidth="1.6" strokeLinejoin="round"/>
          </svg>
          <span className="absolute left-0 top-0 -z-10 block h-7 w-7 rounded-full"
            style={{ background:'radial-gradient(circle, rgba(124,58,237,.45), transparent 70%)',
                     transform:`translate(-9px,-4px) scale(${apertado ? 1.4 : 0.4})`,
                     opacity: apertado ? 1 : 0,
                     transition:'transform .3s cubic-bezier(.2,.7,.2,1), opacity .3s ease' }}></span>
        </div>
        {arrastando && (
          <div className="absolute left-3 top-3 flex w-[186px] items-start gap-2 rounded-lg border border-violet-300 bg-white px-2.5 py-2 shadow-[0_16px_30px_-12px_rgba(26,18,51,.45)]">
            <span className="mt-0.5 text-[#f59e0b]"><II.Truck size={13}/></span>
            <span className="min-w-0">
              <span className="block text-[11.5px] font-semibold leading-tight text-[#1a1233]">Barra de frete grátis</span>
              <span className="block text-[9.5px] leading-tight text-[#1a1233]/50">arrastando…</span>
            </span>
          </div>
        )}
      </div>
    );
  }

  // "Etapa N" pequeno em cima, nome do passo embaixo — como no editor.
  function Etapa({ n, t, cor }) {
    return (
      <div className="flex items-center gap-2 pt-1">
        <span className="grid h-6 w-6 shrink-0 place-items-center rounded-full text-[10px] font-bold text-white transition-colors" style={{ background: cor }}>{n}</span>
        <span className="leading-tight">
          <span className="block text-[9px] font-semibold uppercase tracking-[0.08em] transition-colors" style={{ color: cor }}>Etapa {n}</span>
          <span className="block text-[12px] font-medium">{t}</span>
        </span>
        <span className="h-px flex-1 bg-[#1a1233]/10"></span>
      </div>
    );
  }

  // Bloco "Contador de urgência" montado no checkout, acima da Etapa 1.
  // Estado próprio: só ele re-renderiza a cada segundo, não o editor inteiro.
  // Tingido em vez de sólido — a barra de anúncio logo acima já é um retângulo
  // escuro cheio, e duas barras sólidas empilhadas viram uma mancha só.
  function Contador({ T, parado }) {
    const [seg, setSeg] = React.useState(14 * 60 + 52);
    React.useEffect(() => {
      if (parado) return;
      const id = setInterval(() => setSeg((s) => (s <= 1 ? 14 * 60 + 52 : s - 1)), 1000);
      return () => clearInterval(id);
    }, [parado]);

    const dois = (v) => String(v).padStart(2, '0');
    const partes = [[dois(Math.floor(seg / 3600)), 'h'],
                    [dois(Math.floor(seg / 60) % 60), 'm'],
                    [dois(seg % 60), 's']];

    return (
      <div className="flex items-center justify-center gap-1.5 rounded-lg px-2 py-1.5 transition-colors"
           style={{ background: T.urgFundo, color: T.urgTexto }}>
        <II.Timer size={11} />
        <span className="text-[9px] font-semibold uppercase tracking-[0.06em]">Oferta termina em</span>
        {partes.map(([v, u], i) => (
          <span key={u} className="flex items-baseline gap-0.5">
            {i > 0 && <span className="mr-0.5 opacity-40">:</span>}
            {/* tabular-nums: o dígito muda, a largura não. Zero layout shift. */}
            <span className="rounded px-1 py-px text-[10px] font-bold tabular-nums transition-colors"
                  style={{ background: T.urgChip, color: T.urgChipTxt }}>{v}</span>
            <span className="text-[8px] opacity-60">{u}</span>
          </span>
        ))}
      </div>
    );
  }

  // Bloco "Cupom desbloqueável" montado no resumo, abaixo do preço.
  // Empilhado porque a coluna tem 148px — é o que ela faz de verdade.
  function Cupom({ T }) {
    return (
      <div className="rounded-lg border border-[#1a1233]/12 p-2">
        <div className="flex items-center gap-1 text-[#1a1233]/70">
          <II.Tag size={10} />
          <span className="text-[9.5px] font-semibold leading-none">Cupom desbloqueável</span>
        </div>
        <div className="mt-1.5 rounded-md border border-[#1a1233]/12 px-1.5 py-1 text-[9px] tracking-[0.06em] text-[#1a1233]/35">
          CUPOM10
        </div>
        <div className="mt-1 grid h-5 place-items-center rounded-md text-[9.5px] font-semibold transition-colors"
             style={{ background: T.primaria, color: T.txt }}>
          Aplicar
        </div>
        <div className="mt-1.5 flex items-start gap-1 text-[8px] leading-tight text-emerald-700">
          <span className="mt-px shrink-0"><II.Check size={8} sw={4} /></span>
          10% liberado acima de R$ 300
        </div>
      </div>
    );
  }

  function AddBloco({ ativo, children, inner }) {
    return (
      <div ref={inner}
        className="grid h-8 place-items-center rounded-lg border border-dashed px-2 text-center text-[10px] font-medium transition-colors"
        style={{
          borderColor: ativo ? '#7c3aed' : 'rgba(26,18,51,.16)',
          background: ativo ? '#f5f3ff' : 'transparent',
          color: ativo ? '#7c3aed' : 'rgba(26,18,51,.42)',
        }}>
        {children || '+ Adicionar bloco'}
      </div>
    );
  }

  function EditorEmUso() {
    const reduzido = useReduced();
    const [etapa, setEtapa] = React.useState(0);
    const [apertado, setApertado] = React.useState(false);
    const [visivel, setVisivel] = React.useState(false);
    const [cursor, setCursor] = React.useState({ x: 120, y: 240 });
    const [cam, setCam] = React.useState({ tx: 0, ty: 0, k: 1 });
    const [deslize, setDeslize] = React.useState(0);
    const [largo, setLargo] = React.useState(true);
    const secaoRef = React.useRef(null), palcoRef = React.useRef(null), alvos = React.useRef({});
    const vpRef = React.useRef(null), conteudoRef = React.useRef(null), bibRef = React.useRef(null);

    // A câmera não roda abaixo de 1024px: ampliar uma maquete num viewport de
    // 390px deixa ilegível o pouco que sobrou — princípio 8.
    React.useEffect(() => {
      if (!window.matchMedia) return;
      const mq = window.matchMedia('(min-width: 1024px)');
      setLargo(mq.matches);
      const on = (e) => setLargo(e.matches);
      mq.addEventListener ? mq.addEventListener('change', on) : mq.addListener(on);
      return () => { mq.removeEventListener ? mq.removeEventListener('change', on) : mq.removeListener(on); };
    }, []);

    React.useEffect(() => {
      const el = secaoRef.current; if (!el) return;
      const io = new IntersectionObserver(([e]) => setVisivel(e.isIntersecting), { threshold: 0.3 });
      io.observe(el); return () => io.disconnect();
    }, []);

    React.useEffect(() => {
      if (reduzido) { setEtapa(FIM); return; }
      if (!visivel) return;
      const t = setTimeout(() => setEtapa((e) => (e + 1) % DUR.length), DUR[etapa]);
      return () => clearTimeout(t);
    }, [etapa, visivel, reduzido]);

    React.useEffect(() => {
      if (reduzido || !visivel) return;
      const atraso = PRESSIONA_EM[etapa];
      if (atraso == null) { setApertado(false); return; }
      const a = setTimeout(() => setApertado(true), atraso);
      const b = setTimeout(() => setApertado(false), atraso + DUR_PRESS);
      return () => { clearTimeout(a); clearTimeout(b); };
    }, [etapa, visivel, reduzido]);

    const alvoDaEtapa = { 1:'categoria', 2:'categoria', 3:'bloco', 4:'bloco',
                          5:'zona', 6:'zona', 7:'zona', 8:'preset', 9:'preset', 10:'preset' };
    React.useLayoutEffect(() => {
      if (reduzido) { setCam({ tx: 0, ty: 0, k: 1 }); setDeslize(0); return; }
      const palco = palcoRef.current, vp = vpRef.current, cont = conteudoRef.current;
      const bib = bibRef.current;
      if (!palco || !vp || !cont) return;

      // Toda medição sai de offsetLeft/offsetTop, que IGNORAM transform e devolvem a
      // coordenada de layout. É isso que deixa mirar onde o alvo VAI estar, e não onde
      // ele está passando: nem a escala da câmera nem o deslize da biblioteca — as
      // duas coisas que estão animando ao mesmo tempo — contaminam a conta.
      const posAte = (el, parada) => {
        if (!el || !el.offsetWidth) return null;   // display:none (mobile) → sem alvo
        let x = 0, y = 0, n = el;
        while (n && n !== parada) { x += n.offsetLeft; y += n.offsetTop; n = n.offsetParent; }
        return n === parada ? { x, y, w: el.offsetWidth, h: el.offsetHeight } : null;
      };

      // Quanto a biblioteca rola. Só a partir do passo 2, quando a lista abre: antes
      // disso não há o que trazer pra cima. Teto de 280px = exatamente o que o acordeão
      // acrescenta, então rolar nunca revela espaço em branco no fim da coluna.
      const cat = posAte(alvos.current.categoria, palco);
      const d = etapa < 2 || !largo || !cat ? 0 : Math.min(Math.max(0, cat.y - 70), 280);
      setDeslize(d);

      // Alvo dentro da biblioteca? Então ele vai subir junto com o deslize.
      const corrige = (el, p) => (p && bib && bib.contains(el) ? { ...p, y: p.y - d } : p);

      const elCursor = alvos.current[alvoDaEtapa[etapa]];
      const pc = corrige(elCursor, posAte(elCursor, palco));
      if (pc) setCursor({ x: pc.x + Math.min(pc.w * 0.45, 120), y: pc.y + pc.h / 2 });

      const c = CAM[etapa] || CAM[0];
      const elFoco = largo && c.a ? alvos.current[c.a] : null;
      const pf = corrige(elFoco, posAte(elFoco, cont));
      if (!pf || c.k <= 1) { setCam({ tx: 0, ty: 0, k: 1 }); return; }

      const W = vp.clientWidth,  H = vp.clientHeight;
      const Cw = cont.offsetWidth, Ch = cont.offsetHeight;
      const k = c.k;
      // Enquadra o centro do alvo e prende nas bordas: a câmera nunca revela vazio.
      const tx = Math.min(0, Math.max(W - k * Cw, W / 2 - k * (pf.x + pf.w / 2)));
      const ty = Math.min(0, Math.max(H - k * Ch, H / 2 - k * (pf.y + pf.h / 2)));
      setCam({ tx, ty, k });
    }, [etapa, reduzido, largo]);

    const listaAberta = etapa >= 2;
    const arrastando  = etapa >= 5 && etapa <= 6;
    const zonaAtiva   = etapa >= 5 && etapa <= 6;
    const inserido    = etapa >= 7;
    const tematizado  = etapa >= FIM;
    const reg = (k) => (el) => { if (el) alvos.current[k] = el; };

    // Tema do preview: muda quando o preset "Noturno" é aplicado.
    // `urg*` é o contador de urgência: fundo tingido, dígitos em chip sólido.
    const T = tematizado
      ? { barra:'#1a1233', txt:'#ffffff', primaria:'#a78bfa',
          urgFundo:'rgba(167,139,250,.18)', urgTexto:'#6d28d9', urgChip:'#6d28d9', urgChipTxt:'#ffffff' }
      : { barra:'#111111', txt:'#ffffff', primaria:'#111111',
          urgFundo:'rgba(17,17,17,.06)',   urgTexto:'rgba(17,17,17,.72)', urgChip:'#111111', urgChipTxt:'#ffffff' };

    const Topo = ({ children, className = '' }) => (
      <span className={`inline-flex items-center gap-1.5 rounded-lg border border-[#1a1233]/12 px-2.5 py-1.5 text-[11px] font-medium text-[#1a1233]/75 ${className}`}>
        {children}
      </span>
    );

    return (
      <section ref={secaoRef} id="editor" className="relative overflow-hidden bg-ink py-20 lg:py-28">
        <style>{`@keyframes ed-assenta { 0%{transform:scale(.97) translateY(-6px);opacity:.35} 100%{transform:none;opacity:1} }`}</style>
        <div className="absolute inset-0 -z-10">
          <div className="mesh-blob bg-violet-700/45 w-[520px] h-[520px] -top-32 left-1/4 animate-drift2"></div>
          <div className="absolute inset-0 dot-grid opacity-[0.16]"></div>
        </div>

        <div className="mx-auto max-w-7xl px-6 lg:px-10">
          <div className="reveal mb-12 max-w-3xl">
            <div className="inline-flex items-center gap-2 rounded-full border border-violet-300/20 bg-violet-500/10 px-3 py-1.5 text-[12px] font-medium text-violet-200">
              <span className="h-1.5 w-1.5 rounded-full bg-cyan-400"></span> Editor visual · arraste e solte
            </div>
            <h2 className="mt-5 text-4xl font-semibold leading-[1.02] tracking-[-0.03em] sm:text-5xl lg:text-6xl">
              Seu checkout,<br /><span className="grad-cyan">do seu jeito.</span>
            </h2>
            <p className="mt-6 text-lg leading-relaxed text-violet-100/70">
              34 blocos avançados além dos essenciais. Você arrasta, solta, aplica um preset de
              marca e o checkout muda na hora. Nenhum dev no caminho.
            </p>
          </div>

          {/* Janela do editor — clara, como o app de verdade */}
          <div className="reveal overflow-hidden rounded-2xl border border-white/10 bg-white text-[#1a1233] shadow-[0_50px_120px_-40px_rgba(124,58,237,.55)]"
               aria-hidden="true">

           {/* VIEWPORT DA CÂMERA — tamanho fixo. Só o conteúdo lá dentro transforma,
               e transform não afeta layout: a janela tem a mesma altura em k=1 e k=1,55. */}
           <div ref={vpRef} className="overflow-hidden">
            <div ref={conteudoRef} className="relative"
                 style={{ transform:`translate(${cam.tx}px, ${cam.ty}px) scale(${cam.k})`,
                          transformOrigin:'0 0',
                          transition:`transform ${(CAM[etapa] || CAM[0]).d}ms cubic-bezier(.2,.7,.2,1)` }}>

            {/* Chrome */}
            <div className="flex flex-wrap items-center gap-2 border-b border-[#1a1233]/10 bg-white px-4 py-2.5">
              <span className="flex items-center gap-1.5 text-[12px] text-[#1a1233]/60">
                <II.ArrowRight size={13} className="rotate-180"/> Voltar
              </span>
              <span className="ml-2 mr-auto leading-tight">
                <span className="block text-[13.5px] font-semibold tracking-[-0.01em]">Editor de checkout</span>
                <span className="block text-[10px] text-[#1a1233]/45">Auto-save ativo</span>
              </span>
              <span className="hidden items-center gap-0.5 rounded-lg bg-[#1a1233]/[0.05] p-0.5 xl:inline-flex">
                <span className="rounded-md bg-white px-2.5 py-1 text-[11px] font-medium shadow-sm">Desktop</span>
                <span className="px-2.5 py-1 text-[11px] text-[#1a1233]/50">Mobile</span>
              </span>
              <Topo className="hidden xl:inline-flex"><II.Sliders size={12}/> Regras e informações</Topo>
              <Topo className="hidden xl:inline-flex">Teste A/B</Topo>
              <span className="hidden items-center gap-1.5 rounded-lg border border-violet-300/60 bg-violet-50 px-2.5 py-1.5 text-[11px] font-medium text-violet-700 sm:inline-flex">
                <span className="grid h-3 w-3 place-items-center rounded-[3px] bg-violet-600 text-white"><II.Check size={8} sw={4}/></span>
                Auto-save
              </span>
              <Topo className="hidden lg:inline-flex">Descartar</Topo>
              <Topo><IconeOlho size={12}/> Ver prévia</Topo>
              <span className="inline-flex items-center gap-1.5 rounded-lg px-2.5 py-1.5 text-[11px] font-semibold transition-colors"
                    style={{ background: tematizado ? '#16a34a' : 'rgba(26,18,51,.08)',
                             color: tematizado ? '#fff' : 'rgba(26,18,51,.45)' }}>
                {tematizado ? <><II.Check size={11} sw={3}/> Salvo</> : 'Salvo'}
              </span>
            </div>

            {/* ALTURA TRAVADA no desktop. O acordeão da biblioteca cresce 280px ao abrir;
                sem isto ele estica a linha do grid, a janela inteira cresce e empurra o
                resto da página pra baixo no meio da animação (princípio 3). Com altura
                fixa + overflow nas colunas, a lista cresce PARA DENTRO e as categorias de
                baixo saem de vista — que é o que a barra lateral real faz mesmo.
                Medidas intrínsecas: lousa 718–769px · painel 745–760px · biblioteca
                798–1078px. 800px acomoda as duas primeiras e recorta a terceira. */}
            <div ref={palcoRef} className="relative grid min-h-[470px] grid-cols-1 lg:h-[800px] lg:grid-cols-[262px_1fr_248px]">

              {/* ---------- Biblioteca de blocos ---------- */}
              <aside className="relative hidden overflow-hidden border-r border-[#1a1233]/10 bg-white lg:block">
               {/* A coluna real rola. O conteúdo é absoluto pra não somar altura na
                   linha do grid, e sobe em translateY pra trazer a categoria aberta
                   pro alto — sem isso o bloco arrastado nasce fora do quadro. */}
               <div ref={bibRef} className="absolute inset-x-0 top-0 p-3.5"
                    style={{ transform:`translateY(${-deslize}px)`,
                             transition:`transform ${(CAM[etapa] || CAM[0]).d}ms cubic-bezier(.2,.7,.2,1)` }}>
                <div className="text-[10.5px] font-semibold uppercase tracking-[0.12em] text-[#1a1233]/55">Biblioteca de blocos</div>
                <div className="mt-3 flex items-center gap-2 rounded-lg border border-[#1a1233]/12 px-2.5 py-2 text-[11.5px] text-[#1a1233]/35">
                  <II.Globe size={12}/> Buscar bloco…
                </div>

                <div className="mt-3 rounded-xl border border-violet-200 bg-violet-50 p-3">
                  <div className="flex items-start gap-1.5">
                    <span className="mt-0.5 text-violet-600"><II.Sparkles size={13}/></span>
                    <span className="text-[12px] font-semibold leading-tight text-[#1a1233]">Layout que mais converte</span>
                  </div>
                  <p className="mt-1.5 text-[10.5px] leading-snug text-[#1a1233]/60">
                    6 blocos na ordem ideal — cabeçalho, resumo, identificação, endereço, pagamento e selos.
                  </p>
                  <div className="mt-2.5 grid h-7 place-items-center rounded-lg border border-violet-300 bg-white text-[11px] font-semibold text-violet-700">
                    Usar layout recomendado
                  </div>
                </div>
                <div className="mt-3 rounded-xl border border-[#1a1233]/10">
                  <div className="flex items-center gap-2 px-3 py-2.5">
                    <span className="grid h-6 w-6 place-items-center rounded-md bg-emerald-50 text-emerald-600"><II.ShieldCheck size={13}/></span>
                    <span className="leading-tight">
                      <span className="block text-[12px] font-semibold">Essenciais</span>
                      <span className="block text-[10px] text-[#1a1233]/45">5 blocos</span>
                    </span>
                    <span className="ml-auto text-[#1a1233]/30"><II.ChevronDown size={13}/></span>
                  </div>
                  <div className="space-y-0.5 px-1.5 pb-1.5">
                    {ESSENCIAIS.map((b) => (
                      <div key={b.n} className="flex items-start gap-2 rounded-lg px-1.5 py-1.5">
                        <span className="mt-0.5 text-[#1a1233]/40">{b.ic}</span>
                        <span className="min-w-0 flex-1">
                          <span className="flex items-center gap-1.5">
                            <span className="truncate text-[11.5px] font-medium leading-tight">{b.n}</span>
                            <span className="shrink-0 rounded bg-emerald-50 px-1 py-0.5 text-[8px] font-bold text-emerald-700">No checkout</span>
                          </span>
                          <span className="block text-[9.5px] leading-tight text-[#1a1233]/45">{b.d}</span>
                        </span>
                      </div>
                    ))}
                  </div>
                </div>

                <div className="mt-4 flex items-center gap-2">
                  <span className="grid h-5 w-5 place-items-center rounded-md bg-violet-600 text-white"><II.Layers size={11}/></span>
                  <span className="text-[10.5px] font-semibold uppercase tracking-[0.1em] text-[#1a1233]/55">Recursos avançados</span>
                  <span className="rounded-full bg-violet-100 px-1.5 py-0.5 text-[9.5px] font-bold text-violet-700">34</span>
                </div>

                {CATEGORIAS.map((cat, i) => {
                  const alvo = i === 0;
                  const aberta = alvo && listaAberta;
                  return (
                    <div key={cat.n} className="mt-2">
                      <div ref={alvo ? reg('categoria') : undefined}
                        className="flex items-center gap-2 rounded-xl border px-3 py-2.5 transition-colors"
                        style={{ borderColor: aberta ? '#c4b5fd' : 'rgba(26,18,51,.10)',
                                 background: aberta ? '#faf8ff' : '#fff' }}>
                        <span className="grid h-6 w-6 place-items-center rounded-md" style={{ background: cat.bg, color: cat.cor }}>{cat.ic}</span>
                        <span className="leading-tight">
                          <span className="block text-[12px] font-semibold">{cat.n}</span>
                          <span className="block text-[10px] text-[#1a1233]/45">{cat.q} blocos</span>
                        </span>
                        <span className="ml-auto text-[#1a1233]/30">
                          <II.ChevronDown size={13} className={aberta ? '' : '-rotate-90'}/>
                        </span>
                      </div>

                      {alvo && (
                        <div className="overflow-hidden"
                             style={{ maxHeight: aberta ? 280 : 0, opacity: aberta ? 1 : 0,
                                      transition:'max-height .5s cubic-bezier(.2,.7,.2,1), opacity .35s ease' }}>
                          <div className="mt-1 space-y-0.5 pl-1">
                            {BLOCOS_CONVERSAO.map((b, k) => {
                              const este = k === ARRASTADO;
                              return (
                                <div key={b.n} ref={este ? reg('bloco') : undefined}
                                  className="flex items-start gap-2 rounded-lg px-2 py-1.5 transition-colors"
                                  style={{ background: este && etapa >= 3 && etapa <= 4 ? '#f5f3ff' : 'transparent',
                                           opacity: este && arrastando ? 0.35 : 1 }}>
                                  <span className="mt-0.5" style={{ color: cat.cor }}>{b.ic}</span>
                                  <span className="min-w-0 flex-1">
                                    <span className="block text-[11.5px] font-semibold leading-tight">{b.n}</span>
                                    <span className="block text-[9.5px] leading-tight text-[#1a1233]/50">{b.d}</span>
                                  </span>
                                  <span className="mt-0.5 text-[#1a1233]/25"><II.Plus size={11}/></span>
                                </div>
                              );
                            })}
                          </div>
                        </div>
                      )}
                    </div>
                  );
                })}
               </div>
              </aside>

              {/* ---------- Lousa ---------- */}
              <div className="bg-[#f6f6f9] p-4">
                <div className="rounded-xl border border-violet-200 bg-violet-50/70 px-3 py-2">
                  <div className="flex flex-wrap items-center gap-2">
                    <span className="flex items-center gap-1.5 text-[11.5px] font-semibold text-violet-800"><II.Sparkles size={12}/> Sobre o checkout:</span>
                    <span className="rounded-lg border border-violet-300 bg-white px-2 py-1 text-[10.5px] font-medium text-violet-700">Oferta ao sair</span>
                  </div>
                  <p className="mt-1 text-[9.5px] text-violet-900/55">Aparecem por cima do checkout — não entram na ordem.</p>
                </div>

                <div className="mt-3 grid gap-3 rounded-xl bg-white p-3 sm:grid-cols-[1fr_148px]">
                  {/* coluna do checkout */}
                  <div className="space-y-2">
                    <AddBloco />
                    <div className="flex items-center justify-between">
                      <span className="text-[12px] font-semibold tracking-[-0.01em]">molduralle</span>
                      <span className="flex items-center gap-1 text-[9px] text-[#1a1233]/45"><II.Lock size={9}/> Seguro</span>
                    </div>

                    <div className="rounded-lg px-3 py-2 text-center text-[10px] font-medium leading-snug transition-colors"
                         style={{ background: T.barra, color: T.txt }}>
                      Parcele em até 3x Sem Juros no cartão<br />Frete Grátis acima de R$400
                    </div>

                    {/* Bloco "Contador de urgência" — Conversão & gatilhos */}
                    <Contador T={T} parado={reduzido || !visivel} />

                    {[['1','Identificação'],['2','Endereço']].map(([n, t]) => (
                      <Etapa key={n} n={n} t={t} cor={T.primaria} />
                    ))}

                    {/* Zona onde o bloco entra */}
                    <AddBloco inner={reg('zona')} ativo={zonaAtiva}>
                      {zonaAtiva ? 'solte para inserir' : '+ Adicionar bloco'}
                    </AddBloco>

                    {inserido && (
                      <div ref={reg('inserido')}
                           className="rounded-lg border border-emerald-200 bg-emerald-50 px-2.5 py-2"
                           style={{ animation:'ed-assenta .5s cubic-bezier(.2,.9,.3,1.1)' }}>
                        <div className="flex items-center justify-between text-[10px]">
                          <span className="flex items-center gap-1 font-semibold text-emerald-800"><II.Truck size={11}/> Você ganhou frete grátis! 🎉</span>
                          <span className="font-semibold tabular-nums text-emerald-700">100%</span>
                        </div>
                        <div className="mt-1 h-1.5 overflow-hidden rounded-full bg-emerald-200/70">
                          <div className="h-full w-full rounded-full bg-emerald-500"></div>
                        </div>
                      </div>
                    )}

                    <Etapa n="3" t="Pagamento" cor={T.primaria} />

                    <div className="flex items-center gap-2 rounded-lg border-2 px-2.5 py-2 transition-colors" style={{ borderColor: T.primaria }}>
                      <span className="h-3 w-3 rounded-[3px] transition-colors" style={{ background: T.primaria }}></span>
                      <span className="text-[11px] font-semibold">PIX</span>
                      <span className="ml-auto rounded bg-emerald-100 px-1.5 py-0.5 text-[9px] font-bold text-emerald-700">5% OFF</span>
                    </div>
                    {['Cartão de crédito','Boleto'].map((m) => (
                      <div key={m} className="flex items-center gap-2 rounded-lg border border-[#1a1233]/12 px-2.5 py-2">
                        <span className="h-3 w-3 rounded-[3px] bg-[#1a1233]/12"></span>
                        <span className="text-[11px] text-[#1a1233]/70">{m}</span>
                      </div>
                    ))}

                    <div className="flex flex-wrap gap-1 pt-0.5">
                      {['🔒 SSL 256-bit','🛡️ Antifraude','💳 Pagamento seguro'].map((x) => (
                        <span key={x} className="rounded-full bg-[#1a1233]/[0.05] px-2 py-0.5 text-[8.5px] text-[#1a1233]/55">{x}</span>
                      ))}
                    </div>

                    <div className="rounded-lg border border-violet-200 bg-violet-50/70 px-2.5 py-1.5">
                      <div className="text-[10px] font-semibold text-violet-900">Dinheiro de volta em 30 dias</div>
                      <div className="text-[9px] text-violet-900/60">Se não amar, devolvemos 100% do valor pago.</div>
                    </div>

                    <div className="border-t border-dashed border-[#1a1233]/12 pt-2">
                      <div className="text-center text-[8.5px] font-semibold uppercase tracking-[0.14em] text-[#1a1233]/40">Rodapé</div>
                      <div className="mt-1 flex justify-center gap-1">
                        {['PIX','Cartão','Boleto'].map((m) => (
                          <span key={m} className="rounded bg-[#1a1233]/[0.06] px-1.5 py-0.5 text-[8px] font-bold text-[#1a1233]/55">{m}</span>
                        ))}
                      </div>
                    </div>
                  </div>

                  {/* coluna do resumo */}
                  <div className="space-y-2">
                    <AddBloco>arraste para cá</AddBloco>
                    <div className="rounded-lg border border-[#1a1233]/10 p-2.5">
                      <div className="h-2 w-3/4 rounded bg-[#1a1233]/[0.08]"></div>
                      <div className="mt-2 flex justify-between text-[10px] text-[#1a1233]/55"><span>Subtotal</span><span className="tabular-nums">R$ 989,90</span></div>
                      <div className="mt-1.5 flex items-baseline justify-between border-t border-[#1a1233]/[0.08] pt-1.5">
                        <span className="text-[11px] font-semibold">Total</span>
                        <span className="text-[13px] font-bold tabular-nums">R$ 1.024,80</span>
                      </div>
                    </div>
                    {/* Bloco "Cupom desbloqueável" — Conversão & gatilhos */}
                    <Cupom T={T} />
                    <AddBloco />
                  </div>
                </div>

                <div className="pt-2 text-center font-mono text-[9.5px] text-[#1a1233]/40">
                  Desktop · 3 etapas · {inserido ? 10 : 9} blocos
                </div>
              </div>

              {/* ---------- Painel Bloco / Tema ---------- */}
              <aside className="hidden overflow-hidden border-l border-[#1a1233]/10 bg-white p-3.5 lg:block">
                <div className="grid grid-cols-2 gap-0.5 rounded-lg bg-[#1a1233]/[0.05] p-0.5 text-[11px] font-medium">
                  <span className="grid h-6 place-items-center rounded-md text-[#1a1233]/50">Bloco</span>
                  <span className="grid h-6 place-items-center rounded-md bg-white shadow-sm">Tema</span>
                </div>

                <div className="mt-4 text-[10px] font-semibold uppercase tracking-[0.12em] text-[#1a1233]/55">Templates por nicho</div>
                <p className="mt-1.5 text-[10px] leading-snug text-[#1a1233]/55">
                  Um clique aplica paleta + gatilhos já configurados para o nicho. Os blocos essenciais não são afetados.
                </p>
                <div className="mt-2.5 grid grid-cols-2 gap-2">
                  {NICHOS.map((t) => (
                    <div key={t.n} className="rounded-xl border border-[#1a1233]/10 p-1.5">
                      <div className="flex h-7 items-center justify-center gap-1.5 rounded-lg"
                           style={{ background: t.bg, border:'1px solid rgba(26,18,51,.06)' }}>
                        <span className="h-2.5 w-2.5 rounded-full" style={{ background: t.a }}></span>
                        <span className="h-2.5 w-2.5 rounded-full" style={{ background: t.b }}></span>
                      </div>
                      <div className="mt-1 text-[9.5px] font-semibold leading-tight">{t.n}</div>
                    </div>
                  ))}
                </div>

                <div className="mt-4 text-[10px] font-semibold uppercase tracking-[0.12em] text-[#1a1233]/55">Presets de marca</div>
                <p className="mt-1.5 text-[10px] leading-snug text-[#1a1233]/55">
                  Aplique um visual completo em um clique. Reflete no checkout na hora.
                </p>

                <div className="mt-3 grid grid-cols-2 gap-2">
                  {PRESETS.map((p, i) => {
                    const alvo = i === PRESET_ALVO;
                    const ativo = alvo && tematizado;
                    return (
                      <div key={p.n} ref={alvo ? reg('preset') : undefined}
                        className="rounded-xl border p-2"
                        style={{
                          borderColor: ativo ? '#7c3aed' : 'rgba(26,18,51,.10)',
                          boxShadow: ativo ? '0 0 0 2px rgba(124,58,237,.18)' : 'none',
                          transform: `scale(${apertado && etapa === 9 && alvo ? 0.94 : 1})`,
                          transition: 'transform .16s cubic-bezier(.2,.7,.2,1), border-color .3s ease, box-shadow .3s ease',
                        }}>
                        <div className="flex h-9 items-center justify-center gap-1.5 rounded-lg"
                             style={{ background: p.escuro ? '#1a1233' : (p.bg || '#fff'),
                                      border: p.escuro ? 'none' : '1px solid rgba(26,18,51,.06)' }}>
                          <span className="h-3 w-3 rounded-full" style={{ background: p.a }}></span>
                          <span className="h-3 w-3 rounded-full" style={{ background: p.b }}></span>
                        </div>
                        <div className="mt-1.5 text-[10.5px] font-semibold leading-tight">{p.n}</div>
                      </div>
                    );
                  })}
                </div>

                <div className="mt-3 text-[9.5px] text-[#1a1233]/45">
                  {tematizado ? 'Preset “Noturno” aplicado.' : 'Tema personalizado — não corresponde a nenhum preset.'}
                </div>

                <div className="mt-4 text-[10px] font-semibold uppercase tracking-[0.12em] text-[#1a1233]/55">Barra de anúncio</div>
                <div className="mt-2 flex items-center justify-between rounded-lg border border-[#1a1233]/10 px-2.5 py-2">
                  <span className="text-[10.5px] text-[#1a1233]/70">Exibir barra no topo</span>
                  <span className="flex h-4 w-7 items-center rounded-full bg-violet-600 px-0.5">
                    <span className="ml-auto h-3 w-3 rounded-full bg-white"></span>
                  </span>
                </div>
              </aside>

              {!reduzido && (
                <Cursor x={cursor.x} y={cursor.y} visivel={etapa >= 1} apertado={apertado} arrastando={arrastando} />
              )}
            </div>
            </div>
           </div>
          </div>

          <div className="reveal mt-9 flex flex-col sm:flex-row gap-3">
            <a href="https://app.cartroi.com/login"
               className="shine-btn group inline-flex items-center justify-center gap-2 rounded-xl bg-gradient-to-b from-violet-500 to-violet-700 px-6 py-3.5 font-medium text-white shadow-glow-violet transition-shadow hover:shadow-[0_0_80px_-5px_rgba(167,139,250,0.6)]">
              Abrir o editor grátis
              <II.ArrowRight size={18} className="transition-transform group-hover:translate-x-0.5"/>
            </a>
            <a href="#oferta"
               className="inline-flex items-center justify-center gap-2 rounded-xl border border-white/10 px-6 py-3.5 font-medium text-violet-100 transition-colors hover:border-cyan-300/40 hover:bg-white/[0.03]">
              Ver a oferta de 0,5%
            </a>
          </div>

          <p className="mt-6 font-mono text-[11.5px] text-violet-200/40">
            Interface reproduzida de app.cartroi.com/editor/checkout.
          </p>
        </div>
      </section>
    );
  }

  setTimeout(() => window.__attachReveal && window.__attachReveal(), 50);

  Object.assign(window, { EditorEmUso });
})();
