// Scene 3 — Editor visual: drag & drop canvas builds a day, then the
// WhatsApp message auto-generates on the right.

function SceneEditor({ start, end }) {
  return (
    <Sprite start={start} end={end}>
      {({ localTime, duration }) => {
        const appT = clamp(localTime / 0.6, 0, 1);
        const app = Easing.easeOutCubic(appT);

        const exitT = clamp((localTime - (duration - 0.5)) / 0.5, 0, 1);
        const exit = Easing.easeInCubic(exitT);

        return (
          <div style={{
            position: 'absolute', inset: 0,
            background: OP_COLORS.bg,
            opacity: 1 - exit,
            transform: `scale(${0.98 + 0.02 * app}) translateY(${exit * -30}px)`,
          }}>
            <ChapterTag index={1} total={3} title="Editor visual del día" />

            {/* App chrome */}
            <AppWindow localTime={localTime}>
              <EditorCanvas localTime={localTime} />
              <PreviewPanel localTime={localTime} />
            </AppWindow>

            {/* Caption */}
            <Caption
              localTime={localTime}
              startAt={0.8}
              text="Armá el día arrastrando."
              sub="El mensaje de WhatsApp se genera solo."
            />
          </div>
        );
      }}
    </Sprite>
  );
}

// ── App window shell ─────────────────────────────────────────
function AppWindow({ children, localTime }) {
  const t = clamp(localTime / 0.6, 0, 1);
  const e = Easing.easeOutCubic(t);
  return (
    <div style={{
      position: 'absolute',
      left: 160, top: 140,
      width: 1600, height: 820,
      background: OP_COLORS.surface,
      borderRadius: 18,
      border: `1px solid ${OP_COLORS.border2}`,
      boxShadow: '0 30px 80px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.02) inset',
      overflow: 'hidden',
      opacity: e,
      transform: `translateY(${(1 - e) * 30}px)`,
    }}>
      {/* Top bar */}
      <div style={{
        display: 'flex', alignItems: 'center',
        padding: '14px 20px',
        borderBottom: `1px solid ${OP_COLORS.border}`,
        background: OP_COLORS.bg2,
      }}>
        <div style={{ display: 'flex', gap: 8 }}>
          {['#ef4444', '#eab308', '#22c55e'].map((c) => (
            <div key={c} style={{ width: 12, height: 12, borderRadius: '50%', background: c }} />
          ))}
        </div>
        <div style={{
          marginLeft: 22, display: 'flex', alignItems: 'center', gap: 10,
          color: OP_COLORS.textDim, fontFamily: SANS, fontSize: 13,
        }}>
          <LogoMark size={22} />
          <span style={{ color: OP_COLORS.text, fontWeight: 600 }}>ObraPlanner</span>
          <span style={{ color: OP_COLORS.textMute }}>/ Editor</span>
          <span style={{ color: OP_COLORS.textMute }}>·</span>
          <span style={{ color: OP_COLORS.textMute }}>mié 15 abr</span>
        </div>
        <div style={{ marginLeft: 'auto', display: 'flex', gap: 10 }}>
          <TopBtn>Guardar</TopBtn>
          <TopBtn primary>Enviar por WhatsApp</TopBtn>
        </div>
      </div>

      {/* Body: 3 panels */}
      <div style={{ display: 'flex', height: 'calc(100% - 56px)' }}>
        {children}
      </div>
    </div>
  );
}

function TopBtn({ children, primary }) {
  return (
    <div style={{
      padding: '7px 14px', borderRadius: 8,
      fontFamily: SANS, fontSize: 13, fontWeight: 600,
      background: primary ? OP_COLORS.green : 'transparent',
      color: primary ? '#fff' : OP_COLORS.textDim,
      border: `1px solid ${primary ? OP_COLORS.green : OP_COLORS.border2}`,
    }}>{children}</div>
  );
}

