<?php
// Inicio de registro de errores
error_reporting(E_ALL);
ini_set('display_errors', '0');
ini_set('log_errors', '1');
ini_set('error_log', __DIR__ . DIRECTORY_SEPARATOR . 'my_custom_error.log');
error_log('--- Inicio de bootstrap PHP: ' . basename(__FILE__) . ' ---');

require_once 'auth.php';

$auth = getAuth();
$auth->requireAuth(); // Requiere inicio de sesión

require_once __DIR__ . '/app/app_header.php';
require_once __DIR__ . '/billing.php';
require_once __DIR__ . '/kyc_helpers.php';

$currentUser = $auth->getCurrentUser();
$db = getDatabaseConnection();
$kyc = getUserKyc($db, $currentUser['id']);
$subscription = getUserSubscription($db, $currentUser['id']);
$kycStatus = $kyc['kyc_estado'] ?? 'no_iniciado';
$kycVerified = $kycStatus === 'verificado';
$subscriptionActive = isSubscriptionActive($subscription);
$accountSteps = [
    [
        'label' => 'Identidad',
        'description' => $kycVerified ? 'Verificacion completada' : ($kycStatus === 'pendiente' ? 'Verificacion en revision' : 'Verificacion pendiente'),
        'status' => $kycVerified ? 'Completado' : ($kycStatus === 'pendiente' ? 'En revision' : 'Pendiente'),
        'complete' => $kycVerified,
        'href' => 'kyc',
        'action' => $kycVerified ? 'Ver' : ($kycStatus === 'rechazado' ? 'Reintentar' : 'Verificar')
    ],
    [
        'label' => 'Suscripcion',
        'description' => $subscriptionActive ? 'Pago activo' : 'Pago pendiente',
        'status' => $subscriptionActive ? 'Completado' : 'Pendiente',
        'complete' => $subscriptionActive,
        'href' => 'subscription',
        'action' => $subscriptionActive ? 'Ver' : 'Pagar'
    ]
];
$missingAccountSteps = [];
foreach ($accountSteps as $step) {
    if (!$step['complete']) {
        $missingAccountSteps[] = $step['label'];
    }
}
$missingStepsCount = count($missingAccountSteps);
error_log('ID de usuario actual: ' . $currentUser['id']);
?>

