<?php

    session_start();

    if(empty($_SESSION['login_appquadrata'])){

        echo"<script language='javascript'>window.location='/appquadrata/login'</script>;";

        exit();

    }

?>

<!DOCTYPE html>

<?php

/*inicializamos valores para la configuracion del template*/

$setting_template='../../../settings_template.txt';

$variables=[];

$_Color='';

$_Template='';

$_Theme_Template='';

$_Css='';

$_Js='';

$_Css_Version='';

$_Js_Version='';

$_Border_Img='Circular';

$_Border_Input='Cuadrado';

if (file_exists($setting_template)) {

    $lines = file($setting_template, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

    foreach ($lines as $line) {

        list($nombre_variable, $valor) = explode('=', $line);

        $variables[$nombre_variable] = $valor;

    }

    /*recogemos los valores de las variables*/

    if (isset($variables['Color'])) {

        $_Color = $variables['Color'];



        //echo "El color es: $_Color";

    }

    if (isset($variables['Template'])) {

        $_Template = $variables['Template'];

        //echo "El Template es: $_template";

    }

    if (isset($variables['Theme_Template'])) {

        $_Theme_Template = $variables['Theme_Template'];

        //echo "El Theme_Template es: $_Theme_Template";

    }

    if (isset($variables['css'])) {

        $_Css = $variables['css'];

        //echo "El css es: $_Css";

    }

    if (isset($variables['js'])) {

        $_Js = $variables['js'];

        //echo "El js es: $_Js";

    }

    if (isset($variables['Rows_Columns'])) {

        $_Rows_Columns = $variables['Rows_Columns'];

    }else{

        $_Rows_Columns=4;

    }

    if (isset($variables['css_version'])) {

        $_Css_Version = $variables['css_version'];

        //echo "El css es: $_Css";

    }

    if (isset($variables['js_version'])) {

        $_Js_Version = $variables['js_version'];

        //echo "El js es: $_Js";

    }

    if (isset($variables['Border_Img'])) {
        $_Border_Img = $variables['Border_Img'];
    }else{
        $_Border_Img = 'Circular';
    }

    if (isset($variables['Border_Input'])) {
        $_Border_Input = $variables['Border_Input'];
    }else{
        $_Border_Input = 'Cuadrado';
    }

}

/*terminan valores de configuracion pára el template*/

?>

<html  style="background-color: rgb(241, 245, 249);" lang="es" class="<?php if($_Color!=''){ echo 'theme-user'; }else{ echo $_Theme_Template; }?>">

<meta http-equiv='Content-Type' content='text/html; charset=ISO-8859-1'>

<meta name='description' content='Información sobre contenido de tu pagina'>

<meta name='keywords' content='aqui van los tags para ser encontrados por los boots de google ejemplo fibora,ti hyper solutions'>

<meta charset="UTF-8" />

<HEAD>



<?php

    //Declaramos la variable time, para que al modificar un archivo, este no se guarde en cache y se vizualicen los cambios

    $time_log_assets=time();

    include('../../path.php');

    //require('../modelo/cat_score_operativo_afianzadoras.php');

    require(ROOT_CONTROLLER.'cat_score_operativo_afianzadoras.php');

    $Obj_cat_score_operativo_afianzadoras = new cat_score_operativo_afianzadoras(); 

?>



    <!---<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">---><!--se agrego esta dependencia para los iconos de lado izquierdo en los inputs-->

    <script src='https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.js'></script>

    <meta name="viewport" content="width=device-width,initial-scale=1">

    <!-- BEGIN: CSS Assets-->

    <link rel="stylesheet" href="../../../dist/css/<?=$_Css;?>?dummy=<?=$_Css_Version;?>" />

    <!-- END: CSS Assets-->

    <link rel="stylesheet" href="../../../dist/css/input_file.css?dummy=<?=$_Css_Version;?>" />

    <script src="../../../dist/js/noback.js?dummy=<?=$_Css_Version;?>" type="text/javascript"></script>

    <!--Comienza plugins JTABLE--->

    <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>

    <!--Termina plugins JTABLE--->

    <!---llamamos la libreria de tinymce--->

    <script defer src="../../../dist/tinymce/tinymce/main.js?dummy=<?=$_Js_Version;?>"></script>

    <link rel="stylesheet" href="../../../dist/tinymce/tinymce/estilos.css?dummy=<?=$_Css_Version;?>" />

    <script src="../../../dist/tinymce/tinymce/tinymce.min.js?dummy=<?=$_Js_Version;?>" referrerpolicy="origin"></script>

    <!---Terminamos de agregar editor tinymce--->

    <!-- Cropper.js CSS -->
    <link href="../../../dist/css/cropper.min.css?dummy=<?=$_Js_Version;?>" rel="stylesheet"/>

    <!---incluimos dependencias para el select con buscador-->

    <script src="https://code.jquery.com/jquery-3.7.1.js" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" crossorigin="anonymous"></script>

    <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />

    <script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>

    <link rel="stylesheet" href="../../../dist/css/app_style.css?dummy=<?=$_Css_Version;?>" />

    <!--termina dependencias para el select con buscador--->

        

<?php



$action=!empty($_REQUEST['action'])?$_REQUEST['action']:'registrar';

$_ScrollTo=!empty($_REQUEST['_ScrollTo'])?$_REQUEST['_ScrollTo']:'';

$_Buscar=!empty($_REQUEST['_Buscar'])?$_REQUEST['_Buscar']:'';

$_Action = $_Buscar!='' ? 'buscar' : '';

$_Pagina=!empty($_REQUEST['pagina'])?$_REQUEST['pagina']:'';

//DECLARAMOS VARIABLES PARA LA RELACION CON ENTIDAD PADRE
$_Clausula_Fk=!empty($_REQUEST['_Clausula_Fk'])?$_REQUEST['_Clausula_Fk']:'';

$_IdFk=!empty($_REQUEST['_IdFk'])?$_REQUEST['_IdFk']:'';

//DECLARAMOS VARIABLES PARA LA RELACION CON ENTIDAD BISABUELO
$_B_Clausula_Fk=!empty($_REQUEST['_B_Clausula_Fk'])?$_REQUEST['_B_Clausula_Fk']:'';

$_B_IdFk=!empty($_REQUEST['_B_IdFk'])?$_REQUEST['_B_IdFk']:'';

//DECLARAMOS VARIABLES PARA LA RELACION CON ENTIDAD ABUELO
$_A_Clausula_Fk=!empty($_REQUEST['_A_Clausula_Fk'])?$_REQUEST['_A_Clausula_Fk']:'';

$_A_IdFk=!empty($_REQUEST['_A_IdFk'])?$_REQUEST['_A_IdFk']:'';

$Id_Cat_Score_Operativo_Afianzadoras=!empty($_REQUEST['Id_Cat_Score_Operativo_Afianzadoras'])?$_REQUEST['Id_Cat_Score_Operativo_Afianzadoras']:'';
$Nivel_Score='';
$Interpretacion='';
$Quien_Registro='';
$Fecha_Registro='';
$Fecha_Modificacion='';
$Quien_Modifico='';
$GPS='';


switch ($action) {

    case 'editar':
        $_Case_Consult='Editar_Columna';
        echo"<TITLE>Editar cat score operativo afianzadoras</TITLE>";
        break;

    default:
        $_Case_Consult='Registrar_Columna';
        echo"<TITLE>Registrar cat score operativo afianzadoras</TITLE>";
        break;

}



require_once(ROOT_CHARACTER_FIX);

$Obj_fix_characters = new fix_characters();

require_once(ROOT_CONTROLLER.'cat_score_operativo_afianzadoras.php');

$Obj_cat_score_operativo_afianzadoras = new cat_score_operativo_afianzadoras();//para los datos del formulario

$Obj_cat_score_operativo_afianzadoras2 = new cat_score_operativo_afianzadoras();//para los datos del paginador


$isMobile = preg_match('/(iPhone|iPad|iPod|Android)/i', $_SERVER['HTTP_USER_AGENT']);

//lee las variables del formulario.

if (!empty($_POST))

{

    /*require_once(ROOT_CONFIG);      

    $Odbj_conexion = new odbconexion;

    $conexion=$Odbj_conexion->openconection();

    $consulta="SELECT * FROM cat_score_operativo_afianzadoras WHERE Id_Cat_Score_Operativo_Afianzadoras='$Id_Cat_Score_Operativo_Afianzadoras' ORDER BY Id_Cat_Score_Operativo_Afianzadoras DESC";

    $Array_adapter_cat_score_operativo_afianzadoras=$conexion->query($consulta);

    $conexion->close();*/

    $Array_adapter_cat_score_operativo_afianzadoras=$Obj_cat_score_operativo_afianzadoras->getbyid_cat_score_operativo_afianzadoras($Id_Cat_Score_Operativo_Afianzadoras);

    while($field_cat_score_operativo_afianzadoras=$Array_adapter_cat_score_operativo_afianzadoras->fetch_assoc())

    {

    $Nivel_Score=$field_cat_score_operativo_afianzadoras['Nivel_Score'];
   $Interpretacion=$field_cat_score_operativo_afianzadoras['Interpretacion'];
   $Quien_Registro=$field_cat_score_operativo_afianzadoras['Quien_Registro'];
   $Fecha_Registro=$field_cat_score_operativo_afianzadoras['Fecha_Registro'];
   $Fecha_Modificacion=$field_cat_score_operativo_afianzadoras['Fecha_Modificacion'];
   $Quien_Modifico=$field_cat_score_operativo_afianzadoras['Quien_Modifico'];
   $GPS=$field_cat_score_operativo_afianzadoras['GPS'];
   

    }

}?>    



<?php  

    $row_registers=0;

    $arreglo_registers = array();

    /*$Odbj_conexion = new odbconexion;

    $conexion=$Odbj_conexion->openconection();

    $consulta="SELECT * FROM cat_score_operativo_afianzadoras ORDER BY Id_Cat_Score_Operativo_Afianzadoras ASC";

    $Array_adapter_cat_score_operativo_afianzadoras_registers=$conexion->query($consulta);

    $conexion->close();*/

    $Array_adapter_cat_score_operativo_afianzadoras_registers=$Obj_cat_score_operativo_afianzadoras2->get_cat_score_operativo_afianzadoras_paginador_frm();

    $rows_registers=$Array_adapter_cat_score_operativo_afianzadoras_registers->num_rows;

    while($field_cat_score_operativo_afianzadoras_register=$Array_adapter_cat_score_operativo_afianzadoras_registers->fetch_assoc())

    {

        $row_registers++;

        array_push($arreglo_registers, array("id" => $field_cat_score_operativo_afianzadoras_register['Id_Cat_Score_Operativo_Afianzadoras'], "numero" => $row_registers));

   

    }

    //permisos de columnas para usuarios no admin
    $Rol_Usuario_Logued_App=$_SESSION['Rol_appquadrata'];
    $Id_Modulo_Fk_En_Modulo_App=0;
    $columnasConPermiso = [];
    try{  
        $Odbj_conexion = new odbconexion;
        $conexion=$Odbj_conexion->openconection();
        $consulta="SELECT p.Id_Permiso_App,p.Id_Fk_Rol,p.Id_Modulo_Fk,p.Registrar,p.Leer,p.Editar,p.Eliminar,p.Exportar,m.Id_Modulo_App,m.Titulo_Modulo,m.Descripcion_Modulo,m.Tipo_Menu,m.Href_Modulo,m.Tipo_Enlace,m.Icon_Fa_Modulo FROM permiso_app_appquadrata p JOIN modulo_app_appquadrata m ON Id_Modulo_Fk=Id_Modulo_App WHERE Id_Fk_Rol='$Rol_Usuario_Logued_App' AND Leer='Si' ORDER BY Id_Permiso_App DESC ";
        $Array_adapter_permiso_modulo=$conexion->query($consulta);
        while($Field_Permiso_Modulo=$Array_adapter_permiso_modulo->fetch_assoc())
        {
            $Id_Modulo_Fk_En_Modulo_App=$Field_Permiso_Modulo['Id_Modulo_Fk'];
        }

        $consulta_columna="SELECT p.Id_Fk_Rol,m.Id_Modulo_App,p.Titulo_Columna,p.Leer_Columna,p.Registrar_Columna,p.Editar_Columna FROM permiso_columna_appquadrata p JOIN modulo_app_appquadrata m ON Id_Modulo_Fk=Id_Modulo_App WHERE Id_Fk_Rol='$Rol_Usuario_Logued_App' AND $_Case_Consult='Si' AND Id_Modulo_Fk='$Id_Modulo_Fk_En_Modulo_App'";
        $Array_adapter_permiso_columna=$conexion->query($consulta_columna);
        $conexion->close();
        while($Field_Permiso_columna=$Array_adapter_permiso_columna->fetch_assoc())
        {
            $columnasConPermiso[] = $Field_Permiso_columna['Titulo_Columna'];
        }

    }catch (Exception $e) {

        echo 'Excepcion capturada: ',  $e->getMessage(), "";

    }

?> 

<script language='JavaScript'> 

var statSend = false;

function checkSubmit() {

    if (!statSend) {

        statSend = true;

        return true;

    } else {

        alert('La Informaci\u00F3n ya se est\u00E1 enviando, por favor espere...');

        return false;

    }

}

</script> 

<style>

     ::-webkit-scrollbar {

        display: none;

    }



</style>

</HEAD>

    <center>

    <BODY onload="noback();">

  <?php

    //Comienza form del formulario

echo "<div class='intro-y box form-box'>";

    

    switch ($action) {

    case 'editar':

        echo "

            <div class='flex items-center p-5 border-b border-slate-200/60 dark:border-darkmode-400'>

                <h2 class='font-medium text-base mr-auto'>

                    EDITAR CAT SCORE OPERATIVO AFIANZADORAS

                </h2>";

            if($rows_registers>1){

                foreach ($arreglo_registers as $elemento) {

                    if ($elemento["id"] === $Id_Cat_Score_Operativo_Afianzadoras) {

                        $numeroEncontrado = $elemento["numero"];

                        break; // Detén el bucle una vez que se encuentre el elemento

                    }

                }

                echo "<p class='mr-3'>".$numeroEncontrado."/".$rows_registers."</p>";



                if($numeroEncontrado>1){

                    $registerPrev=$numeroEncontrado-1;

                    

                    foreach ($arreglo_registers as $elemento) {

                        if ($elemento["numero"] === $registerPrev) {

                            $idEncontradoPrev = $elemento["id"];

                            break; // Detén el bucle una vez que se encuentre el elemento

                        }

                    }

                    echo "<form action='./formulario.php' method='Post' onsubmit='loadingpage();'>

                        <input type='hidden' value='$idEncontradoPrev' name='Id_Cat_Score_Operativo_Afianzadoras'>

                        <input name='action' value='editar' type='hidden'>

                        <button type='submit' class='btn-navigation-registers'><svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' icon-name='chevron-left' data-lucide='chevron-left' class='lucide chevron-left w-6 h-6 mr-1 mt-1'><path d='M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z'></path><circle cx='12' cy='12' r='3'></circle></svg></button>

                    </form>";

                }



                if($numeroEncontrado<$row_registers){

                    $registerNext=$numeroEncontrado+1;

                    

                    foreach ($arreglo_registers as $elemento) {

                        if ($elemento["numero"] === $registerNext) {

                            $idEncontradoNext = $elemento["id"];

                            break; // Detén el bucle una vez que se encuentre el elemento

                        }

                    }

                    echo "<form action='./formulario.php' method='Post' onsubmit='loadingpage();'>

                        <input type='hidden' value='$idEncontradoNext' name='Id_Cat_Score_Operativo_Afianzadoras'>

                        <input name='action' value='editar' type='hidden'>

                        <button type='submit' class='btn-navigation-registers'><svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' icon-name='chevron-right' data-lucide='chevron-right' class='lucide chevron-right w-6 h-6 mr-1 mt-1'><path d='M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z'></path><circle cx='12' cy='12' r='3'></circle></svg></button>

                    </form>";

                }

            }

        echo "</div>";

        break;

    

    default:

        echo"

            <div class='flex items-center p-5 border-b border-slate-200/60 dark:border-darkmode-400'>

                <h2 class='font-medium text-base mr-auto'>

                    REGISTRAR CAT SCORE OPERATIVO AFIANZADORAS

                </h2>

            </div>";

        break;

    }



    switch($_Rows_Columns){

        case 1:

        $cols_columns=12;

        break;

        case 2:

        $cols_columns=6;

        break;

        case 3:

        $cols_columns=4;

        break;

        case 4:

        $cols_columns=3;

        break;

        default:

        $cols_columns=12;

        break;



    }



    echo "<div class='p-5'>

            <form name='registrar'onsubmit='loadingpage();return checkSubmit();' action='../bussines/guardar.php' method='Post' enctype='multipart/form-data'>      

            <div class='grid grid-cols-12 gap-x-5'>

                <div class='col-span-12 xl:col-span-12'>";

                    echo "<input type='hidden' name='_ScrollTo' value='$_ScrollTo'>";

                    echo "<input type='hidden' name='_Pagina' value='$_Pagina'>";

                    echo "<input type='hidden' name='Id_Cat_Score_Operativo_Afianzadoras' value='$Id_Cat_Score_Operativo_Afianzadoras'>";

                    echo "<div class='grid grid-cols-12 gap-x-5'  style='max-height: calc(100vh - 150px);overflow: auto;'>";

                      echo " 

                                <div class='mt-3  col-span-12 lg:col-span-$cols_columns xl:col-span-$cols_columns' ".(($Rol_Usuario_Logued_App <= 2) || (in_array('Nivel_Score', $columnasConPermiso) && $Rol_Usuario_Logued_App > 2) ? "" : "style='display:none;'").">

                                    <label for='update-profile-form-7' class='form-label'>Nivel Score: </label>

                                   <input id='Nivel_Score' name='Nivel_Score' value='$Nivel_Score' type='text' class='form-control  ".($_Border_Input=='Semi-Redondo' ? "border-semi-circular-input" : "")."'  placeholder='Nivel Score' >

                                </div>";
                                 echo " 

                                <div class='mt-3  col-span-12 lg:col-span-$cols_columns xl:col-span-$cols_columns' ".(($Rol_Usuario_Logued_App <= 2) || (in_array('Interpretacion', $columnasConPermiso) && $Rol_Usuario_Logued_App > 2) ? "" : "style='display:none;'").">

                                    <label for='update-profile-form-7' class='form-label'>Interpretacion: </label>

                                   <input id='Interpretacion' name='Interpretacion' value='$Interpretacion' type='text' class='form-control  ".($_Border_Input=='Semi-Redondo' ? "border-semi-circular-input" : "")."'  placeholder='Interpretacion' >

                                </div>";
                                                   

echo "          

                   </div><!---Este div cierra el grid para los campos del formulario -->     

                </div>

            </div>";


        //Datos que vamos a mantener en cualquier situacion 
            $params = [];
            if (!empty($_Clausula_Fk))   $params[] = '_Clausula_Fk=' . urlencode($_Clausula_Fk);
            if (!empty($_IdFk))          $params[] = '_IdFk=' . urlencode($_IdFk);
            if (!empty($_A_Clausula_Fk)) $params[] = '_A_Clausula_Fk=' . urlencode($_A_Clausula_Fk);
            if (!empty($_A_IdFk))        $params[] = '_A_IdFk=' . urlencode($_A_IdFk);
            if (!empty($_B_Clausula_Fk)) $params[] = '_B_Clausula_Fk=' . urlencode($_B_Clausula_Fk);
            if (!empty($_B_IdFk))        $params[] = '_B_IdFk=' . urlencode($_B_IdFk);
            
            // Parámetros obligatorios
            $params[] = 'action=' . urlencode($_Action);
            $params[] = 'buscar=' . urlencode($_Buscar);
            $params[] = 'pagina=' . urlencode($_Pagina);
            $params[] = '_Id_Registro=' . urlencode($Id_Cat_Score_Operativo_Afianzadoras);
            $params[] = '_ScrollTo=' . urlencode($_ScrollTo);
            // Construcción de la URL
            $_Url_Param = './?' . implode('&', $params);

         switch ($action) {

            case 'editar':
            
            echo "<div class='flex justify-end mt-4'>
                    <input type='hidden' name='action' value='editar'>
                    <a href='$_Url_Param' class='btn btn-danger flex items-center w-20 mr-auto'> Cancelar</a>
                    <button type='submit' class='btn btn-primary'>Guardar</button>
                </div>";
            break;

            case 'duplicar':
            
            echo "<div class='flex justify-end mt-4'>
                    <input type='hidden' name='action' value='duplicar'>
                    <a href='$_Url_Param' class='btn btn-danger flex items-center w-20 mr-auto'> Cancelar</a>
                    <button type='submit' class='btn btn-primary'>Guardar</button>
                </div>";
            break;

            default:
            
            echo "<div class='flex justify-end mt-4'>
                    <input type='hidden' name='action' value='registrar'>
                    <a href='$_Url_Param' class='btn btn-danger flex items-center w-20 mr-auto'> Cancelar</a>
                    <button type='submit' class='btn btn-primary'>Guardar</button>
                </div>";
            break;

        }                

echo "
        <!-- Campos para la relacion con entidad padre -->
        <input type='hidden' name='_IdFk' value='$_IdFk'>
        <input type='hidden' name='_Clausula_Fk' value='$_Clausula_Fk'>

        <!-- Campos para la relacion con entidad bisabuelo _B -->
        <input type='hidden' name='_B_IdFk' value='$_B_IdFk'>
        <input type='hidden' name='_B_Clausula_Fk' value='$_B_Clausula_Fk'>

        <!-- Campos para la relacion con entidad abuelo _A -->
        <input type='hidden' name='_A_IdFk' value='$_A_IdFk'>
        <input type='hidden' name='_A_Clausula_Fk' value='$_A_Clausula_Fk'>

";

echo "  </form>

        </div>

    </div>";





    //Termina form del formulario

?>



    </BODY>
    
    <!---nuevo script eliminar imagenes--->
    <div id="toast-container" style="position: fixed; top: 20px; right: 20px; z-index: 9999;"></div>

    <!-- ========================= -->
    <!-- MODAL: Elegir Origen -->
    <!-- ========================= -->
    <div id="sourceModal" style="display:none; position:fixed; z-index:10000; top:0; left:0; width:100vw; height:100vh; background:rgba(0,0,0,0.85); align-items:center; justify-content:center;">
      <div style="background:#fff; padding:14px; border-radius:10px; width:92vw; max-width:420px; display:flex; flex-direction:column; gap:10px;">
        <h5 style="text-align:center; margin:0;">Selecciona origen</h5>
        <p style="text-align:center; margin:0; font-size:14px; color:#444;">
          Elige cómo quieres cargar la imagen.
        </p>

        <div style="display:flex; flex-direction:column; gap:10px; margin-top:6px;">
          <!-- Se muestra solo si cámara está disponible -->
          <button id="btnOpenCamera" type="button" class="btn btn-primary" style="display:none; width:100%; border:none; padding:10px; border-radius:8px;">
            <i class="fa fa-camera" style="margin-right:8px;"></i> Usar cámara
          </button>

          <button id="btnOpenGallery" type="button" class="btn btn-primary" style="width:100%; border:none; padding:10px; border-radius:8px;">
            <i class="fa fa-image" style="margin-right:8px;"></i> Elegir de galería
          </button>

          <button id="btnCloseSourceModal" type="button" class="btn btn-danger" style="width:100%; border:none; padding:10px; border-radius:8px;">
            <i class="fa fa-times" style="margin-right:8px;"></i> Cancelar
          </button>
        </div>
      </div>
    </div>

    <!-- ========================= -->
    <!-- MODAL: Webcam (Windows/Laptop) -->
    <!-- ========================= -->
    <div id="webcamModal" style="display:none; position:fixed; z-index:10001; top:0; left:0; width:100vw; height:100vh; background:rgba(0,0,0,0.85); align-items:center; justify-content:center;">
      <div style="background:#fff; padding:12px; border-radius:10px; width:94vw; max-width:520px; display:flex; flex-direction:column; gap:10px;">
        <h5 style="text-align:center; margin:0;">Webcam</h5>

        <!-- Selector de cámara -->
        <div id="webcamDeviceWrap" style="display:none; gap:8px; align-items:center; justify-content:space-between; flex-wrap:wrap;">
          <div style="font-size:13px; color:#333;">
            <i class="fa fa-video-camera" style="margin-right:6px;"></i> Cámara:
          </div>
          <select id="webcamDeviceSelect" style="flex:1; min-width:180px; padding:8px; border-radius:8px; border:1px solid #ddd;">
            <option value="">Detectando...</option>
          </select>
        </div>

        <div style="width:100%; display:flex; justify-content:center; align-items:center; background:#000; border-radius:10px; overflow:hidden;">
          <video id="webcamVideo" autoplay playsinline style="width:100%; max-height:60vh;"></video>
        </div>

        <div style="display:flex; gap:10px; justify-content:space-between; flex-wrap:wrap;">
          
            <button id="btnCloseWebcamModal" type="button" class="btn btn-danger" style="flex:1; min-width:140px; border:none; padding:10px; border-radius:8px;">
                <i class="fa fa-times" style="margin-right:8px;"></i> Cancelar
            </button>

            <button id="btnCaptureWebcam" type="button" class="btn btn-primary" style="flex:1; min-width:140px; border:none; padding:10px; border-radius:8px;">
                <i class="fa fa-camera-retro" style="margin-right:8px;"></i> Capturar
            </button>
        </div>
      </div>
    </div>

    <!-- ========================= -->
    <!-- MODAL: Crop -->
    <!-- ========================= -->
    <div id="cropModal" style="display:none; position:fixed; z-index:10002; top:0; left:0; width:100vw; height:100vh; background:rgba(0,0,0,0.8); align-items:center; justify-content:center;">
      <div style="background:#fff; padding:10px; border-radius:8px; width:90vw; max-width:450px; max-height:90vh; display:flex; flex-direction:column;">
        <h5 style="text-align:center; margin:6px 0 10px 0;">Recorta tu imagen</h5>

        <!-- Toolbar: modo + rotación + zoom (SIN cambiar clases existentes) -->
        <div style="display:flex; flex-direction:column; gap:10px; margin-bottom:8px;">
          <!-- 1 línea: cuadrado/libre/rotar -->
          <div style="display:flex; gap:8px; justify-content:space-between; align-items:center;">
            <button id="btnCropSquare" type="button" class="btn btn-secondary"
                    title="Cuadrado"
                    style="flex:1; background:#6c757d; border:none; padding:10px; border-radius:8px; color:#111; font-size:18px; line-height:1;">
              ⛶
            </button>

            <button id="btnCropFree" type="button" class="btn btn-secondary"
                    title="Libre"
                    style="flex:1; background:#adb5bd; border:none; padding:10px; border-radius:8px; color:#111; font-size:18px; line-height:1;">
              🔃
            </button>

            <button id="btnRotateLeft" type="button" class="btn btn-secondary"
                    title="Rotar -90°"
                    style="flex:1; background:#e9ecef; border:none; padding:10px; border-radius:8px; color:#111; font-size:18px; line-height:1;">
              ↩️
            </button>

            <button id="btnRotateRight" type="button" class="btn btn-secondary"
                    title="Rotar +90°"
                    style="flex:1; background:#e9ecef; border:none; padding:10px; border-radius:8px; color:#111; font-size:18px; line-height:1;">
              ↪️
            </button>
          </div>

          <!-- Zoom -->
          <div style="display:flex; gap:10px; align-items:center;">
            <div style="font-size:16px; color:#111; white-space:nowrap; line-height:1;">➖</div>
            <input id="cropZoomRange" type="range" min="0.2" max="5" step="0.01" value="1" style="width:100%;">
            <div style="font-size:16px; color:#111; white-space:nowrap; line-height:1;">➕</div>
          </div>
        </div>

        <div style="flex:1; overflow:auto; text-align:center;">
          <img id="imageToCrop" src="" style="max-width:100%; max-height:70vh;">
        </div>

        <div style="width:-webkit-fill-available; margin-top:10px; display:flex; justify-content:space-between; gap:8px; flex-wrap:wrap;">
          

          <button onclick="keepOriginalImage()" type="button" class="btn btn-primary" style="border:none; padding:10px; border-radius:8px; flex:1; min-width:140px;">
            <i class="fa fa-expand" style="margin-right:8px;"></i> Mantener original
          </button>

          <button onclick="cropImage()" type="button" class="btn btn-primary" style="border:none; padding:10px; border-radius:8px; flex:1; min-width:140px;">
            <i class="fa fa-crop" style="margin-right:8px;"></i> Recortar
          </button>

          <button onclick="closeCropModal()" type="button" class="btn btn-danger" style="border:none; padding:10px; border-radius:8px; flex:1; min-width:140px;">
            <i class="fa fa-times" style="margin-right:8px;"></i> Cancelar
          </button>
        </div>
      </div>
    </div>

    <!-- ========================= -->
    <!-- INPUTS ocultos (cámara/galería) -->
    <!-- ========================= -->
    <input id="hiddenCameraInput" type="file" accept="image/*" capture="environment" style="display:none;">
    <input id="hiddenGalleryInput" type="file" accept="image/*" style="display:none;">
    <script>
    document.addEventListener("DOMContentLoaded", function () {
      const inputsFile = document.querySelectorAll("input[type='file']");

      function showToast(message, type = 'success') {
        const toast = document.createElement("div");
        toast.textContent = message;
        toast.style.padding = "12px 20px";
        toast.style.marginBottom = "10px";
        toast.style.backgroundColor = type === 'error' ? "#dc3545" : "#28a745";
        toast.style.color = "white";
        toast.style.borderRadius = "4px";
        toast.style.boxShadow = "0 2px 8px rgba(0,0,0,0.3)";
        toast.style.fontSize = "14px";
        toast.style.opacity = "0.95";
        toast.style.textAlign = "center";
        const cont = document.getElementById("toast-container");
        if (cont) cont.appendChild(toast);
        setTimeout(() => toast.remove(), 3500);
      }

      // Decide si el botón "Quitar archivo" debe verse (según tus reglas)
      function shouldShowDeleteButtonForInput(input) {
        if (!input) return false;

        const inputId = input.name || input.id || "";
        const hasFile = !!(input.files && input.files.length > 0);
        if (hasFile) return true;

        // _file => depende del hidden input (name sin _file)
        if (inputId.endsWith("_file")) {
          const num = inputId.replace("_file", "");
          const hidden = document.querySelector(`input[name='${num}']`);
          return !!(hidden && hidden.value && hidden.value.trim() !== "");
        }

        // archivo_ => depende del hidden del mismo num
        if (inputId.startsWith("archivo_")) {
          const num = inputId.replace("archivo_", "");
          const hidden = document.querySelector(`input[name='${num}']`);
          return !!(hidden && hidden.value && hidden.value.trim() !== "");
        }

        // video => SOLO si existe contenedor de video y su hidden_*
        const contVideo = document.getElementById("video_preview_" + inputId);
        if (contVideo) {
          const hidden = document.querySelector("input[name='hidden_" + inputId + "']");
          return !!(hidden && hidden.value && hidden.value.trim() !== "");
        }

        return false;
      }

      function syncDeleteButtonForInput(input) {
        if (!input) return;
        const wrapper = input.closest(".inputfile-wrapper") || input.parentElement;
        if (!wrapper) return;
        const btn = wrapper.querySelector("button.delete-media-UI");
        if (!btn) return;
        btn.style.display = shouldShowDeleteButtonForInput(input) ? "inline-flex" : "none";
      }

      // Exponemos la función para que el script 2 la pueda usar (sin cambiar clases ni CSS)
      window.__syncDeleteButtonForInput = syncDeleteButtonForInput;

      inputsFile.forEach(function (input) {

        // ✅ NO crear botón "quitar" para inputs ocultos de cámara/galería
        if (input.id === "hiddenCameraInput" || input.id === "hiddenGalleryInput") return;

        const inputId = input.name || input.id || "";

        if (!input.dataset.btnQuitarAgregado) {
          const btn = document.createElement("button");
          btn.type = "button";
          btn.className = "delete-media-UI";
          btn.innerHTML = `
            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"
                 fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                 stroke-linejoin="round" class="lucide lucide-trash2-icon lucide-trash-2">
              <path d="M10 11v6"/><path d="M14 11v6"/>
              <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/>
              <path d="M3 6h18"/>
              <path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/>
            </svg>
            Quitar archivo
          `;

          /* ---- FIX BUG "BOTÓN FLOTANDO" (sin CSS externo) ---- */
          btn.style.display = "none";
          btn.style.position = "static";
          btn.style.float = "none";
          btn.style.clear = "both";
          /*btn.style.margin = "8px 0 0 0";*/
          btn.style.padding = "8px 10px";
          btn.style.alignSelf = "flex-start";
          btn.style.transform = "none";
          btn.style.top = "auto";
          btn.style.right = "auto";
          btn.style.bottom = "auto";
          btn.style.left = "auto";
          btn.style.zIndex = "auto";
          /* ----------------------------------------------------- */

          const wrapper = input.closest(".inputfile-wrapper") || input.parentElement;
          if (wrapper) {
            if (getComputedStyle(wrapper).position === "static") {
              wrapper.style.position = "relative";
            }
            wrapper.appendChild(btn);
          } else {
            input.insertAdjacentElement("afterend", btn);
          }

          input.dataset.btnQuitarAgregado = "true";

          input.addEventListener("change", function () {
            // No “fuerces” visible si no corresponde: usa la misma lógica
            btn.style.display = shouldShowDeleteButtonForInput(input) ? "inline-flex" : "none";
          });

          btn.addEventListener("click", function () {
            input.value = "";
            btn.style.display = "none";

            // ✅ CRÍTICO: permitir que al volver a seleccionar SIEMPRE pregunte origen (modal)
            input.dataset._skipIntercept = "0";
            input.dataset._lastSig = "";
            input.dataset._lastTs  = "0";

            let mensajeToast = "Archivo eliminado correctamente.";

            // Imagen con preview (tu regla _file)
            if (inputId.endsWith("_file")) {
              const id = inputId.replace("_file", "");
              const img = document.getElementById("blah" + id);
              const span = document.getElementById("span" + id);
              const imgHidden = inputId.replace(/_file$/, "");
              const hiddenInput = document.querySelector(`input[name='${imgHidden}']`);
              if (img) img.src = "../../../dist/images/upload.gif";
              if (span) span.textContent = "Seleccionar archivo";
              if (hiddenInput) hiddenInput.value = "";
            }

            // PDF (archivo_)
            if (inputId.startsWith("archivo_")) {
              const num = inputId.replace("archivo_", "");
              const canvas = document.getElementById(num + "Canvas");
              const icon = document.getElementById("img" + num);
              const hiddenInput = document.querySelector(`input[name='${num}']`);
              if (canvas) canvas.style.display = "none";
              if (icon) {
                icon.style.display = "block";
                icon.src = "../../../dist/images/img_pdf.png";
              }
              if (hiddenInput) hiddenInput.value = "";
            }

            // ✅ Video: SOLO si existe su contenedor real (evita falso positivo en imágenes)
            const contVideo = document.getElementById("video_preview_" + inputId);
            if (contVideo) {
              const hiddenInput = document.querySelector("input[name='hidden_" + inputId + "']");
              contVideo.innerHTML = `<p style="color:white;">No video</p>`;
              if (hiddenInput) hiddenInput.value = "";
              mensajeToast = "Video eliminado del formulario. Aún puede previsualizarse en caché.";
            }

            showToast(mensajeToast);
          });

          // Mostrar botón si ya hay archivo en modo edición (misma lógica)
          btn.style.display = shouldShowDeleteButtonForInput(input) ? "inline-flex" : "none";
        }
      });
    });
    </script>
    <!--end nuevo script eliminar imagenes-->
    <script src="../../../dist/js/form_keypad.js?time=<?=$_Js_Version;?>"></script> 

       

<script type="text/javascript">

    window.onload=function(){

        window.scrollTo(0,0);

        window.parent.scrollTo(0,0);

        if(parent.document.getElementById('loadingpage')){

            parent.document.getElementById('loadingpage').style.display='none';

        }

    }



    function loadingpage(){

        if(parent.document.getElementById('loadingpage')){

          parent.document.getElementById('loadingpage').style.display='block'; 

        }

    }

</script>

<script>

    //document.getElementsByClassName('').select2();

    $('.select-search').select2();

</script>   


    <!---CODIGO PARA IMAGENES CROP--->
    <script src="../../../dist/js/cropper.min.js"></script>

    <script>
        let cropper = null;
        let currentInput = null;        // input REAL del formulario
        let currentPreview = null;      // miniatura
        let originalFile = null;        // archivo original seleccionado
        let originalObjectURL = null;

        let pendingOpenForInput = null; // input que disparó modal de origen

        // Crop UI state
        let cropMode = "square";        // "square" | "free"
        let cropZoom = 1;               // ratio real del cropper (se sincroniza con pellizco + trackbar)
        let suppressZoomSync = false;   // evita loops feos

        // Webcam (Desktop/Tablet)
        let webcamStream = null;
        let webcamDevices = [];
        let currentDeviceId = "";       // deviceId seleccionado

        document.addEventListener('DOMContentLoaded', () => {

          // Bind ÚNICO a inputs reales del crop (evita doble bind si el script se carga 2 veces)
          document.querySelectorAll('.data-img-crop input[type="file"]').forEach(input => {
            if (input.dataset._carlitosBound === '1') return;
            input.dataset._carlitosBound = '1';

            input.addEventListener('click', async (e) => {
              // Si un flujo previo disparó el input programáticamente, no interceptar
              if (input.dataset._skipIntercept === '1') {
                input.dataset._skipIntercept = '0';
                return;
              }

              e.preventDefault();
              e.stopPropagation();

              pendingOpenForInput = input;

              const isLikelyMobile = isMobileDevice();
              const camAvailable = await canUseCamera();

              // Desktop/Laptop: si NO hay cámara, abre galería directo
              if (!isLikelyMobile && !camAvailable) {
                openGalleryPickerFor(input);
                return;
              }

              // Móvil o desktop con webcam: mostrar modal origen
              openSourceModal(camAvailable);
            }, true);

            // Fallback: si por alguna razón cambia directo (sin modal), procesar igual
            input.addEventListener('change', handleFileChange);
          });

          // Botones del modal origen
          document.getElementById('btnCloseSourceModal')?.addEventListener('click', () => {
            // Cancelar modal origen => NO debe aparecer "Quitar archivo" si no corresponde
            if (pendingOpenForInput && window.__syncDeleteButtonForInput) {
              window.__syncDeleteButtonForInput(pendingOpenForInput);
            }
            pendingOpenForInput = null;
            closeSourceModal();
          });

          document.getElementById('btnOpenGallery')?.addEventListener('click', () => {
            if (!pendingOpenForInput) return closeSourceModal();
            openGalleryPickerFor(pendingOpenForInput);
          });

          document.getElementById('btnOpenCamera')?.addEventListener('click', async () => {
            if (!pendingOpenForInput) return closeSourceModal();

            // Móvil: input capture (nativo)
            if (isMobileDevice()) {
              openCameraPickerFor(pendingOpenForInput);
              return;
            }

            // Desktop/Tablet: getUserMedia + modal webcam
            await openWebcamModal();
          });

          // Inputs ocultos (galería/cámara) -> asignan archivo al input real
          document.getElementById('hiddenGalleryInput')?.addEventListener('change', (e) => {
            assignHiddenFileToRealInput(e.target, pendingOpenForInput);
            // Si canceló (no hay file), sincroniza botón quitar
            if ((!e.target.files || !e.target.files[0]) && pendingOpenForInput && window.__syncDeleteButtonForInput) {
              window.__syncDeleteButtonForInput(pendingOpenForInput);
            }
          });

          document.getElementById('hiddenCameraInput')?.addEventListener('change', (e) => {
            assignHiddenFileToRealInput(e.target, pendingOpenForInput);
            if ((!e.target.files || !e.target.files[0]) && pendingOpenForInput && window.__syncDeleteButtonForInput) {
              window.__syncDeleteButtonForInput(pendingOpenForInput);
            }
          });

          // Webcam modal
          document.getElementById('btnCloseWebcamModal')?.addEventListener('click', () => {
            // Cancelar webcam => NO debe “inventar” quitar archivo
            if (pendingOpenForInput && window.__syncDeleteButtonForInput) {
              window.__syncDeleteButtonForInput(pendingOpenForInput);
            }
            closeWebcamModal();
            closeSourceModal();
            pendingOpenForInput = null;
          });

          document.getElementById('btnCaptureWebcam')?.addEventListener('click', async () => {
            await captureFromWebcamToCrop(pendingOpenForInput);
          });

          // Selector de cámaras
          const sel = document.getElementById('webcamDeviceSelect');
          if (sel && !sel.dataset._bound) {
            sel.dataset._bound = '1';
            sel.addEventListener('change', async () => {
              currentDeviceId = sel.value || "";
              if (document.getElementById('webcamModal')?.style.display === 'flex') {
                await restartWebcamStream();
              }
            });
          }

          // Crop controls: modo, zoom, rotación
          bindCropControlsOnce();
        });

        /* ===========================
           Helpers: Device / Camera
        =========================== */
        function isMobileDevice() {
          return /Android|iPhone|iPad|iPod/i.test(navigator.userAgent || '');
        }

        async function canUseCamera() {
          if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) return isMobileDevice();
          try {
            const devices = await navigator.mediaDevices.enumerateDevices();
            return devices.some(d => d.kind === 'videoinput');
          } catch (e) {
            return isMobileDevice();
          }
        }

        /* ===========================
           Modal Origen
        =========================== */
        function openSourceModal(cameraAvailable) {
          const btnCam = document.getElementById('btnOpenCamera');
          if (btnCam) btnCam.style.display = cameraAvailable ? 'block' : 'none';
          const m = document.getElementById('sourceModal');
          if (m) m.style.display = 'flex';
        }

        function closeSourceModal() {
          const m = document.getElementById('sourceModal');
          if (m) m.style.display = 'none';
        }

        /* ===========================
           Pickers nativos (ocultos)
        =========================== */
        function openGalleryPickerFor(realInput) {
          closeSourceModal();
          const hidden = document.getElementById('hiddenGalleryInput');
          if (!hidden) return;
          hidden.value = '';
          hidden.click();
        }

        function openCameraPickerFor(realInput) {
          closeSourceModal();
          const hidden = document.getElementById('hiddenCameraInput');
          if (!hidden) return;
          hidden.value = '';
          hidden.click();
        }

        function assignHiddenFileToRealInput(hiddenInput, realInput) {
          try {
            if (!realInput) return;

            const file = hiddenInput.files && hiddenInput.files[0];
            if (!file) return;

            const dt = new DataTransfer();
            dt.items.add(file);

            // Evitar reabrir modal por click programático
            realInput.dataset._skipIntercept = '1';
            realInput.files = dt.files;

            realInput.dispatchEvent(new Event('change', { bubbles: true }));
          } finally {
            hiddenInput.value = '';
          }
        }

        /* ===========================
           Preview helper (ANTI-ESTIRADO)
        =========================== */
        function applyPreviewFit(imgEl) {
          if (!imgEl) return;
          imgEl.style.objectFit = 'cover';
          imgEl.style.objectPosition = 'center';
          imgEl.style.display = 'block';
          imgEl.style.maxWidth = '100%';
        }

        /* ===========================
           File Change -> Cropper
           (anti doble modal + UX)
        =========================== */
        function handleFileChange(event) {
          const input = event.target;
          const file = input.files?.[0];
          if (!file) {
            // Si se “canceló” una selección, sincroniza botón quitar
            if (window.__syncDeleteButtonForInput) window.__syncDeleteButtonForInput(input);
            return;
          }

          if (!file.type || !file.type.startsWith('image/')) {
            alert('Por favor selecciona una imagen válida.');
            input.value = '';
            if (window.__syncDeleteButtonForInput) window.__syncDeleteButtonForInput(input);
            return;
          }

          // Anti-duplicado (misma selección disparada 2 veces)
          const sig = `${file.name}|${file.size}|${file.lastModified}`;
          const now = Date.now();
          const lastSig = input.dataset._lastSig || '';
          const lastTs = parseInt(input.dataset._lastTs || '0', 10);
          if (sig === lastSig && (now - lastTs) < 600) return;
          input.dataset._lastSig = sig;
          input.dataset._lastTs = String(now);

          currentInput = input;
          pendingOpenForInput = input;

          currentPreview = input.closest('.data-img-crop')
            ?.querySelector('.data-preview-img-crop') || null;

          applyPreviewFit(currentPreview);

          originalFile = file;

          if (originalObjectURL) URL.revokeObjectURL(originalObjectURL);
          originalObjectURL = URL.createObjectURL(file);

          const image = document.getElementById('imageToCrop');
          if (!image) return;

          // Destruir cropper previo
          if (cropper) {
            cropper.destroy();
            cropper = null;
          }

          // Reset UI por imagen nueva
          cropMode = "square";
          cropZoom = 1;
          syncCropUiVisualState();

          image.onload = () => {
            cropper = new Cropper(image, {
              aspectRatio: 1,
              viewMode: 1,
              autoCropArea: 1,
              responsive: true,
              cropBoxResizable: true,
              zoomOnWheel: false
            });

            // 🔥 Sincroniza con pellizco / gestures (cuando el cropper emite zoom)
            // Nota: si tu build de Cropper no soporta on('zoom'), igual no rompe.
            try {
              cropper.on('zoom', (e) => {
                if (suppressZoomSync) return;
                const r = e?.detail?.ratio;
                if (typeof r !== 'number' || !isFinite(r)) return;
                cropZoom = clamp(r, 0.2, 5);
                const range = document.getElementById('cropZoomRange');
                if (range) range.value = String(cropZoom);
              });
            } catch (err) {}

            // Aplica estado inicial y abre modal UNA vez
            requestAnimationFrame(() => {
              try {
                suppressZoomSync = true;
                cropper.zoomTo(cropZoom);
              } catch(e) {}
              suppressZoomSync = false;

              const cm = document.getElementById('cropModal');
              if (cm) cm.style.display = 'flex';
            });
          };

          image.onerror = () => alert('No se pudo cargar la imagen seleccionada.');

          image.removeAttribute('src');
          setTimeout(() => { image.src = originalObjectURL; }, 30);
        }

        /* ===========================
           Acciones del modal Crop
        =========================== */
        function cropImage() {
          if (!cropper || !currentInput) return;

          const canvas = cropper.getCroppedCanvas({ width: 300, height: 300 });
          canvas.toBlob(blob => {
            if (!blob) return;

            const url = URL.createObjectURL(blob);

            if (currentPreview) {
              applyPreviewFit(currentPreview);
              currentPreview.src = url;
            }

            const file = new File([blob], 'cropped.png', { type: 'image/png' });
            const dt = new DataTransfer();
            dt.items.add(file);
            currentInput.files = dt.files;

            closeCropModal();

            if (window.__syncDeleteButtonForInput) window.__syncDeleteButtonForInput(currentInput);
          }, 'image/png');
        }

        function keepOriginalImage() {
          if (!currentInput || !originalFile) {
            closeCropModal();
            return;
          }

          if (currentPreview) {
            applyPreviewFit(currentPreview);
            currentPreview.src = originalObjectURL;
          }

          const dt = new DataTransfer();
          dt.items.add(originalFile);
          currentInput.files = dt.files;

          closeCropModal();

          if (window.__syncDeleteButtonForInput) window.__syncDeleteButtonForInput(currentInput);
        }

        function closeCropModal() {
          const cm = document.getElementById('cropModal');
          if (cm) cm.style.display = 'none';

          if (cropper) {
            try { cropper.destroy(); } catch(e) {}
            cropper = null;
          }

          const image = document.getElementById('imageToCrop');
          if (image) image.removeAttribute('src');

          // Limpieza
          currentInput = null;
          currentPreview = null;
          originalFile = null;
          pendingOpenForInput = null;
        }

        /* ===========================
           Crop UI: Zoom + Modo + Rotación
        =========================== */
        function bindCropControlsOnce() {
          const range = document.getElementById('cropZoomRange');
          const btnSq  = document.getElementById('btnCropSquare');
          const btnFr  = document.getElementById('btnCropFree');
          const btnRl  = document.getElementById('btnRotateLeft');
          const btnRr  = document.getElementById('btnRotateRight');

          if (range && range.dataset._bound === '1') return;
          if (range) range.dataset._bound = '1';

          // Zoom: proporcional a pellizco (si pellizcas, el event zoom lo actualiza; si mueves range, zoomTo exacto)
          if (range) {
            range.addEventListener('input', () => {
              const v = clamp(parseFloat(range.value || '1'), 0.2, 5);
              cropZoom = v;

              if (cropper) {
                try {
                  suppressZoomSync = true;
                  cropper.zoomTo(cropZoom);
                } catch(e) {}
                suppressZoomSync = false;
              }
            });
          }

          if (btnSq && !btnSq.dataset._bound) {
            btnSq.dataset._bound = '1';
            btnSq.addEventListener('click', () => {
              cropMode = "square";
              syncCropUiVisualState();
              if (cropper) {
                try { cropper.setAspectRatio(1); } catch(e) {}
              }
            });
          }

          if (btnFr && !btnFr.dataset._bound) {
            btnFr.dataset._bound = '1';
            btnFr.addEventListener('click', () => {
              cropMode = "free";
              syncCropUiVisualState();
              if (cropper) {
                try { cropper.setAspectRatio(NaN); } catch(e) {}
              }
            });
          }

          // Rotar: NO debe resetear zoom ni perder relatividad del range
          if (btnRl && !btnRl.dataset._bound) {
            btnRl.dataset._bound = '1';
            btnRl.addEventListener('click', () => rotateCropper(-90));
          }
          if (btnRr && !btnRr.dataset._bound) {
            btnRr.dataset._bound = '1';
            btnRr.addEventListener('click', () => rotateCropper(90));
          }

          syncCropUiVisualState();
        }

        function rotateCropper(deg) {
          if (!cropper) return;

          // Guardamos zoom actual (ya sincronizado con pellizco/range)
          const keepZoom = cropZoom;

          try { cropper.rotate(deg); } catch(e) {}

          // Re-aplicamos zoom EXACTO después de rotar (mantiene proporcionalidad)
          requestAnimationFrame(() => {
            try {
              suppressZoomSync = true;
              cropper.zoomTo(keepZoom);
            } catch(e) {}
            suppressZoomSync = false;

            cropZoom = keepZoom;
            const range = document.getElementById('cropZoomRange');
            if (range) range.value = String(cropZoom);
          });
        }

        function syncCropUiVisualState() {
          const range = document.getElementById('cropZoomRange');
          const btnSq  = document.getElementById('btnCropSquare');
          const btnFr  = document.getElementById('btnCropFree');

          if (range) range.value = String(clamp(cropZoom || 1, 0.2, 5));

          // Indicar seleccionado SOLO con estilos inline
          if (btnSq && btnFr) {
            if (cropMode === "square") {
              btnSq.style.background = "#6c757d";
              btnFr.style.background = "#adb5bd";
            } else {
              btnSq.style.background = "#adb5bd";
              btnFr.style.background = "#6c757d";
            }
            btnSq.style.color = "#111";
            btnFr.style.color = "#111";
          }
        }

        function clamp(n, a, b) {
          n = Number(n);
          if (!isFinite(n)) return a;
          return Math.max(a, Math.min(b, n));
        }

        /* ===========================
           Webcam (Desktop/Tablet) + Selector de cámaras
        =========================== */
        async function openWebcamModal() {
          closeSourceModal();

          const hasCam = await canUseCamera();
          if (!hasCam) {
            if (pendingOpenForInput) openGalleryPickerFor(pendingOpenForInput);
            return;
          }

          await loadWebcamDevices();

          try {
            await startWebcamStream();
            const wm = document.getElementById('webcamModal');
            if (wm) wm.style.display = 'flex';
          } catch (e) {
            if (pendingOpenForInput) openGalleryPickerFor(pendingOpenForInput);
          }
        }

        function closeWebcamModal() {
          const wm = document.getElementById('webcamModal');
          if (wm) wm.style.display = 'none';

          const video = document.getElementById('webcamVideo');
          if (video) video.srcObject = null;

          if (webcamStream) {
            webcamStream.getTracks().forEach(t => t.stop());
            webcamStream = null;
          }
        }

        async function loadWebcamDevices() {
          const wrap = document.getElementById('webcamDeviceWrap');
          const sel  = document.getElementById('webcamDeviceSelect');

          if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices || !sel) {
            if (wrap) wrap.style.display = 'none';
            return;
          }

          try {
            const devices = await navigator.mediaDevices.enumerateDevices();
            webcamDevices = devices.filter(d => d.kind === 'videoinput');

            if (!webcamDevices.length) {
              if (wrap) wrap.style.display = 'none';
              return;
            }

            if (wrap) {
              wrap.style.display = 'flex';
              wrap.style.marginBottom = '6px';
            }

            sel.innerHTML = '';
            webcamDevices.forEach((d, idx) => {
              const opt = document.createElement('option');
              opt.value = d.deviceId;
              opt.textContent = d.label ? d.label : `Cámara ${idx + 1}`;
              sel.appendChild(opt);
            });

            if (!currentDeviceId || !webcamDevices.some(d => d.deviceId === currentDeviceId)) {
              currentDeviceId = webcamDevices[0].deviceId;
            }
            sel.value = currentDeviceId;

          } catch (e) {
            if (wrap) wrap.style.display = 'none';
          }
        }

        async function startWebcamStream() {
          if (webcamStream) {
            webcamStream.getTracks().forEach(t => t.stop());
            webcamStream = null;
          }

          const constraints = {
            video: currentDeviceId ? { deviceId: { exact: currentDeviceId } } : true,
            audio: false
          };

          webcamStream = await navigator.mediaDevices.getUserMedia(constraints);

          const video = document.getElementById('webcamVideo');
          if (video) video.srcObject = webcamStream;

          // refresca labels tras permiso
          await loadWebcamDevices();
        }

        async function restartWebcamStream() {
          try {
            await startWebcamStream();
          } catch (e) {
            if (webcamDevices.length) {
              currentDeviceId = webcamDevices[0].deviceId;
              await startWebcamStream();
              const sel = document.getElementById('webcamDeviceSelect');
              if (sel) sel.value = currentDeviceId;
            }
          }
        }

        async function captureFromWebcamToCrop(realInput) {
          if (!realInput) {
            closeWebcamModal();
            return;
          }

          const video = document.getElementById('webcamVideo');
          if (!video || !video.videoWidth) return;

          const canvas = document.createElement('canvas');
          canvas.width = video.videoWidth;
          canvas.height = video.videoHeight;

          const ctx = canvas.getContext('2d');
          ctx.drawImage(video, 0, 0, canvas.width, canvas.height);

          const blob = await new Promise(resolve => canvas.toBlob(resolve, 'image/png'));
          if (!blob) return;

          const file = new File([blob], 'webcam.png', { type: 'image/png' });
          const dt = new DataTransfer();
          dt.items.add(file);

          // Evita re-abrir modal origen al reasignar
          realInput.dataset._skipIntercept = '1';
          realInput.files = dt.files;
          realInput.dispatchEvent(new Event('change', { bubbles: true }));

          closeWebcamModal();
        }
    </script>
    <!---END CODIGO PARA IMAGENES CROP--->
    <script src="../../../dist/js/app.js"></script> 

    </center>

</HTML>