// ── Editor canvas (the drag & drop map) ──────────────────────────
// Layout plan (canvas area ~1020×760 after sidebar):
//   OBRAS     column at x=200 (narrow nodes, 190w)
//   PERSONAL  column at x=500 (narrow nodes, 170w)
//   MOV/EQUI  column at x=800 (narrow nodes, 190w)
// Each node anchors connections to its right-center or left-center edge.
// Rows are spaced generously so nothing overlaps.
function EditorCanvas({ localTime }) {
  const appear = (at) => Easing.easeOutBack(clamp((localTime - at) / 0.35, 0, 1));

  // Build timings
  const t1=1.0, t2=1.3, t3=1.6, t4=2.0, t5=2.3, t6=2.55, t7=2.85, t8=3.3, t9=3.6, t10=3.9;

  // Chofer-picker timing (for M2 — Utilitario 07 — since its driver gets animated)
  const choferPickStart = 3.05;
  const choferPickEnd   = 3.45;
  const choferPickT = clamp((localTime - choferPickStart) / (choferPickEnd - choferPickStart), 0, 1);

  // Node geometry constants — single source of truth
  const OBRA_W = 210, PERS_W = 180, MOV_W = 210;
  const NODE_H = 62; // compact card height used for edge anchoring

  // Positions (x = left, y = top)
  const obraX = 200, persX = 520, movX  = 820;

  const nodes = {
    O1:  { x: obraX,  y:  90, kind:'obra', w: OBRA_W, title:'Av. San Martín 1250', sub:'ejec · 64%', appear: appear(t1) },
    O2:  { x: obraX,  y: 310, kind:'obra', w: OBRA_W, title:'Edif. Puerto Norte',  sub:'ejec · 82%', appear: appear(t4) },
    O3:  { x: obraX,  y: 530, kind:'obra', w: OBRA_W, title:'Ruta 11 · Km 42',     sub:'ejec · 30%', appear: appear(t8) },

    P1:  { x: persX,  y:  70, kind:'pers', w: PERS_W, title:'M. Ruiz',   sub:'albañil',  appear: appear(t2) },
    P2:  { x: persX,  y: 250, kind:'pers', w: PERS_W, title:'J. Gómez',  sub:'oficial',  appear: appear(t5) },
    P3:  { x: persX,  y: 340, kind:'pers', w: PERS_W, title:'A. López',  sub:'ayudante', appear: appear(t6) },
    P4:  { x: persX,  y: 560, kind:'pers', w: PERS_W, title:'D. Ponce',  sub:'chofer',   appear: appear(t10) },

    M1:  { x: movX,   y:  90, kind:'moto', w: MOV_W,  title:'Camioneta 03', sub:'AB 421 JK', chofer:'M. Torres', choferPickT: 1,        appear: appear(t3) },
    M2:  { x: movX,   y: 310, kind:'moto', w: MOV_W,  title:'Utilitario 07',sub:'MM 881',    chofer:'F. Rivas',  choferPickT: choferPickT, appear: appear(t7) },
    E1:  { x: movX,   y: 530, kind:'equi', w: MOV_W,  title:'Grúa 210T',    sub:'equipo',    chofer:'D. Ponce',  choferPickT: 1,        appear: appear(t9) },
  };

  // Connection list: from-node right edge → to-node left edge
  const conns = [
    ['O1','P1'], ['O1','M1'],
    ['O2','P2'], ['O2','P3'], ['O2','M2'],
    ['O3','E1'], ['O3','P4'],
  ];

  const colorFor = (kind) => kind === 'pers' ? OP_COLORS.greenLight
                         : kind === 'moto' ? OP_COLORS.amber
                         : kind === 'equi' ? OP_COLORS.orange
                         : OP_COLORS.blueLight;

  return (
    <div style={{
      flex: 1,
      position: 'relative',
      background: `
        radial-gradient(circle at 30% 40%, rgba(37,99,235,0.05), transparent 60%),
        ${OP_COLORS.bg}`,
      backgroundImage: `radial-gradient(${OP_COLORS.border} 1px, transparent 1px)`,
      backgroundSize: '24px 24px',
      overflow: 'hidden',
    }}>
      <EditorSidebar localTime={localTime} />

      {/* Organic curved connections */}
      <svg style={{
        position:'absolute', left: 160, top: 0,
        width: 'calc(100% - 160px)', height: '100%',
        pointerEvents:'none',
      }} viewBox="0 0 1020 760" preserveAspectRatio="none">
        {conns.map(([from, to], i) => {
          const a = nodes[from], b = nodes[to];
          // anchor from a's right-center to b's left-center (in sidebar-adjusted coords)
          const x1 = (a.x - 160) + a.w;
          const y1 = a.y + NODE_H / 2;
          const x2 = (b.x - 160);
          const y2 = b.y + NODE_H / 2;
          const ap = Math.min(a.appear, b.appear);
          return (
            <OrganicEdge key={i} x1={x1} y1={y1} x2={x2} y2={y2}
                         appear={ap} color={colorFor(b.kind)} />
          );
        })}
      </svg>

      {/* Nodes */}
      {Object.entries(nodes).map(([k, n]) => (
        <Node key={k} appear={n.appear} x={n.x} y={n.y} w={n.w}
              kind={n.kind} title={n.title} sub={n.sub}
              chofer={n.chofer} choferPickT={n.choferPickT} />
      ))}

      {/* Chofer picker popover over M2 */}
      <ChoferPicker x={movX + MOV_W + 16} y={300}
                    startT={choferPickStart} endT={choferPickEnd}
                    localTime={localTime} />

      <DraggingCursor localTime={localTime} />

      <ColumnHeader x={obraX} y={30} label="OBRAS"         color={OP_COLORS.blueLight} />
      <ColumnHeader x={persX} y={30} label="PERSONAL"      color={OP_COLORS.greenLight} />
      <ColumnHeader x={movX}  y={30} label="MOV / EQUIPOS" color={OP_COLORS.amber} />
    </div>
  );
}