<!DOCTYPE html> 
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="icon" href="graphics/signatureicon.ico" type="image/x-icon">
    <link rel="shortcut icon" href="graphics/signatureicon.ico" type="image/x-icon">
    <title>Firmador Codex Documentos PDF</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
    <style>
        <?php echo renderAppHeaderStyles(); ?>
        /* Estilos base para layout, navegación, carga y áreas de firma/PDF */
        * { 
            margin: 0;
            padding: 0;
            box-sizing: border-box; 
        } 

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #29648D 0%, #29648D 100%);
            min-height: 100vh;
            padding: 20px;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 0 0 8px 8px;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
            overflow: hidden;
        }

        .navbar {
            background: linear-gradient(135deg, #29648D 0%, #29648D 100%);
            color: white;
            padding: 20px 40px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }

        .navbar h1 {
            font-size: 1.5rem;
        }

        .navbar-actions {
            display: flex;
            gap: 15px;
            align-items: center;
        }

        .account-status {
            background: #f8fafc;
            border-bottom: 1px solid #e2e8f0;
            padding: 18px 30px;
            display: grid;
            grid-template-columns: minmax(220px, 0.75fr) 1fr;
            gap: 18px;
            align-items: center;
        }

        .account-status.ready {
            background: #ecfdf5;
            border-bottom-color: #bbf7d0;
        }

        .account-status-summary {
            color: #163f5f;
        }

        .account-status-summary span {
            display: block;
            color: #64748b;
            font-size: 0.82rem;
            font-weight: 700;
            letter-spacing: 0;
            margin-bottom: 4px;
            text-transform: uppercase;
        }

        .account-status-summary strong {
            display: block;
            font-size: 1.05rem;
            line-height: 1.35;
        }

        .account-steps {
            display: grid;
            grid-template-columns: repeat(2, minmax(0, 1fr));
            gap: 12px;
        }

        .account-step {
            background: white;
            border: 1px solid #dbe5ef;
            border-radius: 8px;
            padding: 12px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            gap: 12px;
        }

        .account-step.complete {
            border-color: #bbf7d0;
            background: #f0fdf4;
        }

        .account-step-title {
            color: #0f3554;
            font-weight: 700;
            margin-bottom: 3px;
        }

        .account-step-detail {
            color: #64748b;
            font-size: 0.85rem;
            line-height: 1.35;
        }

        .account-step-status {
            display: inline-block;
            margin-top: 7px;
            padding: 4px 9px;
            border-radius: 999px;
            background: #fef3c7;
            color: #92400e;
            font-size: 0.78rem;
            font-weight: 700;
        }

        .account-step.complete .account-step-status {
            background: #dcfce7;
            color: #166534;
        }

        .account-step-action {
            white-space: nowrap;
            padding: 8px 13px;
            border-radius: 18px;
            background: #29648D;
            color: white;
            text-decoration: none;
            font-size: 0.85rem;
            font-weight: 700;
        }

        .account-step.complete .account-step-action {
            background: #e2e8f0;
            color: #274864;
        }
 
        .user-info {
            background: rgba(255,255,255,0.2);
            padding: 8px 15px;
            border-radius: 20px;
            font-size: 0.9rem;
        }

        .btn {
            padding: 10px 20px;
            border-radius: 20px;
            border: none;
            cursor: pointer;
            font-size: 0.9rem;
            transition: all 0.3s;
            text-decoration: none;
            display: inline-block;
        }

        .btn-primary {
            background: white;
            color: #29648D;
        }

        .btn-primary:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(255,255,255,0.3);
        }

        .btn-outline {
            background: transparent;
            border: 2px solid white;
            color: white;
        }

        .btn-outline:hover {
            background: white;
            color: #29648D;
        }

        .content {
            padding: 30px;
        }

        /* Extiende el visor PDF a todo el ancho del contenido para evitar márgenes laterales */
        .content .pdf-viewer {
            margin-left: -30px;
            margin-right: -30px;
        }
        @media (max-width: 768px) {
            .content .pdf-viewer {
                margin-left: 0;
                margin-right: 0;
            }
        }

        .upload-section {
            text-align: center;
            padding: 40px;
            border: 3px dashed #29648D;
            border-radius: 10px;
            margin-bottom: 30px;
            transition: all 0.3s;
        }

        .upload-section:hover {
            border-color: #764ba2;
            background: #f8f9ff;
        }

        .upload-section.hidden {
            display: none;
        }

        .file-input {
            display: none;
        }

        .upload-btn {
            background: linear-gradient(135deg, #29648D 0%, #29648D 100%);
            color: white;
            padding: 15px 40px;
            border: none;
            border-radius: 25px;
            font-size: 1.1rem;
            cursor: pointer;
            transition: transform 0.3s;
        }

        .upload-btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
        }

        /* Sección de administración de firmas */
        .signature-management {
            background: #f8f9ff;
            border-radius: 10px;
            padding: 30px;
            margin-bottom: 30px;
        }

        .signature-management h2 {
            color: #29648D;
            margin-bottom: 20px;
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .signature-management.saved-signature-only {
            background: transparent;
            padding: 8px 0 22px;
            margin-bottom: 18px;
        }

        .signature-management.saved-signature-only .signature-tabs {
            display: none;
        }

        .signature-tabs {
            display: none;
            gap: 10px;
            max-width: 700px;
            width: 100%;
            margin: 0 auto 14px;
            border-bottom: 2px solid #ddd;
        }

        .signature-tabs.single-tab {
            border-bottom: 0;
            margin-bottom: 8px;
        }

        .tab-btn {
            padding: 12px 24px;
            background: transparent;
            border: none;
            cursor: pointer;
            font-size: 1rem;
            color: #666;
            border-bottom: 3px solid transparent;
            transition: all 0.3s;
        }

        .tab-btn.active {
            color: #29648D;
            border-bottom-color: #29648D;
            font-weight: 600;
        }

        .tab-btn:hover {
            color: #29648D;
        }

        .signature-tabs.single-tab .tab-btn {
            padding: 0;
            cursor: default;
            border-bottom: 0;
            color: #29648D;
            font-weight: 700;
        }

        .tab-content {
            display: none;
        }

        .tab-content.active {
            display: block;
        }

        /* Pestaña para crear firma */
        .signature-creator {
            background: transparent;
            border-radius: 0;
            padding: 14px 0 8px;
            display: grid;
            gap: 14px;
        }

        .signature-canvas-wrapper {
            border: 2px solid #ddd;
            border-radius: 10px;
            background: white;
            position: relative;
            overflow: hidden;
            max-width: 700px;      /* iguala el ancho del área de dibujo */
            margin-left: auto;
            margin-right: auto;
            width: 100%;
        }

        #create-signature-canvas {
            display: block;
            width: 100%;
            cursor: crosshair;
            touch-action: none;
        }

        #create-signature-svg {
            width: 100%;
            cursor: crosshair;
        }

        #create-signature-svg.node-edit-mode {
            cursor: default;
        }

        .signature-editor-toolbar {
            max-width: 700px;
            width: 100%;
            margin: 0 auto;
            display: flex;
            justify-content: space-between;
            gap: 12px;
            flex-wrap: wrap;
            align-items: center;
        }

        .signature-tool-group {
            display: flex;
            gap: 8px;
            flex-wrap: wrap;
            align-items: center;
        }

        .signature-editor-btn {
            padding: 9px 14px;
            border: 1px solid #d7dee8;
            border-radius: 8px;
            background: #eef2f7;
            color: #274864;
            cursor: pointer;
            font-size: 0.9rem;
            font-weight: 700;
        }

        .signature-editor-btn.active {
            background: #29648D;
            border-color: #29648D;
            color: #fff;
        }

        .signature-editor-btn:disabled {
            opacity: 0.45;
            cursor: not-allowed;
        }

        .signature-thickness-control {
            display: inline-flex;
            align-items: center;
            gap: 8px;
            padding: 8px 10px;
            border: 1px solid #d7dee8;
            border-radius: 8px;
            background: #fff;
            color: #274864;
            font-size: 0.88rem;
            font-weight: 700;
        }

        .signature-thickness-control input[type="range"] {
            width: 110px;
        }

        .signature-thickness-value {
            min-width: 38px;
            text-align: right;
            color: #163f5f;
        }

        .signature-node-layer {
            pointer-events: none;
        }

        .signature-node-handle {
            pointer-events: auto;
            cursor: move;
            fill: #fff;
            stroke: #2d7dd2;
            stroke-width: 1.5;
            vector-effect: non-scaling-stroke;
        }

        .signature-node-handle.endpoint {
            fill: #e8f2ff;
            stroke: #ef4444;
        }

        .signature-node-handle.active {
            fill: #29648D;
            stroke: #0f3554;
        }
   
        .signature-canvas-controls {
            width: 100%;
            max-width: 700px;
            margin: 0 auto;
            display: grid;
            grid-template-columns: minmax(220px, 1fr) auto;
            align-items: center;
            gap: 10px;
        }

        .signature-name-input {
            width: 100%;
            min-width: 0;
            padding: 12px;
            border: 2px solid #ddd;
            border-radius: 8px;
            font-size: 1rem;
        }

        .signature-name-input:focus {
            outline: none;
            border-color: #29648D;
        }

        .canvas-action-btns {
            display: flex;
            justify-content: flex-end;
            gap: 10px;
            flex-wrap: wrap;
            flex: 0 0 auto;
        }

        .canvas-btn {
            padding: 12px 24px;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            font-size: 0.95rem;
            transition: all 0.3s;
            white-space: nowrap;
        }

        .canvas-btn-clear {
            background: #f44336;
            color: white;
        }

        .canvas-btn-clear:hover {
            background: #d32f2f;
        }

        .canvas-btn-save {
            background: #29648D;
            color: white;
        }

        .canvas-btn-save:hover {
            background: #1e4d6b;
        }

        @media (max-width: 720px) {
            .signature-creator {
                padding: 12px 0 0;
            }

            .signature-editor-toolbar {
                align-items: stretch;
                flex-direction: column;
            }

            .signature-tool-group {
                width: 100%;
            }

            .signature-editor-btn {
                flex: 1 1 120px;
                padding-left: 10px;
                padding-right: 10px;
            }

            .signature-thickness-control {
                width: 100%;
                justify-content: space-between;
            }

            .signature-thickness-control input[type="range"] {
                flex: 1;
                min-width: 120px;
            }

            .signature-canvas-controls {
                grid-template-columns: 1fr;
            }

            .canvas-action-btns {
                display: grid;
                grid-template-columns: 1fr 1fr;
                width: 100%;
            }
        }

        @media (max-width: 420px) {
            .canvas-action-btns {
                grid-template-columns: 1fr;
            }
        }

        /* Pestaña de firmas guardadas */
        .saved-signatures-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
            gap: 20px;
        }

        .signature-card {
            background: white;
            border: 2px solid #ddd;
            border-radius: 10px;
            padding: 15px;
            text-align: center;
            transition: all 0.3s;
            cursor: pointer;
            position: relative;
        }

        .signature-card:hover {
            border-color: #29648D;
            box-shadow: 0 5px 15px rgba(41, 100, 141, 0.2);
            transform: translateY(-2px);
        }

        .signature-card.selected {
            border-color: #29648D;
            background: #f0f7ff;
            box-shadow: 0 0 0 3px rgba(41, 100, 141, 0.2);
        }

        .signature-preview {
            width: 100%;
            height: 100px;
            display: flex;
            align-items: center;
            justify-content: center;
            margin-bottom: 10px;
            background: #f9f9f9;
            border-radius: 5px;
            padding: 10px;
        }

        .signature-preview img {
            max-width: 100%;
            max-height: 100%;
            object-fit: contain;
        }

        .signature-card-name {
            font-weight: 600;
            color: #333;
            margin-bottom: 8px;
            word-break: break-word;
        }

        .signature-card-actions {
            display: flex;
            gap: 8px;
            justify-content: center;
        }

        .signature-card-btn {
            padding: 6px 12px;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            font-size: 0.85rem;
            transition: all 0.3s;
        }

        .signature-card-btn-delete {
            background: #f44336;
            color: white;
        }

        .signature-card-btn-delete:hover {
            background: #d32f2f;
        }

        .signature-management.saved-signature-only .saved-signatures-grid {
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 140px;
            gap: 18px;
        }

        .signature-management.saved-signature-only .signature-card {
            width: auto;
            min-width: 180px;
            background: transparent;
            border: 0;
            border-radius: 0;
            padding: 0;
            box-shadow: none;
        }

        .signature-management.saved-signature-only .signature-card:hover,
        .signature-management.saved-signature-only .signature-card.selected {
            background: transparent;
            border-color: transparent;
            box-shadow: none;
            transform: none;
        }

        .signature-management.saved-signature-only .signature-preview {
            height: 120px;
            margin-bottom: 8px;
            padding: 0;
            background: transparent;
        }

        .signature-management.saved-signature-only .signature-preview svg,
        .signature-management.saved-signature-only .signature-preview img {
            max-width: 260px;
            max-height: 120px;
        }

        .empty-state {
            text-align: center;
            padding: 60px 20px;
            color: #666;
        }
 
        .empty-state-icon {
            font-size: 4rem;
            margin-bottom: 15px;
            opacity: 0.3;
        }

        /* Visor de PDF */
        .pdf-viewer {
            display: none;
            margin-bottom: 30px;
        }

        .pdf-controls {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            padding: 15px;
            background: #f8f9ff;
            border-radius: 10px;
            flex-wrap: wrap;
            gap: 15px;
        }

        .page-controls {
            display: flex;
            align-items: center;
            gap: 15px;
        }

        .control-btn {
            background: #2596be;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 5px;
            cursor: pointer;
            transition: background 0.3s;
        }

        .control-btn:hover {
            background: #1e7a9a;
        }

        .control-btn:disabled {
            background: #ccc;
            cursor: not-allowed;
        }

        .tool-controls {
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
        }

        .tool-btn {
            padding: 10px 20px;
            border: 2px solid #29648D;
            background: white;
            color: #29648D;
            border-radius: 5px;
            cursor: pointer;
            transition: all 0.3s;
        }

        .tool-btn.active {
            background: #29648D;
            color: white;
        }

        .canvas-container {
            position: relative;
            width: 100%;
            border: 0;
            border-radius: 0;
            overflow: hidden;
            margin: 0; /* sin márgenes automáticos de centrado */
            background: transparent;
        }

        #pdf-canvas, #signature-canvas, #sig-overlay {
            display: block;
            margin: 0 auto;
        }

        #signature-canvas {
            position: absolute;
            top: 0;
            left: 0;
            cursor: crosshair;
            z-index: 20;
            pointer-events: auto;
        }

        /* Capa vectorial para las firmas */
        #sig-overlay {
            position: absolute;
            top: 0;
            left: 0;
            z-index: 22;
            pointer-events: auto;
            touch-action: none;
        }

        .placed-signature-image {
            cursor: move;
        }

        .signature-transform-controls {
            pointer-events: none;
        }

        .signature-transform-box {
            fill: none;
            stroke: #69a7ff;
            stroke-width: 1.5;
            vector-effect: non-scaling-stroke;
            pointer-events: all;
            cursor: move;
        }

        .signature-resize-handle {
            fill: #fff;
            stroke: #69a7ff;
            stroke-width: 2;
            vector-effect: non-scaling-stroke;
            pointer-events: all;
        }

        .signature-resize-handle[data-handle="nw"],
        .signature-resize-handle[data-handle="se"] {
            cursor: nwse-resize;
        }

        .signature-resize-handle[data-handle="ne"],
        .signature-resize-handle[data-handle="sw"] {
            cursor: nesw-resize;
        }

        .signature-resize-handle[data-handle="n"],
        .signature-resize-handle[data-handle="s"] {
            cursor: ns-resize;
        }

        .signature-resize-handle[data-handle="e"],
        .signature-resize-handle[data-handle="w"] {
            cursor: ew-resize;
        }

        #signature-canvas { display: none; }

        #pdf-canvas {
            z-index: 10;
        }

        .action-buttons {
            display: flex;
            gap: 15px;
            justify-content: center;
            margin-top: 20px;
            flex-wrap: wrap;
        } 

        .action-btn {
            padding: 15px 40px;
            border: none;
            border-radius: 25px;
            font-size: 1.1rem;
            cursor: pointer;
            transition: all 0.3s;
        }

        .save-btn {
            background: linear-gradient(135deg, #29648D 0%, #29648D 100%);
            color: white;
        }

        .save-btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(17, 153, 142, 0.4);
        }

        .clear-btn {
            background: linear-gradient(135deg, #f44336 0%, #e91e63 100%);
            color: white;
        }

        .clear-btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(238, 9, 121, 0.4);
        }

        .reset-btn {
            background: #eef2f7;
            color: #293845;
            border: 1px solid #d4d8de;
        }

        .reset-btn:hover {
            background: #e2e8f0;
        }

        .use-saved-btn {
            background: linear-gradient(135deg, #4caf50 0%, #8bc34a 100%);
            color: white;
        }

        .use-saved-btn:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(76, 175, 80, 0.4);
        }

        .status-message {
            text-align: center;
            padding: 15px;
            border-radius: 5px;
            margin-top: 20px;
            display: none;
        }

        .status-message.success {
            background: #d4edda;
            color: #155724;
            border: 1px solid #c3e6cb;
        }

        .status-message.error {
            background: #f8d7da;
            color: #721c24;
            border: 1px solid #f5c6cb;
        }

        .loading {
            text-align: center;
            padding: 20px;
            display: none;
        }

        .spinner {
            border: 4px solid #f3f3f3;
            border-top: 4px solid #29648D;
            border-radius: 50%;
            width: 40px;
            height: 40px;
            animation: spin 1s linear infinite;
            margin: 0 auto;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

        @media (max-width: 768px) {
            .navbar {
                flex-direction: column;
                gap: 15px;
            }

            .account-status {
                grid-template-columns: 1fr;
                padding: 16px;
            }

            .account-steps {
                grid-template-columns: 1fr;
            }

            .pdf-controls {
                flex-direction: column;
            }

            .saved-signatures-grid {
                grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
            }
        }

        /* Ajustes mÃ³viles adicionales para evitar desbordes en navbar y espacios */
        @media (max-width: 640px) {
            body { padding: 12px; }
            .navbar {
                padding: 16px;
                gap: 12px;
                text-align: center;
            }
            .navbar h1 { font-size: 1.1rem; line-height: 1.3; }
            .navbar-actions {
                width: 100%;
                flex-wrap: wrap;
                justify-content: center;
                gap: 8px;
            }
            .navbar-actions .btn,
            .navbar-actions .user-info {
                flex: 1 1 120px;
                text-align: center;
                padding: 10px 14px;
            }
            .account-step {
                align-items: stretch;
                flex-direction: column;
            }
            .account-step-action {
                text-align: center;
            }
            .signature-tabs {
                flex-wrap: wrap;
                justify-content: center;
            }
        }
    </style>
</head>
<body> 
    <?php renderAppHeader($currentUser, 'firma'); ?>
    <div class="container">
        <?php if ($missingStepsCount > 0): ?>
        <section class="account-status" aria-label="Estado de activacion de cuenta">
            <div class="account-status-summary">
                <span>Estado de activacion</span>
                <strong>
                    <?php if ($missingStepsCount === 1): ?>
                        Falta 1 paso: <?php echo htmlspecialchars(implode(', ', $missingAccountSteps)); ?>.
                    <?php else: ?>
                        Faltan <?php echo $missingStepsCount; ?> pasos: <?php echo htmlspecialchars(implode(', ', $missingAccountSteps)); ?>.
                    <?php endif; ?>
                </strong>
            </div>
            <div class="account-steps">
                <?php foreach ($accountSteps as $step): ?>
                    <div class="account-step <?php echo $step['complete'] ? 'complete' : ''; ?>">
                        <div>
                            <div class="account-step-title"><?php echo htmlspecialchars($step['label']); ?></div>
                            <div class="account-step-detail"><?php echo htmlspecialchars($step['description']); ?></div>
                            <span class="account-step-status"><?php echo htmlspecialchars($step['status']); ?></span>
                        </div>
                        <a class="account-step-action" href="<?php echo htmlspecialchars($step['href']); ?>">
                            <?php echo htmlspecialchars($step['action']); ?>
                        </a>
                    </div>
                <?php endforeach; ?>
            </div>
        </section>
        <?php endif; ?>
        <!-- Franja introductoria -->
        <div style="text-align: center; padding: 20px; background: linear-gradient(135deg, #29648D 0%, #29648D 100%); color: white;">
            <p>Cargue su documento, fírmelo digitalmente y obtenga verificación segura</p>
        </div>

        <div class="content">
            <!-- Sección de administración de firmas -->
            <div class="signature-management">
                <h2><span aria-hidden="true">✍️</span> <span id="signature-section-title">Dibuje firma</span></h2>
                
                <div class="signature-tabs single-tab">
                    <button class="tab-btn active" onclick="switchTab('create')">Crear firma</button>
                    <button class="tab-btn" onclick="switchTab('saved')" style="display: none;">Firmas guardadas</button>
                </div>

                <!-- Pestaña para crear firma -->
                <div class="tab-content active" id="create-tab">
                    <div class="signature-creator">
                        <div class="signature-editor-toolbar">
                            <div class="signature-tool-group">
                                <button type="button" id="signatureDrawModeBtn" class="signature-editor-btn active" title="Dibujar firma">Dibujar</button>
                                <button type="button" id="signatureEditModeBtn" class="signature-editor-btn" title="Editar nodos">Editar nodos</button>
                                <button type="button" id="signatureAddNodeBtn" class="signature-editor-btn" title="Agregar un nodo en el trazo">Agregar nodo</button>
                                <button type="button" id="signatureDeleteNodeBtn" class="signature-editor-btn" title="Eliminar el nodo seleccionado">Eliminar nodo</button>
                                <button type="button" id="signatureUndoBtn" class="signature-editor-btn" title="Deshacer ultimo trazo">Deshacer</button>
                            </div>
                            <div class="signature-tool-group">
                                <label class="signature-thickness-control" title="Grosor del trazo">
                                    Grosor
                                    <input type="range" id="signatureStrokeWidth" min="0.4" max="4" step="0.1" value="0.7">
                                    <span id="signatureStrokeWidthValue" class="signature-thickness-value">0.7 px</span>
                                </label>
                            </div>
                        </div>
                        <div class="signature-canvas-wrapper">
                            <svg id="create-signature-svg" 
                            width="700" 
                            height="270" 
                            viewBox="0 0 700 270"
                            style="border:1px solid #ccc; background:#fff; display:block; touch-action:none; user-select:none; pointer-events:auto;"></svg>
                        </div>
                        <div class="signature-canvas-controls">
                            <input type="text" id="signature-name-input" class="signature-name-input" 
                                   placeholder="Nombre de la firma (ej: Mi Firma Principal)" maxlength="50">
                            <div class="canvas-action-btns">
                                <button class="canvas-btn canvas-btn-clear" onclick="clearSignatureCanvas()">
                                    🗑️ Limpiar
                                </button>
                                <button class="canvas-btn canvas-btn-save" onclick="saveNewSignature()">
                                    💾 Guardar Firma
                                </button>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- Pestaña de firmas guardadas -->
                <div class="tab-content" id="saved-tab">
                    <div id="saved-signatures-container">
                        <div class="empty-state">
                            <div class="empty-state-icon">✍️</div>
                            <p>No hay firmas guardadas. Cree su primera firma en la pestaña "Crear Firma".</p>
                        </div>
                    </div>
                </div>
            </div>

            <!-- Sección de carga -->
            <div class="upload-section" id="uploadSection">
                <h2 style="margin-bottom: 20px;">Cargar Documento PDF</h2>
                <input type="file" id="pdfFile" class="file-input" accept=".pdf">
                <button class="upload-btn" onclick="document.getElementById('pdfFile').click()">
                    📄 Seleccionar PDF
                </button>
                <p style="margin-top: 15px; color: #616161ff;">Tamaño máximo: 10MB</p>
            </div>

            <!-- Visor de PDF -->
            <div class="pdf-viewer" id="pdfViewer">
                <div class="pdf-controls">
                    <div class="page-controls">
                        <button class="control-btn" id="prevPage">← Anterior</button>
                        <span id="pageInfo">Página 1 de 1</span>
                        <button class="control-btn" id="nextPage">Siguiente →</button>
                    </div>
                    <div class="tool-controls">
                        <button class="tool-btn" id="penTool">🖊️ Dibujar Firma</button>
                        <button class="tool-btn" id="useSavedTool">📋 Usar Firma Guardada</button>
                        <button class="tool-btn" id="eraserTool">🧹 Borrar</button>
                    </div>
                </div>

                <div class="canvas-container" id="canvasContainer">
                    <canvas id="pdf-canvas"></canvas>
                    <canvas id="signature-canvas"></canvas>
                    <svg id="sig-overlay"></svg>
                </div>

                <div class="action-buttons">
                    <button class="action-btn clear-btn" id="clearSignature">🗑️ Limpiar Firma</button>
                    <button class="action-btn save-btn" id="saveDocument">💾 Guardar y Firmar</button>
                    <button class="action-btn reset-btn" id="newDocument">📄 Firmar otro documento</button>
                </div>
            </div>

            <div class="loading" id="loading">
                <div class="spinner"></div>
                <p style="margin-top: 15px;">Procesando documento...</p>
            </div>

            <div class="status-message" id="statusMessage"></div>
        </div>
    </div>

    <script>
        // ================== CONFIGURACIÓN INICIAL ==================
        // Ruta del worker de PDF.js y recuperación de datos del usuario autenticado.
        pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';

        const currentUserFullName = <?php echo json_encode($currentUser['full_name']); ?>;
        const currentUserId = <?php echo json_encode($currentUser['id']); ?>;

        // Parámetros de trazo para dibujo de firmas.
        const STROKE_WIDTH = 0.7;
        const COLOR = '#000';
        const SMOOTHING = 0.22;
        const MIN_DIST = 0.6;
        const RDP_EPSILON = 0.8;

        // Estado global de la aplicación y caches de trabajo.
        let pdfDoc = null;            // Documento PDF cargado
        let pageNum = 1;              // Página visible
        let pageRendering = false;    // Flag de render en progreso
        let pageNumPending = null;    // Render pendiente al navegar
        let scale = 1.5;              // Escala base del PDF (ajustada a contenedor)
        let signatures = {};          // Firmas por página
        let isDrawing = false;        // Dibujo manual en curso
        let currentTool = 'pen';      // Herramienta activa (lápiz, firma guardada, borrador)
        let uploadedFile = null;      // Archivo PDF subido
        let activePointerId = null;   // ID de puntero actual
        let strokePoints = [];        // Puntos de la firma en curso
        let currentPathEl = null;     // Path SVG activo en overlay
        let selectedSavedSignature = null; // Firma guardada seleccionada
        let userSavedSignatures = [];      // Lista de firmas del usuario
        let lastSavedSignatureSize = null; // Ultimo tamano usado al colocar una firma guardada
        let signatureTransformDrag = null; // Arrastre activo para mover/redimensionar firma
        const SIGNATURE_MIN_SIZE = 18;

        // Referencias a lienzos y contextos de dibujo.
        const pdfCanvas = document.getElementById('pdf-canvas');
        const sigCanvas = document.getElementById('signature-canvas'); // legado: bitmap oculto
        const sigOverlay = document.getElementById('sig-overlay');     // overlay vectorial (SVG)
        const pdfCtx = pdfCanvas.getContext('2d');
        const sigCtx = sigCanvas.getContext('2d'); 

        const scaleCanva = window.devicePixelRatio || 1;
        //sigCanvas.width = sigCanvas.clientWidth * scaleCanva;
        //sigCanvas.height = sigCanvas.clientHeight * scaleCanva;
        //sigCtx.scale(scaleCanva, scaleCanva);

        function createSvgElement(tag, attributes = {}) {
            const el = document.createElementNS('http://www.w3.org/2000/svg', tag);
            Object.entries(attributes).forEach(([key, value]) => el.setAttribute(key, value));
            return el;
        }

        function getOverlaySignatureElements() {
            return Array.from(sigOverlay.children).filter(el => {
                return !(el.classList && el.classList.contains('signature-transform-controls'));
            });
        }

        function clearSignatureTransformControls() {
            sigOverlay.querySelectorAll('.signature-transform-controls').forEach(el => el.remove());
        }

        function getPlacedSignatureImage() {
            return sigOverlay.querySelector('image.placed-signature-image') ||
                getOverlaySignatureElements().find(el => el.tagName && el.tagName.toLowerCase() === 'image') ||
                null;
        }

        function getOverlayCssSize() {
            const rect = pdfCanvas.getBoundingClientRect();
            return {
                width: Math.max(1, rect.width),
                height: Math.max(1, rect.height)
            };
        }

        function readSignatureImageBox(imgEl = getPlacedSignatureImage()) {
            if (!imgEl) return null;
            const x = parseFloat(imgEl.getAttribute('x') || '0') || 0;
            const y = parseFloat(imgEl.getAttribute('y') || '0') || 0;
            const w = Math.max(1, parseFloat(imgEl.getAttribute('width') || '0') || 0);
            const h = Math.max(1, parseFloat(imgEl.getAttribute('height') || '0') || 0);
            return { x, y, w, h };
        }

        function rememberSavedSignatureSize(box) {
            if (!box || !(box.w > 0) || !(box.h > 0)) return;
            lastSavedSignatureSize = { w: box.w, h: box.h };
        }

        function getSavedSignaturePlacementSize() {
            const currentBox = readSignatureImageBox();
            if (currentBox) return { w: currentBox.w, h: currentBox.h };

            if (lastSavedSignatureSize && lastSavedSignatureSize.w > 0 && lastSavedSignatureSize.h > 0) {
                return { w: lastSavedSignatureSize.w, h: lastSavedSignatureSize.h };
            }

            return null;
        }

        function clampSignatureBox(box) {
            const bounds = getOverlayCssSize();
            const aspect = box.w > 0 && box.h > 0 ? box.w / box.h : 1;
            let w = Math.max(SIGNATURE_MIN_SIZE, box.w);
            let h = Math.max(SIGNATURE_MIN_SIZE, box.h);

            if (w > bounds.width) {
                w = bounds.width;
                h = w / aspect;
            }
            if (h > bounds.height) {
                h = bounds.height;
                w = h * aspect;
            }

            const x = Math.min(Math.max(0, box.x), Math.max(0, bounds.width - w));
            const y = Math.min(Math.max(0, box.y), Math.max(0, bounds.height - h));
            return { x, y, w, h };
        }

        function updateSignatureObjectFromBox(box, options = {}) {
            const sig = signatures[pageNum];
            if (!sig) return;

            const bounds = getOverlayCssSize();
            const DPR = window.devicePixelRatio || 1;
            sig.x = Math.round(box.x * DPR);
            sig.y = Math.round(box.y * DPR);
            sig.width = Math.round(box.w * DPR);
            sig.height = Math.round(box.h * DPR);
            sig.canvasPixelWidth = Math.round(bounds.width * DPR);
            sig.canvasPixelHeight = Math.round(bounds.height * DPR);
            sig.xNorm = box.x / bounds.width;
            sig.yNorm = box.y / bounds.height;
            sig.wNorm = box.w / bounds.width;
            sig.hNorm = box.h / bounds.height;
            rememberSavedSignatureSize(box);

            if (options.resetScaleBase) {
                sig.baseWNorm = sig.wNorm;
                sig.baseHNorm = sig.hNorm;
                sig.scale = 1;
            }
        }

        function setPlacedSignatureBox(box, options = {}) {
            const imgEl = getPlacedSignatureImage();
            if (!imgEl) return;

            const safeBox = clampSignatureBox(box);
            imgEl.setAttribute('x', safeBox.x);
            imgEl.setAttribute('y', safeBox.y);
            imgEl.setAttribute('width', safeBox.w);
            imgEl.setAttribute('height', safeBox.h);
            updateSignatureObjectFromBox(safeBox, options);

            if (options.renderControls !== false) {
                renderSignatureTransformHandles();
            }
        }

        function bindPlacedSignatureImage(imgEl) {
            if (!imgEl) return;
            imgEl.classList.add('placed-signature-image');
            imgEl.dataset.signatureElement = 'signature';
            if (imgEl.dataset.transformBound === '1') return;
            imgEl.dataset.transformBound = '1';
            imgEl.addEventListener('pointerdown', e => startSignatureTransform(e, 'move'));
        }

        function renderSignatureTransformHandles() {
            clearSignatureTransformControls();
            const imgEl = getPlacedSignatureImage();
            const box = readSignatureImageBox(imgEl);
            if (!imgEl || !box || !signatures[pageNum]) return;

            const group = createSvgElement('g', { class: 'signature-transform-controls' });
            const rect = createSvgElement('rect', {
                class: 'signature-transform-box',
                x: box.x,
                y: box.y,
                width: box.w,
                height: box.h
            });
            rect.addEventListener('pointerdown', e => startSignatureTransform(e, 'move'));
            group.appendChild(rect);

            const handles = [
                ['nw', box.x, box.y],
                ['n', box.x + box.w / 2, box.y],
                ['ne', box.x + box.w, box.y],
                ['e', box.x + box.w, box.y + box.h / 2],
                ['se', box.x + box.w, box.y + box.h],
                ['s', box.x + box.w / 2, box.y + box.h],
                ['sw', box.x, box.y + box.h],
                ['w', box.x, box.y + box.h / 2]
            ];

            handles.forEach(([handle, cx, cy]) => {
                const node = createSvgElement('circle', {
                    class: 'signature-resize-handle',
                    'data-handle': handle,
                    cx,
                    cy,
                    r: 5
                });
                node.addEventListener('pointerdown', e => startSignatureTransform(e, handle));
                group.appendChild(node);
            });

            sigOverlay.appendChild(group);
        }

        function calculateTransformedSignatureBox(drag, point) {
            const start = drag.startBox;
            const dx = point.x - drag.startPoint.x;
            const dy = point.y - drag.startPoint.y;

            if (drag.handle === 'move') {
                return {
                    x: start.x + dx,
                    y: start.y + dy,
                    w: start.w,
                    h: start.h
                };
            }

            const scales = [];
            if (drag.handle.includes('e')) scales.push((start.w + dx) / start.w);
            if (drag.handle.includes('w')) scales.push((start.w - dx) / start.w);
            if (drag.handle.includes('s')) scales.push((start.h + dy) / start.h);
            if (drag.handle.includes('n')) scales.push((start.h - dy) / start.h);

            let scaleFactor = scales.reduce((best, current) => {
                return Math.abs(current - 1) > Math.abs(best - 1) ? current : best;
            }, 1);

            const minScale = Math.max(SIGNATURE_MIN_SIZE / start.w, SIGNATURE_MIN_SIZE / start.h);
            if (!isFinite(scaleFactor) || scaleFactor < minScale) {
                scaleFactor = minScale;
            }

            const w = start.w * scaleFactor;
            const h = start.h * scaleFactor;
            let x = start.x;
            let y = start.y;

            if (drag.handle.includes('w')) x = start.x + start.w - w;
            else if (!drag.handle.includes('e')) x = start.x + (start.w - w) / 2;

            if (drag.handle.includes('n')) y = start.y + start.h - h;
            else if (!drag.handle.includes('s')) y = start.y + (start.h - h) / 2;

            return { x, y, w, h };
        }

        function startSignatureTransform(e, handle = 'move') {
            if (currentTool === 'eraser') return;

            const imgEl = getPlacedSignatureImage();
            const box = readSignatureImageBox(imgEl);
            if (!imgEl || !box) return;

            e.preventDefault();
            e.stopPropagation();
            signatureTransformDrag = {
                pointerId: e.pointerId,
                handle,
                startPoint: getEventPos(e),
                startBox: box
            };

            try { sigOverlay.setPointerCapture(e.pointerId); } catch (ex) {}
        }

        function updateSignatureTransform(e) {
            if (!signatureTransformDrag || e.pointerId !== signatureTransformDrag.pointerId) return;

            e.preventDefault();
            e.stopPropagation();
            const point = getEventPos(e);
            const nextBox = calculateTransformedSignatureBox(signatureTransformDrag, point);
            setPlacedSignatureBox(nextBox, {
                resetScaleBase: signatureTransformDrag.handle !== 'move'
            });
        }

        function finishSignatureTransform(e) {
            if (!signatureTransformDrag || e.pointerId !== signatureTransformDrag.pointerId) return;
            e.preventDefault();
            e.stopPropagation();
            try { sigOverlay.releasePointerCapture(e.pointerId); } catch (ex) {}
            signatureTransformDrag = null;
            renderSignatureTransformHandles();
        }

        // ---------- Inicialización del creador de firmas SVG ----------
        document.addEventListener('DOMContentLoaded', () => {
            const svg = document.getElementById('create-signature-svg');
            if (!svg) {
                console.warn('No se encontró el elemento create-signature-svg');
                return;
            }
            // Parámetros del trazo dentro del creador de firmas.
            const STROKE_WIDTH = 0.7;
            const COLOR = '#000';
            const SMOOTHING = 0.22;
            const MIN_DIST = 0.6;
            const RDP_EPSILON = 1.0;

            // --- utilidades de cálculo ---
            function dist(a, b) { const dx=a.x-b.x, dy=a.y-b.y; return Math.hypot(dx, dy); }
            function midpoint(a, b) { return { x: (a.x+b.x)/2, y: (a.y+b.y)/2 }; }

            // Simplificación ligera con Ramer–Douglas–Peucker.
            function rdp(points, eps) {
                if (points.length < 3) return points.slice();
                const keep = Array(points.length).fill(false);
                keep[0] = keep[points.length - 1] = true;

                function perpendicularDistance(p, a, b) {
                    const num = Math.abs((b.y-a.y)*p.x - (b.x-a.x)*p.y + b.x*a.y - b.y*a.x);
                    const den = Math.hypot(b.y-a.y, b.x-a.x);
                    return den === 0 ? Math.hypot(p.x-a.x, p.y-a.y) : num/den;
                }

                function simplify(start, end) {
                    let maxD = 0, idx = -1;
                    for (let i = start + 1; i < end; i++) {
                    const d = perpendicularDistance(points[i], points[start], points[end]);
                    if (d > maxD) { maxD = d; idx = i; }
                    }
                    if (maxD > eps) {
                    keep[idx] = true;
                    simplify(start, idx);
                    simplify(idx, end);
                    }
                }
                simplify(0, points.length - 1);
                return points.filter((_, i) => keep[i]);
            }

            // Construye un path suavizado usando puntos medios y llega hasta el último punto.
            function toSmoothPath(pts) {
                if (pts.length < 2) return '';
                let d = `M ${pts[0].x} ${pts[0].y}`;
                for (let i = 1; i < pts.length - 1; i++) {
                    const cp = pts[i];
                    const m = midpoint(cp, pts[i + 1]);
                    d += ` Q ${cp.x} ${cp.y} ${m.x} ${m.y}`;
                }
                // Dibuja hasta el último punto para evitar que se quede atrás la punta.
                const last = pts[pts.length - 1];
                d += ` L ${last.x} ${last.y}`;
                return d;
            }

            // --- estado de dibujo dentro del creador ---
            let isDrawing = false;
            let rawPoints = [];
            let smoothPoints = [];
            let smoothed = null;      // seguidor suavizado (promedio móvil)
            let pathEl = null;
            const SVG_NS = 'http://www.w3.org/2000/svg';
            const drawModeBtn = document.getElementById('signatureDrawModeBtn');
            const editModeBtn = document.getElementById('signatureEditModeBtn');
            const addNodeBtn = document.getElementById('signatureAddNodeBtn');
            const deleteNodeBtn = document.getElementById('signatureDeleteNodeBtn');
            const undoBtn = document.getElementById('signatureUndoBtn');
            const strokeWidthInput = document.getElementById('signatureStrokeWidth');
            const strokeWidthValue = document.getElementById('signatureStrokeWidthValue');
            let creatorStrokeWidth = strokeWidthInput ? parseFloat(strokeWidthInput.value) || STROKE_WIDTH : STROKE_WIDTH;
            let creatorMode = 'draw';
            let nodeTool = 'move';
            let selectedNode = null;
            let activeNodeDrag = null;
            let signatureCtrlZoomKeyDown = false;
            const signatureInitialViewBox = { x: 0, y: 0, w: 700, h: 270 };
            const signatureZoomLimits = {
                minWidth: signatureInitialViewBox.w / 8,
                maxWidth: signatureInitialViewBox.w * 2
            };

            function setPathStyle(el) {
                el.classList.add('signature-stroke');
                el.setAttribute('fill', 'none');
                el.setAttribute('stroke', COLOR);
                el.setAttribute('stroke-width', creatorStrokeWidth);
                el.setAttribute('stroke-linecap', 'round');
                el.setAttribute('stroke-linejoin', 'round');
                el.setAttribute('shape-rendering', 'geometricPrecision');
            }

            function getSelectedPath() {
                if (!selectedNode) return null;
                return getSignaturePaths()[selectedNode.pathIndex] || null;
            }

            function syncStrokeWidthControl() {
                if (!strokeWidthInput || !strokeWidthValue) return;
                strokeWidthInput.value = String(creatorStrokeWidth);
                strokeWidthValue.textContent = creatorStrokeWidth.toFixed(1) + ' px';
            }

            function applyStrokeWidth(width, targetPath = null) {
                creatorStrokeWidth = Math.max(0.4, Math.min(4, Number(width) || STROKE_WIDTH));
                syncStrokeWidthControl();

                if (targetPath) {
                    targetPath.setAttribute('stroke-width', creatorStrokeWidth);
                    return;
                }

                const selectedPath = getSelectedPath();
                if (creatorMode === 'edit' && selectedPath) {
                    selectedPath.setAttribute('stroke-width', creatorStrokeWidth);
                } else {
                    getSignaturePaths().forEach(path => path.setAttribute('stroke-width', creatorStrokeWidth));
                }
            }

            function roundPoint(p) {
                return {
                    x: Math.round(p.x * 100) / 100,
                    y: Math.round(p.y * 100) / 100
                };
            }

            function getSignaturePaths() {
                return Array.from(svg.querySelectorAll('path.signature-stroke'));
            }

            function getSignatureViewBox() {
                const vb = svg.viewBox && svg.viewBox.baseVal;
                if (vb && vb.width && vb.height) {
                    return { x: vb.x, y: vb.y, w: vb.width, h: vb.height };
                }
                return { ...signatureInitialViewBox };
            }

            function setSignatureViewBox(box) {
                svg.setAttribute('viewBox', `${box.x} ${box.y} ${box.w} ${box.h}`);
            }

            function getSignatureZoomLevel() {
                const box = getSignatureViewBox();
                return signatureInitialViewBox.w / box.w;
            }

            function resetSignatureZoom() {
                setSignatureViewBox(signatureInitialViewBox);
                renderNodeHandles();
            }

            function getEditorLayer() {
                let layer = svg.querySelector('.signature-node-layer');
                if (!layer) {
                    layer = document.createElementNS(SVG_NS, 'g');
                    layer.setAttribute('class', 'signature-node-layer');
                    svg.appendChild(layer);
                }
                return layer;
            }

            function getPathPoints(path) {
                try {
                    const points = JSON.parse(path.dataset.points || '[]');
                    return Array.isArray(points) ? points : [];
                } catch (err) {
                    return [];
                }
            }

            function setPathPoints(path, points) {
                const normalized = points.map(roundPoint);
                path.dataset.points = JSON.stringify(normalized);
                path.setAttribute('d', toSmoothPath(normalized));
            }

            function clearSelectedNode() {
                selectedNode = null;
            }

            function isSelectedNode(pathIndex, pointIndex) {
                return selectedNode &&
                    selectedNode.pathIndex === pathIndex &&
                    selectedNode.pointIndex === pointIndex;
            }

            function updateEditorButtons() {
                const hasPaths = getSignaturePaths().length > 0;
                if (drawModeBtn) drawModeBtn.classList.toggle('active', creatorMode === 'draw');
                if (editModeBtn) {
                    editModeBtn.classList.toggle('active', creatorMode === 'edit');
                    editModeBtn.disabled = !hasPaths;
                }
                if (addNodeBtn) {
                    addNodeBtn.classList.toggle('active', creatorMode === 'edit' && nodeTool === 'add');
                    addNodeBtn.disabled = creatorMode !== 'edit' || !hasPaths;
                }
                if (deleteNodeBtn) {
                    deleteNodeBtn.classList.toggle('active', creatorMode === 'edit' && nodeTool === 'delete');
                    deleteNodeBtn.disabled = creatorMode !== 'edit' || !hasPaths;
                }
                if (undoBtn) undoBtn.disabled = !hasPaths;
                svg.classList.toggle('node-edit-mode', creatorMode === 'edit');
            }

            function setCreatorMode(mode) {
                const hasPaths = getSignaturePaths().length > 0;
                creatorMode = (mode === 'edit' && hasPaths) ? 'edit' : 'draw';
                if (creatorMode !== 'edit') {
                    nodeTool = 'move';
                    clearSelectedNode();
                }
                updateEditorButtons();
                renderNodeHandles();
            }

            function setNodeTool(tool) {
                if (creatorMode !== 'edit') return;
                nodeTool = nodeTool === tool ? 'move' : tool;
                if (nodeTool !== 'delete') {
                    clearSelectedNode();
                }
                updateEditorButtons();
                renderNodeHandles();
            }

            function renderNodeHandles() {
                const layer = getEditorLayer();
                layer.innerHTML = '';
                if (creatorMode !== 'edit') return;

                const handleScale = 1 / Math.max(0.4, getSignatureZoomLevel());
                getSignaturePaths().forEach((path, pathIndex) => {
                    const points = getPathPoints(path);
                    points.forEach((point, pointIndex) => {
                        const handle = document.createElementNS(SVG_NS, 'circle');
                        const isEndpoint = pointIndex === 0 || pointIndex === points.length - 1;
                        const isActive = isSelectedNode(pathIndex, pointIndex);
                        handle.setAttribute('class', 'signature-node-handle' + (isEndpoint ? ' endpoint' : '') + (isActive ? ' active' : ''));
                        handle.setAttribute('cx', point.x);
                        handle.setAttribute('cy', point.y);
                        handle.setAttribute('r', (isEndpoint ? 4.2 : 3.8) * handleScale);
                        handle.dataset.pathIndex = String(pathIndex);
                        handle.dataset.pointIndex = String(pointIndex);
                        handle.addEventListener('pointerdown', startNodeDrag);
                        layer.appendChild(handle);
                    });
                });
            }

            function startNodeDrag(e) {
                if (creatorMode !== 'edit') return;
                const handle = e.currentTarget;
                const path = getSignaturePaths()[Number(handle.dataset.pathIndex)];
                if (!path) return;

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

                const pathIndex = Number(handle.dataset.pathIndex);
                const pointIndex = Number(handle.dataset.pointIndex);
                if (nodeTool === 'delete') {
                    deleteNodeAt(pathIndex, pointIndex);
                    return;
                }

                selectedNode = { pathIndex, pointIndex };
                const selectedWidth = parseFloat(path.getAttribute('stroke-width'));
                if (isFinite(selectedWidth)) {
                    creatorStrokeWidth = selectedWidth;
                    syncStrokeWidthControl();
                }
                activeNodeDrag = {
                    handle,
                    path,
                    points: getPathPoints(path),
                    pathIndex,
                    pointIndex,
                    pointerId: e.pointerId
                };
                handle.classList.add('active');
                if (svg.setPointerCapture) {
                    try { svg.setPointerCapture(e.pointerId); } catch (err) {}
                }
            }

            function moveActiveNode(e) {
                if (!activeNodeDrag || e.pointerId !== activeNodeDrag.pointerId) return false;
                e.preventDefault();
                const p = getSVGPos(e, svg);
                activeNodeDrag.points[activeNodeDrag.pointIndex] = p;
                setPathPoints(activeNodeDrag.path, activeNodeDrag.points);
                activeNodeDrag.handle.setAttribute('cx', p.x);
                activeNodeDrag.handle.setAttribute('cy', p.y);
                return true;
            }

            function stopActiveNode(e) {
                if (!activeNodeDrag || e.pointerId !== activeNodeDrag.pointerId) return false;
                if (svg.releasePointerCapture) {
                    try { svg.releasePointerCapture(e.pointerId); } catch (err) {}
                }
                activeNodeDrag.handle.classList.remove('active');
                activeNodeDrag = null;
                renderNodeHandles();
                return true;
            }

            function deleteNodeAt(pathIndex, pointIndex) {
                const path = getSignaturePaths()[pathIndex];
                if (!path) return;

                const points = getPathPoints(path);
                if (points.length <= 2) {
                    path.remove();
                    clearSelectedNode();
                } else {
                    points.splice(pointIndex, 1);
                    setPathPoints(path, points);
                    clearSelectedNode();
                }

                if (getSignaturePaths().length === 0) {
                    setCreatorMode('draw');
                    return;
                }

                nodeTool = 'move';
                updateEditorButtons();
                renderNodeHandles();
            }

            function deleteSelectedNodeOrEnableMode() {
                if (creatorMode !== 'edit') return;
                if (selectedNode) {
                    deleteNodeAt(selectedNode.pathIndex, selectedNode.pointIndex);
                    return;
                }
                setNodeTool('delete');
            }

            function closestPointOnSegment(point, a, b) {
                const dx = b.x - a.x;
                const dy = b.y - a.y;
                const lenSq = dx * dx + dy * dy;
                if (lenSq === 0) {
                    return { x: a.x, y: a.y, t: 0, distance: dist(point, a) };
                }
                const t = Math.max(0, Math.min(1, ((point.x - a.x) * dx + (point.y - a.y) * dy) / lenSq));
                const x = a.x + t * dx;
                const y = a.y + t * dy;
                return { x, y, t, distance: Math.hypot(point.x - x, point.y - y) };
            }

            function addNodeNearPointer(e) {
                if (creatorMode !== 'edit' || nodeTool !== 'add') return false;
                e.preventDefault();

                const point = getSVGPos(e, svg);
                let best = null;
                getSignaturePaths().forEach((path, pathIndex) => {
                    const points = getPathPoints(path);
                    for (let i = 0; i < points.length - 1; i++) {
                        const candidate = closestPointOnSegment(point, points[i], points[i + 1]);
                        if (!best || candidate.distance < best.distance) {
                            best = {
                                path,
                                pathIndex,
                                segmentIndex: i,
                                point: { x: candidate.x, y: candidate.y },
                                distance: candidate.distance
                            };
                        }
                    }
                });

                const addTolerance = 18 / Math.max(0.4, getSignatureZoomLevel());
                if (!best || best.distance > addTolerance) return false;

                const points = getPathPoints(best.path);
                points.splice(best.segmentIndex + 1, 0, best.point);
                setPathPoints(best.path, points);
                selectedNode = {
                    pathIndex: best.pathIndex,
                    pointIndex: best.segmentIndex + 1
                };
                nodeTool = 'move';
                updateEditorButtons();
                renderNodeHandles();
                return true;
            }

            function zoomSignatureAtPointer(e) {
                if (!signatureCtrlZoomKeyDown || !e.ctrlKey) return;
                e.preventDefault();

                const rect = svg.getBoundingClientRect();
                if (!rect.width || !rect.height) return;

                const box = getSignatureViewBox();
                const cursorX = box.x + ((e.clientX - rect.left) / rect.width) * box.w;
                const cursorY = box.y + ((e.clientY - rect.top) / rect.height) * box.h;
                const direction = e.deltaY < 0 ? 1 : -1;
                const factor = direction > 0 ? 0.88 : 1.12;
                const nextW = Math.max(signatureZoomLimits.minWidth, Math.min(signatureZoomLimits.maxWidth, box.w * factor));
                const nextH = nextW * (signatureInitialViewBox.h / signatureInitialViewBox.w);

                const ratioX = (cursorX - box.x) / box.w;
                const ratioY = (cursorY - box.y) / box.h;

                setSignatureViewBox({
                    x: cursorX - ratioX * nextW,
                    y: cursorY - ratioY * nextH,
                    w: nextW,
                    h: nextH
                });

                renderNodeHandles();
            }

            function undoLastStroke() {
                const paths = getSignaturePaths();
                const last = paths[paths.length - 1];
                if (last) last.remove();
                clearSelectedNode();
                if (getSignaturePaths().length === 0) {
                    setCreatorMode('draw');
                } else {
                    updateEditorButtons();
                    renderNodeHandles();
                }
            }

            function getSignatureBounds(paths) {
                let bounds = null;
                paths.forEach(path => {
                    try {
                        const box = path.getBBox();
                        if (!box || box.width === 0 || box.height === 0) return;
                        if (!bounds) {
                            bounds = {
                                x1: box.x,
                                y1: box.y,
                                x2: box.x + box.width,
                                y2: box.y + box.height
                            };
                        } else {
                            bounds.x1 = Math.min(bounds.x1, box.x);
                            bounds.y1 = Math.min(bounds.y1, box.y);
                            bounds.x2 = Math.max(bounds.x2, box.x + box.width);
                            bounds.y2 = Math.max(bounds.y2, box.y + box.height);
                        }
                    } catch (err) {}
                });
                if (!bounds) return null;
                return {
                    x: bounds.x1,
                    y: bounds.y1,
                    width: bounds.x2 - bounds.x1,
                    height: bounds.y2 - bounds.y1
                };
            }

            if (drawModeBtn) drawModeBtn.addEventListener('click', () => setCreatorMode('draw'));
            if (editModeBtn) editModeBtn.addEventListener('click', () => setCreatorMode('edit'));
            if (addNodeBtn) addNodeBtn.addEventListener('click', () => setNodeTool('add'));
            if (deleteNodeBtn) deleteNodeBtn.addEventListener('click', deleteSelectedNodeOrEnableMode);
            if (undoBtn) undoBtn.addEventListener('click', undoLastStroke);
            if (strokeWidthInput) {
                strokeWidthInput.addEventListener('input', () => applyStrokeWidth(strokeWidthInput.value));
                strokeWidthInput.addEventListener('change', () => applyStrokeWidth(strokeWidthInput.value));
            }
            syncStrokeWidthControl();
            svg.addEventListener('wheel', zoomSignatureAtPointer, { passive: false });
            document.addEventListener('keydown', e => {
                if (e.key === 'Control') {
                    signatureCtrlZoomKeyDown = true;
                }
            });
            document.addEventListener('keyup', e => {
                if (e.key === 'Control') {
                    signatureCtrlZoomKeyDown = false;
                }
            });
            window.addEventListener('blur', () => {
                signatureCtrlZoomKeyDown = false;
            });
            document.addEventListener('keydown', e => {
                const tag = (document.activeElement && document.activeElement.tagName || '').toLowerCase();
                if (tag === 'input' || tag === 'textarea' || tag === 'select') return;
                if (creatorMode === 'edit' && selectedNode && (e.key === 'Delete' || e.key === 'Backspace')) {
                    e.preventDefault();
                    deleteNodeAt(selectedNode.pathIndex, selectedNode.pointIndex);
                }
            });

            svg.style.touchAction = 'none';
            svg.style.pointerEvents = 'auto';
            getEditorLayer();
            updateEditorButtons();

            svg.addEventListener('pointerdown', e => {
                if (creatorMode === 'edit') {
                    addNodeNearPointer(e);
                    return;
                }
                if (creatorMode !== 'draw') return;
                isDrawing = true;
                rawPoints = [];
                smoothPoints = [];
                const p = getSVGPos(e, svg);
                rawPoints.push(p);
                smoothed = { x: p.x, y: p.y }; // inicia el seguidor (EMA)

                pathEl = document.createElementNS('http://www.w3.org/2000/svg', 'path');
                setPathStyle(pathEl);
                svg.insertBefore(pathEl, getEditorLayer());

                // ▶️ Inicia el trazado para que aparezca un punto inmediato.
                smoothPoints.push({ x: p.x, y: p.y });
                pathEl.setAttribute('d', `M ${p.x} ${p.y} L ${p.x + 0.01} ${p.y + 0.01}`);
            });


            svg.addEventListener('pointermove', e => {
                if (moveActiveNode(e)) return;
                if (!isDrawing) return;
                const r = getSVGPos(e, svg);
                const last = rawPoints[rawPoints.length - 1] || r;
                const dpx = dist(r, last);
                // Evita puntos en bruto demasiado densos.
                if (dpx < MIN_DIST) return;

                rawPoints.push(r);

                // Suavizado dinámico: menos suavizado a baja velocidad, más a velocidad alta.
                const speedFactor = Math.min(1, dpx / 8); // 0..1 aproximado
                const alpha = Math.max(0.08, Math.min(0.22, 0.08 + 0.14 * speedFactor));
                smoothed.x += (r.x - smoothed.x) * alpha;
                smoothed.y += (r.y - smoothed.y) * alpha;

                const prevS = smoothPoints[smoothPoints.length - 1] || smoothed;
                if (dist(smoothed, prevS) >= MIN_DIST) smoothPoints.push({ x: smoothed.x, y: smoothed.y });

                pathEl.setAttribute('d', toSmoothPath(smoothPoints));
            });

            svg.addEventListener('pointerup', e => {
                if (stopActiveNode(e)) return;
                if (!isDrawing) return;
                isDrawing = false;

                // Simplificación final para eliminar vibraciones y actualizar una sola vez.
                const simplified = rdp(smoothPoints, RDP_EPSILON);
                if (simplified.length >= 2) {
                    setPathPoints(pathEl, simplified);
                } else if (smoothPoints.length >= 2) {
                    setPathPoints(pathEl, smoothPoints);
                }
                updateEditorButtons();
                rawPoints = smoothPoints = [];
                smoothed = null;
            });

            svg.addEventListener('pointerleave', () => {
                if (!isDrawing) return;
                isDrawing = false;
                const simplified = rdp(smoothPoints, RDP_EPSILON);
                if (simplified.length >= 2) {
                    setPathPoints(pathEl, simplified);
                } else if (smoothPoints.length >= 2) {
                    setPathPoints(pathEl, smoothPoints);
                }
                updateEditorButtons();
                rawPoints = smoothPoints = [];
                smoothed = null;
            });


            function getSVGPos(e, svg) {
                const rect = svg.getBoundingClientRect();

                // Usa el viewBox si existe; si no, toma tamaño renderizado.
                const vb = svg.viewBox && svg.viewBox.baseVal
                    ? { x: svg.viewBox.baseVal.x, y: svg.viewBox.baseVal.y, w: svg.viewBox.baseVal.width, h: svg.viewBox.baseVal.height }
                    : { x: 0, y: 0, w: rect.width, h: rect.height };

                const scaleX = vb.w / rect.width;
                const scaleY = vb.h / rect.height;

                return {
                    x: vb.x + (e.clientX - rect.left) * scaleX,
                    y: vb.y + (e.clientY - rect.top) * scaleY
                };
            }


            // Eventos de interfaz del creador de firma (debajo).
            // === Botón de limpiar ===
            window.clearSignatureCanvas = function() {
                svg.innerHTML = '';
                activeNodeDrag = null;
                getEditorLayer();
                resetSignatureZoom();
                setCreatorMode('draw');
            }

            // === Botón de guardar ===
            window.saveNewSignature = function () {
            const signatureName = document.getElementById('signature-name-input').value.trim();
            if (!signatureName) {
                alert('Por favor, asigne un nombre a la firma.');
                return;
            }

            // Caja ajustada de los paths vectoriales (sin incluir el grosor).
            const signaturePaths = getSignaturePaths();
            const bbox = getSignatureBounds(signaturePaths);
            if (!bbox || bbox.width === 0 || bbox.height === 0) {
                alert('Por favor dibuje la firma antes de guardar.');
                return;
            }

            // --- Margen para que los trazos no se corten en los bordes ---
            const maxStrokeWidth = signaturePaths.reduce((max, path) => {
                const width = parseFloat(path.getAttribute('stroke-width'));
                return Math.max(max, isFinite(width) ? width : creatorStrokeWidth);
            }, creatorStrokeWidth);
            const PAD = Math.max(10, maxStrokeWidth * 4);
            const px = Math.floor(bbox.x - PAD);
            const py = Math.floor(bbox.y - PAD);
            const pw = Math.ceil(bbox.width + PAD * 2);
            const ph = Math.ceil(bbox.height + PAD * 2);

            // Rasteriza a mayor densidad para PNG nítido.
            const exportScale = Math.max(2, window.devicePixelRatio || 1);
            const canvas = document.createElement('canvas');
            canvas.width  = Math.max(1, Math.round(pw * exportScale));
            canvas.height = Math.max(1, Math.round(ph * exportScale));
            const ctx = canvas.getContext('2d');

            // Construye un SVG independiente recortado con margen.
            const exportSvg = svg.cloneNode(true);
            exportSvg.querySelectorAll('.signature-node-layer, .signature-node-handle').forEach(el => el.remove());
            const serialized = new XMLSerializer().serializeToString(exportSvg);
            const inner = serialized.replace(/^[\s\S]*?<svg[^>]*>|<\/svg>[\s\S]*$/g, '');
            const wrapped =
                `<svg xmlns="http://www.w3.org/2000/svg"
                    viewBox="${px} ${py} ${pw} ${ph}"
                    preserveAspectRatio="xMidYMid meet">
                ${inner}
                </svg>`;

            // Guarda directamente el SVG envuelto para mantener nitidez.
            const formData = new FormData();
            formData.append('signature_name', signatureName);
            formData.append('signature_data', wrapped);

            fetch('save_signature.php', { method: 'POST', body: formData })
            .then(async res => {
                const text = await res.text();
                try { return JSON.parse(text); }
                catch (e) { throw new Error('Respuesta inválida del servidor: ' + text); }
            })
            .then(data => {
                if (data.success) {
                alert('✅ Firma guardada correctamente');
                svg.innerHTML = '';
                activeNodeDrag = null;
                getEditorLayer();
                resetSignatureZoom();
                setCreatorMode('draw');
                document.getElementById('signature-name-input').value = '';
                // recarga el listado
                if (typeof loadSavedSignatures === 'function') loadSavedSignatures();
                } else {
                alert('❌ Error al guardar: ' + (data.message || 'desconocido'));
                }
            })
            .catch(err => {
                console.error('Error en saveNewSignature:', err);
                alert('❌ Error al guardar la firma: ' + err.message);
            });
            };


            // Reutiliza la función global loadSavedSignatures para no duplicar lógica.

            window.useSavedSignature = function(svgDataEncoded) {
                const svgMarkup = decodeURIComponent(svgDataEncoded);
                const signatureCanvas = document.getElementById('signature-canvas');
                const ctx = signatureCanvas.getContext('2d');

                // Dibuja el SVG sobre el canvas de firmas del PDF.
                const img = new Image();
                const svgBlob = new Blob([svgMarkup], { type: 'image/svg+xml;charset=utf-8' });
                const url = URL.createObjectURL(svgBlob);
                img.onload = function() {
                ctx.drawImage(img, 50, 50); // ajustar coordenadas si se requiere
                URL.revokeObjectURL(url);
                };
                img.src = url;
            };

            // Cargar las firmas guardadas al iniciar la página.
            loadSavedSignatures();
            });
        
        // ===== GESTIÓN DE FIRMAS =====
        document.getElementById('pdfFile').addEventListener('change', handleFileSelect);
        document.getElementById('prevPage').addEventListener('click', onPrevPage);
        document.getElementById('nextPage').addEventListener('click', onNextPage);
        document.getElementById('penTool').addEventListener('click', () => setTool('pen'));
        document.getElementById('useSavedTool').addEventListener('click', () => setTool('useSaved'));
        document.getElementById('eraserTool').addEventListener('click', () => setTool('eraser'));
        document.getElementById('clearSignature').addEventListener('click', clearCurrentSignature);
        document.getElementById('saveDocument').addEventListener('click', saveDocument);
        document.getElementById('newDocument').addEventListener('click', resetForNewDocument);
        
        
        function switchTab(tab) {
            document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
            document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
            const signatureSectionTitle = document.getElementById('signature-section-title');
            
            if (tab === 'create') {
                document.querySelector('.tab-btn:nth-child(1)').classList.add('active');
                document.getElementById('create-tab').classList.add('active');
                if (signatureSectionTitle) signatureSectionTitle.textContent = 'Dibuje firma';
                initSignatureSvgIfNeeded();
            } else {
                document.querySelector('.tab-btn:nth-child(2)').classList.add('active');
                document.getElementById('saved-tab').classList.add('active');
                if (signatureSectionTitle) signatureSectionTitle.textContent = 'Usar firma';
                loadSavedSignatures();
            }
        }

        function initSignatureSvgIfNeeded() {
            const svg = document.getElementById('create-signature-svg');
            if (!svg) return;
            if (!svg.getAttribute('viewBox')) {
                const w = svg.clientWidth || 800, h = svg.clientHeight || 200;
                svg.setAttribute('viewBox', `0 0 ${w} ${h}`);
            }
            svg.style.touchAction = 'none';
            svg.style.pointerEvents = 'auto';
        }
        // Se retiró el creador en canvas para evitar conflictos con la versión SVG.

        async function loadSavedSignatures() {
            try {
                const response = await fetch('list_signatures.php?user_id=' + currentUserId);
                const sigList = await response.json();

                const container = document.getElementById('saved-signatures-container');
                const createBtn = document.querySelector('.signature-tabs .tab-btn:nth-child(1)');
                const savedBtn = document.querySelector('.signature-tabs .tab-btn:nth-child(2)');
                const tabs = document.querySelector('.signature-tabs');
                const signatureManagement = document.querySelector('.signature-management');
                const signatureSectionTitle = document.getElementById('signature-section-title');
                const createTab = document.getElementById('create-tab');
                const savedTab = document.getElementById('saved-tab');
                if (tabs) tabs.classList.add('single-tab');

                // Caché local para auto-seleccionar firmas por defecto.
                userSavedSignatures = Array.isArray(sigList) ? sigList : [];

                // Si no hay firmas: se muestra solo "Crear Firma".
                if (!sigList || sigList.length === 0) {
                    if (signatureManagement) signatureManagement.classList.remove('saved-signature-only');
                    if (signatureSectionTitle) signatureSectionTitle.textContent = 'Dibuje firma';
                    if (createBtn) createBtn.style.display = '';
                    if (savedBtn) savedBtn.style.display = 'none';

                    // Garantiza que la pestaña de creación quede activa.
                    document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
                    document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active'));
                    if (createBtn) createBtn.classList.add('active');
                    if (createTab) createTab.classList.add('active');

                    // Mantiene el estado vacío informativo aunque la pestaña se oculte.
                    container.innerHTML = `
                        <div class="empty-state">
                            <div class="empty-state-icon">✍️</div>
                            <p>No hay firmas guardadas. Cree su primera firma en la pestaña "Crear Firma".</p>
                        </div>
                    `;

                    // Asegura la inicialización del creador SVG.
                    initSignatureSvgIfNeeded();
                    // Limpia cualquier selección previa de firma guardada.
                    selectedSavedSignature = null;
                    applyDefaultSigningTool();
                    return;
                }

                // Si hay firmas: muestra solo "Firmas Guardadas" y la activa.
                if (signatureManagement) signatureManagement.classList.add('saved-signature-only');
                if (signatureSectionTitle) signatureSectionTitle.textContent = 'Usar firma';
                if (createBtn) createBtn.style.display = 'none';
                if (savedBtn) savedBtn.style.display = '';

                document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
                document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active'));
                if (savedBtn) savedBtn.classList.add('active');
                if (savedTab) savedTab.classList.add('active');

                container.innerHTML = '<div class="saved-signatures-grid" id="signatures-grid"></div>';
                const grid = document.getElementById('signatures-grid');

                sigList.forEach(sig => {
                    const card = document.createElement('div');
                    card.className = 'signature-card';

                // Prefiere SVG incrustado devuelto como `svg` o legado `svg_de_la_firma`.
                    let previewHtml = '';
                if(sig.svg_de_la_firma.startsWith('<svg')) {
                    previewHtml = sig.svg_de_la_firma;
                } else if(sig.svg_de_la_firma.startsWith('data:image'))
                {
                 previewHtml = `<img src="${sig.svg_de_la_firma}" alt="Firma" style="max-width:100%; height:auto;">`;   
                } else {
                    previewHtml = `<img src="data:image/png;base64,${sig.svg_de_la_firma}" alt="Firma">`;
                }
                    // preview alternativo: sig.svg || sig.svg_de_la_firma

                const displayName = (sig.name || sig.nombre_de_la_firma || '');
                const signatureId = sig.id;
                card.dataset.signatureName = displayName;


                card.innerHTML = `
                <div class="signature-preview">${previewHtml}</div>
                <div class="signature-card-actions">
                    <button type="button" class="signature-card-btn signature-card-btn-delete" title="Eliminar firma">
                        🗑️
                    </button>
                </div>
                `;

                // Conecta las acciones con los valores reales (sin JSON enplantilla).
                const deleteBtn = card.querySelector('.signature-card-btn-delete');
                const svgContent = sig.svg || sig.svg_de_la_firma || '';
                card.addEventListener('click', (ev) => selectSignatureFromSvg(svgContent, displayName, ev));
                deleteBtn.addEventListener('click', (ev) => deleteSignatureById(sig.id, ev));

                    grid.appendChild(card);
                });

                // Auto-selección: prioriza la firma por defecto; si hay solo una, se elige.
                selectPreferredSavedSignature(false);
                applyDefaultSigningTool();
            } catch (error) {
                console.error('Error al cargar las firmas:', error);
            }
        }

        function selectSignatureFromSvg(svg, name, event) {
            if (event) event.stopPropagation();
            selectedSavedSignature = { type: 'svg', svg, name };

            // Actualiza la selección visual.
            document.querySelectorAll('.signature-card').forEach(card => card.classList.remove('selected'));
            event.target.closest('.signature-card').classList.add('selected');

            showStatus(`Firma "${name}" seleccionada. Use la herramienta "Usar Firma Guardada" para colocarla en el documento`, 'success');
        }

        async function deleteSignatureById(id, event) {
            if (event) event.stopPropagation();
            if (!confirm('¿Está seguro que desea eliminar esta firma?')) return;
            try {
                const response = await fetch('delete_signature.php', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ id })
                });
                const result = await response.json();
                if (result.success) {
                    showStatus('Firma eliminada exitosamente', 'success');
                    selectedSavedSignature = null;
                    loadSavedSignatures();
                } else {
                    showStatus('Error: ' + (result.message || 'No se pudo eliminar'), 'error');
                }
            } catch (error) {
                showStatus('Error al eliminar la firma', 'error');
            }
        }

        // ===== MANEJO DEL PDF =====

        function getEventPos(e) {
            const rect = sigOverlay.getBoundingClientRect();
            const x = (e.clientX - rect.left);
            const y = (e.clientY - rect.top);
            return { x, y };
        }

        function handleFileSelect(e) {
            const file = e.target.files[0];
            if (file && file.type === 'application/pdf') {
                uploadedFile = file;
                const fileReader = new FileReader();
                fileReader.onload = function() {
                    const typedarray = new Uint8Array(this.result);
                    loadPDF(typedarray);
                };
                fileReader.readAsArrayBuffer(file);
            }
        }

        function loadPDF(data) {
            pdfjsLib.getDocument(data).promise.then(function(pdf) {
                pdfDoc = pdf;
                document.getElementById('uploadSection').classList.add('hidden');
                document.getElementById('pdfViewer').style.display = 'block';
                renderPage(pageNum);
                attachCanvasEvents();
            });
        }

        function resetForNewDocument() {
            // Limpia estados y vuelve a mostrar la carga inicial.
            signatures = {};
            selectedSavedSignature = null;
            uploadedFile = null;
            pdfDoc = null;
            pageNum = 1;
            pageRendering = false;
            pageNumPending = null;
            signatureTransformDrag = null;

            // Limpia contenidos de lienzos y overlay.
            [pdfCanvas, sigCanvas].forEach(c => {
                c.width = 0;
                c.height = 0;
                c.style.width = '';
                c.style.height = '';
            });
            while (sigOverlay.firstChild) sigOverlay.removeChild(sigOverlay.firstChild);
            sigCtx.clearRect(0, 0, sigCanvas.width || 1, sigCanvas.height || 1);

            // UI: muestra cargador, oculta visor, resetea textos/controles.
            document.getElementById('uploadSection').classList.remove('hidden');
            document.getElementById('pdfViewer').style.display = 'none';
            document.getElementById('pageInfo').textContent = 'Página 1 de 1';
            document.getElementById('prevPage').disabled = true;
            document.getElementById('nextPage').disabled = true;

            // Limpia inputs y mensajes.
            const fileInput = document.getElementById('pdfFile');
            if (fileInput) fileInput.value = '';
            const statusEl = document.getElementById('statusMessage');
            if (statusEl) statusEl.style.display = 'none';
            const loadingEl = document.getElementById('loading');
            if (loadingEl) loadingEl.style.display = 'none';
        }

        function renderPage(num) {
            pageRendering = true;
            pdfDoc.getPage(num).then(function(page) {
                // Calcula la escala para llenar el ancho del contenedor sin márgenes laterales.
                const container = document.getElementById('canvasContainer');
                const DPR = window.devicePixelRatio || 1;
                const baseViewport = page.getViewport({ scale: 1 });
                const containerCSSWidth = Math.max(1, container.clientWidth);
                const computedScale = containerCSSWidth / baseViewport.width;
                const viewport = page.getViewport({ scale: computedScale });

                 

                pdfCanvas.style.width = viewport.width + 'px';
                pdfCanvas.style.height = viewport.height + 'px';
                sigCanvas.style.width = viewport.width + 'px';
                sigCanvas.style.height = viewport.height + 'px';
                sigOverlay.style.width = viewport.width + 'px';
                sigOverlay.style.height = viewport.height + 'px';
                sigOverlay.setAttribute('viewBox', `0 0 ${viewport.width} ${viewport.height}`);

                pdfCanvas.width = Math.floor(viewport.width * DPR);
                pdfCanvas.height = Math.floor(viewport.height * DPR);
                sigCanvas.width = Math.floor(viewport.width * DPR);
                sigCanvas.height = Math.floor(viewport.height * DPR);

                pdfCtx.setTransform(1,0,0,1,0,0);
                pdfCtx.scale(DPR, DPR);
                sigCtx.setTransform(1,0,0,1,0,0);
                sigCtx.scale(DPR, DPR);

                const renderContext = {
                    canvasContext: pdfCtx,
                    viewport: viewport
                }; 

                const renderTask = page.render(renderContext);
                renderTask.promise.then(function() {
                    pageRendering = false;
                    if (pageNumPending !== null) {
                        renderPage(pageNumPending);
                        pageNumPending = null;
                    }
                    loadSignatureForPage(num);
                });
            });

            document.getElementById('pageInfo').textContent = `Página ${num} de ${pdfDoc.numPages}`;
            document.getElementById('prevPage').disabled = (num <= 1);
            document.getElementById('nextPage').disabled = (num >= pdfDoc.numPages);
        }

        function queueRenderPage(num) {
            if (pageRendering) {
                pageNumPending = num;
            } else {
                renderPage(num);
            }
        }

        function onPrevPage() {
            if (pageNum <= 1) return;
            saveCurrentSignature();
            pageNum--;
            queueRenderPage(pageNum);
        }

        function onNextPage() {
            if (pageNum >= pdfDoc.numPages) return;
            saveCurrentSignature();
            pageNum++;
            queueRenderPage(pageNum);
        }

        // Obtiene el recuadro ajustado de píxeles dibujados; usa devicePixelRatio para exportar nítido.
        function getSignatureBoundingBox(canvas, ctx, padding = 0, exportScale = Math.max(2, window.devicePixelRatio || 1)) {
            const w = canvas.width, h = canvas.height;
            const img = ctx.getImageData(0, 0, w, h).data;
            let minX = w, minY = h, maxX = 0, maxY = 0;
            let found = false;

            for (let y = 0; y < h; y++) {
                for (let x = 0; x < w; x++) {
                    const idx = (y * w + x) * 4;
                    const alpha = img[idx + 3];
                    if (alpha > 10) {
                        found = true;
                        if (x < minX) minX = x;
                        if (x > maxX) maxX = x;
                        if (y < minY) minY = y;
                        if (y > maxY) maxY = y;
                    }
                }
            }

            if (!found) return null;

            minX = Math.max(0, minX - padding);
            minY = Math.max(0, minY - padding);
            maxX = Math.min(w - 1, maxX + padding);
            maxY = Math.min(h - 1, maxY + padding);

            const sw = maxX - minX + 1;
            const sh = maxY - minY + 1;

            const tmp = document.createElement('canvas');
            tmp.width = Math.round(sw * exportScale);
            tmp.height = Math.round(sh * exportScale);
            const tctx = tmp.getContext('2d', { alpha: true });
            // Mantiene líneas nítidas evitando difuminado al reescalar.
            tctx.imageSmoothingEnabled = false;
            tctx.drawImage(canvas,
                minX, minY, sw, sh,
                0, 0, tmp.width, tmp.height
            );

            const dataUrl = tmp.toDataURL('image/png');
            return { dataUrl, x: minX, y: minY, width: sw, height: sh, exportScale };
        }

        /// Intenta capturar el contenido del overlay como SVG (vector). Devuelve true si lo logra.
        function captureVectorFromOverlay() {
            if (!sigOverlay || !sigOverlay.firstChild) return false;
            const children = getOverlaySignatureElements();
            if (children.length === 0) return false;

            // Calcula el bbox ajustado de todos los elementos.
            let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
            let any = false;
            // Caso especial: solo un <image> que ya apunta a data:image/svg+xml.
            if (children.length === 1 && children[0].tagName && children[0].tagName.toLowerCase() === 'image') {
                const imgEl = children[0];
                const href = imgEl.getAttribute('href') || imgEl.getAttribute('xlink:href') || '';
                if (href.startsWith('data:image/svg+xml')) {
                    const x = parseFloat(imgEl.getAttribute('x') || '0') || 0;
                    const y = parseFloat(imgEl.getAttribute('y') || '0') || 0;
                    const w = Math.max(1, parseFloat(imgEl.getAttribute('width') || '0') || 0);
                    const h = Math.max(1, parseFloat(imgEl.getAttribute('height') || '0') || 0);

                    const rectNow = pdfCanvas.getBoundingClientRect();
                    const cssW = Math.max(1, rectNow.width);
                    const cssH = Math.max(1, rectNow.height);
                    const xNorm = x / cssW;
                    const yNorm = y / cssH;
                    const wNorm = w / cssW;
                    const hNorm = h / cssH;
                    const DPR = window.devicePixelRatio || 1;

                    signatures[pageNum] = {
                        image: href,
                        x: Math.round(x * DPR),
                        y: Math.round(y * DPR),
                        width: Math.round(w * DPR),
                        height: Math.round(h * DPR),
                        canvasPixelWidth: Math.round(cssW * DPR),
                        canvasPixelHeight: Math.round(cssH * DPR),
                        xNorm, yNorm, wNorm, hNorm,
                        dpr: DPR,
                        vector: true
                    };
                    return true; 
                }
            }
            for (const el of children) {
                if (typeof el.getBBox === 'function') {
                    const b = el.getBBox();
                    if (!b || !(b.width > 0 && b.height > 0)) continue;
                    any = true;
                    if (b.x < minX) minX = b.x;
                    if (b.y < minY) minY = b.y;
                    if (b.x + b.width > maxX) maxX = b.x + b.width;
                    if (b.y + b.height > maxY) maxY = b.y + b.height;
                }
            }
            if (!any) return false;

            const PAD = Math.max(10, (typeof STROKE_WIDTH === 'number' ? STROKE_WIDTH : 2) * 3);
            const px = Math.floor(minX - PAD);
            const py = Math.floor(minY - PAD);
            const pw = Math.ceil((maxX - minX) + PAD * 2);
            const ph = Math.ceil((maxY - minY) + PAD * 2);

            // Serializa los elementos dentro de un SVG recortado.
            const serializer = new XMLSerializer();
            const inner = children.map(el => serializer.serializeToString(el)).join('');
            const wrapped = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${px} ${py} ${pw} ${ph}" preserveAspectRatio="xMidYMid meet">${inner}</svg>`;
            const dataUrl = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(wrapped);

            const rectNow = pdfCanvas.getBoundingClientRect();
            const cssW = Math.max(1, rectNow.width);
            const cssH = Math.max(1, rectNow.height);
            const xNorm = px / cssW;
            const yNorm = py / cssH;
            const wNorm = pw / cssW;
            const hNorm = ph / cssH;
            const DPR = window.devicePixelRatio || 1;

            signatures[pageNum] = {
                image: dataUrl,
                x: Math.round(px * DPR),
                y: Math.round(py * DPR),
                width: Math.round(pw * DPR),
                height: Math.round(ph * DPR),
                canvasPixelWidth: Math.round(cssW * DPR),
                canvasPixelHeight: Math.round(cssH * DPR),
                xNorm, yNorm, wNorm, hNorm,
                dpr: DPR,
                vector: true
            };
            return true;
        }

        function saveCurrentSignature() {
            const placedImage = getPlacedSignatureImage();
            if (signatures[pageNum] && placedImage) {
                const box = readSignatureImageBox(placedImage);
                if (box) updateSignatureObjectFromBox(box);
                return;
            }

            // Si ya es vector, no sobrescribe.
            if (signatures[pageNum] && signatures[pageNum].vector === true) return;
            // Prefiere capturar el overlay vectorial existente.
            if (captureVectorFromOverlay()) return;
            const bbox = getSignatureBoundingBox(sigCanvas, sigCtx, 0);
            if (!bbox) {
                delete signatures[pageNum];
                strokePoints = [];
                return;
            }

            // Normaliza usando el tamaño en píxeles CSS del canvas PDF (independiente del DPR).
            const DPR = window.devicePixelRatio || 1;
            const rectNow = document.getElementById('pdf-canvas').getBoundingClientRect();
            const cssW = Math.max(1, rectNow.width);
            const cssH = Math.max(1, rectNow.height);
            const xNorm = (bbox.x / DPR) / cssW;
            const yNorm = (bbox.y / DPR) / cssH;
            const wNorm = (bbox.width / DPR) / cssW;
            const hNorm = (bbox.height / DPR) / cssH;

            

            signatures[pageNum] = {
                image: bbox.dataUrl,
                // coordenadas absolutas (píxeles de dispositivo al capturar)
                x: Math.round(bbox.x),
                y: Math.round(bbox.y),
                width: Math.round(bbox.width),
                height: Math.round(bbox.height),
                canvasPixelWidth: sigCanvas.width,
                canvasPixelHeight: sigCanvas.height,
                // fracciones normalizadas del canvas
                xNorm, yNorm, wNorm, hNorm,
                exportScale: bbox.exportScale || 1,
                dpr: DPR
            };

            strokePoints = [];
        }

        function loadSignatureForPage(num) {
            // Limpia el overlay.
            while (sigOverlay.firstChild) sigOverlay.removeChild(sigOverlay.firstChild);
            const sigObj = signatures[num];
            if (!sigObj) return;

            const rectNow = pdfCanvas.getBoundingClientRect();
            const cssW = Math.max(1, rectNow.width);
            const cssH = Math.max(1, rectNow.height);
            let xCss, yCss, wCss, hCss;
            if (typeof sigObj.xNorm === 'number' && typeof sigObj.wNorm === 'number') {
                xCss = sigObj.xNorm * cssW;
                yCss = sigObj.yNorm * cssH;
                wCss = Math.max(1, sigObj.wNorm * cssW);
                hCss = Math.max(1, sigObj.hNorm * cssH);
            } else {
                const DPR = window.devicePixelRatio || 1;
                xCss = (sigObj.x || 0) / DPR;
                yCss = (sigObj.y || 0) / DPR;
                wCss = Math.max(1, (sigObj.width  || 0) / DPR);
                hCss = Math.max(1, (sigObj.height || 0) / DPR);
            }

            const imgEl = document.createElementNS('http://www.w3.org/2000/svg','image');
            imgEl.setAttribute('href', sigObj.image);
            imgEl.setAttribute('x', xCss);
            imgEl.setAttribute('y', yCss);
            imgEl.setAttribute('width', wCss);
            imgEl.setAttribute('height', hCss);
            bindPlacedSignatureImage(imgEl);
            sigOverlay.appendChild(imgEl);
            rememberSavedSignatureSize({ x: xCss, y: yCss, w: wCss, h: hCss });
            renderSignatureTransformHandles();
        }

        function getSavedSignatureName(signature) {
            if (!signature) return '';
            return (signature.name || signature.nombre_de_la_firma || '').toString();
        }

        function getPreferredSavedSignature() {
            if (!userSavedSignatures || userSavedSignatures.length === 0) return null;
            return userSavedSignatures.find(s => s.is_default == 1 || s.es_por_defecto == 1) || userSavedSignatures[0];
        }

        function markSelectedSavedSignatureCard(signature) {
            const targetName = getSavedSignatureName(signature).trim();
            document.querySelectorAll('.signature-card').forEach(card => {
                const cardName = (card.dataset.signatureName || '').trim();
                if (targetName && cardName === targetName) card.classList.add('selected');
                else card.classList.remove('selected');
            });
        }

        function selectPreferredSavedSignature(showMessage = false) {
            const signature = getPreferredSavedSignature();
            if (!signature) return null;

            selectedSavedSignature = signature;
            markSelectedSavedSignatureCard(signature);

            if (showMessage) {
                const signatureName = getSavedSignatureName(signature);
                showStatus(`Firma "${signatureName}" seleccionada automÃ¡ticamente`, 'success');
            }

            return signature;
        }

        function applyDefaultSigningTool() {
            if (userSavedSignatures && userSavedSignatures.length > 0) {
                if (!selectedSavedSignature) selectPreferredSavedSignature(false);
                setTool('useSaved');
            } else {
                setTool('pen');
            }
        }

        function setTool(tool) {
            currentTool = tool;
            document.querySelectorAll('.tool-btn').forEach(btn => btn.classList.remove('active'));
            
            if (tool === 'pen') {
                document.getElementById('penTool').classList.add('active');
                sigOverlay.style.cursor = 'crosshair';
            } else if (tool === 'useSaved') {
                document.getElementById('useSavedTool').classList.add('active');
                sigOverlay.style.cursor = 'pointer';
                // Si no hay selección, intenta elegir la predeterminada o la única disponible.
                if (!selectedSavedSignature && userSavedSignatures && userSavedSignatures.length) {
                    selectPreferredSavedSignature(true);
                }
                if (!selectedSavedSignature) {
                    showStatus('Por favor seleccione una firma guardada primero', 'error');
                    setTool('pen');
                }
            } else {
                document.getElementById('eraserTool').classList.add('active');
                sigOverlay.style.cursor = 'crosshair';
            }
        }

        function clearCurrentSignature() {
            signatureTransformDrag = null;
            while (sigOverlay.firstChild) sigOverlay.removeChild(sigOverlay.firstChild);
            delete signatures[pageNum];
            strokePoints = []; 
        }

        function stopDrawing(e) {
            if (!isDrawing) return;
            isDrawing = false;
            if (!currentPathEl) return;
            // Construye el path final con el último segmento trazado.
            if (strokePoints.length >= 2) {
                let d = `M ${strokePoints[0].x} ${strokePoints[0].y}`;
                for (let i = 1; i < strokePoints.length - 1; i++) {
                    const cp = strokePoints[i];
                    const mx = (cp.x + strokePoints[i + 1].x) / 2;
                    const my = (cp.y + strokePoints[i + 1].y) / 2;
                    d += ` Q ${cp.x} ${cp.y} ${mx} ${my}`;
                }
                currentPathEl.setAttribute('d', d);
            }

            // Captura todo lo dibujado en el overlay (incluyendo trazos previos) como SVG.
            const captured = captureVectorFromOverlay();
            if (!captured) {
                // Si no se capturó nada, limpia el path vacío.
                if (currentPathEl.parentNode === sigOverlay) {
                    sigOverlay.removeChild(currentPathEl);
                }
            }

            currentPathEl = null;
            strokePoints = [];
        }

        function startDrawing(e) {
            if (e.button !== undefined && e.button !== 0) return;
            e.preventDefault();

            // Maneja la herramienta "Usar firma guardada".
            if (currentTool === 'useSaved') {
                if (!selectedSavedSignature) {
                    showStatus('Por favor seleccione una firma guardada primero', 'error');
                    return;
                }
                placeSavedSignature(e);
                return;
            }
            if (currentTool === 'eraser') {
                clearCurrentSignature();
                return;
            }

            activePointerId = e.pointerId;
            try { sigOverlay.setPointerCapture(activePointerId); } catch (ex) {}

            isDrawing = true;
            strokePoints = [];
  
            const { x, y } = getEventPos(e);
            strokePoints.push({ x, y });
            currentPathEl = document.createElementNS('http://www.w3.org/2000/svg','path');
            currentPathEl.setAttribute('fill', 'none');
            currentPathEl.setAttribute('stroke', '#000');
            currentPathEl.setAttribute('stroke-width', STROKE_WIDTH);
            currentPathEl.setAttribute('stroke-linecap', 'round');
            currentPathEl.setAttribute('stroke-linejoin', 'round');
            currentPathEl.setAttribute('shape-rendering', 'geometricPrecision');
            sigOverlay.appendChild(currentPathEl);
        }

        // Función de dibujo en overlay para firmas manuales.
        function draw(e) {
            if (!isDrawing) return;
            if (e.pointerId !== activePointerId) return;
            e.preventDefault();

            const { x, y } = getEventPos(e);
            
            // Filtrado de puntos para mantener trazos suaves en movimientos lentos.
            if (strokePoints.length > 0) {
                const lastPoint = strokePoints[strokePoints.length - 1];
                // Solo registra el punto si la distancia es mayor a 2 píxeles CSS.
                const distance = Math.sqrt(Math.pow(x - lastPoint.x, 2) + Math.pow(y - lastPoint.y, 2));
                if (distance < 2) { 
                    return; 
                }
            }
 
            strokePoints.push({ x, y });
  
            // Evita descartar puntos previos (antes desaparecían segmentos viejos).
            // Si se requiere, se podrían segmentar trazos largos; aquí no se mueve nada.

            if (strokePoints.length < 2 || !currentPathEl) return;
            let d = `M ${strokePoints[0].x} ${strokePoints[0].y}`;
            for (let i = 1; i < strokePoints.length - 1; i++) {
                const cp = strokePoints[i];
                const mx = (cp.x + strokePoints[i + 1].x) / 2;
                const my = (cp.y + strokePoints[i + 1].y) / 2;
                d += ` Q ${cp.x} ${cp.y} ${mx} ${my}`;
            }
            currentPathEl.setAttribute('d', d);
        }

        async function placeSavedSignature(e) {
            if (!selectedSavedSignature) return;
            try {
                const { x, y } = getEventPos(e);
                const preservedPlacementSize = getSavedSignaturePlacementSize();
                const img = new Image();
                let imageSource = '';
                const value = selectedSavedSignature.svg_de_la_firma || selectedSavedSignature.svg || '';
                let svgDataUrl = '';

                if (value.startsWith('<svg')) {
                    // SVG: crea un blob URL.
                    const svgBlob = new Blob([value], { type: 'image/svg+xml;charset=utf-8' });
                    imageSource = URL.createObjectURL(svgBlob);
                    svgDataUrl = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(value);
                }
                else if (value.startsWith('data:image')) {
                    // PNG/JPEG: ya es un data URL.
                    imageSource = value;
                    if (value.startsWith('data:image/svg+xml')) {
                        svgDataUrl = value;
                    }
                }
                else if (/^[A-Za-z0-9+/=]+$/.test(value)) {
                    // Base64 crudo (sin prefijo).
                    imageSource = 'data:image/png;base64,' + value;
                }
                else {
                    showStatus('Formato de firma no soportado', 'error');
                    return;
                }

                if(!imageSource){
                    showStatus('Fuente de firma inválida', 'error');
                    return;
                }   
                
                img.onload = function() {
                        const pdfRect = document.getElementById('pdf-canvas').getBoundingClientRect();
                        // Tama�o base reducido en m�vil: ~28% del ancho del PDF, con l�mites inferiores/superiores.
                        const baseMaxWidth = Math.max(80, Math.min(160, pdfRect.width * 0.28));
                        const scaleFactor = 1.0;
                        let baseWidth = baseMaxWidth;
                        let baseHeight = baseWidth * (img.height / img.width);
                        let width = baseWidth * scaleFactor;
                        let height = baseHeight * scaleFactor;

                        if (preservedPlacementSize) {
                            width = preservedPlacementSize.w;
                            height = preservedPlacementSize.h;
                            baseWidth = width / scaleFactor;
                            baseHeight = height / scaleFactor;
                        }
                        const drawX = x - (width / 2);
                        const drawY = y - (height / 2);
                        // Renderiza la vista previa como <image> en el overlay vectorial.
                        while (sigOverlay.firstChild) sigOverlay.removeChild(sigOverlay.firstChild);
                        const imgEl = document.createElementNS('http://www.w3.org/2000/svg','image');
                        imgEl.setAttribute('href', svgDataUrl || imageSource);
                        imgEl.setAttribute('x', drawX);
                        imgEl.setAttribute('y', drawY);
                        imgEl.setAttribute('width', width);
                        imgEl.setAttribute('height', height);
                        bindPlacedSignatureImage(imgEl);
                        sigOverlay.appendChild(imgEl);
                        
                        if(imageSource.startsWith('blob:')){
                            URL.revokeObjectURL(imageSource);
                        }
                        // Guarda la posición usando coordenadas normalizadas y prioriza vector si existe.
                        const rectNow = document.getElementById('pdf-canvas').getBoundingClientRect();
                        const cssW = Math.max(1, rectNow.width);
                        const cssH = Math.max(1, rectNow.height);
                        const xNorm = drawX / cssW;
                        const yNorm = drawY / cssH;
                        const wNorm = width / cssW;
                        const hNorm = height / cssH;
                        const baseWNorm = baseWidth / cssW;
                        const baseHNorm = baseHeight / cssH;
                        const DPR = window.devicePixelRatio || 1;

                        signatures[pageNum] = {
                            image: svgDataUrl || imageSource,
                            x: Math.round(drawX * DPR),
                            y: Math.round(drawY * DPR),
                            width: Math.round(width * DPR),
                            height: Math.round(height * DPR),
                            canvasPixelWidth: sigCanvas.width,
                            canvasPixelHeight: sigCanvas.height,
                            xNorm, yNorm, wNorm, hNorm,
                            baseWNorm, baseHNorm,
                            dpr: DPR,
                            vector: !!svgDataUrl
                        };

                        rememberSavedSignatureSize({ x: drawX, y: drawY, w: width, h: height });
                        renderSignatureTransformHandles();
                        showStatus('Firma colocada exitosamente', 'success');
                    };
                    img.onerror = function(event) {
                        console.error('Error al cargar la imagen de firma:', event);
                        console.error('La fuente de la imagen era:', imageSource); 
                        showStatus('Error al cargar la firma guardada', 'error'); 

                    };
                    img.src = imageSource;
            } catch (error) {
                console.error(error);
                showStatus('Error al colocar la firma', 'error');
            }
        }

        async function saveDocument() {
            if (Object.keys(signatures).length === 0) {
                showStatus('Por favor agregue al menos una firma al documento', 'error');
                return;
            }

            saveCurrentSignature();
            document.getElementById('loading').style.display = 'block';

            const formData = new FormData();
            formData.append('pdf', uploadedFile);
            formData.append('signerName', currentUserFullName);
            formData.append('signatures', JSON.stringify(signatures));
            formData.append('totalPages', pdfDoc.numPages);

            try {
                const response = await fetch('process_signature.php', {
                    method: 'POST',
                    body: formData
                });

                const result = await response.json();
                document.getElementById('loading').style.display = 'none';

                if (result.success) {
                    showStatus('Documento firmado exitosamente. Descargando...', 'success');
                    window.location.href = result.downloadUrl;
                } else {
                    showStatus('Error: ' + result.message, 'error');
                }
            } catch (error) {
                document.getElementById('loading').style.display = 'none';
                showStatus('Error al procesar el documento', 'error');
            }
        }

        function showStatus(message, type) {
            const statusEl = document.getElementById('statusMessage');
            statusEl.textContent = message;
            statusEl.className = 'status-message ' + type;
            statusEl.style.display = 'block';
            setTimeout(() => {
                statusEl.style.display = 'none';
            }, 5000);
        }

        function attachCanvasEvents() {
            // Enlaza eventos al overlay vectorial.
            sigOverlay.style.touchAction = 'none';
            sigOverlay.style.position = 'absolute';
            sigOverlay.style.top = '0';
            sigOverlay.style.left = '0';
            sigOverlay.style.zIndex = '22';

            sigOverlay.removeEventListener('pointerdown', startDrawing);
            sigOverlay.removeEventListener('pointermove', updateSignatureTransform);
            sigOverlay.removeEventListener('pointerup', finishSignatureTransform);
            sigOverlay.removeEventListener('pointercancel', finishSignatureTransform);
            sigOverlay.removeEventListener('pointermove', draw);
            sigOverlay.removeEventListener('pointerup', stopDrawing);
            sigOverlay.removeEventListener('pointercancel', stopDrawing);
            sigOverlay.removeEventListener('pointerleave', stopDrawing);

            sigOverlay.addEventListener('pointerdown', startDrawing, { passive: false });
            sigOverlay.addEventListener('pointermove', updateSignatureTransform, { passive: false });
            sigOverlay.addEventListener('pointerup', finishSignatureTransform, { passive: false });
            sigOverlay.addEventListener('pointercancel', finishSignatureTransform, { passive: false });
            sigOverlay.addEventListener('pointermove', draw, { passive: false });
            sigOverlay.addEventListener('pointerup', stopDrawing, { passive: false });
            sigOverlay.addEventListener('pointercancel', stopDrawing, { passive: false });
            sigOverlay.addEventListener('pointerleave', stopDrawing, { passive: false });
        }

        function logout() {
            if (confirm('¿Está seguro que desea cerrar sesión?')) {
                window.location.href = 'logout';
            }
        }

        // Re-renderiza al redimensionar la ventana para mantener alineados PDF y overlay.
        // Recalcula DPR, reinicia tamaños de canvas y repinta firmas desde coordenadas normalizadas.
        let _resizeTimer = null;
        window.addEventListener('resize', () => {
            if (!pdfDoc) return;
            clearTimeout(_resizeTimer);
            _resizeTimer = setTimeout(() => {
                // No re-muestrea el bitmap actual; solo vuelve a renderizar y repinta desde coordenadas normalizadas.
                queueRenderPage(pageNum);
            }, 120);
        });

        applyDefaultSigningTool();
    </script>
</body>
</html>



