// === Escena 02 — «EL GESTO» · CLÍMAX de la pieza · 27.50 s (toma del 13/08) ===
// LOCUCIÓN (audio/escena-02.mp3): clic derecho ENCIMA del nombre del campo → no sobre el cuadro:
// sobre el nombre → (break 0.4 s) → sale una sola opción: historial de cambios → y se abre esto →
// quién → cuándo → y lo que había antes → el valor viejo, tachado en rojo → el nuevo, en verde →
// tres cambios, cada uno con su nombre y su hora → ¿quién ha tocado esto? clic derecho en el
// nombre del campo → y este gesto no vive solo aquí.
//
// EN PANTALLA (plan, Fase 3): «la misma ficha, AMPLIADA sobre la fila del campo». Aquí eso son dos
// instancias del MISMO componente <FichaProducto/>:
//   · la ficha COMPLETA al fondo, atenuada — es literalmente la de la escena 01 (persona continua:
//     mismo registro, mismos campos, mismo formulario), y es lo que hace que el plano llegue a
//     y≈995 en vez de quedarse en una tira en el centro;
//   · encima, la misma ficha en modo 'zoom' —solo la fila del protagonista, a 28/44 px— colocada
//     justo sobre la fila que amplía: una lupa, no una segunda ficha.
// Ni el diálogo, ni el menú, ni los anillos se pintan aquí: son los componentes compartidos de
// scenes/historial.jsx. La ficha tampoco: es scenes/ficha.jsx. Esta escena SOLO los cablea.
//
// COLUMNA SEGURA 4:5 (Fase 5): todo lo que porta información vive en x 568..1352. Las dos fichas
// miden 864 px (528..1392 = el recorte 4:5 exacto) y su contenido cae en los 784 px útiles; el
// diálogo va de 570 a 1350. Fuera de 528..1392 solo ambiente (la marca).
function EscenaHC02({ t }){
  const T = {
    clicDerecho:   0.2,   // "Clic derecho encima" → el puntero viaja a la ETIQUETA (bezier 0.6 s) + anillo de clic derecho
    noElCuadro:    3.3,   // "No sobre el cuadro" → el cuadro del valor se apaga; la etiqueta recibe subrayado azul que SE DIBUJA
    unaSolaOpcion: 6.9,   // "una sola opción" → el menú entra desde el puntero, scale .9→1 easeOutBack; UN item; único overshoot
    abre:          9.5,   // "Y se abre esto" → item resaltado, menú en fade y el diálogo entra desde el punto del menú; el resto al 0.28
    quien:        10.7,   // "Quién." → halo AZUL sobre avatar + nombre de la 1ª entrada
    cuando:       11.2,   // "Cuándo." → el halo se traslada a la fecha; el anterior queda atenuado
    antes:        12.2,   // "lo que había antes" → el halo baja a la fila de valores
    tachado:      14.7,   // "tachado en rojo" → EL MOMENTO: la línea de tachado SE DIBUJA sobre el 1290 de izq a der
    verde:        16.1,   // "El nuevo, en verde" → arrow_forward se dibuja + el 990 verde aterriza (scale 1.12→1)
    tres:         17.9,   // "Tres cambios" → el badge «3 cambios» pulsa UNA vez; entradas 2 y 3 en cascada + sus cabeceras
    unaCosa1:     21.5,   // "¿Quién ha tocado esto" → el diálogo encoge a .80 y sube; ÚNICA COSA mitad 1
    unaCosa2:     22.9,   // "Clic derecho en el nombre del campo" → mitad 2
    noVive:       26.2,   // "no vive solo aquí" → el diálogo se encoge hacia arriba-izquierda (scale .62, 0.7 s)
  };

  // ── Geometría (lienzo 1920×1080) ───────────────────────────────────────────────────────────
  // La ficha COMPLETA y la LUPA van las dos en su colocación por defecto (FICHA_BASE y
  // FICHA_BASE_ZOOM): es la condición para poder leer FICHA_ANCLAS tal cual, sin recalcular.
  const ANC   = FICHA_ANCLAS.zoom.precioEtiquetaTexto;   // las LETRAS «PRECIO DE VENTA» ampliadas
  const PUNT  = { x: ANC.cx, y: ANC.cy };                // el clic derecho cae sobre el TEXTO de la
                                                         // etiqueta: de ahí cuelga el menú del
                                                         // producto (<RadzenLabel>, DnzControl.razor:65)
  const MENU  = { x: ANC.cx, y: ANC.y + ANC.h };         // el menú nace del puntero pero justo BAJO la
                                                         // fila: crece hacia abajo-derecha y así no tapa
                                                         // «Precio de venta», que es lo que este beat
                                                         // acaba de subrayar
  const ITEM  = { x: MENU.x + 170, y: MENU.y + 38 };     // el único item del menú, donde se pulsa
  const DLG   = { x:570, y:90, w:780, h:900 };           // 570..1350 · 90..990 (tabla de la Fase 5)

  // Los retratos, locales y en un solo sitio (nunca una URL remota: el mp4 se captura con Playwright
  // y una imagen que tarde deja el fotograma vacío). Son LOS MISMOS ficheros que usan los cursores
  // de presencia de la escena 01, y el anillo sale de la MISMA constante PRES_RUEDA que los tiñe
  // allí: no pueden desincronizarse. Ese es el remate de la pieza — el espectador acaba de ver tres
  // caras irse sin dejar rastro y aquí reconoce dos de ellas con nombre y hora.
  // LICENCIA CONSCIENTE, declarada también en historial.jsx: DnzHistoricoDialog pinta hoy SIEMPRE la
  // inicial porque su DTO no trae foto. La foto es coherente con AvatarU/FotoUsuarioU del resto del
  // producto (y con UserPresence), no con ese diálogo tal como está hoy.
  const AVATAR = {
    marta:  '/_engine/assets/avatares/marta.jpg',
    javier: '/_engine/assets/avatares/javier.jpg',
  };

  // Las tres entradas de la persona continua. Valores CRUDOS, sin € y sin separadores: el diálogo
  // pinta el valor tal como está guardado (HistoricoService.vb:243-261).
  // `inicial` se queda aunque haya foto: es el plan B del componente y lo que se pintaría si un día
  // esta entrada llegara sin retrato.
  const ENTRADAS = [
    { grupo:'Hoy',         inicial:'M', autor:'Marta Ruiz',  fecha:'18:02',        antes:'1290', despues:'990',
      foto:AVATAR.marta,  borde:PRES_RUEDA.azul  },
    { grupo:'Ayer',        inicial:'J', autor:'Javier Sanz', fecha:'12 ago 09:41', antes:'1350', despues:'1290',
      foto:AVATAR.javier, borde:PRES_RUEDA.verde },
    { grupo:'Esta semana', inicial:'M', autor:'Marta Ruiz',  fecha:'8 ago 11:15',  antes:'1200', despues:'1350',
      foto:AVATAR.marta,  borde:PRES_RUEDA.azul  },
  ];

  // ── Progresiones ───────────────────────────────────────────────────────────────────────────
  // «No sobre el cuadro: sobre el nombre» — el cuadro se apaga y la etiqueta se subraya dibujando.
  // Los dos entran por props numéricas de <FichaProducto/>: la escena no repinta ningún campo.
  const apagaP   = Easing.easeOutCubic(clamp((t-T.noElCuadro)/0.35, 0, 1));
  const subrayaP = Easing.easeOutCubic(clamp((t-T.noElCuadro)/0.40, 0, 1));

  // Velo de protección del clímax: «el resto de la pantalla baja a opacity 0.28» → velo blanco 0.72.
  // En la mitad 1 de La Única Cosa sube a 0.94: la ficha ya no tiene nada que decir y la banda de
  // texto necesita fondo limpio (los 64 px de La Única Cosa caen justo encima del formulario).
  const veloBase = 0.72 * Easing.easeOutCubic(clamp((t-T.abre)/0.5, 0, 1));
  const velo     = lerp(veloBase, 0.94, Easing.easeOutCubic(clamp((t-T.unaCosa1)/0.6, 0, 1)));

  // Recorrido del diálogo: 1 → 0.80 (sube, se mantiene centrado) → 0.62 (se encoge arriba-izq).
  // transformOrigin '0% 0%' todo el tiempo desde unaCosa1 y la x compensada a mano: cambiar de
  // origen con escala ≠ 1 daría un salto de 78 px. Antes de unaCosa1 la escala es 1, así que el
  // origen del menú (continuidad espacial de la apertura) no cuesta nada.
  const encoge = Easing.easeOutCubic(clamp((t-T.unaCosa1)/0.6, 0, 1));
  const final  = Easing.easeOutCubic(clamp((t-T.noVive)/0.7, 0, 1));
  const dlgEscala = lerp(lerp(1, 0.80, encoge), 0.62, final);
  const dlgX = lerp(960 - (DLG.w/2)*dlgEscala, DLG.x, final);        // centrado ↔ pegado a la izquierda
  const dlgY = lerp(lerp(DLG.y, 30, encoge), 22, final);
  // Origen del menú expresado en % de la caja del diálogo (continuidad espacial de la apertura)
  const ORIGEN_MENU = `${Math.round((MENU.x-DLG.x)/DLG.w*100)}% ${Math.round((MENU.y-DLG.y)/DLG.h*100)}%`;

  // La Única Cosa, en dos mitades
  const m1P = clamp((t-T.unaCosa1)/0.6, 0, 1), m1E = Easing.easeOutCubic(m1P);
  const m2P = clamp((t-T.unaCosa2)/0.6, 0, 1), m2E = Easing.easeOutCubic(m2P);

  // El puntero se retira en cuanto el diálogo toma la pantalla (nada compite con el clímax)
  const curOp = 1 - clamp((t-(T.abre+0.10))/0.35, 0, 1);

  // Puntero: aparcado → ETIQUETA (0.6 s) → item del menú. El −2 es el desfase de la punta del
  // CineCursor (su path arranca en 2,2). Los anillos los pinta AnilloClicDerecho (determinista);
  // ScriptedCursor no lleva clicks porque su anillo es una animación CSS.
  const cursor = [
    { t:0,                  x:1198, y:952 },
    { t:T.clicDerecho,      x:1198, y:952 },
    { t:T.clicDerecho+0.6,  x:PUNT.x-2, y:PUNT.y-2 },
    { t:T.abre-0.45,        x:PUNT.x-2, y:PUNT.y-2 },
    { t:T.abre-0.05,        x:ITEM.x-2, y:ITEM.y-2 },
  ];

  return (
    <SlideCanvas variant="light">

      {/* ── La ficha COMPLETA, al fondo y atenuada: es la de la escena 01, el mismo registro ──
             («990» sin decimales porque es donde acaba el contador 1290→990 de la escena 01 y es
             lo que el plan escribe en pantalla; el diálogo lo pinta igual de crudo.) */}
      <FichaProducto
        t={t}
        precio="990"
        estadoPrecio="normal"
        atenuacion={0.62}
        zIndex={4}
      />

      {/* ── La LUPA: la misma ficha en modo 'zoom', encima de la fila que amplía ──────────────
             Colocación por defecto (FICHA_BASE_ZOOM) porque de ahí salen las anclas que usan el
             puntero, el anillo y el menú. La sombra es lo único que la separa del fondo: incluye
             el borde interior del componente, que `estilo` sustituiría. */}
      <FichaProducto
        t={t}
        modo="zoom"
        precio="990"
        estadoPrecio="normal"
        apagarControlPrecio={apagaP}
        subrayadoPrecio={subrayaP}
        zIndex={6}
        estilo={{boxShadow:'inset 0 0 0 1px #eef1f5, 0 30px 70px rgba(15,23,42,0.28)'}}
      />

      {/* ── Velo: «el resto de la pantalla baja a opacity 0.28» ────────────────────────────── */}
      {velo > 0 ? <div style={{position:'absolute', inset:0, background:'#fff', opacity:velo, zIndex:10}}/> : null}

      {/* ── Marca: ambiente, fuera del recorte 4:5 (x < 528), nunca compite ────────────────── */}
      <DinaupLogo size={30} style={{position:'absolute', left:96, top:966, opacity:0.30, zIndex:12}}/>

      {/* ── El diálogo «Historial» (componente compartido; aquí solo se cablea) ────────────── */}
      <DialogoHistorial
        t={t}
        campo="Precio de venta"
        valorActual="990"
        entradas={ENTRADAS}
        escala={dlgEscala}
        x={dlgX} y={dlgY}
        ancho={DLG.w} alto={DLG.h}
        transformOrigin={t < T.unaCosa1 ? ORIGEN_MENU : '0% 0%'}
        escalaEntrada={0.72}
        indiceAnimado={0}
        zIndex={20}
        aparicion={T.abre}
        bloqueActual={T.abre}
        rail={T.abre + 0.25}
        haloQuien={T.quien}
        haloCuando={T.cuando}
        haloValores={T.antes}
        tachado={T.tachado}
        valorNuevo={T.verde}
        badge={T.tres}
        entradasResto={T.tres}
      />

      {/* ── El menú contextual de UN item, colgando de la etiqueta ─────────────────────────── */}
      <MenuContextualUnItem
        t={t}
        x={MENU.x} y={MENU.y}
        texto="Historial de cambios"
        start={T.unaSolaOpcion}
        resalte={T.abre}
        salida={T.abre + 0.15}
        zIndex={30}
      />

      {/* ── Anillos: el clic derecho sobre la etiqueta y el clic sobre el item (misma primitiva) ── */}
      <AnilloClicDerecho t={t} x={PUNT.x} y={PUNT.y} start={T.clicDerecho + 0.6} duracion={0.45} tamano={118} zIndex={32}/>
      <AnilloClicDerecho t={t} x={ITEM.x} y={ITEM.y} start={T.abre}              duracion={0.40} tamano={86}  zIndex={32}/>

      {/* ── LA ÚNICA COSA (prueba). 64 px y no 68-76: la mitad 2 no cabe en los 784 px de la
             columna segura por encima de ese cuerpo, y la columna segura no se negocia. ────── */}
      {m1P > 0 ? (
        <div style={{
          position:'absolute', left:568, top:780, width:784, textAlign:'center', zIndex:40,
          opacity:m1E, transform:`translateY(${(1-m1E)*14}px)`,
        }}>
          <div className="f-plex" style={{fontSize:64, fontWeight:800, letterSpacing:'-0.03em', lineHeight:1.06, color:'#0F172A'}}>
            ¿Quién ha tocado esto?
          </div>
        </div>
      ) : null}
      {m2P > 0 ? (
        <div style={{
          position:'absolute', left:568, top:858, width:784, textAlign:'center', zIndex:40,
          opacity:m2E, transform:`translateY(${(1-m2E)*14}px)`,
        }}>
          <div className="f-plex" style={{fontSize:64, fontWeight:800, letterSpacing:'-0.03em', lineHeight:1.06}}>
            <span className="grad-text">Clic derecho<br/>en el nombre del campo.</span>
          </div>
        </div>
      ) : null}

      {/* ── El puntero, por encima de todo hasta que el diálogo toma la pantalla ───────────── */}
      {curOp > 0 ? (
        <div style={{position:'absolute', inset:0, zIndex:34, opacity:curOp, pointerEvents:'none'}}>
          <ScriptedCursor frames={cursor} t={t} clickTimes={[]}/>
        </div>
      ) : null}

    </SlideCanvas>
  );
}
Object.assign(window, { EscenaHC02 });