function ColumnHeader({ x, y, label, color }) {
  return (
    <div style={{
      position: 'absolute', left: x, top: y,
      fontFamily: MONO, fontSize: 11, fontWeight: 600,
      color, letterSpacing: '0.2em',
      padding: '6px 10px',
      border: `1px solid ${color}44`,
      borderRadius: 999,
      background: `${color}14`,
    }}>{label}</div>
  );
}

function OrganicEdge({ x1, y1, x2, y2, appear, color }) {
  if (appear <= 0) return null;
  // Bezier horizontally-biased with slight vertical jitter for organic feel
  const dx = x2 - x1;
  const c1x = x1 + dx * 0.55;
  const c2x = x2 - dx * 0.55;
  const c1y = y1;
  const c2y = y2;
  const d = `M ${x1} ${y1} C ${c1x} ${c1y}, ${c2x} ${c2y}, ${x2} ${y2}`;
  // Dash-in reveal
  const len = 800;
  return (
    <g>
      <path d={d}
            stroke={color} strokeOpacity={0.55 * appear}
            strokeWidth={1.8}
            fill="none" strokeLinecap="round"
            strokeDasharray={len}
            strokeDashoffset={len * (1 - appear)} />
      {/* glow */}
      <path d={d}
            stroke={color} strokeOpacity={0.15 * appear}
            strokeWidth={5}
            fill="none" strokeLinecap="round"
            strokeDasharray={len}
            strokeDashoffset={len * (1 - appear)} />
      {/* end dot */}
      {appear > 0.95 && (
        <circle cx={x2} cy={y2} r={3} fill={color} opacity={0.9} />
      )}
    </g>
  );
}

function Node({ appear, x, y, w = 190, kind, title, sub, chofer, choferPickT }) {
  if (appear <= 0) return null;
  const colors = {
    obra: { bg: '#1e3a8a', border: '#3b82f6', dot: OP_COLORS.blueLight,  label: 'obra' },
    pers: { bg: '#14532d', border: '#22c55e', dot: OP_COLORS.greenLight, label: 'personal' },
    moto: { bg: '#78350f', border: '#eab308', dot: OP_COLORS.amber,      label: 'movilidad' },
    equi: { bg: '#7c2d12', border: '#f97316', dot: OP_COLORS.orange,     label: 'equipo' },
  }[kind];

  const scale = 0.6 + 0.4 * appear;
  const showChofer = (kind === 'moto' || kind === 'equi') && chofer;
  const choferShow = choferPickT != null ? clamp(choferPickT, 0, 1) : 1;

  return (
    <div style={{
      position: 'absolute', left: x, top: y,
      width: w,
      padding: '10px 12px',
      background: colors.bg,
      border: `1px solid ${colors.border}`,
      borderRadius: 10,
      color: '#fff',
      fontFamily: SANS,
      transform: `scale(${scale})`,
      opacity: clamp(appear, 0, 1),
      transformOrigin: 'center',
      boxShadow: `0 8px 24px ${colors.border}22, 0 0 0 1px ${colors.border}33 inset`,
    }}>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 6,
        fontSize: 9, fontFamily: MONO, letterSpacing: '0.18em',
        opacity: 0.75, textTransform: 'uppercase', marginBottom: 2,
      }}>
        <span style={{
          width: 5, height: 5, borderRadius: '50%',
          background: colors.dot, boxShadow: `0 0 6px ${colors.dot}`,
        }} />
        {colors.label}
      </div>
      <div style={{ fontSize: 14, fontWeight: 600, letterSpacing: '-0.01em', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{title}</div>
      <div style={{ fontSize: 11, opacity: 0.7, marginTop: 1 }}>{sub}</div>
      {showChofer && (
        <div style={{
          marginTop: 8, paddingTop: 8,
          borderTop: `1px dashed ${colors.border}66`,
          display: 'flex', alignItems: 'center', gap: 6,
          fontSize: 11,
          opacity: choferShow,
          transform: `translateY(${(1 - choferShow) * 6}px)`,
        }}>
          <svg width={11} height={11} viewBox="0 0 16 16" fill="none">
            <circle cx="8" cy="5" r="2.5" stroke="#fff" strokeWidth="1.2"/>
            <path d="M3 13c0-2.5 2.2-4.5 5-4.5s5 2 5 4.5" stroke="#fff" strokeWidth="1.2" strokeLinecap="round"/>
          </svg>
          <span style={{ opacity: 0.75, fontSize: 9, fontFamily: MONO, letterSpacing: '0.12em', textTransform: 'uppercase' }}>chofer</span>
          <span style={{ marginLeft: 'auto', fontWeight: 600, color: colors.dot }}>{chofer}</span>
        </div>
      )}
    </div>
  );
}

function DraggingCursor({ localTime }) {
  // Active between 2.2s and 2.9s — cursor drags "A. López" into place
  const active = localTime >= 2.0 && localTime <= 2.9;
  if (!active) return null;
  const t = clamp((localTime - 2.0) / 0.9, 0, 1);
  const x = interpolate([0, 0.5, 1], [900, 650, 520], Easing.easeInOutCubic)(t);
  const y = interpolate([0, 0.5, 1], [200, 320, 360], Easing.easeInOutCubic)(t);
  return (
    <>
      {/* Ghost of the item being dragged */}
      <div style={{
        position: 'absolute', left: x - 20, top: y - 14,
        padding: '6px 10px',
        background: `${OP_COLORS.green}dd`,
        border: `1px solid ${OP_COLORS.greenLight}`,
        borderRadius: 8,
        color: '#fff', fontFamily: SANS, fontSize: 12, fontWeight: 600,
        boxShadow: '0 8px 20px rgba(0,0,0,0.5)',
        opacity: 0.9,
      }}>A. López</div>
      {/* Cursor */}
      <svg style={{ position: 'absolute', left: x, top: y }} width={24} height={24} viewBox="0 0 24 24">
        <path d="M4 2 L4 18 L9 14 L12 22 L15 21 L12 13 L19 13 Z" fill="#fff" stroke="#000" strokeWidth="1" />
      </svg>
    </>
  );
}

function EditorSidebar({ localTime }) {
  // Each row lights up when its node gets added to the canvas
  // Timings mirror the node appear timings in EditorCanvas
  const rows = [
    { name: 'Ruiz M.',   pickT: 1.3 },
    { name: 'Gómez J.',  pickT: 2.3 },
    { name: 'López A.',  pickT: 2.55 },
    { name: 'Ponce D.',  pickT: 3.9 },
    { name: 'Rivas E.',  pickT: 3.05 }, // chofer picked for Utilitario 07
    { name: 'Suárez C.', pickT: null },
  ];
  return (
    <div style={{
      position: 'absolute', left: 0, top: 0, bottom: 0,
      width: 160,
      background: OP_COLORS.bg2,
      borderRight: `1px solid ${OP_COLORS.border}`,
      padding: 16,
      fontFamily: SANS, color: OP_COLORS.textDim,
      fontSize: 12,
    }}>
      <div style={{
        display: 'flex', gap: 4, marginBottom: 12,
        padding: 2, background: OP_COLORS.surface,
        borderRadius: 6, fontSize: 10,
      }}>
        {['Obras', 'Pers.', 'Mov.'].map((tab, i) => (
          <div key={i} style={{
            flex: 1, padding: '6px 6px', textAlign: 'center',
            borderRadius: 4,
            background: i === 1 ? OP_COLORS.surface2 : 'transparent',
            color: i === 1 ? OP_COLORS.text : OP_COLORS.textMute,
            fontWeight: 600,
          }}>{tab}</div>
        ))}
      </div>
      {rows.map((r, i) => {
        // Pulse animation window: 0.4s flash starting at pickT
        const since = r.pickT != null ? localTime - r.pickT : -1;
        const pulse = since >= 0 && since < 0.5 ? 1 - since / 0.5 : 0;
        const picked = r.pickT != null && localTime >= r.pickT;
        const bg = picked
          ? `rgba(34,197,94,${0.12 + pulse * 0.35})`
          : 'transparent';
        const borderC = picked
          ? `rgba(34,197,94,${0.4 + pulse * 0.5})`
          : 'transparent';
        return (
          <div key={i} style={{
            padding: '6px 8px',
            marginBottom: 3,
            borderRadius: 4,
            background: bg,
            border: `1px solid ${borderC}`,
            color: picked ? OP_COLORS.text : OP_COLORS.textMute,
            fontSize: 11,
            display: 'flex', alignItems: 'center', justifyContent: 'space-between',
            transform: `translateX(${pulse * 3}px)`,
            transition: 'none',
          }}>
            <span style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              {picked && (
                <span style={{
                  width: 5, height: 5, borderRadius: '50%',
                  background: '#22c55e',
                  boxShadow: `0 0 ${4 + pulse * 6}px #22c55e`,
                }} />
              )}
              {r.name}
            </span>
            <span style={{ fontSize: 9, opacity: picked ? 0.8 : 0.4 }}>
              {picked ? '✓' : '↕'}
            </span>
          </div>
        );
      })}
    </div>
  );
}

// ── Chofer picker popover (appears briefly next to M2) ───────────────
function ChoferPicker({ x, y, startT, endT, localTime }) {
  if (localTime < startT || localTime > endT + 0.1) return null;
  const t = clamp((localTime - startT) / (endT - startT), 0, 1);
  const appear = Easing.easeOutCubic(clamp(t / 0.25, 0, 1));
  const exit   = Easing.easeInCubic(clamp((t - 0.85) / 0.15, 0, 1));
  const opacity = appear * (1 - exit);

  // Highlight travels through the list and lands on "F. Rivas" (index 2)
  const names = ['M. Torres', 'L. Vega', 'F. Rivas', 'D. Ponce'];
  const highlightIdx = t < 0.35 ? 0 : t < 0.55 ? 1 : 2;

  return (
    <div style={{
      position: 'absolute', left: x, top: y,
      width: 180,
      background: OP_COLORS.bg2,
      border: `1px solid ${OP_COLORS.border}`,
      borderRadius: 8,
      boxShadow: '0 12px 30px rgba(0,0,0,0.5)',
      padding: 6,
      fontFamily: SANS,
      opacity,
      transform: `translate(${-12 + appear * 12}px, ${-10 + appear * 10}px) scale(${0.9 + 0.1 * appear})`,
      transformOrigin: 'top left',
      zIndex: 50,
    }}>
      <div style={{
        fontSize: 9, fontFamily: MONO, letterSpacing: '0.14em',
        textTransform: 'uppercase', color: OP_COLORS.textMute,
        padding: '4px 8px 6px',
      }}>Asignar chofer</div>
      {names.map((n, i) => (
        <div key={i} style={{
          padding: '6px 8px',
          borderRadius: 4,
          background: i === highlightIdx ? 'rgba(59,130,246,0.2)' : 'transparent',
          border: i === highlightIdx ? '1px solid rgba(59,130,246,0.4)' : '1px solid transparent',
          color: i === highlightIdx ? '#fff' : OP_COLORS.textDim,
          fontSize: 11,
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          marginBottom: 2,
        }}>
          <span>{n}</span>
          {i === 2 && t > 0.6 && <span style={{ color: '#22c55e' }}>✓</span>}
        </div>
      ))}
    </div>
  );
}

// ── WhatsApp preview panel (right side) ───────────────
function PreviewPanel({ localTime }) {
  const emojiMode = (window.__opTweaks && window.__opTweaks.emoji) !== false;
  // The message "types out" as nodes are added
  const E = emojiMode
    ? { obra: '🏗 ', pers: '👷 ', mov: '🚐 ', equi: '⚙ ' }
    : { obra: '', pers: '• ', mov: '→ ', equi: '» ' };

  const messageLines = [
    { t: 1.1, s: '*Programación del día — mié 15/04*' },
    { t: 1.2, s: '' },
    { t: 1.2, s: `${E.obra}*Av. San Martín 1250*` },
    { t: 1.35,s: `${E.pers}M. Ruiz` },
    { t: 1.65,s: `${E.mov}Camioneta 03 (AB 421 JK) — chofer: M. Torres` },
    { t: 2.1, s: '' },
    { t: 2.1, s: `${E.obra}*Edificio Puerto Norte*` },
    { t: 2.35,s: `${E.pers}J. Gómez, A. López` },
    { t: 2.9, s: `${E.mov}Utilitario 07` },
    { t: 3.45,s: `     ↳ chofer: F. Rivas` },
    { t: 3.6, s: '' },
    { t: 3.6, s: `${E.obra}*Ruta 11 Km 42*` },
    { t: 3.75,s: `${E.equi}Grúa 210T — chofer: D. Ponce` },
    { t: 4.2, s: '' },
    { t: 4.2, s: '_Enviado desde ObraPlanner_' },
  ];

  // Panel appear
  const panelAppear = Easing.easeOutCubic(clamp((localTime - 0.4) / 0.5, 0, 1));

  return (
    <div style={{
      width: 420, flexShrink: 0,
      background: OP_COLORS.bg2,
      borderLeft: `1px solid ${OP_COLORS.border}`,
      display: 'flex', flexDirection: 'column',
      opacity: panelAppear,
      transform: `translateX(${(1 - panelAppear) * 40}px)`,
    }}>
      <div style={{
        padding: '14px 18px',
        borderBottom: `1px solid ${OP_COLORS.border}`,
        display: 'flex', alignItems: 'center', gap: 10,
        fontFamily: SANS, color: OP_COLORS.text, fontWeight: 600,
      }}>
        <svg width={18} height={18} viewBox="0 0 24 24" fill="#22c55e">
          <path d="M12 0C5.4 0 0 5.4 0 12c0 2.1.6 4.2 1.6 6L0 24l6.2-1.6c1.8 1 3.8 1.5 5.8 1.5 6.6 0 12-5.4 12-12S18.6 0 12 0z"/>
        </svg>
        Vista previa — WhatsApp
        <span style={{
          marginLeft: 'auto',
          fontSize: 11, color: OP_COLORS.textMute, fontFamily: MONO,
        }}>auto-generado</span>
      </div>

      <div style={{
        flex: 1,
        padding: 18,
        overflow: 'hidden',
        fontFamily: SANS,
        color: OP_COLORS.text,
        fontSize: 14, lineHeight: 1.55,
      }}>
        {messageLines.map((ln, i) => {
          const appeared = localTime >= ln.t;
          if (!appeared) return null;
          const t = clamp((localTime - ln.t) / 0.2, 0, 1);
          const isBold = ln.s.startsWith('*') || ln.s.includes('*');
          const clean = ln.s.replace(/\*/g, '').replace(/_/g, '');
          const italic = ln.s.startsWith('_');

          return (
            <div key={i} style={{
              opacity: t,
              transform: `translateY(${(1 - t) * 4}px)`,
              fontWeight: isBold ? 700 : 400,
              fontStyle: italic ? 'italic' : 'normal',
              color: italic ? OP_COLORS.textMute : OP_COLORS.text,
              minHeight: clean === '' ? 10 : 'auto',
            }}>
              {clean || '\u00A0'}
            </div>
          );
        })}

        {/* Blinking caret */}
        {localTime < 4.4 && (
          <span style={{
            display: 'inline-block',
            width: 8, height: 16,
            background: OP_COLORS.greenLight,
            opacity: Math.sin(localTime * 8) > 0 ? 1 : 0.2,
            verticalAlign: 'text-top',
            marginTop: 2,
          }} />
        )}
      </div>

      {/* Bottom CTA — one click to WhatsApp */}
      <OneClickWhatsApp localTime={localTime} />
    </div>
  );
}

// The cursor, the click, the WhatsApp sent confirmation overlay
function OneClickWhatsApp({ localTime }) {
  const clickAt = 4.6; // inside editor scene (which is 6s long)
  const pulse = localTime > 4.2 && localTime < clickAt;
  const clicked = localTime > clickAt && localTime < clickAt + 0.25;
  const sentOpenT = clamp((localTime - (clickAt + 0.15)) / 0.4, 0, 1);

  return (
    <>
      <div style={{
        padding: 14,
        borderTop: `1px solid ${OP_COLORS.border}`,
        display: 'flex', gap: 8,
        position: 'relative',
      }}>
        <div style={{
          flex: 1,
          padding: '12px 14px',
          background: OP_COLORS.green,
          color: '#fff',
          borderRadius: 8,
          textAlign: 'center',
          fontFamily: SANS, fontWeight: 700, fontSize: 13,
          display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
          boxShadow: pulse
            ? `0 0 0 ${Math.abs(Math.sin(localTime * 10)) * 8 + 2}px ${OP_COLORS.green}44`
            : 'none',
          transform: clicked ? 'scale(0.96)' : 'scale(1)',
          transition: 'transform 0.12s',
        }}>
          <svg width={16} height={16} viewBox="0 0 24 24" fill="#fff">
            <path d="M12 0C5.4 0 0 5.4 0 12c0 2.1.6 4.2 1.6 6L0 24l6.2-1.6c1.8 1 3.8 1.5 5.8 1.5 6.6 0 12-5.4 12-12S18.6 0 12 0z"/>
          </svg>
          Enviar por WhatsApp
        </div>
        {localTime > 4.1 && localTime < clickAt + 0.8 && (
          <AnimatedCursor localTime={localTime} clickAt={clickAt} />
        )}
      </div>

      {/* WhatsApp "sent" toast that slides up over the button */}
      {sentOpenT > 0 && (
        <div style={{
          position: 'absolute',
          left: 16, right: 16, bottom: 80,
          padding: '14px 16px',
          background: '#005c4b',
          borderRadius: 12,
          color: '#fff', fontFamily: SANS,
          boxShadow: '0 20px 60px rgba(0,0,0,0.6)',
          opacity: Easing.easeOutCubic(sentOpenT),
          transform: `translateY(${(1 - sentOpenT) * 20}px)`,
          display: 'flex', alignItems: 'center', gap: 12,
        }}>
          <div style={{
            width: 36, height: 36, borderRadius: '50%', background: '#00a884',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontWeight: 700, fontSize: 15,
          }}>O</div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 13, fontWeight: 700 }}>Obras — grupo</div>
            <div style={{ fontSize: 12, opacity: 0.85 }}>Programación enviada ✓✓</div>
          </div>
          <div style={{
            fontFamily: MONO, fontSize: 11,
            color: '#a5d6c4', letterSpacing: '0.05em',
          }}>1 clic</div>
        </div>
      )}
    </>
  );
}

function AnimatedCursor({ localTime, clickAt }) {
  // Slide from top-right toward the button, land at click time
  const t = clamp((localTime - 4.1) / 0.5, 0, 1);
  const ease = Easing.easeOutCubic(t);
  // Button center is around x=170 (inside the 420-wide panel), y=20 (within this inset cont.)
  const x = 340 - ease * 180;
  const y = -80 + ease * 90;
  const clicked = localTime > clickAt && localTime < clickAt + 0.25;
  return (
    <svg style={{
      position: 'absolute',
      left: x, top: y,
      transform: clicked ? 'scale(0.85)' : 'scale(1)',
      transition: 'transform 0.1s',
      pointerEvents: 'none',
    }} width={22} height={22} viewBox="0 0 24 24">
      <path d="M4 2 L4 18 L9 14 L12 22 L15 21 L12 13 L19 13 Z" fill="#fff" stroke="#000" strokeWidth="1" />
    </svg>
  );
}

// ── Caption below ───────────
function Caption({ localTime, startAt, text, sub }) {
  const t = clamp((localTime - startAt) / 0.5, 0, 1);
  return (
    <div style={{
      position: 'absolute',
      left: 160, bottom: 40,
      opacity: Easing.easeOutCubic(t),
      transform: `translateY(${(1 - t) * 12}px)`,
      fontFamily: SANS,
    }}>
      <div style={{
        fontSize: 38, fontWeight: 700, color: OP_COLORS.text,
        letterSpacing: '-0.02em',
      }}>{text}</div>
      <div style={{
        fontSize: 18, color: OP_COLORS.textDim, marginTop: 6,
      }}>{sub}</div>
    </div>
  );
}

Object.assign(window, { SceneEditor });
