{"id":632,"date":"2026-05-22T20:58:50","date_gmt":"2026-05-22T20:58:50","guid":{"rendered":"https:\/\/cementeriodigitalhispano.com\/?page_id=632"},"modified":"2026-09-09T12:14:49","modified_gmt":"2026-09-09T12:14:49","slug":"la-cripta","status":"publish","type":"page","link":"https:\/\/cementeriodigitalhispano.com\/index.php\/la-cripta\/","title":{"rendered":"La Cripta"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"632\" class=\"elementor elementor-632\">\n\t\t\t\t<div class=\"elementor-element elementor-element-1cdc3ceb e-flex e-con-boxed e-con e-parent\" data-id=\"1cdc3ceb\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-bcaba92 e-flex e-con-boxed e-con e-parent\" data-id=\"bcaba92\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-12fcaaf elementor-widget elementor-widget-html\" data-id=\"12fcaaf\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"es\">\r\n<head>\r\n<meta charset=\"UTF-8\">\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n<title>La Cripta<\/title>\r\n<style>\r\n  @import url('https:\/\/fonts.googleapis.com\/css2?family=Cinzel:wght@400;600&family=Crimson+Text:ital,wght@0,400;1,400&display=swap');\r\n  * { margin:0; padding:0; box-sizing:border-box; }\r\n\r\n  .cripta-fullscreen {\r\n    position: fixed !important;\r\n    top:0 !important; left:0 !important;\r\n    width:100vw !important; height:100vh !important;\r\n    height:100svh !important;   \/* alto REAL en movil: descuenta la barra del navegador *\/\r\n    z-index:100005 !important;\r\n    background-image: url('\/wp-content\/uploads\/cripta\/religionesyespiritualidad\/agnostico.png');\r\n    background-size: cover;\r\n    background-position: center center;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    overflow: hidden;\r\n    opacity: 0;\r\n    transition: opacity 0.4s ease;\r\n  }\r\n  .cripta-fullscreen.visible {\r\n    opacity: 1;\r\n  }\r\n  .cripta-fullscreen::before {\r\n    content:''; position:absolute; inset:0;\r\n    background: radial-gradient(ellipse at 50% 65%, rgba(0,0,0,0.05) 0%, rgba(0,0,0,0.48) 100%);\r\n    pointer-events:none; z-index:0;\r\n  }\r\n\r\n  \/* \u2500\u2500 Cabecera fija arriba \u2500\u2500 *\/\r\n  .c-cabecera {\r\n    position: absolute;\r\n    top: 0; left: 0; right: 0;\r\n    z-index: 10;\r\n    text-align: center;\r\n    padding: 16px 80px 14px;\r\n    background: linear-gradient(180deg, rgba(0,0,0,0.60) 0%, rgba(0,0,0,0.20) 70%, transparent 100%);\r\n  }\r\n  .c-nombre {\r\n    font-family: 'Cinzel', serif;\r\n    font-size: clamp(15px, 1.7vw, 24px);\r\n    font-weight: 600;\r\n    color: rgba(255,255,255,0.93);\r\n    text-shadow: 0 2px 14px rgba(0,0,0,0.95), 0 0 30px rgba(180,130,20,0.3);\r\n    letter-spacing: 3px;\r\n  }\r\n  .c-anios {\r\n    font-family: 'Cinzel', serif;\r\n    font-size: clamp(12px, 1.0vw, 16px);\r\n    color: rgba(230,200,120,0.88);\r\n    text-shadow: 0 2px 10px rgba(0,0,0,0.95);\r\n    letter-spacing: 6px;\r\n    margin-top: 4px;\r\n  }\r\n  .c-separador {\r\n    width: 90px; height: 1px;\r\n    background: linear-gradient(90deg, transparent, rgba(210,175,80,0.5), transparent);\r\n    margin: 7px auto 0;\r\n  }\r\n\r\n  \/* \u2500\u2500 Iconos \u2500\u2500 *\/\r\n  .c-iconos {\r\n    position: relative; z-index: 10;\r\n    display: flex; gap: clamp(40px,7vw,120px);\r\n    align-items: flex-end;\r\n    margin-top: 4vh;\r\n  }\r\n  .c-icono {\r\n    position: relative; z-index: 10;\r\n    display: flex; flex-direction: column; align-items: center; gap: 14px;\r\n    cursor: pointer; transition: transform 0.3s ease;\r\n  }\r\n  .c-icono:hover { transform: translateY(-8px); }\r\n  .c-icono svg {\r\n    width: clamp(80px,7.2vw,120px); height: clamp(80px,7.2vw,120px);\r\n    filter:\r\n      drop-shadow(0 0 2px rgba(0,0,0,1))\r\n      drop-shadow(0 0 6px rgba(0,0,0,0.95))\r\n      drop-shadow(0 4px 16px rgba(0,0,0,0.90))\r\n      drop-shadow(0 8px 30px rgba(0,0,0,0.75))\r\n      drop-shadow(0 0 40px rgba(0,0,0,0.5));\r\n    transition: filter 0.3s ease;\r\n  }\r\n  .c-icono:hover svg {\r\n    filter:\r\n      drop-shadow(0 0 2px rgba(0,0,0,1))\r\n      drop-shadow(0 0 8px rgba(0,0,0,0.95))\r\n      drop-shadow(0 6px 22px rgba(0,0,0,0.90))\r\n      drop-shadow(0 12px 40px rgba(0,0,0,0.80))\r\n      drop-shadow(0 0 50px rgba(230,175,60,0.45));\r\n  }\r\n  .c-label {\r\n    font-family: Arial, sans-serif; font-size: clamp(11px,0.95vw,14px);\r\n    letter-spacing: 1px; color: rgba(255,255,255,0.98);\r\n    text-align: center; line-height: 1.55;\r\n    text-shadow:\r\n      0 0 3px rgba(0,0,0,1),\r\n      0 0 6px rgba(0,0,0,1),\r\n      0 2px 12px rgba(0,0,0,0.95),\r\n      0 4px 20px rgba(0,0,0,0.85);\r\n  }\r\n\r\n  \/* \u2500\u2500 Rueda dentada \u2500\u2500 *\/\r\n  .c-gear {\r\n    position: absolute; top: 16px; right: 22px;\r\n    width: 46px; height: 46px; border-radius: 50%;\r\n    background: rgba(12,6,2,0.82);\r\n    border: 1.5px solid rgba(200,155,50,0.45);\r\n    cursor: pointer; display: flex; align-items: center; justify-content: center;\r\n    font-size: 22px; color: #ffffff; z-index: 20;\r\n    transition: transform 0.4s, border-color 0.3s;\r\n    box-shadow: 0 0 20px rgba(0,0,0,0.7);\r\n  }\r\n  .c-gear:hover { transform: rotate(50deg); border-color: rgba(220,175,70,0.9); }\r\n\r\n  \/* \u2500\u2500 Bot\u00f3n previsualizar \u2500\u2500 *\/\r\n  .c-preview-btn {\r\n    position: absolute; top: 16px; right: 76px;\r\n    width: 46px; height: 46px; border-radius: 50%;\r\n    background: rgba(12,6,2,0.82);\r\n    border: 1.5px solid rgba(200,155,50,0.45);\r\n    cursor: pointer; display: flex; align-items: center; justify-content: center;\r\n    font-size: 20px; color: #ffffff; z-index: 20;\r\n    transition: transform 0.25s, border-color 0.3s;\r\n    box-shadow: 0 0 20px rgba(0,0,0,0.7);\r\n    text-decoration: none;\r\n  }\r\n  .c-preview-btn:hover { transform: scale(1.12); border-color: rgba(220,175,70,0.9); color: #f0c060; }\r\n\r\n  \/* \u2500\u2500 Modal de previsualizaci\u00f3n \u2500\u2500 *\/\r\n  .c-preview-modal {\r\n    position: fixed; inset: 0; z-index: 100015;\r\n    background-size: cover;\r\n    background-position: center center;\r\n    display: flex; flex-direction: column;\r\n    align-items: center; justify-content: center;\r\n    overflow: hidden;\r\n    visibility: hidden; pointer-events: none; opacity: 0;\r\n    transition: opacity 0.35s ease;\r\n  }\r\n  .c-preview-modal::before {\r\n    content:''; position:absolute; inset:0;\r\n    background: radial-gradient(ellipse at 50% 65%, rgba(0,0,0,0.05) 0%, rgba(0,0,0,0.48) 100%);\r\n    pointer-events:none; z-index:0;\r\n  }\r\n  .c-preview-modal.open { visibility: visible; pointer-events: auto; opacity: 1; }\r\n\r\n  \/* Cabecera dentro del modal preview *\/\r\n  .c-preview-modal .c-cabecera { position: absolute; top:0; left:0; right:0; z-index:10; }\r\n\r\n  \/* Bot\u00f3n cerrar preview *\/\r\n  .c-preview-close {\r\n    position: absolute; top: 16px; right: 22px;\r\n    width: 46px; height: 46px; border-radius: 50%;\r\n    background: rgba(12,6,2,0.82);\r\n    border: 1.5px solid rgba(200,155,50,0.45);\r\n    cursor: pointer; display: flex; align-items: center; justify-content: center;\r\n    font-size: 20px; color: #c8903a; z-index: 20;\r\n    transition: transform 0.25s, border-color 0.3s;\r\n    box-shadow: 0 0 20px rgba(0,0,0,0.7);\r\n  }\r\n  .c-preview-close:hover { transform: scale(1.12); border-color: rgba(220,175,70,0.9); color: #f0c060; }\r\n\r\n  \/* Etiqueta \"VISTA PREVIA\" *\/\r\n  .c-preview-badge {\r\n    position: absolute; top: 72px; right: 22px;\r\n    background: rgba(10,5,1,0.82);\r\n    border: 1.5px solid rgba(210,165,55,0.75);\r\n    border-radius: 20px;\r\n    padding: 6px 18px;\r\n    font-family: Arial, sans-serif; font-size: 11px;\r\n    font-weight: bold;\r\n    letter-spacing: 3px; text-transform: uppercase;\r\n    color: #f0c060;\r\n    z-index: 20;\r\n    text-shadow:\r\n      0 0 4px rgba(0,0,0,1),\r\n      0 2px 10px rgba(0,0,0,0.95);\r\n    box-shadow: 0 4px 18px rgba(0,0,0,0.75);\r\n  }\r\n\r\n  \/* \u00c1rea de carpetas en preview *\/\r\n  .c-preview-carpetas { position: absolute; inset: 0; z-index: 10; pointer-events: none; }\r\n  .c-preview-carpeta {\r\n    display: flex; flex-direction: column; align-items: center; gap: 10px;\r\n    cursor: grab; position: absolute; user-select: none;\r\n  }\r\n  .c-preview-carpeta:active { cursor: grabbing; }\r\n  .c-preview-carpeta.dragging-free { filter: drop-shadow(0 8px 24px rgba(210,165,55,0.6)); z-index: 100; }\r\n  .c-preview-carpeta svg {\r\n    width: clamp(51px,5.1vw,77px); height: clamp(51px,5.1vw,77px);\r\n    filter:\r\n      drop-shadow(0 0 2px rgba(0,0,0,1))\r\n      drop-shadow(0 4px 16px rgba(0,0,0,0.90));\r\n  }\r\n  .c-preview-hint {\r\n    position: absolute; bottom: 80px; left: 50%; transform: translateX(-50%);\r\n    background: rgba(10,5,1,0.88); border: 1.5px solid rgba(210,165,55,0.6);\r\n    border-radius: 20px; padding: 10px 24px;\r\n    font-family: Arial, sans-serif; font-size: 13px; color: #f0c060; letter-spacing: 1px;\r\n    z-index: 50; white-space: nowrap; pointer-events: none;\r\n    transition: opacity 0.5s ease;\r\n  }\r\n  .c-preview-hint.hide { opacity: 0; }\r\n  .c-preview-carpeta .c-label {\r\n    font-family: Arial, sans-serif;\r\n    font-size: clamp(10px,0.85vw,13px);\r\n    font-weight: bold;\r\n    color: rgba(255,255,255,0.98);\r\n    text-shadow:\r\n      0 0 3px rgba(0,0,0,1),\r\n      0 0 6px rgba(0,0,0,1),\r\n      0 2px 10px rgba(0,0,0,0.95);\r\n    letter-spacing: 0.2px;\r\n    text-align: center;\r\n    max-width: clamp(90px,9vw,120px);\r\n    overflow: hidden;\r\n    display: -webkit-box;\r\n    -webkit-line-clamp: 2;\r\n    -webkit-box-orient: vertical;\r\n    white-space: normal;\r\n    word-break: break-word;\r\n    line-height: 1.3;\r\n  }\r\n\r\n  \/* Mensaje vac\u00edo en preview *\/\r\n  .c-preview-empty {\r\n    position: relative; z-index: 10;\r\n    margin-top: 8vh;\r\n    font-family: Arial, sans-serif; font-size: clamp(13px,1.2vw,17px);\r\n    font-weight: bold;\r\n    color: #f0c060;\r\n    letter-spacing: 3px;\r\n    text-align: center;\r\n    text-shadow:\r\n      0 0 4px rgba(0,0,0,1),\r\n      0 0 10px rgba(0,0,0,1),\r\n      0 3px 18px rgba(0,0,0,0.98),\r\n      0 6px 30px rgba(0,0,0,0.90);\r\n  }\r\n\r\n  \/* \u2500\u2500 Panel \u2500\u2500 *\/\r\n  .c-panel {\r\n    position: absolute; top: 70px; right: 22px; width: 245px;\r\n    max-height: calc(100vh - 88px);\r\n    max-height: calc(100svh - 88px);   \/* alto real: descuenta la barra del navegador *\/\r\n    overflow-y: auto;                  \/* overflow-x sigue en hidden: el borde redondeado no se rompe *\/\r\n    overscroll-behavior: contain;      \/* al llegar al final no arrastra la pagina de detras *\/\r\n    -webkit-overflow-scrolling: touch;\r\n    background: rgba(10,5,1,0.97);\r\n    border: 1px solid rgba(180,130,40,0.35); border-radius: 9px;\r\n    z-index: 20; overflow-x: hidden; display: none;   \/* -x solo: el scroll vertical de arriba debe seguir activo *\/\r\n    box-shadow: 0 12px 40px rgba(0,0,0,0.95);\r\n  }\r\n  .c-panel.open { display: block; }\r\n  .c-ph {\r\n    padding: 11px 16px; background: rgba(48,25,4,0.92);\r\n    border-bottom: 1px solid rgba(150,100,25,0.3);\r\n    font-family: Arial, sans-serif; font-size: 11px; letter-spacing: 2.5px; color: #d4a850;\r\n  }\r\n  .c-pi {\r\n    padding: 12px 16px; display: flex; align-items: center; gap: 11px;\r\n    cursor: pointer; color: #c8903a; font-size: 13px;\r\n    font-family: Arial, sans-serif; font-weight: bold;\r\n    border-bottom: 1px solid rgba(55,30,4,0.3);\r\n    transition: background 0.15s, color 0.15s;\r\n  }\r\n  .c-pi:hover { background: rgba(75,40,4,0.5); color: #f0c060; }\r\n  .c-pi:last-child { border-bottom: none; }\r\n  .c-arr { margin-left: auto; font-size: 12px; transition: transform 0.2s; }\r\n  .c-arr.rot { transform: rotate(90deg); }\r\n  .c-sub { display: none; background: rgba(6,3,1,0.96); }\r\n  .c-sub.open { display: block; }\r\n  .c-si {\r\n    padding: 8px 16px 8px 40px; font-size: 12px; color: #c0903a;\r\n    cursor: pointer; font-family: Arial, sans-serif;\r\n    transition: color 0.15s, background 0.15s;\r\n  }\r\n  .c-si:hover { color: #f0c060; background: rgba(55,30,4,0.45); }\r\n\r\n  \/* \u2500\u2500 Subcarpetas (segundo nivel) \u2500\u2500 *\/\r\n  .c-cat {\r\n    padding: 9px 16px 9px 28px; display: flex; align-items: center; gap: 9px;\r\n    cursor: pointer; color: #c8903a; font-size: 12px;\r\n    font-family: Arial, sans-serif; font-weight: bold;\r\n    border-bottom: 1px solid rgba(55,30,4,0.2);\r\n    transition: background 0.15s, color 0.15s;\r\n  }\r\n  .c-cat:hover { background: rgba(65,35,4,0.45); color: #f0c060; }\r\n  .c-cat-arr { margin-left: auto; font-size: 11px; transition: transform 0.2s; }\r\n  .c-cat-arr.rot { transform: rotate(90deg); }\r\n  .c-cat-sub { display: none; background: rgba(4,2,0,0.97); }\r\n  .c-cat-sub.open { display: block; }\r\n  .c-cat-si {\r\n    padding: 7px 16px 7px 52px; font-size: 12px; color: #b08030;\r\n    cursor: pointer; font-family: Arial, sans-serif;\r\n    transition: color 0.15s, background 0.15s;\r\n    border-bottom: 1px solid rgba(40,20,2,0.2);\r\n  }\r\n  .c-cat-si:last-child { border-bottom: none; }\r\n  .c-cat-si:hover { color: #f0c060; background: rgba(50,25,3,0.5); }\r\n\r\n  \/* \u2500\u2500 Panel imagen personalizada \u2500\u2500 *\/\r\n  .c-custom-panel {\r\n    position: fixed; top: 0; left: 0; right: 0; bottom: 0;\r\n    background: rgba(6,3,1,0.97);\r\n    z-index: 100030;\r\n    display: flex; flex-direction: column;\r\n    align-items: center; justify-content: center;\r\n    padding: 30px 24px;\r\n    visibility: hidden; pointer-events: none; opacity: 0;\r\n    transition: opacity 0.2s;\r\n  }\r\n  .c-custom-panel.open { visibility: visible; pointer-events: auto; opacity: 1; }\r\n  .c-custom-title {\r\n    font-family: Arial, sans-serif; font-size: 14px; letter-spacing: 2px;\r\n    color: #d4a850; margin-bottom: 18px; text-align: center; font-weight: bold;\r\n  }\r\n  .c-custom-drop {\r\n    width: 100%; border: 2px dashed rgba(180,130,40,0.4); border-radius: 10px;\r\n    padding: 28px 16px; text-align: center; cursor: pointer;\r\n    transition: border-color 0.2s, background 0.2s;\r\n    background: rgba(20,10,2,0.6);\r\n  }\r\n  .c-custom-drop:hover, .c-custom-drop.drag { border-color: rgba(210,165,60,0.8); background: rgba(40,20,4,0.7); }\r\n  .c-custom-drop-icon { font-size: 36px; margin-bottom: 10px; }\r\n  .c-custom-drop-text {\r\n    font-family: Arial, sans-serif; font-size: 13px; color: #c8903a; line-height: 1.7;\r\n  }\r\n  .c-custom-drop-text span { color: #f0c060; text-decoration: underline; cursor: pointer; }\r\n  .c-custom-note {\r\n    margin-top: 14px; padding: 12px 16px;\r\n    background: rgba(30,15,2,0.8); border-radius: 7px;\r\n    border-left: 2px solid rgba(180,130,40,0.35);\r\n    font-family: Arial, sans-serif; font-size: 12px;\r\n    color: rgba(200,165,90,0.9); line-height: 1.9; width: 100%;\r\n  }\r\n  .c-custom-note strong { color: #d4a850; }\r\n  .c-custom-preview {\r\n    width: 100%; height: 90px; border-radius: 7px; object-fit: cover;\r\n    margin-top: 12px; display: none !important;\r\n    border: 1px solid rgba(180,130,40,0.3);\r\n  }\r\n  .c-custom-preview.visible {\r\n    display: block !important;\r\n  }\r\n  .c-custom-btns { display: flex; gap: 10px; margin-top: 14px; width: 100%; }\r\n  .c-custom-btn {\r\n    flex: 1; padding: 11px; border-radius: 6px; border: none; cursor: pointer;\r\n    font-family: Arial, sans-serif; font-size: 12px; letter-spacing: 1px; font-weight: bold;\r\n    transition: background 0.2s;\r\n  }\r\n  .c-custom-btn.save { background: rgba(160,110,30,0.85); color: #fff5e0; }\r\n  .c-custom-btn.save:hover { background: rgba(200,145,40,0.95); }\r\n  .c-custom-btn.cancel { background: rgba(40,20,4,0.8); color: #c8903a; border: 1px solid rgba(120,80,20,0.3); }\r\n  .c-custom-btn.cancel:hover { background: rgba(60,30,6,0.9); color: #f0c060; }\r\n  .c-custom-progress {\r\n    width: 100%; height: 4px; background: rgba(40,20,4,0.8);\r\n    border-radius: 2px; margin-top: 10px; display: none; overflow: hidden;\r\n  }\r\n  .c-custom-progress-bar {\r\n    height: 100%; width: 0%; background: linear-gradient(90deg, #8a5c1a, #c8903a);\r\n    border-radius: 2px; transition: width 0.3s;\r\n  }\r\n  .c-custom-status {\r\n    font-family: Arial, sans-serif; font-size: 12px; color: #907030;\r\n    margin-top: 8px; text-align: center; min-height: 16px;\r\n  }\r\n\r\n  \/* \u2500\u2500 Avatar \/ bot\u00f3n usuario \u2500\u2500 *\/\r\n  .c-user-btn {\r\n    position: absolute; top: 16px; left: 22px;\r\n    width: 46px; height: 46px; border-radius: 50%;\r\n    background: rgba(12,6,2,0.82);\r\n    border: 1.5px solid rgba(200,155,50,0.45);\r\n    cursor: pointer; display: flex; align-items: center; justify-content: center;\r\n    font-size: 20px; color: #ffffff; z-index: 20;\r\n    transition: border-color 0.3s;\r\n    box-shadow: 0 0 20px rgba(0,0,0,0.7);\r\n  }\r\n  .c-user-btn:hover { border-color: rgba(220,175,70,0.9); }\r\n\r\n  \/* \u2500\u2500 Panel usuario \u2500\u2500 *\/\r\n  .c-user-panel {\r\n    position: absolute; top: 70px; left: 22px; width: 260px;\r\n    max-height: calc(100vh - 88px);\r\n    max-height: calc(100svh - 88px);   \/* alto real: descuenta la barra del navegador *\/\r\n    overflow-y: auto;                  \/* overflow-x sigue en hidden: el borde redondeado no se rompe *\/\r\n    overscroll-behavior: contain;      \/* al llegar al final no arrastra la pagina de detras *\/\r\n    -webkit-overflow-scrolling: touch;\r\n    background: rgba(10,5,1,0.97);\r\n    border: 1px solid rgba(180,130,40,0.35); border-radius: 9px;\r\n    z-index: 20; overflow-x: hidden; display: none;   \/* -x solo: el scroll vertical de arriba debe seguir activo *\/\r\n    box-shadow: 0 12px 40px rgba(0,0,0,0.95);\r\n  }\r\n  .c-user-panel.open { display: block; }\r\n\r\n  .c-up-head {\r\n    padding: 14px 16px;\r\n    background: rgba(48,25,4,0.92);\r\n    border-bottom: 1px solid rgba(150,100,25,0.3);\r\n  }\r\n  .c-up-name {\r\n    font-family: Arial, sans-serif; font-size: 13px; font-weight: bold;\r\n    letter-spacing: 0.5px; color: #d4a850;\r\n    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\r\n  }\r\n  .c-up-email {\r\n    font-family: Arial, sans-serif; font-size: 12px;\r\n    color: rgba(200,165,80,0.7); margin-top: 3px;\r\n    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\r\n  }\r\n  .c-up-divider {\r\n    height: 1px;\r\n    background: rgba(150,100,25,0.2);\r\n    margin: 0;\r\n  }\r\n  .c-up-item {\r\n    padding: 11px 16px; display: flex; align-items: center; gap: 11px;\r\n    cursor: pointer; color: #c8903a; font-size: 13px;\r\n    font-family: Arial, sans-serif;\r\n    border-bottom: 1px solid rgba(55,30,4,0.3);\r\n    transition: background 0.15s, color 0.15s;\r\n    text-decoration: none;\r\n  }\r\n  .c-up-item:hover { background: rgba(75,40,4,0.5); color: #f0c060; }\r\n  .c-up-item:last-child { border-bottom: none; }\r\n  .c-up-item.danger { color: #c06060; }\r\n  .c-up-item.danger:hover { background: rgba(80,20,20,0.4); color: #e08080; }\r\n\r\n  \/* \u2500\u2500 Modal eliminar cuenta \u2500\u2500 *\/\r\n  .cdh-modal-overlay {\r\n    display: none; position: fixed; inset: 0; z-index: 100040;\r\n    background: rgba(0,0,0,0.75); backdrop-filter: blur(4px);\r\n    align-items: center; justify-content: center; padding: 20px;\r\n  }\r\n  .cdh-modal {\r\n    background: linear-gradient(160deg, rgba(60,20,10,0.97) 0%, rgba(20,40,28,0.97) 100%);\r\n    border: 1px solid rgba(201,169,110,0.3); border-radius: 6px;\r\n    padding: 36px 32px; max-width: 480px; width: 100%;\r\n    box-shadow: 0 20px 60px rgba(0,0,0,0.7);\r\n  }\r\n  .cdh-modal h3 {\r\n    font-family: 'Cinzel', serif; font-size: 14px; letter-spacing: 3px;\r\n    text-transform: uppercase; color: #c06060; text-align: center;\r\n    margin-bottom: 20px;\r\n  }\r\n  .cdh-modal p {\r\n    font-size: 14px; line-height: 1.7; color: rgba(245,240,232,0.75);\r\n    margin-bottom: 20px; text-align: center;\r\n  }\r\n  .cdh-modal-btns { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; }\r\n  .cdh-btn-descargar {\r\n    padding: 11px 20px; background: rgba(30,58,43,0.5);\r\n    border: 1px solid rgba(201,169,110,0.35); border-radius: 3px;\r\n    color: #c9a96e; font-family: 'Cinzel', serif; font-size: 11px;\r\n    letter-spacing: 2px; text-transform: uppercase; cursor: pointer;\r\n    transition: all 0.2s;\r\n  }\r\n  .cdh-btn-descargar:hover { background: rgba(30,58,43,0.8); }\r\n  .cdh-btn-eliminar-final {\r\n    padding: 12px 20px; background: rgba(120,30,30,0.5);\r\n    border: 1px solid rgba(200,80,80,0.4); border-radius: 3px;\r\n    color: #e08080; font-family: 'Cinzel', serif; font-size: 11px;\r\n    letter-spacing: 2px; text-transform: uppercase; cursor: pointer;\r\n    transition: all 0.2s;\r\n  }\r\n  .cdh-btn-eliminar-final:hover:not(:disabled) { background: rgba(150,40,40,0.7); }\r\n  .cdh-btn-eliminar-final:disabled { opacity: 0.4; cursor: not-allowed; }\r\n  .cdh-btn-cancelar-modal {\r\n    padding: 10px 20px; background: transparent;\r\n    border: 1px solid rgba(245,240,232,0.15); border-radius: 3px;\r\n    color: rgba(245,240,232,0.4); font-family: 'Cinzel', serif; font-size: 11px;\r\n    letter-spacing: 2px; text-transform: uppercase; cursor: pointer;\r\n    transition: all 0.2s;\r\n  }\r\n  .cdh-btn-cancelar-modal:hover { border-color: rgba(245,240,232,0.35); color: rgba(245,240,232,0.7); }\r\n  .cdh-confirmar-input {\r\n    width: 100%; background: rgba(0,0,0,0.4);\r\n    border: 1px solid rgba(200,80,80,0.3); border-radius: 3px;\r\n    padding: 10px 14px; color: #f5f0e8; font-family: 'Georgia', serif;\r\n    font-size: 14px; outline: none; text-align: center; margin-bottom: 6px;\r\n    transition: border-color 0.2s;\r\n  }\r\n  .cdh-confirmar-input:focus { border-color: rgba(200,80,80,0.7); }\r\n  .cdh-aviso { display: none; padding: 10px; border-radius: 3px; font-size: 13px; text-align: center; margin-bottom: 10px; }\r\n  .cdh-aviso-error { background: rgba(120,30,30,0.3); border: 1px solid rgba(200,80,80,0.3); color: #e08080; display: block; }\r\n  .cdh-aviso-ok    { background: rgba(30,58,43,0.3); border: 1px solid rgba(45,90,61,0.4); color: #7ec89a; display: block; }\r\n  .cdh-confirmar-nota { font-size: 12px; color: rgba(245,240,232,0.35); text-align: center; font-style: italic; margin-bottom: 14px; }\r\n  .c-up-sep {\r\n    height: 1px;\r\n    background: rgba(150,100,25,0.15);\r\n  }\r\n\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     CARPETAS EN LA CRIPTA\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n\r\n  \/* \u2500\u2500 Zona de carpetas libres en la cripta \u2500\u2500 *\/\r\n  .c-carpetas-zona {\r\n    position: absolute;\r\n    inset: 0;\r\n    z-index: 10;\r\n    pointer-events: none;\r\n  }\r\n  .c-carpetas-zona.vacia { }\r\n\r\n  .c-icono-grande {\r\n    position:relative;\r\n    width:clamp(42px,4.2vw,64px); height:clamp(42px,4.2vw,64px);\r\n    display:flex; align-items:center; justify-content:center;\r\n    cursor:pointer; transition:transform 0.3s ease;\r\n    filter:drop-shadow(0 4px 14px rgba(0,0,0,0.85));\r\n  }\r\n  .c-icono-grande:hover { transform:translateY(-5px) scale(1.05); }\r\n  .c-icono-grande > svg { width:clamp(42px,4.2vw,64px) !important; height:clamp(42px,4.2vw,64px) !important; }\r\n  .c-icono-grande-lock { position:absolute; top:-4px; right:-4px; font-size:clamp(10px,0.9vw,14px); }\r\n  \/* Carpeta libre arrastrable en la cripta *\/\r\n  .c-carpeta-item {\r\n    position: absolute;\r\n    display: flex; flex-direction: column; align-items: center; gap: 5px;\r\n    cursor: grab;\r\n    padding: 4px 6px;\r\n    border-radius: 6px;\r\n    pointer-events: auto;\r\n    user-select: none;\r\n    transition: filter 0.2s;\r\n  }\r\n  .c-carpeta-item:active { cursor: grabbing; }\r\n  .c-carpeta-item:hover  { filter: brightness(1.15); }\r\n  .c-carpeta-item.dragging { filter: drop-shadow(0 8px 24px rgba(210,165,55,0.6)); z-index: 100; }\r\n\r\n  .c-carpeta-icono-wrap {\r\n    position: relative;\r\n    width: clamp(42px,4vw,58px);\r\n    height: clamp(37px,3.6vw,51px);\r\n    display: flex; align-items: center; justify-content: center;\r\n  }\r\n\r\n  \/* SVG de la carpeta *\/\r\n  .c-carpeta-svg {\r\n    width: 100%; height: 100%;\r\n    filter:\r\n      drop-shadow(0 0 2px rgba(0,0,0,1))\r\n      drop-shadow(0 4px 14px rgba(0,0,0,0.92))\r\n      drop-shadow(0 8px 28px rgba(0,0,0,0.75));\r\n    transition: filter 0.3s ease;\r\n  }\r\n  .c-carpeta-item:hover .c-carpeta-svg {\r\n    filter:\r\n      drop-shadow(0 0 3px rgba(0,0,0,1))\r\n      drop-shadow(0 6px 20px rgba(0,0,0,0.95))\r\n      drop-shadow(0 0 40px rgba(230,175,60,0.35));\r\n  }\r\n\r\n  \/* Emoji icono sobre la carpeta *\/\r\n  .c-carpeta-emoji {\r\n    position: absolute;\r\n    top: 58%; left: 50%;\r\n    transform: translate(-50%, -50%);\r\n    font-size: clamp(13px,1.3vw,19px);\r\n    line-height: 1;\r\n    pointer-events: none;\r\n    filter: drop-shadow(0 2px 5px rgba(0,0,0,0.9)) drop-shadow(0 0 3px rgba(0,0,0,1));\r\n  }\r\n\r\n  \/* Candado para carpetas cerradas\/ocultas *\/\r\n  .c-carpeta-lock {\r\n    position: absolute; top: -4px; right: -4px;\r\n    font-size: clamp(10px,0.9vw,14px);\r\n    filter: drop-shadow(0 1px 3px rgba(0,0,0,0.9));\r\n  }\r\n\r\n  \/* Nombre de la carpeta *\/\r\n  .c-carpeta-nombre {\r\n    font-family: Arial, sans-serif;\r\n    font-size: clamp(11px,0.95vw,13px);\r\n    font-weight: bold;\r\n    color: #ffffff;\r\n    text-align: center;\r\n    text-shadow:\r\n      0 0 4px rgba(0,0,0,1),\r\n      0 1px 6px rgba(0,0,0,1),\r\n      0 2px 10px rgba(0,0,0,0.95);\r\n    max-width: clamp(90px,9vw,120px);\r\n    overflow: hidden;\r\n    display: -webkit-box;\r\n    -webkit-line-clamp: 2;\r\n    -webkit-box-orient: vertical;\r\n    white-space: normal;\r\n    word-break: break-word;\r\n    letter-spacing: 0.2px;\r\n    line-height: 1.3;\r\n  }\r\n\r\n  \/* Fecha de apertura para cerradas *\/\r\n  .c-carpeta-fecha {\r\n    font-family: Arial, sans-serif;\r\n    font-size: clamp(8px,0.7vw,11px);\r\n    color: rgba(210,175,80,0.85);\r\n    text-align: center;\r\n    text-shadow: 0 1px 6px rgba(0,0,0,1);\r\n    margin-top: -4px;\r\n  }\r\n\r\n  \/* Iconos de edici\u00f3n sobre cada carpeta (solo propietario) *\/\r\n  .c-carpeta-acciones {\r\n    display: flex; gap: 6px;\r\n    margin-top: 2px;\r\n  }\r\n  .c-carpeta-accion {\r\n    width: 22px; height: 22px; border-radius: 50%;\r\n    background: rgba(10,5,1,0.82);\r\n    border: 1px solid rgba(180,130,40,0.5);\r\n    display: flex; align-items: center; justify-content: center;\r\n    font-size: 11px; cursor: pointer; color: #c8903a;\r\n    transition: background 0.15s, color 0.15s, border-color 0.15s;\r\n  }\r\n  .c-carpeta-accion:first-child { font-size: 15px; font-weight: bold; line-height: 1; }\r\n  .c-carpeta-accion:hover { background: rgba(75,40,4,0.85); color: #f0c060; border-color: rgba(220,170,60,0.8); }\r\n\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     BOT\u00d3N FLOTANTE MAPA DE LA CRIPTA\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  #mapaBtn, #mapaBtnPublico {\r\n    position: absolute;\r\n    top: 14px;\r\n    left: 14px;\r\n    z-index: 200;\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 7px;\r\n    padding: 8px 14px 8px 10px;\r\n    background: linear-gradient(135deg, rgba(28,14,2,0.88) 0%, rgba(52,30,6,0.88) 100%);\r\n    border: 1px solid rgba(200,155,50,0.7);\r\n    border-radius: 4px;\r\n    cursor: pointer;\r\n    box-shadow: 0 3px 14px rgba(0,0,0,0.75), inset 0 1px 0 rgba(220,175,70,0.18);\r\n    backdrop-filter: blur(4px);\r\n    transition: border-color 0.2s, box-shadow 0.2s, background 0.2s;\r\n    text-shadow: 0 1px 4px rgba(0,0,0,0.9);\r\n  }\r\n  #mapaBtn:hover, #mapaBtnPublico:hover {\r\n    border-color: rgba(230,185,70,0.95);\r\n    box-shadow: 0 4px 20px rgba(0,0,0,0.85), 0 0 10px rgba(200,155,40,0.3), inset 0 1px 0 rgba(220,175,70,0.25);\r\n    background: linear-gradient(135deg, rgba(40,20,4,0.92) 0%, rgba(70,42,10,0.92) 100%);\r\n  }\r\n  #mapaBtn .mapa-btn-ico, #mapaBtnPublico .mapa-btn-ico {\r\n    font-size: 16px;\r\n    line-height: 1;\r\n    filter: drop-shadow(0 1px 3px rgba(0,0,0,0.8));\r\n  }\r\n  #mapaBtn .mapa-btn-txt, #mapaBtnPublico .mapa-btn-txt {\r\n    font-family: 'Cinzel', Georgia, serif;\r\n    font-size: 11px;\r\n    letter-spacing: 2px;\r\n    text-transform: uppercase;\r\n    color: #e8c86a;\r\n    font-weight: 600;\r\n    white-space: nowrap;\r\n  }\r\n\r\n  \/* Scrollbar del modal mapa *\/\r\n  #mapaBox::-webkit-scrollbar { width: 5px; }\r\n  #mapaBox::-webkit-scrollbar-track { background: rgba(160,110,40,0.2); }\r\n  #mapaBox::-webkit-scrollbar-thumb { background: rgba(120,70,10,0.5); border-radius: 3px; }\r\n\r\n  \/* \u00c1rbol del mapa *\/\r\n  .mapa-carpeta-raiz {\r\n    margin-bottom: 14px;\r\n    border-left: 2px solid rgba(120,70,10,0.4);\r\n    padding-left: 12px;\r\n  }\r\n  .mapa-carpeta-raiz:last-child { margin-bottom: 0; }\r\n  .mapa-nodo {\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 7px;\r\n    padding: 5px 8px;\r\n    border-radius: 3px;\r\n    margin-bottom: 3px;\r\n    background: rgba(120,70,10,0.08);\r\n    border: 1px solid rgba(120,70,10,0.15);\r\n    cursor: default;\r\n  }\r\n  .mapa-nodo:hover { background: rgba(120,70,10,0.15); }\r\n  .mapa-estado-badge {\r\n    font-size: 9px;\r\n    font-weight: bold;\r\n    padding: 2px 5px;\r\n    border-radius: 2px;\r\n    font-family: Arial, sans-serif;\r\n    letter-spacing: 0.5px;\r\n    flex-shrink: 0;\r\n  }\r\n  .mapa-estado-a { background: #4a8a4a; color: #fff; }\r\n  .mapa-estado-c { background: #7a4a20; color: #fff; }\r\n  .mapa-estado-o { background: #3a3a6a; color: #fff; }\r\n  .mapa-nodo-nombre {\r\n    font-family: Georgia, serif;\r\n    font-size: 13px;\r\n    color: #3a1e02;\r\n    flex: 1;\r\n    white-space: nowrap;\r\n    overflow: hidden;\r\n    text-overflow: ellipsis;\r\n  }\r\n  .mapa-nodo-ficheros {\r\n    font-family: Arial, sans-serif;\r\n    font-size: 10px;\r\n    color: #7a5010;\r\n    white-space: nowrap;\r\n    flex-shrink: 0;\r\n  }\r\n  \/* Carpeta oculta vista por un visitante: la carpeta, y nada mas *\/\r\n  .mapa-nodo-sellada { opacity: 0.5; }\r\n  \/* Fecha de apertura de las carpetas cerradas \/ ocultas *\/\r\n  .mapa-nodo-fecha {\r\n    font-family: Arial, sans-serif;\r\n    font-size: 10px;\r\n    font-weight: bold;\r\n    color: #7a4a20;\r\n    background: rgba(160,110,30,0.14);\r\n    border: 1px solid rgba(140,90,20,0.28);\r\n    border-radius: 3px;\r\n    padding: 2px 6px;\r\n    white-space: nowrap;\r\n    flex-shrink: 0;\r\n  }\r\n  \/* En pantallas estrechas la fecha baja a su propia l\u00ednea en vez de\r\n     comerse el nombre de la carpeta. *\/\r\n  @media (max-width: 620px) {\r\n    .mapa-nodo { flex-wrap: wrap; }\r\n    .mapa-nodo-nombre { flex: 1 1 60%; min-width: 0; }\r\n    .mapa-nodo-fecha,\r\n    .mapa-nodo-ficheros { margin-left: 22px; }\r\n  }\r\n  .mapa-hijos {\r\n    padding-left: 18px;\r\n    border-left: 1px dashed rgba(120,70,10,0.3);\r\n    margin-left: 8px;\r\n    margin-top: 2px;\r\n  }\r\n  .mapa-vacio {\r\n    text-align: center;\r\n    font-family: Georgia, serif;\r\n    font-size: 13px;\r\n    color: #7a5010;\r\n    padding: 24px 0;\r\n    opacity: 0.7;\r\n  }\r\n\r\n\r\n\r\n  .cdh-modal-carpetas {\r\n    position: fixed; inset: 0; z-index: 100010;\r\n    background: rgba(0,0,0,0.78);\r\n    backdrop-filter: blur(5px);\r\n    display: flex; align-items: center; justify-content: center;\r\n    padding: 20px;\r\n    visibility: hidden; opacity: 0; pointer-events: none;\r\n    transition: opacity 0.25s;\r\n  }\r\n  .cdh-modal-carpetas.open {\r\n    visibility: visible; opacity: 1; pointer-events: auto;\r\n  }\r\n\r\n  .cdh-mc-box {\r\n    background: linear-gradient(160deg, rgba(52,28,8,0.97) 0%, rgba(28,52,36,0.97) 100%);\r\n    border: 1px solid rgba(201,169,110,0.5);\r\n    border-radius: 8px;\r\n    width: 100%; max-width: 560px;\r\n    max-height: 88vh; max-height: 88svh;\r\n    overflow-y: auto;\r\n    box-shadow: 0 20px 60px rgba(0,0,0,0.9);\r\n    padding: 28px 28px 24px;\r\n    position: relative;\r\n  }\r\n  .cdh-mc-box::-webkit-scrollbar { width: 5px; }\r\n  .cdh-mc-box::-webkit-scrollbar-track { background: rgba(0,0,0,0.3); }\r\n  .cdh-mc-box::-webkit-scrollbar-thumb { background: rgba(180,130,40,0.4); border-radius: 3px; }\r\n\r\n  .cdh-mc-titulo {\r\n    font-family: 'Cinzel', serif; font-size: 15px;\r\n    letter-spacing: 3px; text-transform: uppercase;\r\n    color: #f5d878; text-align: center;\r\n    margin-bottom: 22px;\r\n  }\r\n\r\n  .cdh-mc-cerrar {\r\n    position: absolute; top: 14px; right: 16px;\r\n    background: none; border: none; color: #c8903a;\r\n    font-size: 20px; cursor: pointer; line-height: 1;\r\n    transition: color 0.15s;\r\n  }\r\n  .cdh-mc-cerrar:hover { color: #f0c060; }\r\n\r\n  \/* Lista de carpetas existentes *\/\r\n  .cdh-mc-lista {\r\n    margin-bottom: 20px;\r\n  }\r\n  .cdh-mc-lista-titulo {\r\n    font-family: Arial, sans-serif; font-size: 12px;\r\n    letter-spacing: 2.5px; text-transform: uppercase;\r\n    color: rgba(240,200,90,0.85); margin-bottom: 10px;\r\n  }\r\n\r\n  .cdh-mc-carpeta-fila {\r\n    display: flex; align-items: center; gap: 10px;\r\n    padding: 9px 12px;\r\n    background: rgba(60,32,8,0.7);\r\n    border: 1px solid rgba(180,130,40,0.35);\r\n    border-radius: 5px; margin-bottom: 6px;\r\n    transition: background 0.15s;\r\n  }\r\n  .cdh-mc-carpeta-fila:hover { background: rgba(80,44,10,0.85); }\r\n\r\n  .cdh-mc-carpeta-emoji { font-size: 20px; min-width: 26px; text-align: center; font-family: 'Segoe UI Emoji', 'Apple Color Emoji', 'Noto Color Emoji', 'Twemoji Mozilla', sans-serif; }\r\n\r\n  .cdh-mc-carpeta-info { flex: 1; min-width: 0; }\r\n  .cdh-mc-carpeta-nombre {\r\n    font-family: Arial, sans-serif; font-size: 14px; font-weight: bold;\r\n    color: #fff5cc;\r\n    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\r\n  }\r\n  .cdh-mc-carpeta-meta {\r\n    font-family: Arial, sans-serif; font-size: 12px;\r\n    color: rgba(230,185,90,0.75); margin-top: 2px;\r\n  }\r\n\r\n  .cdh-mc-carpeta-btns { display: flex; gap: 6px; }\r\n  .cdh-mc-btn-ico {\r\n    width: 28px; height: 28px; border-radius: 50%;\r\n    background: rgba(10,5,1,0.7);\r\n    border: 1px solid rgba(160,110,30,0.4);\r\n    display: flex; align-items: center; justify-content: center;\r\n    font-size: 13px; cursor: pointer; color: #c8903a;\r\n    transition: background 0.15s, color 0.15s;\r\n  }\r\n  .cdh-mc-btn-ico:hover { background: rgba(75,40,4,0.8); color: #f0c060; }\r\n  .cdh-mc-btn-ico.danger:hover { background: rgba(80,20,20,0.7); color: #e08080; }\r\n\r\n  .cdh-mc-vacia {\r\n    text-align: center; padding: 14px 0;\r\n    font-family: Arial, sans-serif; font-size: 13px;\r\n    color: rgba(230,185,80,0.6); letter-spacing: 1px;\r\n  }\r\n\r\n  \/* Separador *\/\r\n  .cdh-mc-sep {\r\n    height: 1px;\r\n    background: linear-gradient(90deg, transparent, rgba(210,165,55,0.45), transparent);\r\n    margin: 18px 0;\r\n  }\r\n\r\n  \/* Formulario nueva \/ editar carpeta *\/\r\n  .cdh-mc-form-titulo {\r\n    font-family: Arial, sans-serif; font-size: 12px;\r\n    letter-spacing: 2.5px; text-transform: uppercase;\r\n    color: rgba(240,200,90,0.85); margin-bottom: 12px;\r\n  }\r\n\r\n  .cdh-mc-campo {\r\n    margin-bottom: 14px;\r\n  }\r\n  .cdh-mc-label {\r\n    font-family: Arial, sans-serif; font-size: 13px;\r\n    letter-spacing: 0.5px; color: rgba(245,220,130,0.9);\r\n    margin-bottom: 6px; display: block; font-weight: bold;\r\n  }\r\n  .cdh-mc-input {\r\n    width: 100%; background: rgba(20,10,2,0.6);\r\n    border: 1px solid rgba(190,140,40,0.5); border-radius: 4px;\r\n    padding: 10px 12px; color: #fff5e0;\r\n    font-family: Arial, sans-serif; font-size: 14px;\r\n    outline: none; transition: border-color 0.2s;\r\n  }\r\n  .cdh-mc-input:focus { border-color: rgba(220,175,60,0.85); }\r\n\r\n  \/* Selector de iconos *\/\r\n  .cdh-mc-iconos-grid {\r\n    display: grid;\r\n    grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));\r\n    gap: 6px;\r\n    max-height: 190px; overflow-y: auto;\r\n    padding: 6px;\r\n    background: rgba(15,8,1,0.5);\r\n    border: 1px solid rgba(180,130,40,0.4);\r\n    border-radius: 5px;\r\n  }\r\n  .cdh-mc-iconos-grid::-webkit-scrollbar { width: 4px; }\r\n  .cdh-mc-iconos-grid::-webkit-scrollbar-thumb { background: rgba(190,140,40,0.5); border-radius: 2px; }\r\n\r\n  .cdh-mc-icono-opt {\r\n    display: flex; flex-direction: column; align-items: center;\r\n    gap: 3px; padding: 8px 4px; border-radius: 5px;\r\n    cursor: pointer; border: 1.5px solid transparent;\r\n    transition: background 0.15s, border-color 0.15s;\r\n    background: rgba(40,20,4,0.6);\r\n  }\r\n  .cdh-mc-icono-opt:hover { background: rgba(75,40,8,0.8); }\r\n  .cdh-mc-icono-opt.sel { border-color: rgba(220,175,60,0.9); background: rgba(85,48,8,0.85); }\r\n  .cdh-mc-icono-opt span:first-child { display:flex; align-items:center; justify-content:center; width:28px; height:28px; }\r\n  .cdh-icono-img { display:flex; align-items:center; justify-content:center; width:28px; height:28px; }\r\n  .cdh-icono-img svg { width:26px !important; height:26px !important; }\r\n  .cdh-mc-icono-opt span:last-child {\r\n    font-family: Arial, sans-serif; font-size: 9px;\r\n    color: rgba(230,190,90,0.8); text-align: center;\r\n    line-height: 1.2;\r\n    display: -webkit-box; -webkit-line-clamp: 2;\r\n    -webkit-box-orient: vertical; overflow: hidden;\r\n  }\r\n\r\n  .cdh-mc-tipo-opts { display:flex; gap:10px; padding:6px 0; }\r\n  .cdh-mc-tipo-opt {\r\n    flex:1; padding:12px 8px; border-radius:6px;\r\n    border:1.5px solid rgba(180,130,40,0.35); background:rgba(30,15,2,0.7);\r\n    cursor:pointer; text-align:center; transition:background 0.15s, border-color 0.15s;\r\n  }\r\n  .cdh-mc-tipo-opt:hover { background:rgba(65,35,5,0.8); }\r\n  .cdh-mc-tipo-opt.sel { border-color:rgba(220,175,60,0.9); background:rgba(75,42,6,0.85); }\r\n  .cdh-mc-tipo-preview { display:flex; align-items:center; justify-content:center; height:56px; margin-bottom:8px; }\r\n  .cdh-mc-tipo-label { font-family:Arial,sans-serif; font-size:13px; font-weight:bold; color:#f5d878; }\r\n  .cdh-mc-tipo-desc { font-family:Arial,sans-serif; font-size:11px; color:rgba(230,185,80,0.65); margin-top:3px; }\r\n  \/* Estado carpeta *\/\r\n  .cdh-mc-estados {\r\n    display: flex; gap: 8px; flex-wrap: wrap;\r\n  }\r\n  .cdh-mc-estado-opt {\r\n    flex: 1; min-width: 100px;\r\n    padding: 10px 8px; border-radius: 5px;\r\n    border: 1.5px solid rgba(180,130,40,0.4);\r\n    background: rgba(35,18,3,0.7);\r\n    cursor: pointer; text-align: center;\r\n    transition: background 0.15s, border-color 0.15s;\r\n  }\r\n  .cdh-mc-estado-opt:hover { background: rgba(65,35,6,0.8); }\r\n  .cdh-mc-estado-opt.sel { border-color: rgba(220,175,60,0.9); background: rgba(75,42,6,0.85); }\r\n  .cdh-mc-estado-opt .estado-ico { font-size: 20px; display: block; margin-bottom: 5px; font-family: 'Segoe UI Emoji', 'Apple Color Emoji', 'Noto Color Emoji', 'Twemoji Mozilla', sans-serif; }\r\n  .cdh-mc-estado-opt .estado-nombre {\r\n    font-family: Arial, sans-serif; font-size: 13px; font-weight: bold;\r\n    color: #f5d878; letter-spacing: 0.5px;\r\n  }\r\n  .cdh-mc-estado-opt .estado-desc {\r\n    font-family: Arial, sans-serif; font-size: 11px;\r\n    color: rgba(230,185,80,0.65); margin-top: 4px; line-height: 1.4;\r\n  }\r\n\r\n  \/* Datepicker para fecha apertura *\/\r\n  .cdh-mc-fecha-wrap {\r\n    display: none;\r\n    margin-top: 12px;\r\n  }\r\n  .cdh-mc-fecha-wrap.visible { display: block; }\r\n\r\n  \/* Botones guardar\/cancelar *\/\r\n  .cdh-mc-form-btns {\r\n    display: flex; gap: 10px; margin-top: 18px;\r\n  }\r\n  .cdh-mc-btn {\r\n    flex: 1; padding: 11px; border-radius: 5px;\r\n    border: none; cursor: pointer;\r\n    font-family: Arial, sans-serif; font-size: 12px;\r\n    font-weight: bold; letter-spacing: 1px;\r\n    transition: background 0.2s;\r\n  }\r\n  .cdh-mc-btn.guardar {\r\n    background: rgba(140,95,25,0.85); color: #fff5e0;\r\n  }\r\n  .cdh-mc-btn.guardar:hover { background: rgba(180,125,35,0.95); }\r\n  .cdh-mc-btn.cancelar {\r\n    background: rgba(30,15,2,0.7); color: #c8903a;\r\n    border: 1px solid rgba(130,85,20,0.3);\r\n  }\r\n  .cdh-mc-btn.cancelar:hover { background: rgba(55,28,4,0.85); color: #f0c060; }\r\n\r\n  \/* Indicador de l\u00edmite *\/\r\n  .cdh-mc-limite {\r\n    font-family: Arial, sans-serif; font-size: 12px;\r\n    color: rgba(230,185,80,0.7);\r\n    text-align: right; margin-bottom: 8px;\r\n  }\r\n  .cdh-mc-limite.lleno { color: rgba(220,90,90,0.85); }\r\n\r\n  \/* Aviso \/ error inline *\/\r\n  \/* \u2500\u2500 Pesta\u00f1as Color \/ Icono \u2500\u2500 *\/\r\n  .cdh-tabs {\r\n    display: flex; gap: 6px; margin-bottom: 10px;\r\n  }\r\n  .cdh-tab {\r\n    flex: 1; padding: 8px 10px; border-radius: 5px;\r\n    border: 1.5px solid rgba(180,130,40,0.35);\r\n    background: rgba(25,12,2,0.6);\r\n    color: rgba(210,175,80,0.7);\r\n    font-family: Arial, sans-serif; font-size: 12px; font-weight: bold;\r\n    cursor: pointer; transition: all 0.15s; letter-spacing: 0.5px;\r\n  }\r\n  .cdh-tab:hover { background: rgba(55,28,5,0.7); color: #f0c060; }\r\n  .cdh-tab.sel {\r\n    background: rgba(75,42,8,0.9);\r\n    border-color: rgba(220,175,60,0.8);\r\n    color: #f5d878;\r\n  }\r\n  .cdh-tab-panel { }\r\n\r\n  \/* \u2500\u2500 Paleta de colores \u2500\u2500 *\/\r\n  .cdh-color-grid {\r\n    display: grid;\r\n    grid-template-columns: repeat(6, 1fr);\r\n    gap: 8px;\r\n    padding: 10px;\r\n    background: rgba(15,8,1,0.5);\r\n    border: 1px solid rgba(180,130,40,0.4);\r\n    border-radius: 5px;\r\n  }\r\n  .cdh-color-opt {\r\n    aspect-ratio: 1;\r\n    border-radius: 6px;\r\n    cursor: pointer;\r\n    border: 2px solid transparent;\r\n    transition: transform 0.15s, border-color 0.15s;\r\n    position: relative;\r\n  }\r\n  .cdh-color-opt:hover { transform: scale(1.12); }\r\n  .cdh-color-opt.sel {\r\n    border-color: #fff;\r\n    box-shadow: 0 0 0 2px rgba(255,255,255,0.4), 0 4px 12px rgba(0,0,0,0.6);\r\n    transform: scale(1.15);\r\n  }\r\n  .cdh-color-opt.sel::after {\r\n    content: '\u2713';\r\n    position: absolute; inset: 0;\r\n    display: flex; align-items: center; justify-content: center;\r\n    font-size: 14px; color: #fff;\r\n    text-shadow: 0 1px 4px rgba(0,0,0,0.9);\r\n  }\r\n\r\n  .cdh-mc-aviso {\r\n    padding: 9px 12px; border-radius: 4px;\r\n    font-family: Arial, sans-serif; font-size: 12px;\r\n    margin-top: 8px; display: none;\r\n  }\r\n  .cdh-mc-aviso.error { background: rgba(100,25,25,0.4); border: 1px solid rgba(200,70,70,0.35); color: #e08080; display: block; }\r\n  .cdh-mc-aviso.ok    { background: rgba(25,65,35,0.4); border: 1px solid rgba(45,100,55,0.4); color: #7ec89a; display: block; }\r\n\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     EXPLORADOR DE SUBCARPETAS\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  .cdh-explorador {\r\n    position: fixed; inset: 0; z-index: 100020;\r\n    background: rgba(0,0,0,0.82); backdrop-filter: blur(6px);\r\n    display: flex; align-items: center; justify-content: center;\r\n    padding: 20px;\r\n    visibility: hidden; opacity: 0; pointer-events: none;\r\n    transition: opacity 0.25s;\r\n  }\r\n  .cdh-explorador.open { visibility: visible; opacity: 1; pointer-events: auto; }\r\n\r\n  .cdh-exp-box {\r\n    background: linear-gradient(160deg, rgba(48,25,7,0.98) 0%, rgba(18,42,28,0.98) 100%);\r\n    border: 1px solid rgba(201,169,110,0.45); border-radius: 10px;\r\n    width: 100%; max-width: 620px; max-height: 86vh; max-height: 86svh;\r\n    display: flex; flex-direction: column;\r\n    box-shadow: 0 24px 70px rgba(0,0,0,0.92); overflow: hidden;\r\n    position: relative; z-index: 1;\r\n  }\r\n\r\n  .cdh-exp-header {\r\n    padding: 16px 20px 12px;\r\n    background: rgba(0,0,0,0.25);\r\n    border-bottom: 1px solid rgba(180,130,40,0.3);\r\n    flex-shrink: 0;\r\n  }\r\n  .cdh-exp-header-top { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }\r\n  .cdh-exp-titulo {\r\n    font-family: 'Cinzel', serif; font-size: 14px;\r\n    letter-spacing: 2px; color: #f5d878;\r\n    flex: 1; min-width: 0;\r\n    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;\r\n  }\r\n  .cdh-exp-cerrar {\r\n    background: none; border: none; color: #c8903a;\r\n    font-size: 20px; cursor: pointer; transition: color 0.15s; flex-shrink: 0;\r\n  }\r\n  .cdh-exp-cerrar:hover { color: #f0c060; }\r\n  .cdh-exp-back {\r\n    background: none; border: none; color: #c8903a;\r\n    font-size: 20px; cursor: pointer; transition: color 0.15s; flex-shrink: 0;\r\n    padding: 0 4px; line-height: 1;\r\n  }\r\n  .cdh-exp-back:hover { color: #f0c060; }\r\n\r\n  .cdh-exp-breadcrumb {\r\n    display: flex; align-items: center; flex-wrap: wrap; gap: 4px;\r\n    font-family: Arial, sans-serif; font-size: 12px;\r\n  }\r\n  .cdh-exp-crumb {\r\n    color: rgba(210,175,80,0.7); cursor: pointer; transition: color 0.15s;\r\n    white-space: nowrap; max-width: 140px;\r\n    overflow: hidden; text-overflow: ellipsis;\r\n  }\r\n  .cdh-exp-crumb:hover { color: #f5d878; }\r\n  .cdh-exp-crumb.activo { color: #f5d878; cursor: default; font-weight: bold; }\r\n  .cdh-exp-crumb-sep { color: rgba(180,130,40,0.4); font-size: 10px; }\r\n\r\n  .cdh-exp-acciones {\r\n    padding: 10px 20px;\r\n    border-bottom: 1px solid rgba(140,95,25,0.2);\r\n    display: flex; align-items: center; gap: 8px;\r\n    flex-shrink: 0; flex-wrap: wrap;\r\n  }\r\n  .cdh-exp-btn {\r\n    padding: 7px 14px; border-radius: 5px; border: none;\r\n    font-family: Arial, sans-serif; font-size: 12px; font-weight: bold;\r\n    cursor: pointer; transition: background 0.2s; letter-spacing: 0.5px;\r\n    display: flex; align-items: center; gap: 6px;\r\n  }\r\n  .cdh-exp-btn.primario { background: rgba(140,95,25,0.85); color: #fff5e0; }\r\n  .cdh-exp-btn.primario:hover { background: rgba(180,125,35,0.95); }\r\n\r\n  .cdh-exp-contenido { flex: 1; overflow-y: auto; padding: 18px 20px; }\r\n  .cdh-exp-contenido::-webkit-scrollbar { width: 5px; }\r\n  .cdh-exp-contenido::-webkit-scrollbar-thumb { background: rgba(180,130,40,0.4); border-radius: 3px; }\r\n\r\n  .cdh-exp-grid {\r\n    display: flex; flex-wrap: wrap;\r\n    gap: clamp(16px,3vw,32px); justify-content: flex-start;\r\n  }\r\n  .cdh-exp-carpeta {\r\n    display: flex; flex-direction: column; align-items: center; gap: 7px;\r\n    cursor: pointer; transition: transform 0.25s;\r\n    width: clamp(90px,12vw,120px);\r\n  }\r\n  .cdh-exp-carpeta:hover { transform: translateY(-5px); }\r\n  .cdh-exp-carpeta-wrap {\r\n    position: relative;\r\n    width: clamp(72px,8vw,96px); height: clamp(64px,7vw,84px);\r\n    display: flex; align-items: center; justify-content: center;\r\n  }\r\n  .cdh-exp-carpeta-wrap svg {\r\n    width: 100%; height: 100%;\r\n    filter: drop-shadow(0 2px 8px rgba(0,0,0,0.85)) drop-shadow(0 0 2px rgba(0,0,0,1));\r\n    transition: filter 0.25s;\r\n  }\r\n  .cdh-exp-carpeta:hover .cdh-exp-carpeta-wrap svg {\r\n    filter: drop-shadow(0 4px 14px rgba(0,0,0,0.9)) drop-shadow(0 0 30px rgba(220,170,50,0.3));\r\n  }\r\n  .cdh-exp-carpeta-emoji {\r\n    position: absolute; top: 58%; left: 50%;\r\n    transform: translate(-50%,-50%);\r\n    font-size: clamp(20px,2vw,28px); line-height: 1;\r\n    pointer-events: none;\r\n    filter: drop-shadow(0 2px 4px rgba(0,0,0,0.9));\r\n  }\r\n  .cdh-exp-carpeta-lock {\r\n    position: absolute; top: -3px; right: -3px;\r\n    font-size: clamp(11px,1vw,16px);\r\n    filter: drop-shadow(0 1px 3px rgba(0,0,0,0.9));\r\n  }\r\n  .cdh-exp-carpeta-nombre {\r\n    font-family: Arial, sans-serif; font-size: clamp(10px,0.9vw,12px);\r\n    color: rgba(245,235,200,0.92); text-align: center;\r\n    width: 100%;\r\n    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;\r\n    overflow: hidden; word-break: break-word; line-height: 1.3;\r\n    text-shadow: 0 1px 6px rgba(0,0,0,0.9);\r\n  }\r\n  .cdh-exp-carpeta-fecha {\r\n    font-family: Arial, sans-serif; font-size: 9px;\r\n    color: rgba(210,175,80,0.75); text-align: center;\r\n    margin-top: -4px; text-shadow: 0 1px 4px rgba(0,0,0,1);\r\n  }\r\n  .cdh-exp-carpeta-btns { display: flex; gap: 5px; }\r\n  .cdh-exp-carpeta-btn {\r\n    width: 20px; height: 20px; border-radius: 50%;\r\n    background: rgba(10,5,1,0.8); border: 1px solid rgba(160,110,30,0.45);\r\n    display: flex; align-items: center; justify-content: center;\r\n    font-size: 10px; cursor: pointer; color: #c8903a;\r\n    transition: background 0.15s, color 0.15s;\r\n  }\r\n  .cdh-exp-carpeta-btn:hover { background: rgba(75,40,4,0.9); color: #f0c060; }\r\n  .cdh-exp-carpeta-btn.danger:hover { background: rgba(80,20,20,0.8); color: #e08080; }\r\n\r\n  .cdh-exp-vacio {\r\n    text-align: center; padding: 32px 0;\r\n    font-family: Arial, sans-serif; font-size: 14px;\r\n    color: rgba(220,180,70,0.45); letter-spacing: 1px;\r\n  }\r\n  .cdh-exp-cerrada-msg {\r\n    display: flex; flex-direction: column; align-items: center;\r\n    justify-content: center; padding: 40px 20px; gap: 14px; text-align: center;\r\n  }\r\n  .cdh-exp-cerrada-ico { font-size: 52px; }\r\n  .cdh-exp-cerrada-titulo {\r\n    font-family: 'Cinzel', serif; font-size: 15px;\r\n    letter-spacing: 2px; color: #f5d878;\r\n  }\r\n  .cdh-exp-cerrada-texto {\r\n    font-family: Arial, sans-serif; font-size: 13px;\r\n    color: rgba(230,190,80,0.65); line-height: 1.7; max-width: 340px;\r\n  }\r\n\r\n  \/* Fecha de apertura y recordatorio dentro del aviso de carpeta cerrada *\/\r\n  .cdh-exp-cerrada-fecha {\r\n    font-family: 'Cinzel', serif; font-size: clamp(17px,2vw,22px);\r\n    letter-spacing: 1.5px; color: #f5d878; line-height: 1.3;\r\n  }\r\n  .cdh-exp-cerrada-cuenta {\r\n    font-family: Arial, sans-serif; font-size: 11.5px;\r\n    letter-spacing: 2px; text-transform: uppercase;\r\n    color: rgba(230,190,80,0.55); margin-top: -6px;\r\n  }\r\n  .cdh-exp-recordar {\r\n    display: flex; flex-wrap: wrap; gap: 10px;\r\n    justify-content: center; margin-top: 4px;\r\n  }\r\n  .cdh-exp-recordar-btn {\r\n    display: inline-flex; align-items: center; justify-content: center; gap: 7px;\r\n    cursor: pointer; user-select: none; -webkit-tap-highlight-color: transparent;\r\n    font-family: Arial, sans-serif; font-size: 12.5px; letter-spacing: 0.5px;\r\n    padding: 11px 17px; border-radius: 6px; text-decoration: none;\r\n    background: rgba(30,72,40,0.55); border: 1px solid rgba(120,180,130,0.45);\r\n    color: #bfe6c8; transition: background .2s, border-color .2s, color .2s;\r\n  }\r\n  .cdh-exp-recordar-btn:hover {\r\n    background: rgba(40,95,52,0.78); border-color: rgba(150,215,160,0.7); color: #e2f6e6;\r\n  }\r\n  .cdh-exp-recordar-nota {\r\n    font-family: Arial, sans-serif; font-size: 11px; line-height: 1.5;\r\n    color: rgba(230,190,80,0.4); max-width: 330px;\r\n  }\r\n  @media (max-width: 700px) {\r\n    .cdh-exp-cerrada-msg { padding: 26px 14px; gap: 12px; }\r\n    .cdh-exp-cerrada-ico { font-size: 42px; }\r\n    .cdh-exp-recordar { flex-direction: column; width: 100%; max-width: 320px; }\r\n    .cdh-exp-recordar-btn { width: 100%; box-sizing: border-box; padding: 13px 14px; }\r\n  }\r\n\r\n  .cdh-exp-form {\r\n    background: rgba(0,0,0,0.3); border: 1px solid rgba(180,130,40,0.35);\r\n    border-radius: 7px; padding: 16px 18px; margin-top: 18px;\r\n    position: relative; z-index: 10;\r\n  }\r\n  .cdh-exp-form input,\r\n  .cdh-exp-form select,\r\n  .cdh-exp-form textarea,\r\n  .cdh-exp-form button {\r\n    pointer-events: auto !important;\r\n    position: relative; z-index: 11;\r\n  }\r\n  .cdh-exp-form-titulo {\r\n    font-family: Arial, sans-serif; font-size: 11px;\r\n    letter-spacing: 2px; text-transform: uppercase;\r\n    color: rgba(230,185,80,0.8); margin-bottom: 12px; font-weight: bold;\r\n  }\r\n  .cdh-exp-aviso {\r\n    padding: 8px 12px; border-radius: 4px;\r\n    font-family: Arial, sans-serif; font-size: 12px;\r\n    margin-top: 8px; display: none;\r\n  }\r\n  .cdh-exp-aviso.error { background: rgba(100,25,25,0.4); border: 1px solid rgba(200,70,70,0.35); color: #e08080; display: block; }\r\n  .cdh-exp-aviso.ok    { background: rgba(25,65,35,0.4); border: 1px solid rgba(45,100,55,0.4); color: #7ec89a; display: block; }\r\n\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     VISOR DE ARCHIVOS\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n\r\n  \/* Zona drop dentro del explorador *\/\r\n  .cdh-drop-zona {\r\n    border: 2px dashed rgba(180,130,40,0.45);\r\n    border-radius: 8px;\r\n    padding: 28px 20px;\r\n    text-align: center;\r\n    cursor: pointer;\r\n    transition: border-color 0.2s, background 0.2s;\r\n    background: rgba(10,5,1,0.35);\r\n    margin-bottom: 16px;\r\n  }\r\n  .cdh-drop-zona:hover, .cdh-drop-zona.drag {\r\n    border-color: rgba(220,175,60,0.8);\r\n    background: rgba(40,22,4,0.5);\r\n  }\r\n  .cdh-drop-ico { font-size: 36px; margin-bottom: 8px; }\r\n  .cdh-drop-txt {\r\n    font-family: Arial, sans-serif; font-size: 13px;\r\n    color: rgba(220,185,80,0.7); line-height: 1.7;\r\n  }\r\n  .cdh-drop-txt span { color: #f0c060; text-decoration: underline; cursor: pointer; }\r\n\r\n  \/* Barra de progreso de subida *\/\r\n  .cdh-upload-progreso {\r\n    display: none; margin-bottom: 12px;\r\n  }\r\n  .cdh-upload-progreso.visible { display: block; }\r\n  .cdh-upload-barra-wrap {\r\n    background: rgba(0,0,0,0.4); border-radius: 20px;\r\n    height: 8px; overflow: hidden; margin-bottom: 6px;\r\n    border: 1px solid rgba(140,95,25,0.2);\r\n  }\r\n  .cdh-upload-barra {\r\n    height: 100%; width: 0%;\r\n    background: linear-gradient(90deg, #5a3a10, #c8903a);\r\n    border-radius: 20px; transition: width 0.3s;\r\n  }\r\n  .cdh-upload-estado {\r\n    font-family: Arial, sans-serif; font-size: 11px;\r\n    color: rgba(200,160,60,0.7); text-align: center;\r\n  }\r\n\r\n  \/* Grid de archivos *\/\r\n  .cdh-archivos-grid {\r\n    display: grid;\r\n    grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));\r\n    gap: 12px;\r\n    margin-top: 4px;\r\n  }\r\n\r\n  \/* Tarjeta de archivo *\/\r\n  .cdh-archivo-card {\r\n    display: flex; flex-direction: column; align-items: center;\r\n    gap: 6px; cursor: pointer;\r\n    padding: 10px 6px; border-radius: 7px;\r\n    background: rgba(30,15,3,0.55);\r\n    border: 1px solid rgba(150,100,25,0.2);\r\n    transition: background 0.15s, border-color 0.15s, transform 0.2s;\r\n    position: relative;\r\n  }\r\n  .cdh-archivo-card:hover {\r\n    background: rgba(55,28,5,0.75);\r\n    border-color: rgba(200,150,40,0.45);\r\n    transform: translateY(-3px);\r\n  }\r\n\r\n  \/* Miniatura imagen *\/\r\n  .cdh-archivo-thumb {\r\n    width: 100%; aspect-ratio: 1;\r\n    object-fit: cover; border-radius: 4px;\r\n    background: rgba(0,0,0,0.3);\r\n  }\r\n\r\n  \/* Icono para no-imagen *\/\r\n  .cdh-archivo-ico {\r\n    font-size: 42px; line-height: 1;\r\n    margin: 4px 0;\r\n  }\r\n\r\n  \/* Nombre *\/\r\n  .cdh-archivo-nombre {\r\n    font-family: Arial, sans-serif; font-size: 10px;\r\n    color: rgba(240,220,160,0.85);\r\n    text-align: center; width: 100%;\r\n    overflow: hidden; text-overflow: ellipsis;\r\n    white-space: nowrap; padding: 0 2px;\r\n  }\r\n\r\n  \/* Tama\u00f1o *\/\r\n  .cdh-archivo-size {\r\n    font-family: Arial, sans-serif; font-size: 9px;\r\n    color: rgba(180,140,50,0.5); text-align: center;\r\n  }\r\n\r\n  \/* Bot\u00f3n borrar sobre la tarjeta *\/\r\n  .cdh-archivo-del {\r\n    position: absolute; top: 4px; right: 4px;\r\n    width: 18px; height: 18px; border-radius: 50%;\r\n    background: rgba(80,20,20,0.85);\r\n    border: 1px solid rgba(200,70,70,0.4);\r\n    display: none; align-items: center; justify-content: center;\r\n    font-size: 10px; color: #e08080; cursor: pointer;\r\n    transition: background 0.15s;\r\n  }\r\n  .cdh-archivo-card:hover .cdh-archivo-del { display: flex; }\r\n  .cdh-archivo-del:hover { background: rgba(140,30,30,0.95); }\r\n\r\n  \/* Pie de foto editable *\/\r\n  .cdh-archivo-caption-input {\r\n    width: 100%; box-sizing: border-box;\r\n    margin-top: 2px; padding: 2px 5px;\r\n    font-family: Arial, sans-serif; font-size: 9px;\r\n    color: rgba(240,220,160,0.9);\r\n    background: rgba(0,0,0,0.35);\r\n    border: 1px solid rgba(150,100,25,0.3); border-radius: 3px;\r\n    text-align: center; outline: none; resize: none;\r\n    transition: border-color 0.15s, background 0.15s;\r\n  }\r\n  .cdh-archivo-caption-input:focus {\r\n    border-color: rgba(200,150,40,0.6);\r\n    background: rgba(0,0,0,0.55);\r\n  }\r\n  .cdh-archivo-caption-input::placeholder { color: rgba(180,140,50,0.4); }\r\n\r\n  \/* Caption en modo lectura (visitantes) *\/\r\n  .cdh-archivo-caption-pub {\r\n    font-family: Arial, sans-serif; font-size: 9px;\r\n    color: rgba(240,220,160,0.7);\r\n    font-style: italic; text-align: center;\r\n    width: 100%; padding: 0 2px;\r\n    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\r\n  }\r\n\r\n  \/* \u2500\u2500 Lightbox \u2500\u2500 *\/\r\n  .cdh-lightbox {\r\n    position: fixed; inset: 0; z-index: 100050;\r\n    background: rgba(0,0,0,0.93);\r\n    display: flex; flex-direction: column;\r\n    align-items: center; justify-content: center;\r\n    padding: 20px;\r\n    visibility: hidden; opacity: 0; pointer-events: none;\r\n    transition: opacity 0.2s;\r\n  }\r\n  .cdh-lightbox.open { visibility: visible; opacity: 1; pointer-events: auto; }\r\n\r\n  .cdh-lb-cerrar {\r\n    position: absolute; top: 16px; right: 20px;\r\n    background: none; border: none; color: rgba(255,255,255,0.6);\r\n    font-size: 28px; cursor: pointer; transition: color 0.15s; z-index: 2;\r\n  }\r\n  .cdh-lb-cerrar:hover { color: #fff; }\r\n\r\n  \/* Flechas navegaci\u00f3n *\/\r\n  .cdh-lb-nav {\r\n    position: absolute; top: 50%; transform: translateY(-50%);\r\n    background: rgba(0,0,0,0.45); border: 1px solid rgba(255,255,255,0.15);\r\n    color: rgba(255,255,255,0.7); font-size: 28px; line-height: 1;\r\n    width: 48px; height: 64px; border-radius: 6px;\r\n    display: flex; align-items: center; justify-content: center;\r\n    cursor: pointer; z-index: 3; transition: background 0.15s, color 0.15s;\r\n    user-select: none;\r\n  }\r\n  .cdh-lb-nav:hover { background: rgba(180,125,35,0.7); color: #fff; }\r\n  .cdh-lb-nav.prev { left: 12px; }\r\n  .cdh-lb-nav.next { right: 12px; }\r\n  .cdh-lb-nav.hidden { visibility: hidden; pointer-events: none; }\r\n\r\n  \/* Contador archivos *\/\r\n  .cdh-lb-contador {\r\n    position: absolute; top: 20px; left: 50%; transform: translateX(-50%);\r\n    font-family: Arial, sans-serif; font-size: 11px;\r\n    color: rgba(255,255,255,0.4); z-index: 2;\r\n  }\r\n\r\n  .cdh-lb-descargar {\r\n    position: absolute; top: 16px; right: 64px;\r\n    background: rgba(140,95,25,0.7);\r\n    border: 1px solid rgba(200,150,40,0.5);\r\n    border-radius: 5px; padding: 6px 14px;\r\n    color: #f5d878; font-family: Arial, sans-serif;\r\n    font-size: 12px; cursor: pointer; text-decoration: none;\r\n    transition: background 0.15s; z-index: 2;\r\n  }\r\n  .cdh-lb-descargar:hover { background: rgba(180,125,35,0.9); }\r\n\r\n  .cdh-lb-nombre {\r\n    position: absolute; bottom: 20px; left: 50%;\r\n    transform: translateX(-50%);\r\n    font-family: Arial, sans-serif; font-size: 13px;\r\n    color: rgba(255,255,255,0.6); text-align: center;\r\n    max-width: 80vw; white-space: nowrap;\r\n    overflow: hidden; text-overflow: ellipsis;\r\n    z-index: 2;\r\n  }\r\n\r\n  .cdh-lb-contenido {\r\n    max-width: 92vw; max-height: 82vh; max-height: 82svh;\r\n    display: flex; align-items: center; justify-content: center;\r\n  }\r\n  .cdh-lb-contenido img {\r\n    max-width: 100%; max-height: 82vh; max-height: 82svh;\r\n    border-radius: 4px; object-fit: contain;\r\n  }\r\n  .cdh-lb-contenido video,\r\n  .cdh-lb-contenido audio {\r\n    max-width: 90vw; outline: none;\r\n  }\r\n  .cdh-lb-contenido iframe {\r\n    width: min(800px, 92vw); height: 80vh; height: 80svh;\r\n    border: none; border-radius: 4px;\r\n    background: #fff;\r\n  }\r\n  .cdh-lb-contenido pre {\r\n    max-width: 80vw; max-height: 75vh; max-height: 75svh;\r\n    overflow: auto; background: rgba(20,10,2,0.9);\r\n    border: 1px solid rgba(180,130,40,0.3);\r\n    border-radius: 6px; padding: 20px;\r\n    color: rgba(240,220,160,0.9);\r\n    font-family: monospace; font-size: 13px;\r\n    line-height: 1.6; white-space: pre-wrap;\r\n  }\r\n  .cdh-lb-otro {\r\n    text-align: center; padding: 40px;\r\n  }\r\n  .cdh-lb-otro-ico { font-size: 60px; margin-bottom: 16px; }\r\n  .cdh-lb-otro-txt {\r\n    font-family: Arial, sans-serif; font-size: 14px;\r\n    color: rgba(220,185,80,0.7); margin-bottom: 20px;\r\n  }\r\n  .cdh-lb-btn-dl {\r\n    display: inline-block; padding: 12px 28px;\r\n    background: rgba(140,95,25,0.85); color: #fff5e0;\r\n    border: 1px solid rgba(200,155,45,0.5); border-radius: 5px;\r\n    font-family: Arial, sans-serif; font-size: 13px;\r\n    font-weight: bold; text-decoration: none; cursor: pointer;\r\n    transition: background 0.2s;\r\n  }\r\n  .cdh-lb-btn-dl:hover { background: rgba(180,125,35,0.95); }\r\n\r\n\r\n\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     BOTONES DE BORRAR \u2014 revisi\u00f3n de agosto 2026\r\n\r\n     Problema anterior: el icono era el emoji \ud83d\uddd1 a 10-11 px dentro\r\n     de c\u00edrculos de 18-22 px. Al ser un emoji multicolor ignoraba\r\n     el `color:` del CSS, as\u00ed que se ve\u00eda como un borr\u00f3n gris que\r\n     adem\u00e1s cambia de dibujo en cada sistema operativo. Y salvo en\r\n     :hover era id\u00e9ntico al bot\u00f3n de editar: nada avisaba de que\r\n     esa acci\u00f3n destruye algo.\r\n\r\n     Ahora: la misma papelera de rejilla del emoji, pero dibujada en\r\n     SVG vectorial (n\u00edtida a cualquier tama\u00f1o e igual en todas\r\n     partes), c\u00edrculo m\u00e1s grande y \u00e1rea de pulsaci\u00f3n de 44 px para\r\n     el m\u00f3vil. Se queda en la gama \u00e1mbar de la cripta; solo vira a\r\n     rojo al pasar por encima, que es cuando ya vas a pulsar.\r\n\r\n     En \u00c1rbol y Biograf\u00eda el bot\u00f3n llama a criptaActivarModulo(), que\r\n     solo quita el m\u00f3dulo de la vista: no borra el \u00e1rbol ni la\r\n     biograf\u00eda. Lleva el mismo icono por coherencia visual, pero\r\n     conviene cambiarle el title a \"Quitar de la cripta\" para que el\r\n     usuario sepa lo que hace; la regla lo sigue cogiendo igual.\r\n\r\n     Los botones se seleccionan por su atributo `title` y por la\r\n     clase `.danger` que ya tra\u00edan, as\u00ed que este bloque NO obliga a\r\n     tocar el JavaScript que los genera.\r\n  \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  :root {\r\n    --cdh-ico-basura: url(\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cdefs%3E%3ClinearGradient%20id%3D%22b%22%20x1%3D%220%22%20y1%3D%220%22%20x2%3D%221%22%20y2%3D%221%22%3E%3Cstop%20offset%3D%220%22%20stop-color%3D%22%23fff1bd%22%2F%3E%3Cstop%20offset%3D%22.22%22%20stop-color%3D%22%23e8b454%22%2F%3E%3Cstop%20offset%3D%22.55%22%20stop-color%3D%22%23a96518%22%2F%3E%3Cstop%20offset%3D%22.78%22%20stop-color%3D%22%23f2c66a%22%2F%3E%3Cstop%20offset%3D%221%22%20stop-color%3D%22%237b420e%22%2F%3E%3C%2FlinearGradient%3E%3ClinearGradient%20id%3D%22l%22%20x1%3D%220%22%20y1%3D%220%22%20x2%3D%220%22%20y2%3D%221%22%3E%3Cstop%20offset%3D%220%22%20stop-color%3D%22%23ffe6a1%22%2F%3E%3Cstop%20offset%3D%22.45%22%20stop-color%3D%22%23d89531%22%2F%3E%3Cstop%20offset%3D%221%22%20stop-color%3D%22%238a4a0e%22%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Cpath%20d%3D%22M8.5%204.1h7l.65%201.55H7.85L8.5%204.1Z%22%20fill%3D%22url%28%23l%29%22%20stroke%3D%22%236f390a%22%20stroke-width%3D%22.65%22%2F%3E%3Crect%20x%3D%224.1%22%20y%3D%225.5%22%20width%3D%2215.8%22%20height%3D%222.45%22%20rx%3D%221.05%22%20fill%3D%22url%28%23l%29%22%20stroke%3D%22%236f390a%22%20stroke-width%3D%22.7%22%2F%3E%3Cpath%20d%3D%22M5.75%208.15h12.5l-1.15%2011.1a1.75%201.75%200%200%201-1.74%201.57H8.64a1.75%201.75%200%200%201-1.74-1.57L5.75%208.15Z%22%20fill%3D%22url%28%23b%29%22%20stroke%3D%22%236f390a%22%20stroke-width%3D%22.75%22%2F%3E%3Cpath%20d%3D%22M8.15%2010.2l.55%207.95M12%2010.2v8.05M15.85%2010.2l-.55%207.95%22%20fill%3D%22none%22%20stroke%3D%22%2370400f%22%20stroke-width%3D%221%22%20stroke-linecap%3D%22round%22%20opacity%3D%22.85%22%2F%3E%3Cpath%20d%3D%22M7.25%209.15h9.5%22%20stroke%3D%22%23fff3c4%22%20stroke-width%3D%22.55%22%20opacity%3D%22.65%22%2F%3E%3Cpath%20d%3D%22M8.15%209.75l.42%207.25%22%20stroke%3D%22%23fff7d8%22%20stroke-width%3D%22.45%22%20opacity%3D%22.55%22%2F%3E%3Cpath%20d%3D%22M16.25%209.8l-.42%206.4%22%20stroke%3D%22%235c2e07%22%20stroke-width%3D%22.45%22%20opacity%3D%22.55%22%2F%3E%3C%2Fsvg%3E\");\r\n    --cdh-ico-basura-hover: url(\"data:image\/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cdefs%3E%3ClinearGradient%20id%3D%22b%22%20x1%3D%220%22%20y1%3D%220%22%20x2%3D%221%22%20y2%3D%221%22%3E%3Cstop%20offset%3D%220%22%20stop-color%3D%22%23ffe0d7%22%2F%3E%3Cstop%20offset%3D%22.22%22%20stop-color%3D%22%23f08f79%22%2F%3E%3Cstop%20offset%3D%22.55%22%20stop-color%3D%22%23a52d22%22%2F%3E%3Cstop%20offset%3D%22.78%22%20stop-color%3D%22%23ffb39f%22%2F%3E%3Cstop%20offset%3D%221%22%20stop-color%3D%22%23721b16%22%2F%3E%3C%2FlinearGradient%3E%3ClinearGradient%20id%3D%22l%22%20x1%3D%220%22%20y1%3D%220%22%20x2%3D%220%22%20y2%3D%221%22%3E%3Cstop%20offset%3D%220%22%20stop-color%3D%22%23ffd6ca%22%2F%3E%3Cstop%20offset%3D%22.45%22%20stop-color%3D%22%23dc705c%22%2F%3E%3Cstop%20offset%3D%221%22%20stop-color%3D%22%2384241b%22%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Cpath%20d%3D%22M8.5%204.1h7l.65%201.55H7.85L8.5%204.1Z%22%20fill%3D%22url%28%23l%29%22%20stroke%3D%22%23641711%22%20stroke-width%3D%22.65%22%2F%3E%3Crect%20x%3D%224.1%22%20y%3D%225.5%22%20width%3D%2215.8%22%20height%3D%222.45%22%20rx%3D%221.05%22%20fill%3D%22url%28%23l%29%22%20stroke%3D%22%23641711%22%20stroke-width%3D%22.7%22%2F%3E%3Cpath%20d%3D%22M5.75%208.15h12.5l-1.15%2011.1a1.75%201.75%200%200%201-1.74%201.57H8.64a1.75%201.75%200%200%201-1.74-1.57L5.75%208.15Z%22%20fill%3D%22url%28%23b%29%22%20stroke%3D%22%23641711%22%20stroke-width%3D%22.75%22%2F%3E%3Cpath%20d%3D%22M8.15%2010.2l.55%207.95M12%2010.2v8.05M15.85%2010.2l-.55%207.95%22%20fill%3D%22none%22%20stroke%3D%22%2374221a%22%20stroke-width%3D%221%22%20stroke-linecap%3D%22round%22%20opacity%3D%22.85%22%2F%3E%3Cpath%20d%3D%22M7.25%209.15h9.5%22%20stroke%3D%22%23fff0eb%22%20stroke-width%3D%22.55%22%20opacity%3D%22.65%22%2F%3E%3Cpath%20d%3D%22M8.15%209.75l.42%207.25%22%20stroke%3D%22%23fff7f3%22%20stroke-width%3D%22.45%22%20opacity%3D%22.55%22%2F%3E%3Cpath%20d%3D%22M16.25%209.8l-.42%206.4%22%20stroke%3D%22%2352120e%22%20stroke-width%3D%22.45%22%20opacity%3D%22.55%22%2F%3E%3C%2Fsvg%3E\");\r\n\r\n    \/* Color del boton de borrar. Cambia estas tres lineas y cambian los\r\n       cuatro botones a la vez. Presets alternativos mas abajo. *\/\r\n    --cdh-borrar-color:  #e9a83f;                 \/* icono *\/\r\n    --cdh-borrar-fondo:  rgba(10,5,1,0.86);       \/* circulo *\/\r\n    --cdh-borrar-borde:  rgba(196,124,52,0.72);   \/* aro *\/\r\n\r\n    \/* Terracota apagado, algo mas serio sin llegar a rojo:\r\n       --cdh-borrar-color: #d98a63;\r\n       --cdh-borrar-fondo: rgba(30,12,6,0.88);\r\n       --cdh-borrar-borde: rgba(196,110,70,0.68);\r\n\r\n       Rojo de aviso, si algun dia quieres marcarlo fuerte:\r\n       --cdh-borrar-color: #ff9d8c;\r\n       --cdh-borrar-fondo: rgba(72,14,12,0.90);\r\n       --cdh-borrar-borde: rgba(235,120,95,0.70); *\/\r\n  }\r\n\r\n  \/* \u2500\u2500 Los tres botones que S\u00cd borran datos \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .c-carpeta-accion[title^=\"Borrar\"],\r\n  .c-carpeta-accion[title^=\"Elimin\"],\r\n  .c-carpeta-accion[title^=\"Quitar\"],\r\n  .cdh-exp-carpeta-btn.danger,\r\n  .cdh-mc-btn-ico.danger,\r\n  .cdh-archivo-del {\r\n    position: relative;\r\n    font-size: 0 !important;              \/* oculta el emoji original *\/\r\n    color: var(--cdh-borrar-color);\r\n    background: var(--cdh-borrar-fondo);\r\n    border: 1px solid var(--cdh-borrar-borde);\r\n    box-shadow: 0 1px 6px rgba(0,0,0,0.65), inset 0 1px 0 rgba(255,215,160,0.14);\r\n    transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.1s;\r\n  }\r\n  .c-carpeta-accion[title^=\"Borrar\"]::before,\r\n  .c-carpeta-accion[title^=\"Elimin\"]::before,\r\n  .c-carpeta-accion[title^=\"Quitar\"]::before,\r\n  .cdh-exp-carpeta-btn.danger::before,\r\n  .cdh-mc-btn-ico.danger::before,\r\n  .cdh-archivo-del::before {\r\n    content: ''; display: block;\r\n    width: 72%; height: 72%;\r\n    background: var(--cdh-ico-basura) center \/ contain no-repeat;\r\n    filter: drop-shadow(0 1px 1px rgba(0,0,0,0.78)) drop-shadow(0 0 2px rgba(255,205,110,0.18));\r\n  }\r\n  \/* Zona de pulsaci\u00f3n ampliada (invisible) para dedos en m\u00f3vil *\/\r\n  .c-carpeta-accion[title^=\"Borrar\"]::after,\r\n  .c-carpeta-accion[title^=\"Elimin\"]::after,\r\n  .c-carpeta-accion[title^=\"Quitar\"]::after,\r\n  .cdh-exp-carpeta-btn.danger::after,\r\n  .cdh-mc-btn-ico.danger::after {\r\n    content: ''; position: absolute; inset: -10px; border-radius: 50%;\r\n  }\r\n  .cdh-archivo-del::after {\r\n    content: ''; position: absolute; inset: -6px; border-radius: 50%;\r\n  }\r\n\r\n  .c-carpeta-accion[title^=\"Borrar\"]:hover,\r\n  .c-carpeta-accion[title^=\"Elimin\"]:hover,\r\n  .c-carpeta-accion[title^=\"Quitar\"]:hover,\r\n  .cdh-exp-carpeta-btn.danger:hover,\r\n  .cdh-mc-btn-ico.danger:hover,\r\n  .cdh-archivo-del:hover {\r\n    background: rgba(120,26,20,0.94);\r\n    border-color: rgba(240,150,120,0.9);\r\n    color: #ffd9cc;\r\n  }\r\n  .c-carpeta-accion[title^=\"Borrar\"]:hover::before,\r\n  .c-carpeta-accion[title^=\"Elimin\"]:hover::before,\r\n  .c-carpeta-accion[title^=\"Quitar\"]:hover::before,\r\n  .cdh-exp-carpeta-btn.danger:hover::before,\r\n  .cdh-mc-btn-ico.danger:hover::before,\r\n  .cdh-archivo-del:hover::before {\r\n    background-image: var(--cdh-ico-basura-hover);\r\n    filter: drop-shadow(0 1px 1px rgba(0,0,0,0.85)) drop-shadow(0 0 3px rgba(255,150,120,0.3));\r\n  }\r\n  .c-carpeta-accion[title^=\"Borrar\"]:active,\r\n  .c-carpeta-accion[title^=\"Elimin\"]:active,\r\n  .c-carpeta-accion[title^=\"Quitar\"]:active,\r\n  .cdh-exp-carpeta-btn.danger:active,\r\n  .cdh-mc-btn-ico.danger:active,\r\n  .cdh-archivo-del:active { transform: scale(0.9); }\r\n\r\n  .c-carpeta-accion[title^=\"Borrar\"]:focus-visible,\r\n  .c-carpeta-accion[title^=\"Elimin\"]:focus-visible,\r\n  .c-carpeta-accion[title^=\"Quitar\"]:focus-visible,\r\n  .cdh-exp-carpeta-btn.danger:focus-visible,\r\n  .cdh-mc-btn-ico.danger:focus-visible,\r\n  .cdh-archivo-del:focus-visible {\r\n    outline: 2px solid var(--cdh-borrar-color); outline-offset: 2px;\r\n  }\r\n\r\n  \/* \u2500\u2500 Tama\u00f1os: la fila entera crece para que no se descuadre \u2500 *\/\r\n  .c-carpeta-accion    { width: 26px; height: 26px; font-size: 12px; }\r\n  .c-carpeta-accion:first-child { font-size: 17px; }\r\n  .cdh-exp-carpeta-btn { width: 24px; height: 24px; font-size: 11px; }\r\n  .cdh-mc-btn-ico      { width: 30px; height: 30px; font-size: 14px; }\r\n\r\n  \/* \u2500\u2500 Borrar archivo: antes estaba display:none hasta pasar el\r\n        rat\u00f3n por encima, as\u00ed que en tableta y m\u00f3vil no aparec\u00eda.\r\n        Ahora est\u00e1 siempre, atenuado, y se enciende al acercarse. \u2500\u2500 *\/\r\n  .cdh-archivo-del {\r\n    display: flex !important;\r\n    width: 24px; height: 24px;\r\n    top: 5px; right: 5px;\r\n    opacity: 0.62;\r\n    transition: opacity 0.15s, background 0.15s, transform 0.1s;\r\n  }\r\n  .cdh-archivo-card:hover .cdh-archivo-del { opacity: 1; }\r\n  @media (hover: none) {\r\n    .cdh-archivo-del { opacity: 1; width: 26px; height: 26px; }\r\n\r\n    \/* Dedo, no raton: los tres botones de cada carpeta necesitan\r\n       mas superficie para poder pulsarlos sin fallar. *\/\r\n    .c-carpeta-acciones { gap: 10px; margin-top: 4px; }\r\n    .c-carpeta-accion {\r\n      width: 32px; height: 32px; font-size: 15px;\r\n      touch-action: manipulation;\r\n    }\r\n    .c-carpeta-accion:first-child { font-size: 20px; }\r\n  }\r\n\r\n  \/* \u2500\u2500 El icono grande del modal de confirmacion usa la misma cesta.\r\n        Solo se sustituye cuando cdhConfirm() recibe la papelera; los\r\n        otros avisos (lapida, candado) siguen con su emoji. \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 *\/\r\n  .cdh-confirm-basura {\r\n    display: inline-block;\r\n    width: 46px; height: 46px;\r\n    background-color: var(--cdh-borrar-color);\r\n    -webkit-mask: var(--cdh-ico-basura) center \/ contain no-repeat;\r\n            mask: var(--cdh-ico-basura) center \/ contain no-repeat;\r\n  }\r\n\r\n  \/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     AVISO: GIRA EL TELEFONO\r\n     Solo se ve en pantallas estrechas Y en vertical. Al girar el\r\n     movil desaparece solo, porque es una media query (sin JS).\r\n     Si el usuario tiene el giro bloqueado, puede continuar igual.\r\n     \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\n  #cdhGiraOverlay { display: none; }\r\n\r\n  @media (orientation: portrait) and (max-width: 900px) {\r\n    #cdhGiraOverlay {\r\n      display: flex;\r\n      position: fixed; inset: 0;\r\n      z-index: 100010;\r\n      flex-direction: column;\r\n      align-items: center; justify-content: center;\r\n      gap: 26px; padding: 34px 28px;\r\n      text-align: center;\r\n      background: linear-gradient(165deg, #563923 0%, #3a281a 100%);\r\n    }\r\n    #cdhGiraOverlay.cdh-gira-ok { display: none; }\r\n    .cdh-gira-ico {\r\n      width: 74px; height: 74px;\r\n      color: #f0c060;\r\n      animation: cdhGiraGiro 2.6s ease-in-out infinite;\r\n    }\r\n    .cdh-gira-tit {\r\n      font-family: 'Cinzel', Georgia, serif;\r\n      font-size: 25px; font-weight: 600;\r\n      letter-spacing: 2px; color: #f4e6c4;\r\n    }\r\n    .cdh-gira-txt {\r\n      font-family: 'Crimson Text', Georgia, serif;\r\n      font-size: 17px; line-height: 1.5;\r\n      color: rgba(244,230,196,0.82);\r\n      max-width: 300px;\r\n    }\r\n    .cdh-gira-sep {\r\n      width: 120px; height: 1px;\r\n      background: linear-gradient(90deg, transparent, rgba(240,192,96,0.45), transparent);\r\n    }\r\n    \/* Acciones del aviso: entrar a pantalla completa o seguir asi *\/\r\n    .cdh-gira-acciones {\r\n      display: flex; flex-direction: column;\r\n      align-items: center; gap: 18px;\r\n    }\r\n    .cdh-gira-fs {\r\n      display: inline-flex; align-items: center; gap: 9px;\r\n      font-family: 'Cinzel', Georgia, serif;\r\n      font-size: 14px; letter-spacing: 1.5px; text-transform: uppercase;\r\n      color: #f4e6c4;\r\n      background: linear-gradient(135deg, rgba(120,72,14,0.92) 0%, rgba(75,44,8,0.92) 100%);\r\n      border: 1px solid rgba(220,175,70,0.72);\r\n      border-radius: 4px; padding: 13px 22px;\r\n      cursor: pointer; -webkit-tap-highlight-color: transparent;\r\n      box-shadow: 0 4px 18px rgba(0,0,0,0.55), inset 0 1px 0 rgba(220,175,70,0.20);\r\n      transition: transform 0.15s, border-color 0.2s;\r\n    }\r\n    .cdh-gira-fs:active { transform: scale(0.97); border-color: rgba(240,192,96,0.95); }\r\n    .cdh-gira-fs svg { width: 17px; height: 17px; fill: currentColor; flex-shrink: 0; }\r\n    \/* Navegador sin pantalla completa (Safari de iPhone): solo queda continuar *\/\r\n    #cdhGiraOverlay.cdh-sin-fs .cdh-gira-fs { display: none; }\r\n\r\n    .cdh-gira-btn {\r\n      font-family: Arial, sans-serif; font-size: 13px;\r\n      letter-spacing: 1px;\r\n      color: rgba(244,230,196,0.62);\r\n      border-bottom: 1px solid rgba(244,230,196,0.32);\r\n      padding-bottom: 2px; cursor: pointer;\r\n      -webkit-tap-highlight-color: transparent;\r\n    }\r\n    .cdh-gira-btn:active { color: #f0c060; }\r\n  }\r\n  @keyframes cdhGiraGiro {\r\n    0%, 32%   { transform: rotate(0deg); }\r\n    58%, 88%  { transform: rotate(-90deg); }\r\n    100%      { transform: rotate(0deg); }\r\n  }\r\n\r\n  \/* \u2500\u2500 Boton de pantalla completa (esquina inferior derecha) \u2500\u2500 *\/\r\n  .c-fs-btn {\r\n    position: absolute; bottom: 18px; right: 18px;\r\n    width: 42px; height: 42px; border-radius: 50%;\r\n    background: rgba(12,6,2,0.72);\r\n    border: 1.5px solid rgba(200,155,50,0.38);\r\n    cursor: pointer; display: flex; align-items: center; justify-content: center;\r\n    color: rgba(255,255,255,0.82); z-index: 20;\r\n    opacity: 0.55;\r\n    transition: opacity 0.25s, transform 0.25s, border-color 0.3s;\r\n    box-shadow: 0 0 18px rgba(0,0,0,0.65);\r\n    -webkit-tap-highlight-color: transparent;\r\n  }\r\n  .c-fs-btn:hover { opacity: 1; transform: scale(1.1); border-color: rgba(220,175,70,0.85); color: #f0c060; }\r\n  .c-fs-btn svg { width: 20px; height: 20px; fill: currentColor; }\r\n  .c-fs-btn .fs-salir { display: none; }\r\n  .c-fs-btn.activo .fs-entrar { display: none; }\r\n  .c-fs-btn.activo .fs-salir  { display: block; }\r\n  @media (hover: none) { .c-fs-btn { opacity: 0.85; } }\r\n\r\n  \/* \u2500\u2500 Barra de desplazamiento de los menus (fina y dorada) \u2500\u2500 *\/\r\n  .c-panel::-webkit-scrollbar,\r\n  .c-user-panel::-webkit-scrollbar { width: 7px; }\r\n  .c-panel::-webkit-scrollbar-track,\r\n  .c-user-panel::-webkit-scrollbar-track { background: rgba(0,0,0,0.35); }\r\n  .c-panel::-webkit-scrollbar-thumb,\r\n  .c-user-panel::-webkit-scrollbar-thumb {\r\n    background: rgba(180,130,40,0.5); border-radius: 4px;\r\n  }\r\n  .c-panel::-webkit-scrollbar-thumb:hover,\r\n  .c-user-panel::-webkit-scrollbar-thumb:hover { background: rgba(220,175,70,0.75); }\r\n  .c-panel, .c-user-panel {\r\n    scrollbar-width: thin;\r\n    scrollbar-color: rgba(180,130,40,0.5) rgba(0,0,0,0.35);\r\n  }\r\n\r\n\r\n<\/style>\r\n<\/head>\r\n<body>\r\n<!-- \u2500\u2500 Aviso de girar el telefono (solo movil en vertical) \u2500\u2500 -->\r\n<div id=\"cdhGiraOverlay\">\r\n  <svg class=\"cdh-gira-ico\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\"\r\n       stroke-width=\"1.4\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\r\n    <rect x=\"7\" y=\"2\" width=\"10\" height=\"20\" rx=\"2\"\/>\r\n    <line x1=\"10.5\" y1=\"19\" x2=\"13.5\" y2=\"19\"\/>\r\n  <\/svg>\r\n  <div class=\"cdh-gira-tit\">Gira el telefono<\/div>\r\n  <div class=\"cdh-gira-sep\"><\/div>\r\n  <div class=\"cdh-gira-txt\">La Cripta se contempla en horizontal, a pantalla completa.<\/div>\r\n  <div class=\"cdh-gira-acciones\">\r\n    <span class=\"cdh-gira-fs\" role=\"button\" tabindex=\"0\" onclick=\"cdhGiraPantallaCompleta()\">\r\n      <svg viewBox=\"0 0 24 24\"><path d=\"M7,14H5v5h5v-2H7V14zM5,10h2V7h3V5H5V10zM17,17h-3v2h5v-5h-2V17zM14,5v2h3v3h2V5H14z\"\/><\/svg>\r\n      Ver a pantalla completa\r\n    <\/span>\r\n    <span class=\"cdh-gira-btn\"\r\n          onclick=\"document.getElementById('cdhGiraOverlay').classList.add('cdh-gira-ok')\">Continuar asi<\/span>\r\n  <\/div>\r\n<\/div>\r\n<div class=\"cripta-fullscreen\" id=\"cripta\">\r\n\r\n  <!-- Cabecera difunto arriba -->\r\n  <div class=\"c-cabecera\">\r\n    <div class=\"c-nombre\" id=\"nombreDifunto\"><\/div>\r\n    <div class=\"c-anios\"  id=\"aniosDifunto\"><\/div>\r\n    <div class=\"c-separador\" id=\"separador\" style=\"display:none\"><\/div>\r\n  <\/div>\r\n\r\n\r\n  <!-- Bot\u00f3n usuario -->\r\n  <button class=\"c-user-btn\" id=\"userBtn\"><svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" fill=\"#ffffff\"><path d=\"M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z\"\/><\/svg><\/button>\r\n\r\n  <!-- Bot\u00f3n Mapa de la Cripta para visitantes p\u00fablicos (oculto por defecto; se muestra si el propietario activ\u00f3 \"Visible tambi\u00e9n p\u00fablicamente\") -->\r\n  <button id=\"mapaBtnPublico\" onclick=\"abrirMapa()\" style=\"display:none\">\r\n    <span class=\"mapa-btn-ico\">\ud83d\uddfa\ufe0f<\/span>\r\n    <span class=\"mapa-btn-txt\">Mapa de la Cripta<\/span>\r\n  <\/button>\r\n\r\n  <!-- Panel usuario -->\r\n  <div class=\"c-user-panel\" id=\"userPanel\">\r\n    <div class=\"c-up-head\">\r\n      <div class=\"c-up-name\" id=\"upNombre\">Cargando...<\/div>\r\n      <div class=\"c-up-email\" id=\"upEmail\"><\/div>\r\n    <\/div>\r\n    <div class=\"c-up-item\" onclick=\"irA('\/index.php\/perfil-de-usuario\/')\">\u270f\ufe0f &nbsp;Editar mis datos<\/div>\r\n    <div class=\"c-up-item\" onclick=\"irA('\/index.php\/cambiar-contrasena\/')\">\ud83d\udd11 &nbsp;Cambiar contrase\u00f1a<\/div>\r\n    <div class=\"c-up-sep\"><\/div>\r\n    <div class=\"c-up-item\" onclick=\"irA('https:\/\/cementeriodigitalhispano.com\/index.php\/pasarela-de-entrada\/')\">\ud83e\udea6 &nbsp;Crear nueva Sepultura o Glosar monumento funerario<\/div>\r\n    <div class=\"c-up-sep\"><\/div>\r\n    <div class=\"c-up-item\" onclick=\"cdh_cerrar_sesion()\">\ud83d\udeaa &nbsp;Cerrar sesi\u00f3n<\/div>\r\n    <div class=\"c-up-item danger\" onclick=\"irA('https:\/\/cementeriodigitalhispano.com\/?page_id=913')\">\u26a0\ufe0f &nbsp;Eliminar mi cuenta<\/div>\r\n    <div class=\"c-up-sep\"><\/div>\r\n    <div class=\"c-up-item\" onclick=\"irA('\/?noredirect=1')\">\ud83c\udfe0 &nbsp;Salir<\/div>\r\n  <\/div>\r\n\r\n  <!-- Bot\u00f3n previsualizar -->\r\n  <button class=\"c-preview-btn\" id=\"previewBtn\" title=\"Vista previa p\u00fablica\">\ud83d\udc41\ufe0f<\/button>\r\n\r\n  <!-- Rueda dentada -->\r\n  <button class=\"c-gear\" id=\"gearBtn\"><svg viewBox=\"0 0 24 24\" width=\"24\" height=\"24\" fill=\"#ffffff\"><path d=\"M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z\"\/><\/svg><\/button>\r\n\r\n  <!-- Boton pantalla completa -->\r\n  <button class=\"c-fs-btn\" id=\"fsBtn\" onclick=\"cdhPantallaCompleta()\">\r\n    <svg class=\"fs-entrar\" viewBox=\"0 0 24 24\"><path d=\"M7,14H5v5h5v-2H7V14zM5,10h2V7h3V5H5V10zM17,17h-3v2h5v-5h-2V17zM14,5v2h3v3h2V5H14z\"\/><\/svg>\r\n    <svg class=\"fs-salir\"  viewBox=\"0 0 24 24\"><path d=\"M5,16h3v3h2v-5H5V16zM8,8H5v2h5V5H8V8zM14,19h2v-3h3v-2h-5V19zM16,8V5h-2v5h5V8H16z\"\/><\/svg>\r\n  <\/button>\r\n\r\n  <!-- Panel opciones -->\r\n  <div class=\"c-panel\" id=\"panel\">\r\n    <div class=\"c-ph\">\u2699 &nbsp;OPCIONES<\/div>\r\n    <div class=\"c-pi\" id=\"decorRow\">\ud83c\udfdb &nbsp;Temas y estilo de la cripta <span class=\"c-arr\" id=\"dArr\">\u203a<\/span><\/div>\r\n    <div class=\"c-sub\" id=\"decorSub\">\r\n\r\n      <!-- Religiones y espiritualidad -->\r\n      <div class=\"c-cat\" onclick=\"toggleCat('cat1',this)\">\ud83d\udd4a &nbsp;Religiones y espiritualidad <span class=\"c-cat-arr\" id=\"cat1Arr\">\u203a<\/span><\/div>\r\n      <div class=\"c-cat-sub\" id=\"cat1\">\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('religionesyespiritualidad','agnostico')\">\ud83d\udd2e &nbsp;Agn\u00f3stico<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('religionesyespiritualidad','budista')\">\u2638 &nbsp;Budista<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('religionesyespiritualidad','catolico')\">\u271d &nbsp;Cat\u00f3lico<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('religionesyespiritualidad','hinduista')\">\ud83e\udeb7 &nbsp;Hinduista<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('religionesyespiritualidad','islamico')\">\ud83c\udf19 &nbsp;Isl\u00e1mico<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('religionesyespiritualidad','judio')\">\u2721 &nbsp;Jud\u00edo<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('religionesyespiritualidad','ortodoxo')\">\u2626 &nbsp;Ortodoxo<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('religionesyespiritualidad','taoista')\">\u262f &nbsp;Tao\u00edsta<\/div>\r\n      <\/div>\r\n\r\n      <!-- Civilizaciones antiguas -->\r\n      <div class=\"c-cat\" onclick=\"toggleCat('cat2',this)\">\ud83c\udffa &nbsp;Civilizaciones antiguas <span class=\"c-cat-arr\" id=\"cat2Arr\">\u203a<\/span><\/div>\r\n      <div class=\"c-cat-sub\" id=\"cat2\">\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('civilizacionesantiguas','arabe')\">\ud83d\udd4c &nbsp;\u00c1rabe<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('civilizacionesantiguas','azteca')\">\ud83c\udf1e &nbsp;Azteca<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('civilizacionesantiguas','egipcio')\">\ud80c\udc80 &nbsp;Egipcio<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('civilizacionesantiguas','griego')\">\ud83c\udfdb &nbsp;Griego<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('civilizacionesantiguas','maya')\">\ud83d\udc0d &nbsp;Maya<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('civilizacionesantiguas','inca')\">\ud83e\udd99 &nbsp;Inca<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('civilizacionesantiguas','persa')\">\ud83e\udd81 &nbsp;Persa<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('civilizacionesantiguas','romano')\">\ud83c\udffa &nbsp;Romano<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('civilizacionesantiguas','vikingo')\">\u2694 &nbsp;Vikingo<\/div>\r\n      <\/div>\r\n\r\n      <!-- Naturaleza y paisajes -->\r\n      <div class=\"c-cat\" onclick=\"toggleCat('cat3',this)\">\ud83c\udf3f &nbsp;Naturaleza y paisajes <span class=\"c-cat-arr\" id=\"cat3Arr\">\u203a<\/span><\/div>\r\n      <div class=\"c-cat-sub\" id=\"cat3\">\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('naturalezaypaisajes','acantilado')\">\ud83c\udf0a &nbsp;Acantilado<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('naturalezaypaisajes','bosqueeterno')\">\ud83c\udf32 &nbsp;Bosque eterno<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('naturalezaypaisajes','cuevadecristal')\">\ud83d\udc8e &nbsp;Cueva de cristal<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('naturalezaypaisajes','islaflotante')\">\ud83c\udfdd &nbsp;Isla flotante<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('naturalezaypaisajes','jardinzen')\">\ud83e\udea8 &nbsp;Jard\u00edn zen<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('naturalezaypaisajes','lagoconniebla')\">\ud83c\udf2b &nbsp;Lago con niebla<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('naturalezaypaisajes','montananevada')\">\ud83c\udfd4 &nbsp;Monta\u00f1a nevada<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('naturalezaypaisajes','playaalamanecer')\">\ud83c\udf05 &nbsp;Playa al amanecer<\/div>\r\n      <\/div>\r\n\r\n      <!-- Cosmos y fantas\u00eda -->\r\n      <div class=\"c-cat\" onclick=\"toggleCat('cat4',this)\">\ud83c\udf0c &nbsp;Cosmos y fantas\u00eda <span class=\"c-cat-arr\" id=\"cat4Arr\">\u203a<\/span><\/div>\r\n      <div class=\"c-cat-sub\" id=\"cat4\">\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('cosmosyfantasia','cieloestrellado')\">\u2b50 &nbsp;Cielo estrellado<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('cosmosyfantasia','galaxias')\">\ud83c\udf00 &nbsp;Galaxias<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('cosmosyfantasia','mundoflotante')\">\ud83c\udf0d &nbsp;Mundo flotante<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('cosmosyfantasia','mundoonerico')\">\ud83d\udcad &nbsp;Mundo on\u00edrico<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('cosmosyfantasia','naveespacial')\">\ud83d\ude80 &nbsp;Nave espacial<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('cosmosyfantasia','reinocelestial')\">\ud83d\udc7c &nbsp;Reino celestial<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('cosmosyfantasia','surrealista')\">\ud83c\udfa8 &nbsp;Surrealista<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('cosmosyfantasia','universo')\">\ud83d\udd2d &nbsp;Universo<\/div>\r\n      <\/div>\r\n\r\n      <!-- Profesiones y pasiones -->\r\n      <div class=\"c-cat\" onclick=\"toggleCat('cat5',this)\">\u2692 &nbsp;Profesiones y pasiones <span class=\"c-cat-arr\" id=\"cat5Arr\">\u203a<\/span><\/div>\r\n      <div class=\"c-cat-sub\" id=\"cat5\">\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('profesionesypasiones','agricultor')\">\ud83c\udf3e &nbsp;Agricultor<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('profesionesypasiones','escritor')\">\u2712 &nbsp;Escritor<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('profesionesypasiones','fotografo')\">\ud83d\udcf7 &nbsp;Fot\u00f3grafo<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('profesionesypasiones','marinero')\">\u2693 &nbsp;Marinero<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('profesionesypasiones','militar')\">\ud83c\udf96 &nbsp;Militar<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('profesionesypasiones','minero')\">\u26cf &nbsp;Minero<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('profesionesypasiones','motero')\">\ud83c\udfcd &nbsp;Motero<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('profesionesypasiones','musico')\">\ud83c\udfb5 &nbsp;M\u00fasico<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('profesionesypasiones','pescador')\">\ud83c\udfa3 &nbsp;Pescador<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('profesionesypasiones','profesor')\">\ud83d\udcda &nbsp;Profesor<\/div>\r\n      <\/div>\r\n\r\n      <!-- Arte y estilos -->\r\n      <div class=\"c-cat\" onclick=\"toggleCat('cat6',this)\">\ud83c\udfad &nbsp;Arte y estilos <span class=\"c-cat-arr\" id=\"cat6Arr\">\u203a<\/span><\/div>\r\n      <div class=\"c-cat-sub\" id=\"cat6\">\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('arteyestilos','barroca')\">\ud83c\udfbc &nbsp;Barroca<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('arteyestilos','minimalista')\">\u25fb &nbsp;Minimalista<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('arteyestilos','renacentista')\">\ud83d\uddbc &nbsp;Renacentista<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('arteyestilos','romanica')\">\u26ea &nbsp;Rom\u00e1nica<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('arteyestilos','rococo')\">\ud83c\udf38 &nbsp;Rococ\u00f3<\/div>\r\n      <\/div>\r\n\r\n      <!-- Infantil y homenaje -->\r\n      <div class=\"c-cat\" onclick=\"toggleCat('cat7',this)\">\u2b50 &nbsp;Infantil y homenaje <span class=\"c-cat-arr\" id=\"cat7Arr\">\u203a<\/span><\/div>\r\n      <div class=\"c-cat-sub\" id=\"cat7\">\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('infantilyhomenaje','bosquemagico')\">\ud83e\uddda &nbsp;Bosque m\u00e1gico<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('infantilyhomenaje','jardindeestrellas')\">\ud83c\udf1f &nbsp;Jard\u00edn de estrellas<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('infantilyhomenaje','mundodecuentos')\">\ud83d\udcd6 &nbsp;Mundo de cuentos<\/div>\r\n        <div class=\"c-cat-si\" onclick=\"cambiarFondo('infantilyhomenaje','nubsycometas')\">\ud83e\ude81 &nbsp;Nubes y cometas<\/div>\r\n      <\/div>\r\n\r\n      <!-- Personalizado -->\r\n      <div class=\"c-cat\" onclick=\"abrirPersonalizado()\" style=\"border-top: 1px solid rgba(180,130,40,0.2); margin-top:4px; padding-top:12px;\">\ud83d\uddbc &nbsp;Personalizado <span style=\"margin-left:auto; font-size:10px;\">+<\/span><\/div>\r\n\r\n    <\/div>\r\n    <div class=\"c-pi\" id=\"menuCarpetas\" onclick=\"abrirModalCarpetas()\">\ud83d\udcc1 &nbsp;Crear Carpetas<\/div>\r\n    <div class=\"c-pi\" id=\"menuWeb\"   onclick=\"if(cdhSepId>0){window.location.href='\/index.php\/edicion-sepultura-web\/?sep_id='+cdhSepId;}else{alert('Selecciona primero una sepultura.');}\">\ud83c\udf10 &nbsp;Sepultura Web<\/div>\r\n    <div class=\"c-pi\" id=\"menuQr\"    onclick=\"if(cdhSepId>0){window.location.href='\/index.php\/editor-qr\/?sep_id='+cdhSepId;}else{alert('Selecciona primero una sepultura.');}\">\ud83d\udcf1 &nbsp;Sepultura QR<\/div>\r\n    <div class=\"c-pi\" id=\"menuBiografia\" onclick=\"criptaActivarModulo('biografia')\">\ud83d\udcd6 &nbsp;Biograf\u00eda<\/div>\r\n    <div class=\"c-pi\" id=\"menuArbol\" onclick=\"criptaActivarModulo('arbol')\">\ud83c\udf33 &nbsp;\u00c1rbol geneal\u00f3gico<\/div>\r\n    <div class=\"c-pi\" id=\"menuEspacio\" onclick=\"abrirEspacio()\">\ud83d\udcbe &nbsp;Espacio utilizado<\/div>\r\n    <div class=\"c-pi\" id=\"menuAdmin\" onclick=\"irA('\/index.php\/administrar-sepulturas\/')\">\u2699\ufe0f &nbsp;Administrar Sepulturas y Monumentos<\/div>\r\n\r\n  <\/div>\r\n\r\n  <!-- \u00c1rbol geneal\u00f3gico (activado desde men\u00fa) -->\r\n  <div id=\"criptaArbol\" style=\"display:none; position:absolute; z-index:11; cursor:pointer; flex-direction:column; align-items:center; gap:8px;\">\r\n    <svg viewBox=\"0 0 120 130\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:clamp(80px,8vw,120px);height:clamp(87px,8.7vw,130px);filter:drop-shadow(0 0 2px rgba(0,0,0,1)) drop-shadow(0 4px 16px rgba(0,0,0,0.90));\">\r\n      <line x1=\"60\" y1=\"118\" x2=\"38\" y2=\"130\" stroke=\"#5a3a10\" stroke-width=\"5\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"60\" y1=\"118\" x2=\"82\" y2=\"130\" stroke=\"#5a3a10\" stroke-width=\"5\" stroke-linecap=\"round\"\/>\r\n      <rect x=\"53\" y=\"72\" width=\"14\" height=\"48\" rx=\"4\" fill=\"#7a5020\"\/>\r\n      <line x1=\"60\" y1=\"80\" x2=\"32\" y2=\"55\" stroke=\"#8a6028\" stroke-width=\"5\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"60\" y1=\"80\" x2=\"88\" y2=\"55\" stroke=\"#8a6028\" stroke-width=\"5\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"60\" y1=\"72\" x2=\"18\" y2=\"62\" stroke=\"#7a5020\" stroke-width=\"4\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"60\" y1=\"72\" x2=\"102\" y2=\"62\" stroke=\"#7a5020\" stroke-width=\"4\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"32\" y1=\"55\" x2=\"20\" y2=\"38\" stroke=\"#7a5020\" stroke-width=\"3.5\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"32\" y1=\"55\" x2=\"38\" y2=\"36\" stroke=\"#7a5020\" stroke-width=\"3.5\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"88\" y1=\"55\" x2=\"100\" y2=\"38\" stroke=\"#7a5020\" stroke-width=\"3.5\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"88\" y1=\"55\" x2=\"82\" y2=\"36\" stroke=\"#7a5020\" stroke-width=\"3.5\" stroke-linecap=\"round\"\/>\r\n      <circle cx=\"60\" cy=\"34\" r=\"24\" fill=\"rgba(40,95,25,0.92)\"\/>\r\n      <circle cx=\"32\" cy=\"46\" r=\"18\" fill=\"rgba(35,85,20,0.90)\"\/>\r\n      <circle cx=\"88\" cy=\"46\" r=\"18\" fill=\"rgba(35,85,20,0.90)\"\/>\r\n      <circle cx=\"20\" cy=\"30\" r=\"14\" fill=\"rgba(45,105,28,0.90)\"\/>\r\n      <circle cx=\"100\" cy=\"30\" r=\"14\" fill=\"rgba(45,105,28,0.90)\"\/>\r\n      <circle cx=\"18\" cy=\"56\" r=\"12\" fill=\"rgba(30,75,15,0.85)\"\/>\r\n      <circle cx=\"102\" cy=\"56\" r=\"12\" fill=\"rgba(30,75,15,0.85)\"\/>\r\n    <\/svg>\r\n    <div class=\"c-label\" style=\"text-align:center;\">\u00c1rbol geneal\u00f3gico<\/div>\r\n    <div class=\"c-carpeta-acciones\">\r\n      <div class=\"c-carpeta-accion\" title=\"Editar \u00e1rbol geneal\u00f3gico\" onclick=\"if(cdhSepId>0){window.location.href='\/index.php\/arbol-genealogico\/?sep_id='+cdhSepId;}else{alert('Selecciona primero una sepultura.');}event.stopPropagation()\">\u270f\ufe0f<\/div>\r\n      <div class=\"c-carpeta-accion\" title=\"Eliminar\" onclick=\"criptaActivarModulo('arbol');event.stopPropagation()\">\ud83d\uddd1<\/div>\r\n    <\/div>\r\n  <\/div>\r\n  <!-- Biograf\u00eda (activado desde men\u00fa) -->\r\n  <div id=\"criptaBiografia\" style=\"display:none; position:absolute; z-index:11; cursor:pointer; flex-direction:column; align-items:center; gap:8px;\">\r\n    <svg viewBox=\"0 0 120 130\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:clamp(80px,8vw,120px);height:clamp(87px,8.7vw,130px);filter:drop-shadow(0 0 2px rgba(0,0,0,1)) drop-shadow(0 4px 16px rgba(0,0,0,0.90));\">\r\n      <!-- Sombra base -->\r\n      <ellipse cx=\"60\" cy=\"126\" rx=\"42\" ry=\"5\" fill=\"rgba(0,0,0,0.35)\"\/>\r\n      <!-- P\u00e1gina izquierda -->\r\n      <path d=\"M10,18 Q10,10 18,10 L58,10 L58,114 Q40,108 18,114 Q10,116 10,108 Z\" fill=\"#c8a87a\" stroke=\"rgba(100,65,20,0.5)\" stroke-width=\"1\"\/>\r\n      <!-- P\u00e1gina derecha -->\r\n      <path d=\"M110,18 Q110,10 102,10 L62,10 L62,114 Q80,108 102,114 Q110,116 110,108 Z\" fill=\"#d4b88a\" stroke=\"rgba(100,65,20,0.5)\" stroke-width=\"1\"\/>\r\n      <!-- Lomo central -->\r\n      <rect x=\"56\" y=\"8\" width=\"8\" height=\"108\" rx=\"3\" fill=\"#7a4e1a\" stroke=\"rgba(60,30,5,0.6)\" stroke-width=\"1\"\/>\r\n      <!-- L\u00edneas de texto p\u00e1gina izquierda -->\r\n      <line x1=\"18\" y1=\"30\" x2=\"52\" y2=\"30\" stroke=\"rgba(90,55,15,0.45)\" stroke-width=\"2\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"18\" y1=\"39\" x2=\"52\" y2=\"39\" stroke=\"rgba(90,55,15,0.40)\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"18\" y1=\"48\" x2=\"52\" y2=\"48\" stroke=\"rgba(90,55,15,0.40)\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"18\" y1=\"57\" x2=\"48\" y2=\"57\" stroke=\"rgba(90,55,15,0.35)\" stroke-width=\"1.6\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"18\" y1=\"66\" x2=\"52\" y2=\"66\" stroke=\"rgba(90,55,15,0.35)\" stroke-width=\"1.6\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"18\" y1=\"75\" x2=\"44\" y2=\"75\" stroke=\"rgba(90,55,15,0.30)\" stroke-width=\"1.5\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"18\" y1=\"84\" x2=\"52\" y2=\"84\" stroke=\"rgba(90,55,15,0.30)\" stroke-width=\"1.5\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"18\" y1=\"93\" x2=\"46\" y2=\"93\" stroke=\"rgba(90,55,15,0.25)\" stroke-width=\"1.4\" stroke-linecap=\"round\"\/>\r\n      <!-- L\u00edneas de texto p\u00e1gina derecha -->\r\n      <line x1=\"68\" y1=\"30\" x2=\"102\" y2=\"30\" stroke=\"rgba(90,55,15,0.45)\" stroke-width=\"2\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"68\" y1=\"39\" x2=\"102\" y2=\"39\" stroke=\"rgba(90,55,15,0.40)\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"68\" y1=\"48\" x2=\"102\" y2=\"48\" stroke=\"rgba(90,55,15,0.40)\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"68\" y1=\"57\" x2=\"98\" y2=\"57\" stroke=\"rgba(90,55,15,0.35)\" stroke-width=\"1.6\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"68\" y1=\"66\" x2=\"102\" y2=\"66\" stroke=\"rgba(90,55,15,0.35)\" stroke-width=\"1.6\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"68\" y1=\"75\" x2=\"94\" y2=\"75\" stroke=\"rgba(90,55,15,0.30)\" stroke-width=\"1.5\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"68\" y1=\"84\" x2=\"102\" y2=\"84\" stroke=\"rgba(90,55,15,0.30)\" stroke-width=\"1.5\" stroke-linecap=\"round\"\/>\r\n      <line x1=\"68\" y1=\"93\" x2=\"96\" y2=\"93\" stroke=\"rgba(90,55,15,0.25)\" stroke-width=\"1.4\" stroke-linecap=\"round\"\/>\r\n      <!-- Reflejos en las p\u00e1ginas -->\r\n      <path d=\"M12,18 Q12,13 18,13 L54,13 L54,22 L12,22 Z\" fill=\"rgba(255,240,200,0.18)\"\/>\r\n      <path d=\"M108,18 Q108,13 102,13 L66,13 L66,22 L108,22 Z\" fill=\"rgba(255,240,200,0.14)\"\/>\r\n    <\/svg>\r\n    <div class=\"c-label\" style=\"text-align:center;\">Biograf\u00eda<\/div>\r\n    <div class=\"c-carpeta-acciones\">\r\n      <div class=\"c-carpeta-accion\" title=\"Editar\" onclick=\"if(cdhSepId>0){window.location.href='\/index.php\/biografia\/?sep_id='+cdhSepId;}else{alert('Selecciona primero una sepultura.');}event.stopPropagation()\">\u270f\ufe0f<\/div>\r\n      <div class=\"c-carpeta-accion\" title=\"Eliminar\" onclick=\"criptaActivarModulo('biografia');event.stopPropagation()\">\ud83d\uddd1<\/div>\r\n    <\/div>\r\n  <\/div>\r\n    <!-- Zona de carpetas flotantes libres -->\r\n  <div class=\"c-carpetas-zona vacia\" id=\"carpetasZona\"><\/div>\r\n  <div class=\"c-preview-hint\" id=\"criptaHint\" style=\"display:none; z-index:50;\">\u2726 Arrastra las carpetas donde quieras<\/div>\r\n\r\n<\/div>\r\n\r\n<!-- \u2500\u2500 Modal Gestor de Carpetas \u2500\u2500 -->\r\n<div class=\"cdh-modal-carpetas\" id=\"modalCarpetas\">\r\n  <div class=\"cdh-mc-box\">\r\n    <div class=\"cdh-mc-titulo\">\ud83d\udcc1 &nbsp;MIS CARPETAS<\/div>\r\n    <button class=\"cdh-mc-cerrar\" onclick=\"cerrarModalCarpetas()\">\u2715<\/button>\r\n\r\n    <!-- Lista de carpetas existentes -->\r\n    <div class=\"cdh-mc-lista\">\r\n      <div class=\"cdh-mc-lista-titulo\">Carpetas creadas<\/div>\r\n      <div class=\"cdh-mc-limite\" id=\"mcLimite\">0 \/ 5 carpetas ra\u00edz<\/div>\r\n      <div id=\"mcListaCarpetas\"><div class=\"cdh-mc-vacia\">A\u00fan no has creado ninguna carpeta.<\/div><\/div>\r\n    <\/div>\r\n\r\n    <div class=\"cdh-mc-sep\"><\/div>\r\n\r\n    <!-- Formulario nueva \/ editar carpeta -->\r\n    <div id=\"mcFormWrap\">\r\n      <div class=\"cdh-mc-form-titulo\" id=\"mcFormTitulo\">Nueva carpeta<\/div>\r\n\r\n      <!-- Nombre -->\r\n      <div class=\"cdh-mc-campo\">\r\n        <label class=\"cdh-mc-label\">Nombre de la carpeta<\/label>\r\n        <input type=\"text\" class=\"cdh-mc-input\" id=\"mcNombre\" placeholder=\"Ej: Fotos de boda\" maxlength=\"60\">\r\n      <\/div>\r\n\r\n      <!-- Pesta\u00f1as Color e Icono -->\r\n      <div class=\"cdh-mc-campo\">\r\n        <label class=\"cdh-mc-label\">Color e icono<\/label>\r\n        <div class=\"cdh-tabs\">\r\n          <button class=\"cdh-tab sel\" onclick=\"mcCambiarTab('color',this)\" type=\"button\">\ud83c\udfa8 Color<\/button>\r\n          <button class=\"cdh-tab\" onclick=\"mcCambiarTab('icono',this)\" type=\"button\">&#128444; Icono<\/button>\r\n        <\/div>\r\n        <div id=\"mcTabColor\" class=\"cdh-tab-panel\">\r\n          <div class=\"cdh-color-grid\" id=\"mcColorGrid\"><\/div>\r\n        <\/div>\r\n        <div id=\"mcTabIcono\" class=\"cdh-tab-panel\" style=\"display:none\">\r\n          <div class=\"cdh-mc-iconos-grid\" id=\"mcIconosGrid\"><\/div>\r\n          <div class=\"cdh-mc-tipo-toggle\" id=\"mcTipoToggle\" style=\"display:none\">\r\n            <label style=\"display:flex;align-items:center;gap:8px;cursor:pointer;padding:10px 4px 2px;font-family:Arial,sans-serif;font-size:12px;color:#c8903a;\">\r\n              <input type=\"checkbox\" id=\"mcTipoCheck\" onchange=\"mcToggleTipo(this)\" style=\"width:16px;height:16px;cursor:pointer;\">\r\n              \u2713 Activado: el icono sustituir\u00e1 a la carpeta\r\n            <\/label>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <!-- Estado -->\r\n      <div class=\"cdh-mc-campo\">\r\n        <label class=\"cdh-mc-label\">Estado de la carpeta<\/label>\r\n        <div class=\"cdh-mc-estados\">\r\n          <div class=\"cdh-mc-estado-opt sel\" data-estado=\"abierta\" onclick=\"selEstado('abierta',this)\">\r\n            <span class=\"estado-ico\">\ud83d\udd13<\/span>\r\n            <div class=\"estado-nombre\">Abierta<\/div>\r\n            <div class=\"estado-desc\">Visible y accesible para todos<\/div>\r\n          <\/div>\r\n          <div class=\"cdh-mc-estado-opt\" data-estado=\"cerrada\" onclick=\"selEstado('cerrada',this)\">\r\n            <span class=\"estado-ico\">\ud83d\udd12<\/span>\r\n            <div class=\"estado-nombre\">Cerrada<\/div>\r\n            <div class=\"estado-desc\">Se ve con candado y fecha<\/div>\r\n          <\/div>\r\n          <div class=\"cdh-mc-estado-opt\" data-estado=\"oculta\" onclick=\"selEstado('oculta',this)\">\r\n            <span class=\"estado-ico\">\u23f3<\/span>\r\n            <div class=\"estado-nombre\">Oculta<\/div>\r\n            <div class=\"estado-desc\">Invisible hasta la fecha<\/div>\r\n          <\/div>\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <!-- Fecha de apertura (solo para cerrada\/oculta) -->\r\n      <div class=\"cdh-mc-fecha-wrap\" id=\"mcFechaWrap\">\r\n        <label class=\"cdh-mc-label\" id=\"mcFechaLabel\">Fecha de apertura<\/label>\r\n        <input type=\"date\" class=\"cdh-mc-input\" id=\"mcFechaApertura\">\r\n      <\/div>\r\n\r\n      <div class=\"cdh-mc-aviso\" id=\"mcAviso\"><\/div>\r\n\r\n      <div class=\"cdh-mc-form-btns\">\r\n        <button class=\"cdh-mc-btn cancelar\" type=\"button\" onclick=\"mcCancelarEdicion()\">Cancelar<\/button>\r\n        <button class=\"cdh-mc-btn guardar\" type=\"button\" id=\"mcBtnGuardar\" onclick=\"mcGuardar()\">Crear carpeta<\/button>\r\n      <\/div>\r\n    <\/div>\r\n\r\n  <\/div>\r\n<\/div>\r\n\r\n<!-- \u2500\u2500 Explorador de subcarpetas \u2500\u2500 -->\r\n<div class=\"cdh-explorador\" id=\"expModal\">\r\n  <div class=\"cdh-exp-box\">\r\n    <div class=\"cdh-exp-header\">\r\n      <div class=\"cdh-exp-header-top\">\r\n        <button class=\"cdh-exp-back\" id=\"expBack\" onclick=\"expSubir()\" title=\"Subir al nivel anterior\" style=\"display:none;\">\u2190<\/button>\r\n        <div class=\"cdh-exp-titulo\" id=\"expTitulo\">\ud83d\udcc1 Carpeta<\/div>\r\n        <button class=\"cdh-exp-cerrar\" onclick=\"cerrarExplorador()\">\u2715<\/button>\r\n      <\/div>\r\n      <div class=\"cdh-exp-breadcrumb\" id=\"expBreadcrumb\"><\/div>\r\n    <\/div>\r\n    <div class=\"cdh-exp-acciones\" id=\"expAcciones\">\r\n      <button class=\"cdh-exp-btn primario\" onclick=\"expNuevaSubcarpeta()\">\ud83d\udcc1 &nbsp;Nueva subcarpeta<\/button>\r\n    <\/div>\r\n    <div class=\"cdh-exp-contenido\" id=\"expContenido\"><\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<div class=\"c-preview-modal\" id=\"previewModal\">\r\n\r\n  <!-- Mismo fondo que la cripta \u2014 se aplica por JS -->\r\n\r\n  <!-- Cabecera difunto -->\r\n  <div class=\"c-cabecera\">\r\n    <div class=\"c-nombre\" id=\"previewNombre\"><\/div>\r\n    <div class=\"c-anios\"  id=\"previewAnios\"><\/div>\r\n    <div class=\"c-separador\" id=\"previewSeparador\" style=\"display:none\"><\/div>\r\n  <\/div>\r\n\r\n  <!-- Etiqueta modo previsualizaci\u00f3n -->\r\n  <div class=\"c-preview-badge\">Vista previa p\u00fablica<\/div>\r\n\r\n  <!-- Bot\u00f3n cerrar -->\r\n  <button class=\"c-preview-close\" id=\"previewClose\" title=\"Cerrar vista previa\">\u2715<\/button>\r\n\r\n  <!-- \u00c1rbol geneal\u00f3gico (oculto por defecto hasta que el propietario lo active) -->\r\n  <!-- Se mostrar\u00e1 aqu\u00ed cuando se implemente el toggle del \u00e1rbol -->\r\n\r\n  <!-- Bot\u00f3n Mapa de la Cripta (solo visible si propietario lo activ\u00f3) -->\r\n  <button id=\"mapaBtn\" onclick=\"abrirMapa()\">\r\n    <span class=\"mapa-btn-ico\">\ud83d\uddfa\ufe0f<\/span>\r\n    <span class=\"mapa-btn-txt\">Mapa de la Cripta<\/span>\r\n  <\/button>\r\n\r\n  <!-- Carpetas p\u00fablicas -->\r\n  <div class=\"c-preview-carpetas\" id=\"previewCarpetas\" style=\"position:absolute;inset:0;\"><\/div>\r\n  <div class=\"c-preview-hint\" id=\"previewHint\" style=\"display:none;\">\u2726 Arrastra las carpetas donde quieras<\/div>\r\n\r\n  <!-- Mensaje si no hay carpetas -->\r\n  <div class=\"c-preview-empty\" id=\"previewEmpty\" style=\"display:none\">\r\n    \u2014 A\u00daN NO HAY CARPETAS CREADAS \u2014\r\n  <\/div>\r\n\r\n<\/div>\r\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n     MODAL MAPA DE LA CRIPTA\r\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\r\n<div id=\"mapaModal\" style=\"\r\n  display:none; position:fixed; inset:0; z-index:100050;\r\n  background:rgba(0,0,0,0.72); backdrop-filter:blur(4px);\r\n  align-items:center; justify-content:center; padding:16px;\r\n\">\r\n  <div id=\"mapaBox\" style=\"\r\n    position:relative;\r\n    background:\r\n      radial-gradient(ellipse at 18% 12%, rgba(210,175,90,0.18) 0%, transparent 55%),\r\n      radial-gradient(ellipse at 82% 88%, rgba(160,110,40,0.15) 0%, transparent 55%),\r\n      linear-gradient(160deg, #e8d9a0 0%, #d4b96a 18%, #c8a84e 38%, #d6c07a 58%, #e2cf8e 78%, #c9aa55 100%);\r\n    border:3px solid #8b6020;\r\n    border-radius:6px;\r\n    box-shadow:\r\n      inset 0 0 60px rgba(120,70,10,0.35),\r\n      inset 0 0 12px rgba(80,40,0,0.25),\r\n      0 12px 48px rgba(0,0,0,0.85),\r\n      0 2px 8px rgba(0,0,0,0.6);\r\n    width:100%; max-width:640px;\r\n    max-height:82vh; max-height:82svh; overflow-y:auto;\r\n    padding:0 0 24px 0;\r\n  \">\r\n    <!-- Textura de fibras de pergamino -->\r\n    <svg style=\"position:absolute;inset:0;width:100%;height:100%;opacity:0.07;pointer-events:none;border-radius:4px;\" preserveAspectRatio=\"none\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\r\n      <filter id=\"pf\"><feTurbulence type=\"fractalNoise\" baseFrequency=\"0.65\" numOctaves=\"4\" stitchTiles=\"stitch\"\/><feColorMatrix type=\"saturate\" values=\"0\"\/><\/filter>\r\n      <rect width=\"100%\" height=\"100%\" filter=\"url(#pf)\"\/>\r\n    <\/svg>\r\n\r\n    <!-- Cabecera -->\r\n    <div style=\"text-align:center; padding:28px 20px 16px; border-bottom:2px solid rgba(120,70,10,0.45); position:relative;\">\r\n\r\n      <!-- Esquina superior izquierda -->\r\n      <svg style=\"position:absolute;top:8px;left:10px;width:30px;height:30px;opacity:0.5;\" viewBox=\"0 0 30 30\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\r\n        <path d=\"M2,28 L2,2 L28,2\" fill=\"none\" stroke=\"#7a5010\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/>\r\n        <circle cx=\"5\" cy=\"5\" r=\"2\" fill=\"#9a6820\"\/>\r\n      <\/svg>\r\n\r\n      <!-- Esquina superior derecha -->\r\n      <svg style=\"position:absolute;top:8px;right:48px;width:30px;height:30px;opacity:0.5;\" viewBox=\"0 0 30 30\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\r\n        <path d=\"M2,2 L28,2 L28,28\" fill=\"none\" stroke=\"#7a5010\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/>\r\n        <circle cx=\"25\" cy=\"5\" r=\"2\" fill=\"#9a6820\"\/>\r\n      <\/svg>\r\n\r\n      <!-- Bot\u00f3n cerrar -->\r\n      <button onclick=\"cerrarMapa()\" title=\"Cerrar\" style=\"\r\n        position:absolute; top:10px; right:12px;\r\n        width:26px; height:26px;\r\n        background:rgba(120,70,10,0.1); border:1px solid rgba(120,70,10,0.3);\r\n        border-radius:50%; cursor:pointer; font-size:12px; color:#7a4e10;\r\n        display:flex; align-items:center; justify-content:center;\r\n        transition:background 0.2s;\r\n      \" onmouseover=\"this.style.background='rgba(120,70,10,0.25)'\"\r\n         onmouseout=\"this.style.background='rgba(120,70,10,0.1)'\">\u2715<\/button>\r\n\r\n      <!-- Logo circular -->\r\n      <div style=\"\r\n        display:inline-block; width:86px; height:86px; border-radius:50%;\r\n        overflow:hidden; margin-bottom:12px;\r\n        box-shadow:0 4px 18px rgba(80,40,0,0.3), 0 1px 4px rgba(0,0,0,0.15);\r\n        border:2px solid rgba(160,110,40,0.5);\r\n      \">\r\n        <img decoding=\"async\" src=\"https:\/\/cementeriodigitalhispano.com\/wp-content\/uploads\/Logos\/Logo_circular.png\"\r\n          style=\"width:100%;height:100%;object-fit:cover;display:block;\">\r\n      <\/div>\r\n\r\n      <div style=\"font-family:'Cinzel',Georgia,serif; font-size:21px; letter-spacing:5px; text-transform:uppercase; color:#3a1e02; text-shadow:1px 1px 0 rgba(255,220,120,0.6); margin-bottom:4px;\">Mapa<\/div>\r\n      <div style=\"font-family:Georgia,serif; font-size:11px; letter-spacing:3px; color:#6a3e08; text-transform:uppercase; opacity:0.8;\">de la cripta<\/div>\r\n    <\/div>\r\n\r\n    <!-- Toggle p\u00fablico (solo propietario) -->\r\n    <div id=\"mapaTogglePublico\" style=\"display:none; padding:10px 20px 0; text-align:center;\">\r\n      <label style=\"\r\n        display:inline-flex; align-items:center; gap:8px; cursor:pointer;\r\n        font-family:Georgia,serif; font-size:12px; color:#5a3208;\r\n        background:rgba(120,70,10,0.1); border:1px solid rgba(120,70,10,0.3);\r\n        border-radius:4px; padding:7px 14px;\r\n      \">\r\n        <input type=\"checkbox\" id=\"mapaCheckPublico\" onchange=\"mapaGuardarPublico(this.checked)\" style=\"width:15px;height:15px;cursor:pointer;accent-color:#6a4010;\">\r\n        <span>Mostrar p\u00fablicamente en la cripta<\/span>\r\n      <\/label>\r\n    <\/div>\r\n\r\n    <!-- T\u00edtulo alternativo (visitantes p\u00fablicos) -->\r\n    <div id=\"mapaTituloPublico\" style=\"display:none; padding:10px 20px 0; text-align:center;\">\r\n      <span style=\"\r\n        display:inline-block;\r\n        font-family:Georgia,serif; font-size:12px; color:#5a3208;\r\n        text-transform:uppercase; letter-spacing:1px;\r\n        background:rgba(120,70,10,0.1); border:1px solid rgba(120,70,10,0.3);\r\n        border-radius:4px; padding:7px 14px;\r\n      \">Estructura de las carpetas<\/span>\r\n    <\/div>\r\n\r\n    <!-- Leyenda -->\r\n    <div style=\"\r\n      display:flex; gap:18px; justify-content:center; flex-wrap:wrap;\r\n      padding:10px 20px 6px;\r\n      font-family:Georgia,serif; font-size:11px; color:#5a3208;\r\n      border-bottom:1px solid rgba(120,70,10,0.25);\r\n    \">\r\n      <span><strong style=\"background:#4a8a4a;color:#fff;padding:1px 5px;border-radius:2px;font-size:10px;\">A<\/strong> Abierta<\/span>\r\n      <span><strong style=\"background:#7a4a20;color:#fff;padding:1px 5px;border-radius:2px;font-size:10px;\">C<\/strong> Cerrada<\/span>\r\n      <span><strong style=\"background:#3a3a6a;color:#fff;padding:1px 5px;border-radius:2px;font-size:10px;\">O<\/strong> Oculta<\/span>\r\n    <\/div>\r\n\r\n    <!-- Contenido \u00e1rbol -->\r\n    <div id=\"mapaContenido\" style=\"padding:16px 24px 4px; font-family:Georgia,serif;\"><\/div>\r\n\r\n    <!-- Pie ornamental -->\r\n    <div style=\"text-align:center; padding:8px 0 0; opacity:0.4;\">\r\n      <svg width=\"180\" height=\"14\" viewBox=\"0 0 180 14\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\">\r\n        <line x1=\"0\" y1=\"7\" x2=\"70\" y2=\"7\" stroke=\"#7a5010\" stroke-width=\"1\"\/>\r\n        <circle cx=\"90\" cy=\"7\" r=\"4\" fill=\"none\" stroke=\"#7a5010\" stroke-width=\"1.2\"\/>\r\n        <circle cx=\"90\" cy=\"7\" r=\"1.5\" fill=\"#9a6820\"\/>\r\n        <line x1=\"110\" y1=\"7\" x2=\"180\" y2=\"7\" stroke=\"#7a5010\" stroke-width=\"1\"\/>\r\n        <circle cx=\"75\" cy=\"7\" r=\"2\" fill=\"#9a6820\"\/>\r\n        <circle cx=\"105\" cy=\"7\" r=\"2\" fill=\"#9a6820\"\/>\r\n      <\/svg>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<div class=\"c-custom-panel\" id=\"customPanel\">\r\n    <div class=\"c-custom-title\">\ud83d\uddbc &nbsp;FONDO PERSONALIZADO<\/div>\r\n\r\n    <div class=\"c-custom-drop\" id=\"customDrop\" onclick=\"document.getElementById('customFile').click()\">\r\n      <div class=\"c-custom-drop-icon\">\ud83d\udcc1<\/div>\r\n      <div class=\"c-custom-drop-text\">\r\n        Arrastra tu imagen aqu\u00ed<br>o <span>haz clic para seleccionarla<\/span>\r\n      <\/div>\r\n    <\/div>\r\n    <input type=\"file\" id=\"customFile\" accept=\"image\/jpeg,image\/png,image\/webp\" style=\"display:none\" onchange=\"if(this.files&&this.files[0])procesarImagen(this.files[0])\">\r\n    <div class=\"c-custom-note\">\r\n      <strong>Recomendaciones para la imagen:<\/strong><br>\r\n      \u2022 Formato: JPG, PNG o WebP<br>\r\n      \u2022 Tama\u00f1o m\u00e1ximo: <strong>5 MB<\/strong><br>\r\n      \u2022 Resoluci\u00f3n ideal: <strong>1920 \u00d7 1080 px<\/strong> (panor\u00e1mica)<br>\r\n      \u2022 M\u00ednimo recomendado: 1280 \u00d7 720 px<br>\r\n      \u2022 Orientaci\u00f3n: <strong>horizontal<\/strong> (paisaje)<br>\r\n      \u2022 Evita im\u00e1genes con texto importante en los bordes\r\n    <\/div>\r\n\r\n    <div class=\"c-custom-progress\" id=\"customProgress\">\r\n      <div class=\"c-custom-progress-bar\" id=\"customProgressBar\"><\/div>\r\n    <\/div>\r\n    <div class=\"c-custom-status\" id=\"customStatus\"><\/div>\r\n\r\n    <div class=\"c-custom-btns\">\r\n      <button class=\"c-custom-btn cancel\" type=\"button\" onclick=\"cerrarPersonalizado()\">Cancelar<\/button>\r\n      <button class=\"c-custom-btn save\" type=\"button\" id=\"customSaveBtn\" style=\"opacity:0.4\">Guardar fondo<\/button>\r\n    <\/div>\r\n  <\/div>\r\n\r\n<script>\r\n\/\/ Cabeceras API: X-WP-Nonce solo si existe (vac\u00eda => 403 para an\u00f3nimos)\r\nfunction cdhApiHeaders() {\r\n  return window.cdhNonce ? { 'X-WP-Nonce': window.cdhNonce } : {};\r\n}\r\n\/\/ \u2500\u2500 Rompe contenedores WordPress\/Elementor \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n(function() {\r\n  var s = document.createElement('style');\r\n  s.innerHTML = 'html,body{overflow:hidden!important;margin:0!important;padding:0!important;}html{margin-top:0!important;}';\r\n  document.head.appendChild(s);\r\n  function fix() {\r\n    var el = document.getElementById('cripta');\r\n    if (!el) return;\r\n    var p = el.parentElement;\r\n    while (p && p !== document.body) {\r\n      p.style.setProperty('max-width','100vw','important');\r\n      p.style.setProperty('width','100vw','important');\r\n      p.style.setProperty('padding','0','important');\r\n      p.style.setProperty('margin','0','important');\r\n      p = p.parentElement;\r\n    }\r\n  }\r\n  document.addEventListener('DOMContentLoaded', fix);\r\n  window.addEventListener('load', fix);\r\n  setTimeout(fix, 200);\r\n})();\r\n\r\n\/\/ \u2500\u2500 Datos sepultura desde API REST \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction anio(fecha) {\r\n  return fecha ? fecha.split('-')[0] : '';\r\n}\r\n\r\nfunction mostrarSepultura(sep) {\r\n  var nombre = (sep.nombre || '') + (sep.apellidos ? ' ' + sep.apellidos : '');\r\n  document.getElementById('nombreDifunto').textContent = nombre;\r\n\r\n  var an = anio(sep.fecha_nacimiento);\r\n  var ad = anio(sep.fecha_fallecimiento);\r\n  var anios = '';\r\n  if (an && ad) anios = an + '  \u2014  ' + ad;\r\n  else if (an)  anios = an;\r\n  else if (ad)  anios = '\u2020 ' + ad;\r\n  document.getElementById('aniosDifunto').textContent = anios;\r\n\r\n  document.getElementById('separador').style.display = (nombre || anios) ? 'block' : 'none';\r\n}\r\n\r\nvar cdhSepId = 0; \/\/ ID de la sepultura activa\r\n\/\/ Modo lectura de la PAGINA: true para cualquiera que no sea el propietario.\r\n\/\/ Es distinto del modo lectura del explorador (expModoLectura), que se\r\n\/\/ recalcula cada vez que se abre una carpeta. Este no se toca en toda la\r\n\/\/ visita: manda siempre y no puede quedar en false por abrir una carpeta.\r\nvar criptaSoloLectura = false;\r\nvar cdhEsMonumento = false; \/\/ true si la publicaci\u00f3n activa es un monumento\r\n\r\n\/\/ Editor de monumentos: widget HTML de Elementor en esta p\u00e1gina.\r\n\/\/ Ojo: lee el id por ?sep=, no por ?sep_id= como el resto de editores.\r\nvar CDH_MON_EDITOR_URL = '\/index.php\/monumento-funerario\/?sep=';\r\n\r\n\/\/ Cripta monumental: sin ojo de previsualizar y con la rueda reducida a\r\n\/\/ \"Editar monumento\", \"Espacio utilizado\" y\r\n\/\/ \"Administrar Sepulturas y Monumentos\".\r\n\/\/ El fondo no se elige aqu\u00ed: lo fija la foto principal del monumento, as\u00ed que\r\n\/\/ \"Temas y estilo de la cripta\" se retira.\r\n\/\/ Las funciones de usuario (bot\u00f3n de usuario) se mantienen intactas.\r\nfunction criptaAplicarModoMonumento(sep) {\r\n  cdhEsMonumento = String((sep && sep.tipo) || '').toLowerCase() === 'monumento';\r\n  console.log('CDH Cripta: tipo=' + ((sep && sep.tipo) || 'sepultura') + (cdhEsMonumento ? ' (modo monumental)' : ''));\r\n  if (!cdhEsMonumento) return;\r\n  var pv = document.getElementById('previewBtn');\r\n  if (pv) pv.style.display = 'none';\r\n  ['menuCarpetas', 'menuWeb', 'menuQr', 'menuBiografia', 'menuArbol'].forEach(function(id) {\r\n    var el = document.getElementById(id);\r\n    if (el) el.style.display = 'none';\r\n  });\r\n\r\n  \/\/ Retirar \"Temas y estilo de la cripta\" y su submen\u00fa de fondos\r\n  var decorRow = document.getElementById('decorRow');\r\n  var decorSub = document.getElementById('decorSub');\r\n  if (decorRow) decorRow.style.display = 'none';\r\n  if (decorSub) { decorSub.style.display = 'none'; decorSub.classList.remove('open'); }\r\n\r\n  \/\/ Poner \"Editar monumento\" en su lugar, arriba del todo del panel\r\n  var panel = document.getElementById('panel');\r\n  if (panel && !document.getElementById('menuMonumento')) {\r\n    var item = document.createElement('div');\r\n    item.className = 'c-pi';\r\n    item.id = 'menuMonumento';\r\n    item.innerHTML = '\ud83c\udfdb &nbsp;Editar monumento';\r\n    item.onclick = function() {\r\n      if (cdhSepId > 0) {\r\n        window.location.href = CDH_MON_EDITOR_URL + cdhSepId;\r\n      } else {\r\n        alert('Selecciona primero un monumento.');\r\n      }\r\n    };\r\n    if (decorRow && decorRow.parentNode === panel) {\r\n      panel.insertBefore(item, decorRow);\r\n    } else {\r\n      panel.appendChild(item);\r\n    }\r\n  }\r\n}\r\n\r\nfunction cargarDatos() {\r\n  var urlParams = new URLSearchParams(window.location.search);\r\n  var sepIdUrl  = parseInt(urlParams.get('sep_id'), 10) || 0;\r\n\r\n  \/\/ Dentro del editor de Elementor: mostrar la cripta sin redirecciones\r\n  \/\/ ni reescritura de URL, para no romper la vista previa del editor.\r\n  var esEditorElementor = urlParams.has('elementor-preview') ||\r\n    (window.elementorFrontend && window.elementorFrontend.isEditMode && window.elementorFrontend.isEditMode());\r\n  if (esEditorElementor) {\r\n    aplicarFondoUrl('religionesyespiritualidad\/agnostico');\r\n    requestAnimationFrame(function() { document.getElementById('cripta').classList.add('visible'); });\r\n    return;\r\n  }\r\n\r\n  \/\/ Marca la sepultura activa del propietario: localStorage + servidor.\r\n  \/\/ As\u00ed, tras salir y volver a entrar, el login regresa a esta sepultura.\r\n  function criptaMarcarActiva(id) {\r\n    try { localStorage.setItem('cdh_sep_activa', id); } catch(e) {}\r\n    fetch('\/index.php\/wp-json\/cdh\/v1\/sep-activa', {\r\n      method: 'POST',\r\n      credentials: 'same-origin',\r\n      headers: Object.assign({ 'Content-Type': 'application\/json' }, cdhApiHeaders()),\r\n      body: JSON.stringify({ sep_id: id })\r\n    }).catch(function(){});\r\n  }\r\n\r\n  if (sepIdUrl > 0) {\r\n    \/\/ Hay sep_id en la URL: comprobar si es propia\r\n    fetch('\/index.php\/wp-json\/cdh\/v1\/mis-sepulturas', {\r\n      headers: Object.assign({ 'Content-Type': 'application\/json' }, cdhApiHeaders()),\r\n      credentials: 'same-origin'\r\n    })\r\n    .then(function(r){ return r.json(); })\r\n    .then(function(data) {\r\n      var esMia = Array.isArray(data) && data.some(function(s){ return parseInt(s.id) === sepIdUrl; });\r\n      if (esMia) {\r\n        var sep = data.find(function(s){ return parseInt(s.id) === sepIdUrl; });\r\n        cdhSepId = parseInt(sep.id) || 0;\r\n        criptaMarcarActiva(cdhSepId);\r\n        criptaAplicarModoMonumento(sep);\r\n        mostrarSepultura(sep);\r\n        criptaCargarModulos();\r\n        cargarCarpetas();\r\n        mapaCargarPublico();\r\n        if (sep.fondo) { aplicarFondoUrl(sep.fondo); } else { aplicarFondoUrl('religionesyespiritualidad\/agnostico'); }\r\n        requestAnimationFrame(function() { document.getElementById('cripta').classList.add('visible'); });\r\n      } else {\r\n        cargarModoPublico(sepIdUrl);\r\n      }\r\n    })\r\n    .catch(function() { cargarModoPublico(sepIdUrl); });\r\n    return;\r\n  }\r\n\r\n  \/\/ Sin sep_id: la cripta siempre va unida a una sepultura.\r\n  \/\/ (Respaldo del guardi\u00e1n del servidor cdh_proteger_cripta)\r\n  fetch('\/index.php\/wp-json\/cdh\/v1\/mis-sepulturas', {\r\n    headers: Object.assign({ 'Content-Type': 'application\/json' }, cdhApiHeaders()),\r\n    credentials: 'same-origin'\r\n  })\r\n  .then(function(r){ return r.json(); })\r\n  .then(function(data) {\r\n    if (!Array.isArray(data)) {\r\n      \/\/ Sin sesi\u00f3n: nunca mostrar la cripta gen\u00e9rica\r\n      window.location.replace('\/?noredirect=1');\r\n      return;\r\n    }\r\n    if (!data.length) {\r\n      \/\/ Logueado sin sepulturas: a crear la primera\r\n      window.location.replace('\/index.php\/pasarela-de-entrada\/');\r\n      return;\r\n    }\r\n    \/\/ v2: sin sep_id en la URL, respetar la sepultura activa elegida\r\n    \/\/ en Administrar Sepulturas (localStorage cdh_sep_activa)\r\n    var activaLS = 0;\r\n    try { activaLS = parseInt(localStorage.getItem('cdh_sep_activa'), 10) || 0; } catch(e) {}\r\n    var sep = data.find(function(s){ return parseInt(s.id) === activaLS; }) || data[0];\r\n    cdhSepId = parseInt(sep.id) || 0;\r\n    criptaMarcarActiva(cdhSepId);\r\n    \/\/ Normalizar la URL: el enlace de la cripta siempre lleva su sepultura\r\n    try { history.replaceState(null, '', '\/index.php\/la-cripta\/?sep_id=' + cdhSepId); } catch(e) {}\r\n    criptaAplicarModoMonumento(sep);\r\n    mostrarSepultura(sep);\r\n    criptaCargarModulos();\r\n    cargarCarpetas();\r\n    mapaCargarPublico();\r\n    if (sep.fondo) { aplicarFondoUrl(sep.fondo); } else { aplicarFondoUrl('religionesyespiritualidad\/agnostico'); }\r\n    requestAnimationFrame(function() { document.getElementById('cripta').classList.add('visible'); });\r\n  })\r\n  .catch(function(e){\r\n    console.log('CDH: sin sesi\u00f3n', e);\r\n    window.location.replace('\/?noredirect=1');\r\n  });\r\n}\r\n\r\nfunction cargarModoPublico(sepIdUrl) {\r\n  fetch('\/index.php\/wp-json\/cdh\/v1\/sepultura-publica\/' + sepIdUrl)\r\n  .then(function(r){\r\n    \/\/ 401\/403 = acceso denegado: tratar como cerrada aunque el cuerpo\r\n    \/\/ de la respuesta no llegue limpio (p\u00e1ginas de error de Nginx, etc.)\r\n    if (r.status === 401 || r.status === 403) return { code: 'cerrada' };\r\n    return r.json();\r\n  })\r\n  .then(function(sep) {\r\n    if (sep.code === 'cerrada') {\r\n      window.location.href = 'https:\/\/cementeriodigitalhispano.com\/index.php\/sepultura-cerrada\/?sep_id=' + sepIdUrl;\r\n      return;\r\n    }\r\n    if (sep.code === 'no_encontrada') {\r\n      document.getElementById('cripta').classList.add('visible');\r\n      return;\r\n    }\r\n    cdhSepId = parseInt(sep.id) || 0;\r\n    criptaSoloLectura = true;\r\n    expModoLectura = true;\r\n    legadoEsPropietario = false;\r\n    mostrarSepultura(sep);\r\n    criptaCargarModulos();\r\n    cargarCarpetas();\r\n    mapaCargarPublico();\r\n    if (sep.fondo) { aplicarFondoUrl(sep.fondo); } else { aplicarFondoUrl('religionesyespiritualidad\/agnostico'); }\r\n    \/\/ Ocultar controles de edici\u00f3n tras cargar\r\n    requestAnimationFrame(function() {\r\n      document.getElementById('cripta').classList.add('visible');\r\n      \/\/ Ocultar bot\u00f3n\/panel de usuario y controles de gesti\u00f3n (preview y rueda)\r\n      ['userBtn', 'userPanel', 'criptaHint', 'previewBtn', 'gearBtn', 'panel'].forEach(function(id) {\r\n        var el = document.getElementById(id); if (el) el.style.display = 'none';\r\n      });\r\n      \/\/ Ocultar botones de acci\u00f3n en m\u00f3dulos\r\n      document.querySelectorAll('.c-carpeta-acciones').forEach(function(el) { el.style.display = 'none'; });\r\n      \/\/ Hacer clickables los m\u00f3dulos activos\r\n      var elArbol = document.getElementById('criptaArbol');\r\n      if (elArbol && elArbol.style.display !== 'none') {\r\n        elArbol.style.cursor = 'pointer';\r\n        elArbol.onclick = function() { criptaAbrirArbolPublico(); };\r\n      }\r\n      var elBio = document.getElementById('criptaBiografia');\r\n      if (elBio && elBio.style.display !== 'none') {\r\n        elBio.style.cursor = 'pointer';\r\n        elBio.onclick = function() {\r\n          if (cdhSepId > 0) window.location.href = '\/biografia-view.php?sep_id=' + cdhSepId;\r\n        };\r\n      }\r\n    });\r\n  })\r\n  .catch(function() { document.getElementById('cripta').classList.add('visible'); });\r\n}\r\n\r\ndocument.addEventListener('DOMContentLoaded', cargarDatos);\r\n\r\n\/\/ \u2500\u2500 Posiciones de carpetas en la cripta \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction criptaPosKey() { return 'cdh_cripta_pos_' + (cdhSepId || '0'); }\r\nfunction criptaLoadPos() { try { return JSON.parse(localStorage.getItem(criptaPosKey()) || '{}'); } catch(e) { return {}; } }\r\nfunction criptaSavePos(id, x, y) { var pos = criptaLoadPos(); pos[id] = {x:x,y:y}; localStorage.setItem(criptaPosKey(), JSON.stringify(pos)); }\r\n\r\n\/\/ \u2500\u2500 M\u00f3dulos de la cripta (\u00e1rbol, QR, Web) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nvar criptaModulos = { arbol: false, qr: false, web: false, mapa: false, biografia: false };\r\nvar criptaModulosPos = {}; \/\/ posiciones guardadas en servidor: { arbol:{x,y}, qr:{x,y}, ... }\r\n\r\nfunction criptaCargarModulos() {\r\n  if (!cdhSepId) return;\r\n  var headers = {};\r\n  if (window.cdhNonce) headers['X-WP-Nonce'] = window.cdhNonce;\r\n  fetch('\/index.php\/wp-json\/cdh\/v1\/sepultura\/' + cdhSepId + '\/modulos', {\r\n    headers: headers, credentials: 'same-origin'\r\n  })\r\n  .then(function(r) { return r.json(); })\r\n  .then(function(data) {\r\n    if (data && data.modulos) {\r\n      criptaModulos = data.modulos;\r\n      criptaModulosPos = (data.modulos_pos && typeof data.modulos_pos === 'object') ? data.modulos_pos : {};\r\n      criptaAplicarModulos();\r\n    }\r\n  }).catch(function(){});\r\n}\r\n\r\nfunction criptaAplicarModulos() {\r\n  ['arbol','biografia'].forEach(function(key) {\r\n    var el = document.getElementById('cripta' + key.charAt(0).toUpperCase() + key.slice(1));\r\n    if (!el) return;\r\n    if (criptaModulos[key]) {\r\n      el.style.display = 'flex';\r\n      criptaPonerModulo(el, key);\r\n      \/\/ En modo lectura p\u00fablica: asignar click a arbol y biografia\r\n      if (expModoLectura) {\r\n        var acciones = el.querySelector('.c-carpeta-acciones');\r\n        if (acciones) acciones.style.display = 'none';\r\n        if (key === 'arbol') {\r\n          el.style.cursor = 'pointer';\r\n          el._clickPublico = function() { criptaAbrirArbolPublico(); };\r\n        } else if (key === 'biografia') {\r\n          el.style.cursor = 'pointer';\r\n          el._clickPublico = function() {\r\n            if (cdhSepId > 0) window.location.href = '\/biografia-view.php?sep_id=' + cdhSepId;\r\n          };\r\n        }\r\n      }\r\n    } else {\r\n      el.style.display = 'none';\r\n    }\r\n  });\r\n  criptaEncajarEnPantalla();\r\n  \/\/ Mapa: siempre activo, no depende de m\u00f3dulos\r\n  criptaActualizarMenu();\r\n}\r\n\r\nfunction criptaUrlArbolPublico() {\r\n  if (!cdhSepId || cdhSepId <= 0) return '';\r\n  return '\/index.php\/arbol-genealogico\/?sep_id=' + encodeURIComponent(cdhSepId) + '&public=1';\r\n}\r\n\r\nfunction criptaAbrirArbolPublico() {\r\n  var url = criptaUrlArbolPublico();\r\n  if (!url) {\r\n    alert('Selecciona primero una sepultura.');\r\n    return;\r\n  }\r\n  window.location.href = url;\r\n}\r\n\r\nfunction criptaPonerModulo(el, key) {\r\n  var posKey = 'cdh_mod_pos_' + (cdhSepId||'0') + '_' + key;\r\n  function guardarPosModulo(x, y) {\r\n    criptaFijarOrigen(el, x, y);   \/\/ lo que acaba de elegir manda\r\n    try { localStorage.setItem(posKey, JSON.stringify({x:x, y:y})); } catch(e) {}\r\n    if (!cdhSepId || !window.cdhNonce || expModoLectura) return;\r\n    fetch('\/index.php\/wp-json\/cdh\/v1\/sepultura\/' + cdhSepId + '\/modulos-pos', {\r\n      method: 'POST',\r\n      headers: { 'Content-Type': 'application\/json', 'X-WP-Nonce': window.cdhNonce },\r\n      credentials: 'same-origin',\r\n      body: JSON.stringify({ modulo: key, x: x, y: y })\r\n    }).catch(function(){});\r\n  }\r\n  var servidorPos = criptaModulosPos[key];\r\n  var saved = null;\r\n  if (!servidorPos) {\r\n    try { saved = JSON.parse(localStorage.getItem(posKey)); } catch(e) {}\r\n  }\r\n  if (servidorPos && typeof servidorPos.x === 'number' && typeof servidorPos.y === 'number') {\r\n    el.style.left = servidorPos.x + 'px'; el.style.top = servidorPos.y + 'px';\r\n  } else if (saved) {\r\n    el.style.left = saved.x + 'px'; el.style.top = saved.y + 'px';\r\n    \/\/ Migraci\u00f3n autom\u00e1tica: hab\u00eda una posici\u00f3n guardada solo en este navegador\r\n    \/\/ (de antes de existir el guardado en servidor) \u2014 la subimos una vez para\r\n    \/\/ que se vea igual desde cualquier dispositivo o visitante.\r\n    if (!expModoLectura && window.cdhNonce && cdhSepId) {\r\n      guardarPosModulo(saved.x, saved.y);\r\n    }\r\n  } else {\r\n    var defaults = { arbol:{x:0.25,y:0.72}, biografia:{x:0.55,y:0.72} };\r\n    var d = defaults[key] || {x:0.4,y:0.72};\r\n    el.style.left = Math.round(window.innerWidth  * d.x) + 'px';\r\n    el.style.top  = Math.round(window.innerHeight * d.y) + 'px';\r\n  }\r\n  \/\/ Posicion recien asignada: pasa a ser el origen desde el que se encaja\r\n  criptaFijarOrigen(el, parseFloat(el.style.left) || 0, parseFloat(el.style.top) || 0);\r\n  if (!el._dragInit) {\r\n    el._dragInit = true;\r\n    var ox=0,oy=0,sx=0,sy=0,dragging=false,moved=false;\r\n    el.addEventListener('mousedown',function(e){if(expModoLectura)return;if(e.button!==0)return;e.preventDefault();dragging=true;moved=false;ox=el.offsetLeft;oy=el.offsetTop;sx=e.clientX;sy=e.clientY;el.style.transition='none';el.style.zIndex=50;});\r\n    document.addEventListener('mousemove',function(e){if(!dragging)return;var dx=e.clientX-sx,dy=e.clientY-sy;if(Math.abs(dx)>5||Math.abs(dy)>5)moved=true;el.style.left=Math.max(0,Math.min(ox+dx,window.innerWidth-el.offsetWidth))+'px';el.style.top=Math.max(0,Math.min(oy+dy,window.innerHeight-el.offsetHeight))+'px';});\r\n    document.addEventListener('mouseup',function(){if(!dragging)return;dragging=false;el.style.zIndex=11;if(moved){guardarPosModulo(el.offsetLeft, el.offsetTop);}});\r\n    el.addEventListener('touchstart',function(e){if(expModoLectura)return;if(e.target&&e.target.closest&&e.target.closest('.c-carpeta-accion')){dragging=false;moved=false;return;}var t=e.touches[0];ox=el.offsetLeft;oy=el.offsetTop;sx=t.clientX;sy=t.clientY;dragging=true;moved=false;},{passive:true});\r\n    el.addEventListener('touchmove',function(e){if(!dragging)return;e.preventDefault();var t=e.touches[0];var dx=t.clientX-sx,dy=t.clientY-sy;if(Math.abs(dx)>5||Math.abs(dy)>5)moved=true;el.style.left=Math.max(0,Math.min(ox+dx,window.innerWidth-el.offsetWidth))+'px';el.style.top=Math.max(0,Math.min(oy+dy,window.innerHeight-el.offsetHeight))+'px';},{passive:false});\r\n    el.addEventListener('touchend',function(){\r\n      dragging=false;\r\n      if(moved){guardarPosModulo(el.offsetLeft, el.offsetTop);}\r\n    });\r\n    el.addEventListener('click', function(e) {\r\n      if (e.target.closest('.c-carpeta-acciones, .c-carpeta-accion')) return;\r\n      if (moved) return;\r\n      e.preventDefault();\r\n      e.stopPropagation();\r\n      if (el._clickPublico) { el._clickPublico(); return; }\r\n      if (key === 'arbol') criptaAbrirArbolPublico();\r\n      if (key === 'biografia' && cdhSepId > 0) window.location.href = '\/biografia-view.php?sep_id=' + cdhSepId;\r\n    });\r\n  }\r\n}\r\n\r\nfunction criptaActivarModulo(key) {\r\n  document.getElementById('panel').classList.remove('open');\r\n  criptaModulos[key] = !criptaModulos[key];\r\n  fetch('\/index.php\/wp-json\/cdh\/v1\/sepultura\/' + cdhSepId + '\/modulos', {\r\n    method: 'POST',\r\n    headers: Object.assign({ 'Content-Type': 'application\/json' }, cdhApiHeaders()),\r\n    credentials: 'same-origin',\r\n    body: JSON.stringify({ modulos: criptaModulos })\r\n  }).catch(function(){});\r\n  criptaAplicarModulos();\r\n}\r\n\r\nfunction criptaActualizarMenu() {\r\n  var cfg = {\r\n    arbol:     { id:'menuArbol',     label:'\ud83c\udf33 &nbsp;\u00c1rbol geneal\u00f3gico' },\r\n    biografia: { id:'menuBiografia', label:'\ud83d\udcd6 &nbsp;Biograf\u00eda' }\r\n  };\r\n  Object.keys(cfg).forEach(function(key) {\r\n    var el = document.getElementById(cfg[key].id);\r\n    if (!el) return;\r\n    el.innerHTML = cfg[key].label + (criptaModulos[key]\r\n      ? ' <span style=\"margin-left:auto;color:#7ec89a;font-size:11px;\">\u2713 Activo<\/span>'\r\n      : ' <span style=\"margin-left:auto;color:rgba(200,160,60,0.5);font-size:10px;\">+ Activar<\/span>');\r\n  });\r\n}\r\n\r\n\/\/ \u2500\u2500 UI \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\ndocument.getElementById('gearBtn').addEventListener('click', function(e) {\r\n  e.stopPropagation();\r\n  document.getElementById('panel').classList.toggle('open');\r\n});\r\ndocument.getElementById('decorRow').addEventListener('click', function(e) {\r\n  e.stopPropagation();\r\n  document.getElementById('decorSub').classList.toggle('open');\r\n  document.getElementById('dArr').classList.toggle('rot');\r\n});\r\ndocument.addEventListener('click', function(e) {\r\n  var p = document.getElementById('panel');\r\n  if (!p.contains(e.target) && e.target !== document.getElementById('gearBtn'))\r\n    p.classList.remove('open');\r\n});\r\n\/\/ Aplica una URL completa de fondo al div cripta\r\nfunction aplicarFondoUrl(url) {\r\n  \/\/ Si es una ruta relativa de tema (carpeta\/archivo), construir URL completa\r\n  if (url.indexOf('http') !== 0 && url.indexOf('\/wp-content') !== 0) {\r\n    url = '\/wp-content\/uploads\/cripta\/' + url + '.png';\r\n  }\r\n  document.getElementById('cripta').style.backgroundImage = \"url('\" + url + \"')\";\r\n}\r\n\r\nfunction cambiarFondo(carpeta, archivo) {\r\n  var ruta = carpeta + '\/' + archivo;\r\n  aplicarFondoUrl(ruta);\r\n  document.getElementById('panel').classList.remove('open');\r\n\r\n  \/\/ Guardar en BD si tenemos sepultura activa\r\n  if (cdhSepId > 0 && window.cdhNonce) {\r\n    fetch('\/index.php\/wp-json\/cdh\/v1\/sepultura\/' + cdhSepId + '\/fondo', {\r\n      method: 'POST',\r\n      headers: {\r\n        'Content-Type': 'application\/json',\r\n        'X-WP-Nonce': window.cdhNonce\r\n      },\r\n      credentials: 'same-origin',\r\n      body: JSON.stringify({ fondo: ruta })\r\n    }).catch(function(e){ console.log('CDH: error guardando fondo', e); });\r\n  }\r\n}\r\n\r\nfunction toggleCat(id, el) {\r\n  var sub = document.getElementById(id);\r\n  var arr = el.querySelector('.c-cat-arr');\r\n  var isOpen = sub.classList.contains('open');\r\n  \/\/ Cerrar todos los dem\u00e1s\r\n  document.querySelectorAll('.c-cat-sub').forEach(function(s){ s.classList.remove('open'); });\r\n  document.querySelectorAll('.c-cat-arr').forEach(function(a){ a.classList.remove('rot'); });\r\n  if (!isOpen) {\r\n    sub.classList.add('open');\r\n    if (arr) arr.classList.add('rot');\r\n  }\r\n}\r\n\r\n\/\/ \u2500\u2500 Panel usuario \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\ndocument.getElementById('userBtn').addEventListener('click', function(e) {\r\n  e.stopPropagation();\r\n  document.getElementById('userPanel').classList.toggle('open');\r\n  document.getElementById('panel').classList.remove('open');\r\n});\r\ndocument.addEventListener('click', function(e) {\r\n  var up = document.getElementById('userPanel');\r\n  if (!up.contains(e.target) && e.target !== document.getElementById('userBtn'))\r\n    up.classList.remove('open');\r\n});\r\n\r\nfunction irA(url) {\r\n  window.location.href = url;\r\n}\r\n\r\nfunction cdh_cerrar_sesion() {\r\n  var nonce = window.cdhLogoutNonce || '';\r\n  window.location.href = '\/?cdh_logout=1&nonce=' + nonce;\r\n}\r\n\r\nfunction confirmarEliminarSepultura() {\r\n  cdhConfirm(\r\n    'Eliminar sepultura',\r\n    '\u00bfSeguro que desea eliminar esta sepultura?<br><br>Esta acci\u00f3n no se puede deshacer.',\r\n    '\ud83e\udea6', 'Eliminar',\r\n    function(ok) {\r\n      if (!ok) return;\r\n      alert('Funci\u00f3n pr\u00f3ximamente disponible.');\r\n    }\r\n  );\r\n}\r\n\r\nfunction confirmarEliminarCuenta() {\r\n  document.getElementById('modalEliminar').style.display = 'flex';\r\n  document.getElementById('cdh-confirmar-texto').value = '';\r\n  document.getElementById('cdh-eliminar-aviso').className = 'cdh-aviso';\r\n  document.getElementById('cdh-btn-eliminar-final').disabled = true;\r\n  document.getElementById('cdh-btn-eliminar-final').style.opacity = '0.4';\r\n}\r\n\r\nfunction cerrarModalEliminar() {\r\n  document.getElementById('modalEliminar').style.display = 'none';\r\n}\r\n\r\nasync function cdh_obtener_nonce() {\r\n  if (window.cdhNonce) return window.cdhNonce;\r\n  try {\r\n    var res = await fetch('\/index.php\/wp-json\/cdh\/v1\/nonce', { credentials: 'same-origin' });\r\n    var data = await res.json();\r\n    if (data.nonce) { window.cdhNonce = data.nonce; return data.nonce; }\r\n  } catch(e) {}\r\n  return '';\r\n}\r\n\r\nasync function descargarMisDatos() {\r\n  var btn = document.getElementById('cdh-btn-descargar');\r\n  btn.textContent = 'Descargando...';\r\n  btn.disabled = true;\r\n  try {\r\n    var nonce = await cdh_obtener_nonce();\r\n    var res = await fetch('\/index.php\/wp-json\/cdh\/v1\/mis-datos', {\r\n      credentials: 'same-origin',\r\n      headers: { 'X-WP-Nonce': nonce }\r\n    });\r\n    var data = await res.json();\r\n    var blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application\/json' });\r\n    var url = URL.createObjectURL(blob);\r\n    var a = document.createElement('a');\r\n    a.href = url;\r\n    a.download = 'mis-datos-cementerio-digital-hispano.json';\r\n    a.click();\r\n    URL.revokeObjectURL(url);\r\n  } catch(e) {}\r\n  btn.textContent = '\u2b07 Descargar mis datos';\r\n  btn.disabled = false;\r\n}\r\n\r\nasync function eliminarCuentaFinal() {\r\n  var texto = document.getElementById('cdh-confirmar-texto').value.trim();\r\n  var aviso = document.getElementById('cdh-eliminar-aviso');\r\n  if (texto !== 'ELIMINAR') {\r\n    aviso.textContent = 'Escriba ELIMINAR para confirmar.';\r\n    aviso.className = 'cdh-aviso cdh-aviso-error';\r\n    return;\r\n  }\r\n  var btn = document.getElementById('cdh-btn-eliminar-final');\r\n  btn.disabled = true;\r\n  btn.textContent = 'Eliminando...';\r\n  try {\r\n    var nonce = await cdh_obtener_nonce();\r\n    var res = await fetch('\/index.php\/wp-json\/cdh\/v1\/eliminar-cuenta', {\r\n      method: 'DELETE',\r\n      credentials: 'same-origin',\r\n      headers: { 'X-WP-Nonce': nonce }\r\n    });\r\n    var data = await res.json();\r\n    if (data.ok) {\r\n      aviso.textContent = '\u2713 Cuenta eliminada. Redirigiendo...';\r\n      aviso.className = 'cdh-aviso cdh-aviso-ok';\r\n      setTimeout(function() { window.location.href = '\/'; }, 2000);\r\n    } else {\r\n      aviso.textContent = data.mensaje || 'Error al eliminar la cuenta.';\r\n      aviso.className = 'cdh-aviso cdh-aviso-error';\r\n      btn.disabled = false;\r\n      btn.textContent = 'Eliminar mi cuenta definitivamente';\r\n    }\r\n  } catch(e) {\r\n    aviso.textContent = 'Error de conexi\u00f3n. Int\u00e9ntalo de nuevo.';\r\n    aviso.className = 'cdh-aviso cdh-aviso-error';\r\n    btn.disabled = false;\r\n    btn.textContent = 'Eliminar mi cuenta definitivamente';\r\n  }\r\n}\r\n\r\n\/\/ \u2500\u2500 Cargar datos del usuario \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction cargarUsuario() {\r\n  fetch('\/index.php\/wp-json\/wp\/v2\/users\/me', {\r\n    headers: cdhApiHeaders(),\r\n    credentials: 'same-origin'\r\n  })\r\n  .then(function(r){ return r.json(); })\r\n  .then(function(u) {\r\n    if (u && u.name) {\r\n      document.getElementById('upNombre').textContent = u.name;\r\n      document.getElementById('upEmail').textContent = u.slug || '';\r\n    }\r\n  })\r\n  .catch(function(){});\r\n}\r\ndocument.addEventListener('DOMContentLoaded', cargarUsuario);\r\n\r\n\/\/ \u2500\u2500 Fondo personalizado \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nvar customFile = null;\r\n\r\nfunction abrirPersonalizado() {\r\n  document.getElementById('panel').classList.remove('open');\r\n  document.getElementById('customPanel').classList.add('open');\r\n  document.getElementById('customStatus').textContent = '';\r\n  document.getElementById('customProgress').style.display = 'none';\r\n  document.getElementById('customProgressBar').style.width = '0%';\r\n  \/\/ Registrar el listener del bot\u00f3n cada vez que se abre\r\n  var btn = document.getElementById('customSaveBtn');\r\n  btn.replaceWith(btn.cloneNode(true)); \/\/ elimina listeners anteriores\r\n  document.getElementById('customSaveBtn').addEventListener('click', function() {\r\n    subirPersonalizado();\r\n  });\r\n}\r\n\r\nfunction cerrarPersonalizado() {\r\n  document.getElementById('customPanel').classList.remove('open');\r\n  customFile = null;\r\n  document.getElementById('customFile').value = '';\r\n  var btn = document.getElementById('customSaveBtn');\r\n  btn.disabled = true; btn.style.opacity = '0.4';\r\n  document.getElementById('customStatus').textContent = '';\r\n}\r\n\r\ndocument.addEventListener('DOMContentLoaded', function() {\r\n  var drop = document.getElementById('customDrop');\r\n  drop.addEventListener('dragover', function(e) {\r\n    e.preventDefault(); this.classList.add('drag');\r\n  });\r\n  drop.addEventListener('dragleave', function() { this.classList.remove('drag'); });\r\n  drop.addEventListener('drop', function(e) {\r\n    e.preventDefault(); this.classList.remove('drag');\r\n    var f = e.dataTransfer.files[0];\r\n    if (f) procesarImagen(f);\r\n  });\r\n});\r\n\r\nfunction procesarImagen(file) {\r\n  var status = document.getElementById('customStatus');\r\n  var allowed = ['image\/jpeg','image\/png','image\/webp'];\r\n  if (!allowed.includes(file.type)) {\r\n    status.textContent = '\u26a0 Solo se admiten JPG, PNG o WebP.';\r\n    status.style.color = '#c87050'; return;\r\n  }\r\n  if (file.size > 5 * 1024 * 1024) {\r\n    status.textContent = '\u26a0 La imagen supera los 5 MB.';\r\n    status.style.color = '#c87050'; return;\r\n  }\r\n  customFile = file;\r\n  var btn = document.getElementById('customSaveBtn');\r\n  btn.disabled = false; btn.style.opacity = '1';\r\n  status.textContent = '\u2713 ' + file.name + ' (' + (file.size\/1024\/1024).toFixed(1) + ' MB)';\r\n  status.style.color = '#8aaa60';\r\n}\r\n\r\nfunction subirPersonalizado() {\r\n  if (!customFile) return;\r\n  var progress = document.getElementById('customProgress');\r\n  var bar = document.getElementById('customProgressBar');\r\n  var status = document.getElementById('customStatus');\r\n  var btn = document.getElementById('customSaveBtn');\r\n\r\n  progress.style.display = 'block';\r\n  btn.disabled = true; btn.style.opacity = '0.5';\r\n  status.textContent = 'Subiendo imagen...';\r\n  status.style.color = '#907030';\r\n\r\n  var formData = new FormData();\r\n  formData.append('file', customFile);\r\n  formData.append('action', 'cdh_subir_fondo_personalizado');\r\n  formData.append('nonce', window.cdhNonce || '');\r\n  if (cdhSepId > 0) formData.append('sep_id', cdhSepId);\r\n\r\n  var xhr = new XMLHttpRequest();\r\n  xhr.upload.addEventListener('progress', function(e) {\r\n    if (e.lengthComputable) {\r\n      var pct = Math.round(e.loaded \/ e.total * 90);\r\n      bar.style.width = pct + '%';\r\n    }\r\n  });\r\n  xhr.addEventListener('load', function() {\r\n    bar.style.width = '100%';\r\n    try {\r\n      var res = JSON.parse(xhr.responseText);\r\n      if (res.success && res.data && res.data.url) {\r\n        status.textContent = '\u2713 Fondo guardado correctamente.';\r\n        status.style.color = '#8aaa60';\r\n        document.getElementById('cripta').style.backgroundImage = \"url('\" + res.data.url + \"')\";\r\n\r\n        \/\/ Guardar la URL en la BD de la sepultura\r\n        if (cdhSepId > 0 && window.cdhNonce) {\r\n          fetch('\/index.php\/wp-json\/cdh\/v1\/sepultura\/' + cdhSepId + '\/fondo', {\r\n            method: 'POST',\r\n            headers: { 'Content-Type': 'application\/json', 'X-WP-Nonce': window.cdhNonce },\r\n            credentials: 'same-origin',\r\n            body: JSON.stringify({ fondo: res.data.url })\r\n          }).catch(function(e){ console.log('CDH: error guardando fondo personalizado', e); });\r\n        }\r\n\r\n        setTimeout(cerrarPersonalizado, 1200);\r\n      } else {\r\n        status.textContent = '\u26a0 Error: ' + (res.data || 'No se pudo guardar.');\r\n        status.style.color = '#c87050';\r\n        btn.disabled = false; btn.style.opacity = '1';\r\n      }\r\n    } catch(ex) {\r\n      status.textContent = '\u26a0 Error inesperado. Int\u00e9ntalo de nuevo.';\r\n      status.style.color = '#c87050';\r\n      btn.disabled = false; btn.style.opacity = '1';\r\n    }\r\n  });\r\n  xhr.addEventListener('error', function() {\r\n    status.textContent = '\u26a0 Error de conexi\u00f3n. Int\u00e9ntalo de nuevo.';\r\n    status.style.color = '#c87050';\r\n    btn.disabled = false; btn.style.opacity = '1';\r\n  });\r\n  xhr.open('POST', '\/wp-admin\/admin-ajax.php');\r\n  if (window.cdhNonce) xhr.setRequestHeader('X-WP-Nonce', window.cdhNonce);\r\n  xhr.send(formData);\r\n}\r\n\r\n<\/script>\r\n\r\n<!-- Panel espacio utilizado -->\r\n<div id=\"panelEspacio\" style=\"\r\n  display:none; position:fixed; top:50%; left:50%; transform:translate(-50%,-50%);\r\n  background:rgba(22,10,4,0.97); border:1px solid rgba(201,169,110,0.3);\r\n  border-radius:6px; padding:32px 28px; width:320px; max-width:90vw;\r\n  z-index:100035; box-shadow:0 8px 40px rgba(0,0,0,0.7); font-family:Arial,sans-serif;\r\n\">\r\n  <div style=\"text-align:center; margin-bottom:22px;\">\r\n    <div style=\"font-size:32px; margin-bottom:10px;\">\ud83d\udcbe<\/div>\r\n    <div style=\"font-size:11px; letter-spacing:3px; text-transform:uppercase; color:#c9a96e;\">Espacio utilizado<\/div>\r\n  <\/div>\r\n\r\n  <div id=\"esp-cargando\" style=\"text-align:center; color:rgba(245,240,232,0.4); font-size:13px; padding:16px 0;\">\r\n    Calculando...\r\n  <\/div>\r\n\r\n  <div id=\"esp-datos\" style=\"display:none;\">\r\n    <div style=\"display:flex; justify-content:space-between; margin-bottom:8px; font-size:13px;\">\r\n      <span style=\"color:rgba(245,240,232,0.6);\">Usado<\/span>\r\n      <span id=\"esp-texto\" style=\"color:#f5f0e8; font-weight:bold;\"><\/span>\r\n    <\/div>\r\n    <div style=\"background:rgba(0,0,0,0.4); border-radius:20px; height:14px; overflow:hidden; margin-bottom:8px; border:1px solid rgba(201,169,110,0.15);\">\r\n      <div id=\"esp-barra\" style=\"height:100%; border-radius:20px; transition:width 0.6s ease; width:0%;\"><\/div>\r\n    <\/div>\r\n    <div style=\"display:flex; justify-content:space-between; font-size:11px; color:rgba(245,240,232,0.35); margin-bottom:24px;\">\r\n      <span>0 MB<\/span>\r\n      <span id=\"esp-porcentaje\" style=\"color:#c9a96e; font-weight:bold;\"><\/span>\r\n      <span>1 GB<\/span>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <div id=\"esp-error\" style=\"display:none; text-align:center; color:#e8a0a0; font-size:13px; padding:8px 0 20px;\"><\/div>\r\n\r\n  <button onclick=\"cerrarEspacio()\" style=\"\r\n    width:100%; padding:12px; background:linear-gradient(135deg,#2d5a3d,#1e3a2b);\r\n    border:1px solid rgba(201,169,110,0.4); border-radius:3px; color:#f5f0e8;\r\n    font-family:'Cinzel',Georgia,serif; font-size:11px; letter-spacing:3px;\r\n    text-transform:uppercase; cursor:pointer;\r\n  \">\u2190 &nbsp;Cerrar<\/button>\r\n<\/div>\r\n<div id=\"panelEspacioOverlay\" onclick=\"cerrarEspacio()\" style=\"display:none; position:fixed; top:0; left:0; right:0; bottom:0; background:rgba(0,0,0,0.5); z-index:100034;\"><\/div>\r\n\r\n<script>\r\nasync function abrirEspacio() {\r\n  \/\/ Cerrar men\u00fa opciones si est\u00e1 abierto\r\n  var panel = document.getElementById('panel');\r\n  if (panel) panel.classList.remove('open');\r\n\r\n  document.getElementById('panelEspacio').style.display = 'block';\r\n  document.getElementById('panelEspacioOverlay').style.display = 'block';\r\n  document.getElementById('esp-cargando').style.display = 'block';\r\n  document.getElementById('esp-datos').style.display = 'none';\r\n  document.getElementById('esp-error').style.display = 'none';\r\n\r\n  try {\r\n    var sepId = window.cdhSepId || cdhSepId || null;\r\n    var url = '\/index.php\/wp-json\/cdh\/v1\/espacio-sepultura' + (sepId ? '?sep_id=' + sepId : '');\r\n    var res = await fetch(url, {\r\n      credentials: 'same-origin',\r\n      headers: cdhApiHeaders()\r\n    });\r\n    var data = await res.json();\r\n\r\n    if (!data.ok) throw new Error(data.mensaje || 'Error');\r\n\r\n    var usadoMB  = data.usado_mb;\r\n    var totalMB  = 1024;\r\n    var pct      = Math.min(100, (usadoMB \/ totalMB) * 100);\r\n    var color    = pct < 60 ? '#4a9a6a' : pct < 85 ? '#c9a040' : '#c05040';\r\n\r\n    var textoUsado = usadoMB < 1\r\n      ? (data.usado_kb).toFixed(0) + ' KB'\r\n      : usadoMB < 1024\r\n        ? usadoMB.toFixed(1) + ' MB'\r\n        : (usadoMB \/ 1024).toFixed(2) + ' GB';\r\n\r\n    document.getElementById('esp-texto').textContent = textoUsado + ' de 1 GB';\r\n    document.getElementById('esp-porcentaje').textContent = pct.toFixed(1) + '%';\r\n    document.getElementById('esp-barra').style.width = pct + '%';\r\n    document.getElementById('esp-barra').style.background = color;\r\n\r\n    document.getElementById('esp-cargando').style.display = 'none';\r\n    document.getElementById('esp-datos').style.display = 'block';\r\n\r\n  } catch(e) {\r\n    document.getElementById('esp-cargando').style.display = 'none';\r\n    document.getElementById('esp-error').style.display = 'block';\r\n    document.getElementById('esp-error').textContent = 'No se pudo calcular el espacio. Int\u00e9ntalo de nuevo.';\r\n  }\r\n}\r\n\r\nfunction cerrarEspacio() {\r\n  document.getElementById('panelEspacio').style.display = 'none';\r\n  document.getElementById('panelEspacioOverlay').style.display = 'none';\r\n}\r\n\r\n\/\/ \u2500\u2500 Previsualizaci\u00f3n p\u00fablica \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\ndocument.getElementById('previewBtn').addEventListener('click', function(e) {\r\n  e.stopPropagation();\r\n  document.getElementById('panel').classList.remove('open');\r\n\r\n  var modal = document.getElementById('previewModal');\r\n  var bgImg = document.getElementById('cripta').style.backgroundImage;\r\n  modal.style.backgroundImage = bgImg || '';\r\n  modal.style.backgroundColor = '#0a0500';\r\n  modal.style.backgroundSize = 'cover';\r\n  modal.style.backgroundPosition = 'center center';\r\n\r\n  document.getElementById('previewNombre').textContent = document.getElementById('nombreDifunto').textContent;\r\n  document.getElementById('previewAnios').textContent  = document.getElementById('aniosDifunto').textContent;\r\n  var tieneInfo = document.getElementById('previewNombre').textContent || document.getElementById('previewAnios').textContent;\r\n  document.getElementById('previewSeparador').style.display = tieneInfo ? 'block' : 'none';\r\n\r\n  cargarCarpetasPreview();\r\n  modal.classList.add('open');\r\n  \/\/ \u00c1rbol en preview: solo si activo. QR y Web: nunca.\r\n  var pvArbolClone = document.getElementById('pvArbolClone');\r\n  var elArbol = document.getElementById('criptaArbol');\r\n  if (criptaModulos.arbol && elArbol) {\r\n    if (!pvArbolClone) {\r\n      pvArbolClone = elArbol.cloneNode(true);\r\n      pvArbolClone.id = 'pvArbolClone';\r\n      pvArbolClone.style.pointerEvents = 'auto';\r\n      pvArbolClone.style.cursor = 'pointer';\r\n      pvArbolClone.onclick = function(e) {\r\n        e.preventDefault();\r\n        e.stopPropagation();\r\n        criptaAbrirArbolPublico();\r\n      };\r\n      \/\/ Ocultar botones de edici\u00f3n en el clon (modo preview)\r\n      var pvArbolAcciones = pvArbolClone.querySelector('.c-carpeta-acciones');\r\n      if (pvArbolAcciones) pvArbolAcciones.style.display = 'none';\r\n      document.getElementById('previewModal').appendChild(pvArbolClone);\r\n    }\r\n    pvArbolClone.style.display = 'flex';\r\n    pvArbolClone.style.left = elArbol.style.left;\r\n    pvArbolClone.style.top  = elArbol.style.top;\r\n  } else if (pvArbolClone) {\r\n    pvArbolClone.style.display = 'none';\r\n  }\r\n\r\n  \/\/ Biograf\u00eda en preview: solo si activo. Sin botones de edici\u00f3n.\r\n  var pvBioClone = document.getElementById('pvBioClone');\r\n  var elBio = document.getElementById('criptaBiografia');\r\n  if (criptaModulos.biografia && elBio) {\r\n    if (!pvBioClone) {\r\n      pvBioClone = elBio.cloneNode(true);\r\n      pvBioClone.id = 'pvBioClone';\r\n      pvBioClone.style.pointerEvents = 'auto';\r\n      pvBioClone.style.cursor = 'pointer';\r\n      var pvBioAcciones = pvBioClone.querySelector('.c-carpeta-acciones');\r\n      if (pvBioAcciones) pvBioAcciones.style.display = 'none';\r\n      pvBioClone.addEventListener('click', function() {\r\n        if (cdhSepId > 0) window.location.href = '\/biografia-view.php?sep_id=' + cdhSepId;\r\n      });\r\n      document.getElementById('previewModal').appendChild(pvBioClone);\r\n    }\r\n    pvBioClone.style.display = 'flex';\r\n    pvBioClone.style.left = elBio.style.left;\r\n    pvBioClone.style.top  = elBio.style.top;\r\n  } else if (pvBioClone) {\r\n    pvBioClone.style.display = 'none';\r\n  }\r\n\r\n});\r\n\r\ndocument.getElementById('previewClose').addEventListener('click', function() {\r\n  document.getElementById('previewModal').classList.remove('open');\r\n});\r\n\r\ndocument.addEventListener('keydown', function(e) {\r\n  if (e.key === 'Escape') document.getElementById('previewModal').classList.remove('open');\r\n});\r\n\r\nfunction cargarCarpetasPreview() {\r\n  var contenedor = document.getElementById('previewCarpetas');\r\n  var empty      = document.getElementById('previewEmpty');\r\n  contenedor.innerHTML = '';\r\n  empty.style.display = 'none';\r\n\r\n  if (!mcCarpetas.length) {\r\n    if (cdhSepId > 0) {\r\n      fetch('\/index.php\/wp-json\/cdh\/v1\/carpetas?sep_id=' + cdhSepId, {\r\n        headers: cdhApiHeaders(),\r\n        credentials: 'same-origin'\r\n      })\r\n      .then(function(r) { return r.json(); })\r\n      .then(function(data) {\r\n        mcCarpetas = Array.isArray(data) ? data : [];\r\n        renderCarpetasEnPreview(contenedor, empty);\r\n        mapaPrecarga(); \/\/ carpetas ya cargadas, precargamos el mapa\r\n      })\r\n      .catch(function() { empty.style.display = 'block'; });\r\n    } else {\r\n      empty.style.display = 'block';\r\n    }\r\n    return;\r\n  }\r\n\r\n  renderCarpetasEnPreview(contenedor, empty);\r\n  mapaPrecarga(); \/\/ carpetas ya estaban en memoria, precargamos el mapa\r\n}\r\n\r\n\/\/ \u2500\u2500 Mapa de la Cripta \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\/\/ IMPORTANTE: la cabecera X-WP-Nonce solo debe enviarse si el nonce existe.\r\n\/\/ Enviarla vac\u00eda hace que WordPress devuelva 403 'Cookie check failed' a los\r\n\/\/ visitantes an\u00f3nimos, aunque el endpoint sea p\u00fablico.\r\nfunction cdhApiHeaders() {\r\n  return window.cdhNonce ? { 'X-WP-Nonce': window.cdhNonce } : {};\r\n}\r\nvar mapaHtmlCache    = null;  \/\/ HTML precargado\r\nvar mapaPromisaActiva = null; \/\/ Promesa en curso (evita doble carga)\r\n\r\n\/\/ Se llama en segundo plano al abrir el preview\r\nfunction mapaPrecarga() {\r\n  if (mapaHtmlCache !== null) return;\r\n  if (mapaPromisaActiva) return;\r\n  if (!mcCarpetas.length) return;\r\n\r\n  mapaPromisaActiva = Promise.all(\r\n    mcCarpetas.map(function(c) { return mapaCargarNodo(c); })\r\n  ).then(function(nodos) {\r\n    mapaHtmlCache = nodos;\r\n    mapaPromisaActiva = null;\r\n    \/\/ Si el modal est\u00e1 abierto, refrescarlo al instante\r\n    var modal = document.getElementById('mapaModal');\r\n    if (modal && modal.style.display !== 'none') {\r\n      mapaVolcarCache(document.getElementById('mapaContenido'));\r\n    }\r\n  }).catch(function() {\r\n    mapaPromisaActiva = null;\r\n  });\r\n}\r\n\r\nfunction abrirMapa() {\r\n  console.log('[CDH] Cripta v7 \u2014 compatible con el editor de Elementor');\r\n  var modal     = document.getElementById('mapaModal');\r\n  var contenido = document.getElementById('mapaContenido');\r\n  modal.style.display = 'flex';\r\n\r\n  \/\/ Checkbox solo para el propietario; para visitantes, t\u00edtulo informativo\r\n  var toggleWrap = document.getElementById('mapaTogglePublico');\r\n  var check      = document.getElementById('mapaCheckPublico');\r\n  var tituloPub  = document.getElementById('mapaTituloPublico');\r\n  var esPropietario = !expModoLectura;\r\n  if (toggleWrap && check) {\r\n    toggleWrap.style.display = esPropietario ? 'block' : 'none';\r\n    check.checked = mapaPublico;\r\n  }\r\n  if (tituloPub) tituloPub.style.display = esPropietario ? 'none' : 'block';\r\n\r\n  \/\/ Si hay cach\u00e9, pintar al instante\r\n  if (mapaHtmlCache !== null) {\r\n    mapaVolcarCache(contenido);\r\n    return;\r\n  }\r\n\r\n  contenido.innerHTML = '<div class=\"mapa-vacio\">Cargando mapa...<\/div>';\r\n\r\n  \/\/ Carga directa desde API \u2014 independiente de mcCarpetas y criptaModulos\r\n  fetch('\/index.php\/wp-json\/cdh\/v1\/carpetas?sep_id=' + cdhSepId, {\r\n    headers: cdhApiHeaders(),\r\n    credentials: 'same-origin',\r\n    cache: 'no-store'\r\n  })\r\n  .then(function(r) { return r.json(); })\r\n  .then(function(data) {\r\n    var raiz = Array.isArray(data) ? data : [];\r\n    if (!raiz.length) {\r\n      contenido.innerHTML = '<div class=\"mapa-vacio\">Esta cripta no tiene carpetas a\u00fan.<\/div>';\r\n      return;\r\n    }\r\n    return Promise.all(raiz.map(function(c) { return mapaCargarNodo(c); }))\r\n      .then(function(nodos) {\r\n        mapaHtmlCache = nodos;\r\n        mapaVolcarCache(contenido);\r\n      });\r\n  })\r\n  .catch(function() {\r\n    contenido.innerHTML = '<div class=\"mapa-vacio\">No se pudo cargar el mapa.<\/div>';\r\n  });\r\n}\r\n\r\nfunction mapaVolcarCache(contenido) {\r\n  contenido.innerHTML = '';\r\n  if (!mapaHtmlCache || !mapaHtmlCache.length) {\r\n    contenido.innerHTML = '<div class=\"mapa-vacio\">Esta cripta no tiene carpetas a\u00fan.<\/div>';\r\n    return;\r\n  }\r\n  mapaHtmlCache.forEach(function(nodoHtml) {\r\n    var wrap = document.createElement('div');\r\n    wrap.className = 'mapa-carpeta-raiz';\r\n    wrap.innerHTML = nodoHtml;\r\n    contenido.appendChild(wrap);\r\n  });\r\n}\r\n\r\nfunction cerrarMapa() {\r\n  document.getElementById('mapaModal').style.display = 'none';\r\n}\r\n\r\n\/\/ Recarga autom\u00e1tica del mapa cada 20 segundos en segundo plano\r\nsetInterval(function() {\r\n  if (!cdhSepId) return;\r\n  mapaHtmlCache = null;\r\n  mapaPromisaActiva = null;\r\n  mapaPrecarga();\r\n}, 20000);\r\n\r\nvar mapaPublico = false;\r\n\r\nfunction mapaGuardarPublico(valor) {\r\n  mapaPublico = valor;\r\n  if (!cdhSepId || !window.cdhNonce) return;\r\n  fetch('\/index.php\/wp-json\/cdh\/v1\/sepultura\/' + cdhSepId + '\/mapa-publico', {\r\n    method: 'POST',\r\n    headers: { 'Content-Type': 'application\/json', 'X-WP-Nonce': window.cdhNonce },\r\n    credentials: 'same-origin',\r\n    body: JSON.stringify({ mapa_publico: valor })\r\n  }).catch(function() {});\r\n}\r\n\r\nfunction mapaCargarPublico() {\r\n  if (!cdhSepId) return;\r\n  var headers = {};\r\n  if (window.cdhNonce) headers['X-WP-Nonce'] = window.cdhNonce;\r\n  fetch('\/index.php\/wp-json\/cdh\/v1\/sepultura\/' + cdhSepId + '\/mapa-publico', {\r\n    headers: headers,\r\n    credentials: 'same-origin'\r\n  })\r\n  .then(function(r) { return r.json(); })\r\n  .then(function(d) {\r\n    mapaPublico = !!(d && d.mapa_publico);\r\n    var check = document.getElementById('mapaCheckPublico');\r\n    if (check) check.checked = mapaPublico;\r\n    if (!window.cdhNonce) {\r\n      var btn = document.getElementById('mapaBtn');\r\n      if (btn) btn.style.display = mapaPublico ? 'flex' : 'none';\r\n    }\r\n    \/\/ Bot\u00f3n visible en la vista p\u00fablica real (visitante sin sesi\u00f3n) cuando el propietario activ\u00f3 el toggle\r\n    var btnPublico = document.getElementById('mapaBtnPublico');\r\n    if (btnPublico) btnPublico.style.display = (expModoLectura && mapaPublico) ? 'flex' : 'none';\r\n  })\r\n  .catch(function() {});\r\n}\r\n\r\ndocument.addEventListener('keydown', function(e) {\r\n  if (e.key === 'Escape') cerrarMapa();\r\n});\r\n\r\nfunction mapaEstadoBadge(estado) {\r\n  var letra = estado === 'abierta' ? 'A' : estado === 'cerrada' ? 'C' : 'O';\r\n  var cls   = estado === 'abierta' ? 'a' : estado === 'cerrada' ? 'c' : 'o';\r\n  return '<span class=\"mapa-estado-badge mapa-estado-' + cls + '\">' + letra + '<\/span>';\r\n}\r\n\r\n\/\/ Devuelve HTML de un nodo (carpeta) con sus hijos\r\nfunction mapaCargarNodo(c, nivel) {\r\n  nivel = nivel || 0;\r\n  return Promise.all([\r\n    \/\/ Subcarpetas\r\n    fetch('\/index.php\/wp-json\/cdh\/v1\/carpetas?sep_id=' + cdhSepId + '&parent_id=' + c.id, {\r\n      headers: cdhApiHeaders(),\r\n      credentials: 'same-origin',\r\n      cache: 'no-store'\r\n    }).then(function(r) { return r.json(); }).catch(function() { return []; }),\r\n    \/\/ Ficheros (conteo) \u2014 la ruta REST es \/archivos\/{carpeta_id} (ID en la ruta)\r\n    fetch('\/index.php\/wp-json\/cdh\/v1\/archivos\/' + c.id, {\r\n      headers: cdhApiHeaders(),\r\n      credentials: 'same-origin',\r\n      cache: 'no-store'\r\n    }).then(function(r) { return r.json(); }).catch(function() { return []; })\r\n  ]).then(function(results) {\r\n    var hijos   = Array.isArray(results[0]) ? results[0] : [];\r\n    var archivos = Array.isArray(results[1]) ? results[1] : (results[1] && results[1].archivos ? results[1].archivos : []);\r\n    var numArchivos = parseInt(archivos.length || (results[1] && (results[1].total || results[1].count)) || 0, 10) || 0;\r\n\r\n    var ficherosTxt = numArchivos > 0\r\n      ? '<span class=\"mapa-nodo-ficheros\">(' + numArchivos + ' Archivo' + (numArchivos !== 1 ? 's' : '') + ')<\/span>'\r\n      : '';\r\n\r\n    \/\/ Si la fecha ya llego, para el visitante esa carpeta esta abierta: el\r\n    \/\/ badge tiene que decir A y sobra la fecha. El propietario sigue viendo\r\n    \/\/ como la tiene marcada, con su fecha.\r\n    var liberadaMapa = cdhCarpetaLiberada(c);\r\n    var estadoMapa   = liberadaMapa ? 'abierta' : c.estado;\r\n\r\n    \/\/ La fecha de una carpeta CERRADA la ve todo el mundo: es justo lo que\r\n    \/\/ mantiene al visitante pendiente del dia. La de una OCULTA solo la ve el\r\n    \/\/ propietario: el visitante sabe que la carpeta esta ahi, pero no cuando\r\n    \/\/ se abrira.\r\n    var fechaMapa = '';\r\n    if (!liberadaMapa && c.fecha_apertura) {\r\n      if (c.estado === 'cerrada') {\r\n        fechaMapa = '<span class=\"mapa-nodo-fecha\">\ud83d\udd12 ' + formatFecha(c.fecha_apertura) + '<\/span>';\r\n      } else if (c.estado === 'oculta' && !expModoLectura) {\r\n        fechaMapa = '<span class=\"mapa-nodo-fecha\">\u23f3 ' + formatFecha(c.fecha_apertura) + '<\/span>';\r\n      }\r\n    }\r\n\r\n    \/\/ Una carpeta OCULTA no le cuenta nada al visitante: ni el nombre (que\r\n    \/\/ daria pistas del contenido y romperia la intriga), ni cuantos archivos\r\n    \/\/ guarda, ni que hay dentro. Solo que existe y que algun dia se abrira.\r\n    var sellada = !liberadaMapa && c.estado === 'oculta' && expModoLectura;\r\n\r\n    var nombreMapa = sellada\r\n      ? '<span class=\"mapa-nodo-nombre mapa-nodo-sellada\">\ud83d\udcc1<\/span>'\r\n      : '<span class=\"mapa-nodo-nombre\">\ud83d\udcc1 ' + escapeHtml(c.nombre) + '<\/span>';\r\n\r\n    var html = '<div class=\"mapa-nodo\">'\r\n      + mapaEstadoBadge(estadoMapa)\r\n      + nombreMapa\r\n      + fechaMapa\r\n      + (sellada ? '' : ficherosTxt)\r\n      + '<\/div>';\r\n\r\n    \/\/ Y tampoco se asoma a lo que lleva dentro: la rama se corta aqui.\r\n    if (sellada) return html;\r\n\r\n    if (!hijos.length) return html;\r\n\r\n    \/\/ Recursivo para cada hijo\r\n    return Promise.all(hijos.map(function(h) {\r\n      return mapaCargarNodo(h, nivel + 1);\r\n    })).then(function(hijosHtml) {\r\n      return html + '<div class=\"mapa-hijos\">' + hijosHtml.join('') + '<\/div>';\r\n    });\r\n  });\r\n}\r\n\r\n\/\/ Posiciones en localStorage por sep_id\r\nfunction pvGetPosKey() { return 'cdh_pv_pos_' + (cdhSepId || '0'); }\r\nfunction pvLoadPos() { try { return JSON.parse(localStorage.getItem(pvGetPosKey()) || '{}'); } catch(e) { return {}; } }\r\nfunction pvSavePos(id, x, y) { var pos = pvLoadPos(); pos[id] = {x:x,y:y}; localStorage.setItem(pvGetPosKey(), JSON.stringify(pos)); }\r\n\r\nfunction renderCarpetasEnPreview(contenedor, empty) {\r\n  var ahora = new Date(), visibles = 0;\r\n  \/\/ Base: posiciones de la cripta; si el usuario mueve en preview se sobreescriben con pvLoadPos\r\n  var criptaPos = criptaLoadPos();\r\n  var pvPos     = pvLoadPos();\r\n  var positions = {};\r\n  Object.keys(criptaPos).forEach(function(k) { positions[k] = criptaPos[k]; });\r\n  Object.keys(pvPos).forEach(function(k)     { positions[k] = pvPos[k]; });\r\n  var autoX = 30;\r\n  var autoY = Math.max(100, window.innerHeight - 180);\r\n\r\n  mcCarpetas.forEach(function(c) {\r\n    if (c.estado === 'oculta') {\r\n      if (!c.fecha_apertura || new Date(c.fecha_apertura) > ahora) return;\r\n    }\r\n    visibles++;\r\n    var colores = carpetaColores(c.estado, c.color);\r\n    var icoDataPv = (c.icono && mcIconosCat[c.icono]) ? mcIconosCat[c.icono] : null;\r\n    var esIconoPv = (c.tipo === 'icono') && icoDataPv;\r\n\r\n    var item = document.createElement('div');\r\n    item.className = 'c-carpeta-item';\r\n    item.dataset.pvId = c.id;\r\n\r\n    \/\/ La previsualizaci\u00f3n es la vista del visitante, as\u00ed que aqu\u00ed la fecha\r\n    \/\/ cumplida libera la carpeta igual que en la cripta p\u00fablica.\r\n    var liberadaPv = (c.estado === 'cerrada' || c.estado === 'oculta') && cdhFechaLlegada(c.fecha_apertura);\r\n\r\n    var lock = '';\r\n    if (!liberadaPv && c.estado === 'cerrada') lock = '<span class=\"' + (esIconoPv ? 'c-icono-grande-lock' : 'c-carpeta-lock') + '\">\ud83d\udd12<\/span>';\r\n    if (!liberadaPv && c.estado === 'oculta')  lock = '<span class=\"' + (esIconoPv ? 'c-icono-grande-lock' : 'c-carpeta-lock') + '\">\u23f3<\/span>';\r\n\r\n    var fechaHtml = '';\r\n    if (!liberadaPv && c.estado === 'cerrada' && c.fecha_apertura) {\r\n      fechaHtml = '<div class=\"c-carpeta-fecha\">Se abre el ' + formatFecha(c.fecha_apertura) + '<\/div>';\r\n    }\r\n\r\n    var iconoWrap;\r\n    if (esIconoPv) {\r\n      iconoWrap = '<div class=\"c-icono-grande\" style=\"position:relative;\">' + icoDataPv.svg + lock + '<\/div>';\r\n    } else {\r\n      var emSvgPv = (icoDataPv && c.icono !== 'carpeta-basica') ? icoDataPv.svg : '';\r\n      iconoWrap = '<div class=\"c-carpeta-icono-wrap\">' + carpetaSVG(colores[0], colores[1]) + (emSvgPv ? '<span class=\"c-carpeta-emoji\">' + emSvgPv + '<\/span>' : '') + lock + '<\/div>';\r\n    }\r\n\r\n    \/\/ Sin botones de edici\u00f3n en preview\r\n    item.innerHTML = iconoWrap\r\n      + '<div class=\"c-carpeta-nombre\">' + escapeHtml(c.nombre) + '<\/div>'\r\n      + fechaHtml;\r\n\r\n    \/\/ Posici\u00f3n guardada o auto-grid (misma l\u00f3gica que cripta)\r\n    var saved = positions[c.id];\r\n    if (saved) {\r\n      item.style.left = saved.x + 'px';\r\n      item.style.top  = saved.y + 'px';\r\n    } else {\r\n      item.style.left = autoX + 'px';\r\n      item.style.top  = autoY + 'px';\r\n      autoX += Math.min(140, Math.round(window.innerWidth * 0.10));\r\n      if (autoX > window.innerWidth - 120) { autoX = 30; autoY -= 130; }\r\n    }\r\n\r\n    \/\/ Click abre el explorador en modo solo lectura (igual que vista p\u00fablica)\r\n    (function(el, cData) {\r\n      el.style.cursor = 'pointer';\r\n      el.addEventListener('click', function() {\r\n        abrirExplorador(cData.id, cData.nombre, cData.estado, cData.fecha_apertura, cData.icono, cData.tipo, true);\r\n      });\r\n    })(item, c);\r\n\r\n    contenedor.appendChild(item);\r\n  });\r\n  if (!visibles) empty.style.display = 'block';\r\n}\r\n\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n\/\/ EXPLORADOR DE SUBCARPETAS\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n\r\nvar expPila         = [];   \/\/ [{id, nombre, estado, fecha_apertura, icono}]\r\nvar expSubIconoSel  = 'carpeta-basica';\r\nvar expSubColorSel  = 'verde';\r\nvar expSubEstadoSel = 'abierta';\r\nvar expSubModoEdicion = null;\r\nvar expModoLectura  = false; \/\/ true cuando se abre desde preview p\u00fablico\r\n\r\nfunction abrirExplorador(id, nombre, estado, fechaApertura, icono, tipo, soloLectura) {\r\n  \/\/ Las carpetas llaman con 6 argumentos, asi que soloLectura llega undefined\r\n  \/\/ y antes esto ponia expModoLectura a false: un visitante anonimo abria una\r\n  \/\/ carpeta y a partir de ahi la cripta le trataba como propietario. El modo\r\n  \/\/ lectura de la pagina manda siempre.\r\n  expModoLectura = criptaSoloLectura || !!soloLectura;\r\n  expPila = [{ id: id, nombre: nombre, estado: estado, fecha_apertura: fechaApertura, icono: icono || 'carpeta-basica', tipo: tipo || 'carpeta' }];\r\n  expRenderizar();\r\n  document.getElementById('expModal').classList.add('open');\r\n}\r\n\r\nfunction cerrarExplorador() {\r\n  document.getElementById('expModal').classList.remove('open');\r\n  expPila = [];\r\n  expModoLectura = criptaSoloLectura;\r\n}\r\n\r\nfunction expEntrar(id, nombre, estado, fechaApertura, icono) {\r\n  expPila.push({ id: id, nombre: nombre, estado: estado, fecha_apertura: fechaApertura, icono: icono || 'carpeta-basica' });\r\n  expRenderizar();\r\n}\r\n\r\nfunction expIrA(nivel) {\r\n  expPila = expPila.slice(0, nivel + 1);\r\n  expRenderizar();\r\n}\r\n\r\nfunction expSubir() {\r\n  if (expPila.length <= 1) return;\r\n  expCancelarForm._skipReset = false;\r\n  expCancelarForm();\r\n  expSubModoEdicion = null;\r\n  expPila.pop();\r\n  expRenderizar();\r\n}\r\n\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n\/\/ FECHA DE APERTURA DE LAS CARPETAS CERRADAS\r\n\/\/ Una carpeta 'cerrada' con fecha deja de estarlo para el visitante en cuanto\r\n\/\/ llega el dia: el servidor ya le sirve los archivos (cdh_servir_archivo del\r\n\/\/ modulo 03), asi que la cripta tiene que dejarle entrar sin que el\r\n\/\/ propietario tenga que tocar nada.\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n\r\n\/\/ 'AAAA-MM-DD' o 'AAAA-MM-DD hh:mm:ss' -> Date a las 00:00 (hora local), o null\r\nfunction cdhFechaApertura(fechaStr) {\r\n  if (!fechaStr) return null;\r\n  var t = String(fechaStr).trim().replace(' ', 'T');\r\n  var d = new Date(t.length > 10 ? t : t + 'T00:00:00');\r\n  if (isNaN(d.getTime())) return null;\r\n  d.setHours(0, 0, 0, 0);\r\n  return d;\r\n}\r\n\r\nfunction cdhHoy0() { var h = new Date(); h.setHours(0, 0, 0, 0); return h; }\r\n\r\nfunction cdhFechaLlegada(fechaStr) {\r\n  var d = cdhFechaApertura(fechaStr);\r\n  if (!d) return false;\r\n  return cdhHoy0().getTime() >= d.getTime();\r\n}\r\n\r\nfunction cdhDiasHasta(fechaStr) {\r\n  var d = cdhFechaApertura(fechaStr);\r\n  if (!d) return null;\r\n  return Math.round((d.getTime() - cdhHoy0().getTime()) \/ 86400000);\r\n}\r\n\r\n\/\/ true si el VISITANTE ya puede entrar aunque siga marcada cerrada\/oculta\r\nfunction cdhCarpetaLiberada(c) {\r\n  if (!c || !expModoLectura) return false;\r\n  if (c.estado !== 'cerrada' && c.estado !== 'oculta') return false;\r\n  return cdhFechaLlegada(c.fecha_apertura);\r\n}\r\n\r\n\/\/ \u2500\u2500 Recordatorio de calendario \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\/\/ No guardamos nada ni pedimos el correo a nadie: el aviso se lo lleva puesto\r\n\/\/ el visitante en su propio calendario (Google, o un .ics para Apple\/Outlook).\r\nvar cdhRecordatorio = null;\r\n\r\nfunction cdhRecordatorioPrep(nombreCarpeta, fechaStr) {\r\n  var d = cdhFechaApertura(fechaStr);\r\n  if (!d) { cdhRecordatorio = null; return false; }\r\n  var difEl = document.getElementById('nombreDifunto');\r\n  cdhRecordatorio = {\r\n    carpeta: nombreCarpeta || 'Carpeta',\r\n    difunto: difEl ? (difEl.textContent || '').trim() : '',\r\n    fecha:   d,\r\n    url:     window.location.href.split('#')[0]\r\n  };\r\n  return true;\r\n}\r\n\r\nfunction cdhRecStamp(d) {\r\n  return d.getFullYear() + ('0' + (d.getMonth() + 1)).slice(-2) + ('0' + d.getDate()).slice(-2);\r\n}\r\n\r\nfunction cdhRecTitulo() {\r\n  return 'Se abre la carpeta ' + cdhRecordatorio.carpeta\r\n       + (cdhRecordatorio.difunto ? ' - ' + cdhRecordatorio.difunto : '');\r\n}\r\n\r\nfunction cdhRecDetalle() {\r\n  return 'Hoy se abre la carpeta \"' + cdhRecordatorio.carpeta + '\" en la cripta'\r\n       + (cdhRecordatorio.difunto ? ' de ' + cdhRecordatorio.difunto : '')\r\n       + ' (Cementerio Digital Hispano).\\n\\n' + cdhRecordatorio.url;\r\n}\r\n\r\nfunction cdhRecordatorioGoogle() {\r\n  if (!cdhRecordatorio) return;\r\n  var ini = cdhRecordatorio.fecha;\r\n  var fin = new Date(ini.getTime() + 86400000);\r\n  var u = 'https:\/\/calendar.google.com\/calendar\/render?action=TEMPLATE'\r\n        + '&text='    + encodeURIComponent(cdhRecTitulo())\r\n        + '&dates='   + cdhRecStamp(ini) + '\/' + cdhRecStamp(fin)\r\n        + '&details=' + encodeURIComponent(cdhRecDetalle());\r\n  window.open(u, '_blank', 'noopener');\r\n}\r\n\r\nfunction cdhRecordatorioIcs() {\r\n  if (!cdhRecordatorio) return;\r\n  var ini = cdhRecordatorio.fecha;\r\n  var fin = new Date(ini.getTime() + 86400000);\r\n  var esc = function(s) {\r\n    return String(s).replace(\/\\\\\/g, '\\\\\\\\').replace(\/;\/g, '\\\\;')\r\n                    .replace(\/,\/g, '\\\\,').replace(\/\\r?\\n\/g, '\\\\n');\r\n  };\r\n  var uid   = 'cdh-' + cdhRecStamp(ini) + '-' + Math.random().toString(36).slice(2) + '@cementeriodigitalhispano.com';\r\n  var sello = new Date().toISOString().replace(\/[-:]\/g, '').split('.')[0] + 'Z';\r\n  var ics = [\r\n    'BEGIN:VCALENDAR',\r\n    'VERSION:2.0',\r\n    'PRODID:-\/\/CDH\/\/Cementerio Digital Hispano\/\/ES',\r\n    'CALSCALE:GREGORIAN',\r\n    'METHOD:PUBLISH',\r\n    'BEGIN:VEVENT',\r\n    'UID:' + uid,\r\n    'DTSTAMP:' + sello,\r\n    'DTSTART;VALUE=DATE:' + cdhRecStamp(ini),\r\n    'DTEND;VALUE=DATE:' + cdhRecStamp(fin),\r\n    'SUMMARY:' + esc(cdhRecTitulo()),\r\n    'DESCRIPTION:' + esc(cdhRecDetalle()),\r\n    'URL:' + cdhRecordatorio.url,\r\n    'BEGIN:VALARM',\r\n    'TRIGGER:-P1D',\r\n    'ACTION:DISPLAY',\r\n    'DESCRIPTION:' + esc(cdhRecTitulo()),\r\n    'END:VALARM',\r\n    'END:VEVENT',\r\n    'END:VCALENDAR'\r\n  ].join('\\r\\n');\r\n  try {\r\n    var blob = new Blob([ics], { type: 'text\/calendar;charset=utf-8' });\r\n    var url  = URL.createObjectURL(blob);\r\n    var a    = document.createElement('a');\r\n    a.href = url;\r\n    a.download = 'recordatorio-cdh.ics';\r\n    document.body.appendChild(a);\r\n    a.click();\r\n    setTimeout(function() { URL.revokeObjectURL(url); if (a.parentNode) a.parentNode.removeChild(a); }, 800);\r\n  } catch (e) {\r\n    window.alert('Tu navegador no ha permitido descargar el recordatorio.');\r\n  }\r\n}\r\n\r\n\/\/ Aviso de carpeta cerrada que ve el visitante al pulsarla\r\nfunction cdhCerradaHtml(c) {\r\n  var html = '<div class=\"cdh-exp-cerrada-msg\">'\r\n    + '<div class=\"cdh-exp-cerrada-ico\">&#128274;<\/div>'\r\n    + '<div class=\"cdh-exp-cerrada-titulo\">Carpeta cerrada<\/div>';\r\n\r\n  if (c.fecha_apertura && cdhRecordatorioPrep(c.nombre, c.fecha_apertura)) {\r\n    var dias = cdhDiasHasta(c.fecha_apertura);\r\n    var cuenta = (dias > 1) ? 'Faltan ' + dias + ' dias'\r\n               : (dias === 1) ? 'Se abre manana'\r\n               : 'Se abre hoy';\r\n    html += '<div class=\"cdh-exp-cerrada-texto\">Su contenido permanece protegido hasta el dia:<\/div>'\r\n      + '<div class=\"cdh-exp-cerrada-fecha\">' + formatFecha(c.fecha_apertura) + '<\/div>'\r\n      + '<div class=\"cdh-exp-cerrada-cuenta\">' + cuenta + '<\/div>'\r\n      + '<div class=\"cdh-exp-recordar\">'\r\n        + '<span class=\"cdh-exp-recordar-btn\" id=\"expRecGoogle\">&#128197; Avisarme en Google Calendar<\/span>'\r\n        + '<span class=\"cdh-exp-recordar-btn\" id=\"expRecIcs\">&#11015; Descargar recordatorio<\/span>'\r\n      + '<\/div>'\r\n      + '<div class=\"cdh-exp-recordar-nota\">El aviso se guarda en tu propio calendario. No recogemos ningun dato tuyo.<\/div>';\r\n  } else {\r\n    html += '<div class=\"cdh-exp-cerrada-texto\">Esta carpeta esta cerrada por el propietario.'\r\n      + '<br><br>Su contenido permanece protegido.<\/div>';\r\n  }\r\n\r\n  return html + '<\/div>';\r\n}\r\n\r\n\/\/ Elementor se lleva mal con los botones nativos, asi que los dos avisos son\r\n\/\/ spans y se enganchan aqui con addEventListener.\r\nfunction cdhCerradaBind() {\r\n  var g = document.getElementById('expRecGoogle');\r\n  if (g) g.addEventListener('click', cdhRecordatorioGoogle);\r\n  var i = document.getElementById('expRecIcs');\r\n  if (i) i.addEventListener('click', cdhRecordatorioIcs);\r\n}\r\n\r\nfunction expRenderizar() {\r\n  var actual = expPila[expPila.length - 1];\r\n  var icoExp = (actual.icono && actual.icono !== 'carpeta-basica' && mcIconosCat[actual.icono]) ? mcIconosCat[actual.icono] : null;\r\n\r\n  \/\/ Bot\u00f3n subir: visible solo si hay m\u00e1s de un nivel en la pila\r\n  var backBtn = document.getElementById('expBack');\r\n  if (backBtn) backBtn.style.display = expPila.length > 1 ? 'inline-block' : 'none';\r\n\r\n  \/\/ T\u00edtulo\r\n  var tituloEl = document.getElementById('expTitulo');\r\n  if (icoExp && icoExp.svg) {\r\n    tituloEl.innerHTML = '<span style=\"display:inline-block;width:18px;height:18px;vertical-align:middle;margin-right:5px;\">' + icoExp.svg + '<\/span>' + escapeHtml(actual.nombre);\r\n  } else {\r\n    tituloEl.textContent = actual.nombre;\r\n  }\r\n\r\n  \/\/ Breadcrumb\r\n  var bc = document.getElementById('expBreadcrumb');\r\n  bc.innerHTML = '';\r\n  expPila.forEach(function(nivel, i) {\r\n    if (i > 0) {\r\n      var sep = document.createElement('span');\r\n      sep.className = 'cdh-exp-crumb-sep';\r\n      sep.textContent = '\u203a';\r\n      bc.appendChild(sep);\r\n    }\r\n    var crumb = document.createElement('span');\r\n    crumb.className = 'cdh-exp-crumb' + (i === expPila.length - 1 ? ' activo' : '');\r\n    crumb.textContent = nivel.nombre;\r\n    if (i < expPila.length - 1) {\r\n      crumb.onclick = (function(idx) { return function() { expIrA(idx); }; })(i);\r\n    }\r\n    bc.appendChild(crumb);\r\n  });\r\n\r\n  \/\/ Si la carpeta est\u00e1 cerrada \u2192 mensaje especial (solo para visitantes;\r\n  \/\/ el propietario siempre puede entrar a gestionar).\r\n  \/\/ Si ten\u00eda fecha de apertura y esa fecha ya lleg\u00f3, el visitante entra sin\r\n  \/\/ m\u00e1s: el servidor ya le sirve los archivos, as\u00ed que seguir ense\u00f1\u00e1ndole el\r\n  \/\/ candado era mentirle.\r\n  if (expModoLectura && actual.estado === 'cerrada' && !cdhFechaLlegada(actual.fecha_apertura)) {\r\n    document.getElementById('expAcciones').style.display = 'none';\r\n    document.getElementById('expContenido').innerHTML = cdhCerradaHtml(actual);\r\n    cdhCerradaBind();\r\n    return;\r\n  }\r\n\r\n  document.getElementById('expAcciones').style.display = expModoLectura ? 'none' : 'flex';\r\n  expCargarHijos(actual.id);\r\n}\r\n\r\nfunction expCargarHijos(parentId) {\r\n  var contenido = document.getElementById('expContenido');\r\n  contenido.innerHTML = '<div class=\"cdh-exp-vacio\" style=\"opacity:0.4;\">Cargando...<\/div>';\r\n\r\n  var hdrs3 = {}; if (window.cdhNonce) hdrs3['X-WP-Nonce'] = window.cdhNonce;\r\n  fetch('\/index.php\/wp-json\/cdh\/v1\/carpetas?sep_id=' + cdhSepId + '&parent_id=' + parentId, {\r\n    headers: hdrs3, credentials: 'same-origin'\r\n  })\r\n  .then(function(r) { return r.json(); })\r\n  .then(function(data) { expRenderHijos(data || [], parentId); })\r\n  .catch(function() {\r\n    contenido.innerHTML = '<div class=\"cdh-exp-vacio\">Error al cargar. Int\u00e9ntalo de nuevo.<\/div>';\r\n  });\r\n}\r\n\r\nfunction expRenderHijos(hijos, parentId) {\r\n  var contenido = document.getElementById('expContenido');\r\n  contenido.innerHTML = '';\r\n\r\n  \/\/ Si no hay subcarpetas \u2192 mostrar solo zona de archivos (comportamiento original)\r\n  if (!hijos.length) {\r\n    legadoRenderZona(parentId, contenido);\r\n    return;\r\n  }\r\n\r\n  \/\/ Si hay subcarpetas \u2192 mostrarlas Y tambi\u00e9n la zona de archivos debajo\r\n  var grid = document.createElement('div');\r\n  grid.className = 'cdh-exp-grid';\r\n\r\n  hijos.forEach(function(c) {\r\n    var colores = carpetaColores(c.estado, c.color);\r\n\r\n    \/\/ Si el visitante ya tiene derecho a entrar (fecha cumplida), fuera\r\n    \/\/ candado y fuera fecha: para \u00e9l esa subcarpeta est\u00e1 abierta.\r\n    var liberadaEx = cdhCarpetaLiberada(c);\r\n\r\n    var lock = '';\r\n    if (!liberadaEx && c.estado === 'cerrada') lock = '<span class=\"cdh-exp-carpeta-lock\">\ud83d\udd12<\/span>';\r\n    if (!liberadaEx && c.estado === 'oculta')  lock = '<span class=\"cdh-exp-carpeta-lock\">\u23f3<\/span>';\r\n\r\n    var fechaHtml = '';\r\n    if (!liberadaEx && c.estado === 'cerrada' && c.fecha_apertura) {\r\n      fechaHtml = '<div class=\"cdh-exp-carpeta-fecha\">Se abre el ' + formatFecha(c.fecha_apertura) + '<\/div>';\r\n    }\r\n\r\n    var item = document.createElement('div');\r\n    item.className = 'cdh-exp-carpeta';\r\n    item.innerHTML =\r\n      (function() {\r\n        var icoDataEx = (c.icono && mcIconosCat[c.icono]) ? mcIconosCat[c.icono] : null;\r\n        var esIconoEx = (c.tipo === 'icono') && icoDataEx;\r\n        if (esIconoEx) {\r\n          return '<div class=\"cdh-exp-carpeta-wrap\" style=\"display:flex;align-items:center;justify-content:center;\">'\r\n            + '<div style=\"width:clamp(42px,4.2vw,64px);height:clamp(42px,4.2vw,64px);\">' + icoDataEx.svg + '<\/div>'\r\n            + lock + '<\/div>';\r\n        }\r\n        var emEx = (icoDataEx && c.icono !== 'carpeta-basica') ? icoDataEx.svg : '';\r\n        return '<div class=\"cdh-exp-carpeta-wrap\">'\r\n          + carpetaSVG(colores[0], colores[1])\r\n          + (emEx ? '<span class=\"cdh-exp-carpeta-emoji\">' + emEx + '<\/span>' : '')\r\n          + lock + '<\/div>';\r\n      })()\r\n      + '<div class=\"cdh-exp-carpeta-nombre\">' + escapeHtml(c.nombre) + '<\/div>'\r\n      + fechaHtml\r\n      + (expModoLectura ? '' :\r\n          '<div class=\"cdh-exp-carpeta-btns\">'\r\n          + '<div class=\"cdh-exp-carpeta-btn\" title=\"Editar\" onclick=\"expEditarSubcarpeta(' + c.id + ',event)\">\u270f\ufe0f<\/div>'\r\n          + '<div class=\"cdh-exp-carpeta-btn danger\" title=\"Borrar\" onclick=\"expBorrarSubcarpeta(' + c.id + ',\\'' + escapeHtml(c.nombre) + '\\',event)\">\ud83d\uddd1<\/div>'\r\n          + '<\/div>'\r\n        );\r\n\r\n    item.addEventListener('click', function(e) {\r\n      if (e.target.closest('.cdh-exp-carpeta-btn')) return;\r\n      expEntrar(c.id, c.nombre, c.estado, c.fecha_apertura, c.icono);\r\n    });\r\n\r\n    grid.appendChild(item);\r\n  });\r\n\r\n  contenido.appendChild(grid);\r\n\r\n  \/\/ Separador visual\r\n  var sep = document.createElement('div');\r\n  sep.style.cssText = 'margin:14px 0 6px; border-top:1px solid rgba(200,160,60,0.15);';\r\n  contenido.appendChild(sep);\r\n\r\n  \/\/ Zona de archivos a continuaci\u00f3n \u2014 legadoRenderZona escribe en contenido\r\n  \/\/ pero necesita un nodo limpio sin hijos previos, as\u00ed que le pasamos un wrapper\r\n  var wrapper = document.createElement('div');\r\n  contenido.appendChild(wrapper);\r\n  legadoRenderZona(parentId, wrapper);\r\n}\r\n\r\n\/\/ \u2500\u2500 Formulario nueva \/ editar subcarpeta \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction expNuevaSubcarpeta() {\r\n  if (document.getElementById('expFormInline')) return; \/\/ evitar duplicado\r\n  expSubModoEdicion = null;\r\n  expSubIconoSel    = 'carpeta-basica';\r\n  expSubColorSel    = 'verde';\r\n  expSubEstadoSel   = 'abierta';\r\n  expInyectarForm('Nueva subcarpeta', 'Crear subcarpeta');\r\n}\r\n\r\nfunction expInyectarForm(tituloForm, labelBoton) {\r\n  var contenido = document.getElementById('expContenido');\r\n\r\n  var formEl = document.createElement('div');\r\n  formEl.className = 'cdh-exp-form';\r\n  formEl.id = 'expFormInline';\r\n  formEl.innerHTML =\r\n    '<div class=\"cdh-exp-form-titulo\">' + tituloForm + '<\/div>'\r\n\r\n    + '<div class=\"cdh-mc-campo\">'\r\n      + '<label class=\"cdh-mc-label\">Nombre<\/label>'\r\n      + '<input type=\"text\" class=\"cdh-mc-input\" id=\"expSubNombre\" placeholder=\"Ej: Ceremonia\" maxlength=\"60\">'\r\n    + '<\/div>'\r\n\r\n    + '<div class=\"cdh-mc-campo\">'\r\n      + '<label class=\"cdh-mc-label\">Color<\/label>'\r\n      + '<div class=\"cdh-color-grid\" id=\"expSubColorGrid\"><\/div>'\r\n    + '<\/div>'\r\n\r\n    + '<div class=\"cdh-mc-campo\">'\r\n      + '<label class=\"cdh-mc-label\">Icono<\/label>'\r\n      + '<div class=\"cdh-mc-iconos-grid\" id=\"expSubIconosGrid\"><\/div>'\r\n    + '<\/div>'\r\n\r\n    + '<div class=\"cdh-mc-campo\">'\r\n      + '<label class=\"cdh-mc-label\">Estado<\/label>'\r\n      + '<div class=\"cdh-mc-estados\" id=\"expSubEstados\">'\r\n        + '<div class=\"cdh-mc-estado-opt sel\" data-estado=\"abierta\" onclick=\"expSelEstado(\\'abierta\\',this)\">'\r\n          + '<span class=\"estado-ico\">\ud83d\udd13<\/span>'\r\n          + '<div class=\"estado-nombre\">Abierta<\/div>'\r\n          + '<div class=\"estado-desc\">Visible para todos<\/div>'\r\n        + '<\/div>'\r\n        + '<div class=\"cdh-mc-estado-opt\" data-estado=\"cerrada\" onclick=\"expSelEstado(\\'cerrada\\',this)\">'\r\n          + '<span class=\"estado-ico\">\ud83d\udd12<\/span>'\r\n          + '<div class=\"estado-nombre\">Cerrada<\/div>'\r\n          + '<div class=\"estado-desc\">Se ve con candado<\/div>'\r\n        + '<\/div>'\r\n        + '<div class=\"cdh-mc-estado-opt\" data-estado=\"oculta\" onclick=\"expSelEstado(\\'oculta\\',this)\">'\r\n          + '<span class=\"estado-ico\">\u23f3<\/span>'\r\n          + '<div class=\"estado-nombre\">Oculta<\/div>'\r\n          + '<div class=\"estado-desc\">Invisible hasta la fecha<\/div>'\r\n        + '<\/div>'\r\n      + '<\/div>'\r\n    + '<\/div>'\r\n\r\n    + '<div class=\"cdh-mc-fecha-wrap\" id=\"expSubFechaWrap\">'\r\n      + '<label class=\"cdh-mc-label\" id=\"expSubFechaLabel\">Fecha de apertura<\/label>'\r\n      + '<input type=\"date\" class=\"cdh-mc-input\" id=\"expSubFecha\">'\r\n    + '<\/div>'\r\n\r\n    + '<div class=\"cdh-exp-aviso\" id=\"expSubAviso\"><\/div>'\r\n\r\n    + '<div class=\"cdh-mc-form-btns\" style=\"margin-top:14px;\">'\r\n      + '<button class=\"cdh-mc-btn cancelar\" type=\"button\" onclick=\"expCancelarForm()\">Cancelar<\/button>'\r\n      + '<button class=\"cdh-mc-btn guardar\" type=\"button\" id=\"expSubBtnGuardar\" onclick=\"expGuardarSubcarpeta()\">' + labelBoton + '<\/button>'\r\n    + '<\/div>';\r\n\r\n  contenido.appendChild(formEl);\r\n\r\n  \/\/ Evitar que clics dentro del formulario propaguen hacia el grid\r\n  formEl.addEventListener('click', function(e) { e.stopPropagation(); });\r\n  formEl.addEventListener('mousedown', function(e) { e.stopPropagation(); });\r\n\r\n  \/\/ Poblar grid de colores\r\n  renderColorGrid('expSubColorGrid', expSubColorSel, function(k) { expSubColorSel = k; });\r\n\r\n  \/\/ Poblar grid de iconos\r\n  var grid = document.getElementById('expSubIconosGrid');\r\n  if (grid && Object.keys(mcIconosCat).length) {\r\n    Object.entries(mcIconosCat).forEach(function(entry) {\r\n      var key = entry[0], ico = entry[1];\r\n      var div = document.createElement('div');\r\n      div.className = 'cdh-mc-icono-opt' + (key === expSubIconoSel ? ' sel' : '');\r\n      div.dataset.key = key;\r\n      div.innerHTML = '<span class=\"cdh-icono-img\">' + (ico.svg||'') + '<\/span><span>' + ico.label + '<\/span>';\r\n      div.onclick = function() {\r\n        expSubIconoSel = key;\r\n        grid.querySelectorAll('.cdh-mc-icono-opt').forEach(function(el) { el.classList.remove('sel'); });\r\n        div.classList.add('sel');\r\n      };\r\n      grid.appendChild(div);\r\n    });\r\n  }\r\n\r\n  \/\/ Scroll y foco con delay para que el DOM se asiente\r\n  setTimeout(function() {\r\n    var input = document.getElementById('expSubNombre');\r\n    if (input) {\r\n      contenido.scrollTop = contenido.scrollHeight;\r\n      input.focus();\r\n    }\r\n  }, 50);\r\n}\r\n\r\nfunction expSelEstado(estado, el) {\r\n  expSubEstadoSel = estado;\r\n  var wrap  = document.getElementById('expSubFechaWrap');\r\n  var label = document.getElementById('expSubFechaLabel');\r\n  document.querySelectorAll('#expSubEstados .cdh-mc-estado-opt').forEach(function(e) { e.classList.remove('sel'); });\r\n  el.classList.add('sel');\r\n  if (estado === 'abierta') {\r\n    wrap.classList.remove('visible');\r\n  } else {\r\n    wrap.classList.add('visible');\r\n    label.textContent = estado === 'oculta' ? 'Fecha en que aparecer\u00e1' : 'Fecha de apertura';\r\n  }\r\n}\r\n\r\nfunction expCancelarForm() {\r\n  var f = document.getElementById('expFormInline');\r\n  if (f) f.remove();\r\n  \/\/ Solo reseteamos expSubModoEdicion si el usuario cancela expl\u00edcitamente,\r\n  \/\/ no desde expEditarSubcarpeta (que lo gestiona \u00e9l mismo para no perder el id)\r\n  if (!expCancelarForm._skipReset) expSubModoEdicion = null;\r\n  expCancelarForm._skipReset = false;\r\n}\r\n\r\nfunction expGuardarSubcarpeta() {\r\n  var nombre = (document.getElementById('expSubNombre').value || '').trim();\r\n  var fechaEl = document.getElementById('expSubFecha');\r\n  var fecha   = fechaEl ? fechaEl.value : '';\r\n  var aviso   = document.getElementById('expSubAviso');\r\n  aviso.className = 'cdh-exp-aviso';\r\n\r\n  if (!nombre) {\r\n    aviso.textContent = 'El nombre es obligatorio.';\r\n    aviso.className = 'cdh-exp-aviso error';\r\n    return;\r\n  }\r\n\r\n  var actual = expPila[expPila.length - 1];\r\n  var url    = expSubModoEdicion\r\n    ? '\/index.php\/wp-json\/cdh\/v1\/carpetas\/' + expSubModoEdicion\r\n    : '\/index.php\/wp-json\/cdh\/v1\/carpetas';\r\n  var method = expSubModoEdicion ? 'PUT' : 'POST';\r\n  var body   = {\r\n    sep_id:         cdhSepId,\r\n    nombre:         nombre,\r\n    icono:          expSubIconoSel,\r\n    color:          expSubColorSel,\r\n    estado:         expSubEstadoSel,\r\n    \/\/ Cadena vac\u00eda = \"borra la fecha\"; si no se manda el campo, el servidor\r\n    \/\/ conserva la que hubiera (ver cdh_editar_carpeta en el m\u00f3dulo 03).\r\n    fecha_apertura: (expSubEstadoSel !== 'abierta' && fecha) ? fecha : ''\r\n  };\r\n  if (!expSubModoEdicion) body.parent_id = actual.id;\r\n\r\n  var btn = document.getElementById('expSubBtnGuardar');\r\n  btn.disabled = true;\r\n\r\n  fetch(url, {\r\n    method: method,\r\n    headers: { 'Content-Type': 'application\/json', 'X-WP-Nonce': window.cdhNonce },\r\n    credentials: 'same-origin',\r\n    body: JSON.stringify(body)\r\n  })\r\n  .then(function(r) { return r.json(); })\r\n  .then(function(data) {\r\n    btn.disabled = false;\r\n    if (data.code) {\r\n      aviso.textContent = data.message || 'Error al guardar.';\r\n      aviso.className = 'cdh-exp-aviso error';\r\n      return;\r\n    }\r\n    expCancelarForm();\r\n    expSubModoEdicion = null;\r\n    mapaHtmlCache = null;\r\n    mapaPrecarga();\r\n    expCargarHijos(actual.id);\r\n  })\r\n  .catch(function() {\r\n    btn.disabled = false;\r\n    aviso.textContent = 'Error de conexi\u00f3n.';\r\n    aviso.className = 'cdh-exp-aviso error';\r\n  });\r\n}\r\n\r\nfunction expEditarSubcarpeta(id, e) {\r\n  if (e) e.stopPropagation();\r\n  var actual = expPila[expPila.length - 1];\r\n  fetch('\/index.php\/wp-json\/cdh\/v1\/carpetas?sep_id=' + cdhSepId + '&parent_id=' + actual.id, {\r\n    headers: cdhApiHeaders(), credentials: 'same-origin'\r\n  })\r\n  .then(function(r) { return r.json(); })\r\n  .then(function(hijos) {\r\n    var c = (hijos || []).find(function(x) { return x.id == id; });\r\n    if (!c) return;\r\n    expSubModoEdicion = id;\r\n    expSubIconoSel    = c.icono;\r\n    expSubColorSel    = c.color || 'verde';\r\n    expSubEstadoSel   = c.estado;\r\n\r\n    \/\/ Si el form ya existe lo quitamos primero (sin resetear expSubModoEdicion)\r\n    expCancelarForm._skipReset = true;\r\n    expCancelarForm();\r\n    expInyectarForm('Editar subcarpeta', 'Guardar cambios');\r\n\r\n    document.getElementById('expSubNombre').value = c.nombre;\r\n\r\n    \/\/ Marcar color\r\n    renderColorGrid('expSubColorGrid', expSubColorSel, function(k) { expSubColorSel = k; });\r\n\r\n    \/\/ Marcar icono\r\n    var grid = document.getElementById('expSubIconosGrid');\r\n    if (grid) grid.querySelectorAll('.cdh-mc-icono-opt').forEach(function(el) {\r\n      el.classList.toggle('sel', el.dataset.key === c.icono);\r\n    });\r\n    \/\/ Marcar estado\r\n    document.querySelectorAll('#expSubEstados .cdh-mc-estado-opt').forEach(function(el) {\r\n      el.classList.toggle('sel', el.dataset.estado === c.estado);\r\n    });\r\n    if (c.estado !== 'abierta') {\r\n      document.getElementById('expSubFechaWrap').classList.add('visible');\r\n      if (c.fecha_apertura) {\r\n        document.getElementById('expSubFecha').value = c.fecha_apertura.split(' ')[0];\r\n      }\r\n    }\r\n  });\r\n}\r\n\r\nfunction expBorrarSubcarpeta(id, nombre, e) {\r\n  if (e) e.stopPropagation();\r\n  cdhConfirm(\r\n    'Borrar subcarpeta',\r\n    '\u00bfBorrar <strong>\"' + escapeHtml(nombre) + '\"<\/strong>?<br><br>Se eliminar\u00e1n tambi\u00e9n todas sus subcarpetas.',\r\n    '\ud83d\uddd1', 'Borrar',\r\n    function(ok) {\r\n      if (!ok) return;\r\n      var actual = expPila[expPila.length - 1];\r\n      fetch('\/index.php\/wp-json\/cdh\/v1\/carpetas\/' + id, {\r\n        method: 'DELETE',\r\n        headers: { 'X-WP-Nonce': window.cdhNonce },\r\n        credentials: 'same-origin'\r\n      })\r\n      .then(function() {\r\n        mapaHtmlCache = null;\r\n        mapaPrecarga();\r\n        expCargarHijos(actual.id);\r\n      })\r\n      .catch(function() { alert('Error al borrar.'); });\r\n    }\r\n  );\r\n}\r\n\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n\/\/ SISTEMA DE ARCHIVOS \u2014 LEGADO\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n\r\nvar legadoEsPropietario = true; \/\/ en la cripta del due\u00f1o siempre true\r\nvar lbArchivos = [];   \/\/ lista de archivos de la carpeta actual\r\nvar lbIndice   = 0;    \/\/ \u00edndice del archivo abierto en el lightbox\r\n\r\n\/\/ Iconos por categor\u00eda\r\nfunction legadoIcono(categoria, mime) {\r\n  if (categoria === 'imagen') return '\ud83d\uddbc\ufe0f';\r\n  if (categoria === 'video')  return '\ud83c\udfac';\r\n  if (categoria === 'audio')  return '\ud83c\udfb5';\r\n  if (categoria === 'pdf')    return '\ud83d\udcd5';\r\n  if (categoria === 'texto')  return '\ud83d\udcc4';\r\n  if (mime && mime.includes('zip'))  return '\ud83d\udddc\ufe0f';\r\n  if (mime && mime.includes('word')) return '\ud83d\udcdd';\r\n  if (mime && mime.includes('excel'))return '\ud83d\udcca';\r\n  return '\ud83d\udcce';\r\n}\r\n\r\n\/\/ Tama\u00f1o legible\r\nfunction legadoTamano(bytes) {\r\n  if (bytes < 1024)           return bytes + ' B';\r\n  if (bytes < 1024*1024)      return (bytes\/1024).toFixed(1) + ' KB';\r\n  if (bytes < 1024*1024*1024) return (bytes\/1024\/1024).toFixed(1) + ' MB';\r\n  return (bytes\/1024\/1024\/1024).toFixed(2) + ' GB';\r\n}\r\n\r\n\/\/ \u2500\u2500 Renderiza la zona de archivos dentro del explorador \u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction legadoRenderZona(carpetaId, contenedorEl) {\r\n  if (expModoLectura) {\r\n    \/\/ Solo lectura: solo el grid de archivos, sin zona de subida\r\n    contenedorEl.innerHTML = '<div class=\"cdh-archivos-grid\" id=\"legGrid\"><\/div>';\r\n    legCargarArchivos(carpetaId);\r\n    return;\r\n  }\r\n\r\n  \/\/ Zona de drop + grid de archivos\r\n  var html =\r\n    '<div class=\"cdh-drop-zona\" id=\"legDropZona\" onclick=\"document.getElementById(\\'legFileInput\\').click()\">'\r\n      + '<div class=\"cdh-drop-ico\">\ud83d\udcc2<\/div>'\r\n      + '<div class=\"cdh-drop-txt\">Arrastra archivos aqu\u00ed<br>o <span>haz clic para seleccionarlos<\/span><\/div>'\r\n    + '<\/div>'\r\n    + '<input type=\"file\" id=\"legFileInput\" multiple style=\"display:none\" onchange=\"legSubirArchivos(' + carpetaId + ',this.files)\">'\r\n    + '<div class=\"cdh-upload-progreso\" id=\"legProgreso\">'\r\n      + '<div class=\"cdh-upload-barra-wrap\"><div class=\"cdh-upload-barra\" id=\"legBarra\"><\/div><\/div>'\r\n      + '<div class=\"cdh-upload-estado\" id=\"legEstado\"><\/div>'\r\n    + '<\/div>'\r\n    + '<div class=\"cdh-archivos-grid\" id=\"legGrid\"><\/div>';\r\n\r\n  contenedorEl.innerHTML = html;\r\n\r\n  \/\/ Drag & drop\r\n  var drop = document.getElementById('legDropZona');\r\n  drop.addEventListener('dragover', function(e) { e.preventDefault(); drop.classList.add('drag'); });\r\n  drop.addEventListener('dragleave', function() { drop.classList.remove('drag'); });\r\n  drop.addEventListener('drop', function(e) {\r\n    e.preventDefault(); drop.classList.remove('drag');\r\n    legSubirArchivos(carpetaId, e.dataTransfer.files);\r\n  });\r\n\r\n  \/\/ Cargar archivos existentes\r\n  legCargarArchivos(carpetaId);\r\n}\r\n\r\n\/\/ \u2500\u2500 Cargar archivos desde API \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction legCargarArchivos(carpetaId) {\r\n  var grid = document.getElementById('legGrid');\r\n  if (!grid) return;\r\n  grid.innerHTML = '<div style=\"color:rgba(200,160,60,0.4);font-family:Arial,sans-serif;font-size:12px;text-align:center;padding:12px;\">Cargando...<\/div>';\r\n\r\n  var hdrs4 = {}; if (window.cdhNonce) hdrs4['X-WP-Nonce'] = window.cdhNonce;\r\n  fetch('\/index.php\/wp-json\/cdh\/v1\/archivos\/' + carpetaId, {\r\n    headers: hdrs4, credentials: 'same-origin'\r\n  })\r\n  .then(function(r) { return r.json(); })\r\n  .then(function(data) { legRenderArchivos(data || [], carpetaId); })\r\n  .catch(function() { if (grid) grid.innerHTML = ''; });\r\n}\r\n\r\n\/\/ \u2500\u2500 Renderizar grid de archivos \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction legRenderArchivos(archivos, carpetaId) {\r\n  var grid = document.getElementById('legGrid');\r\n  if (!grid) return;\r\n  grid.innerHTML = '';\r\n  lbArchivos = archivos; \/\/ guardar para navegaci\u00f3n lightbox\r\n\r\n  if (!archivos.length) {\r\n    grid.innerHTML = '<div style=\"color:rgba(200,160,60,0.35);font-family:Arial,sans-serif;font-size:12px;text-align:center;padding:16px;grid-column:1\/-1;\">\u2014 Sin archivos a\u00fan \u2014<\/div>';\r\n    return;\r\n  }\r\n\r\n  archivos.forEach(function(a) {\r\n    var card = document.createElement('div');\r\n    card.className = 'cdh-archivo-card';\r\n    card.dataset.id = a.id;\r\n    card.dataset.url = a.url;\r\n    card.dataset.nombre = a.nombre_original;\r\n    card.dataset.mime = a.tipo_mime;\r\n    card.dataset.categoria = a.categoria;\r\n    card.dataset.caption = a.caption || '';\r\n\r\n    var vistaHtml = '';\r\n    if (a.categoria === 'imagen') {\r\n      vistaHtml = '<img decoding=\"async\" class=\"cdh-archivo-thumb\" src=\"' + a.url + '\" alt=\"' + escapeHtml(a.nombre_original) + '\" loading=\"lazy\">';\r\n    } else {\r\n      vistaHtml = '<div class=\"cdh-archivo-ico\">' + legadoIcono(a.categoria, a.tipo_mime) + '<\/div>';\r\n    }\r\n\r\n    var delBtn = (!expModoLectura && legadoEsPropietario)\r\n      ? '<div class=\"cdh-archivo-del\" title=\"Borrar\" onclick=\"legBorrarArchivo(' + a.id + ',' + carpetaId + ',event)\">\u2715<\/div>'\r\n      : '';\r\n\r\n    var captionField = (!expModoLectura && legadoEsPropietario)\r\n      ? '<input class=\"cdh-archivo-caption-input\" type=\"text\" maxlength=\"120\" placeholder=\"Pie de foto\u2026\" value=\"' + escapeHtml(a.caption || '') + '\">'\r\n      : '';\r\n\r\n    card.innerHTML =\r\n      vistaHtml\r\n      + '<div class=\"cdh-archivo-nombre\">' + escapeHtml(a.caption || a.nombre_original) + '<\/div>'\r\n      + '<div class=\"cdh-archivo-size\">' + legadoTamano(a.tamano) + '<\/div>'\r\n      + captionField\r\n      + delBtn;\r\n\r\n    \/\/ Guardar caption al perder el foco o pulsar Enter\r\n    if (!expModoLectura && legadoEsPropietario) {\r\n      var inp = card.querySelector('.cdh-archivo-caption-input');\r\n      if (inp) {\r\n        inp.addEventListener('blur', function() { legGuardarCaption(a.id, inp.value, card); });\r\n        inp.addEventListener('keydown', function(e) { if (e.key === 'Enter') { e.preventDefault(); inp.blur(); } });\r\n      }\r\n    }\r\n\r\n    card.addEventListener('click', function(e) {\r\n      if (e.target.closest('.cdh-archivo-del')) return;\r\n      if (e.target.closest('.cdh-archivo-caption-input')) return;\r\n      var captionActual = card.dataset.caption !== undefined ? card.dataset.caption : (a.caption || '');\r\n      var idx = lbArchivos.indexOf(a);\r\n      abrirLightbox(Object.assign({}, a, { caption: captionActual }), idx);\r\n    });\r\n\r\n    grid.appendChild(card);\r\n  });\r\n}\r\n\r\n\/\/ \u2500\u2500 Guardar caption de un archivo \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction legGuardarCaption(archivoId, valor, card) {\r\n  var texto = valor.trim();\r\n  fetch('\/index.php\/wp-json\/cdh\/v1\/archivo\/' + archivoId + '\/caption', {\r\n    method: 'POST',\r\n    headers: Object.assign({ 'Content-Type': 'application\/json' }, cdhApiHeaders()),\r\n    credentials: 'same-origin',\r\n    body: JSON.stringify({ caption: texto })\r\n  })\r\n  .then(function(r) { return r.json(); })\r\n  .then(function(data) {\r\n    if (data.ok && card) {\r\n      card.dataset.caption = texto;\r\n      \/\/ Actualizar tambi\u00e9n el nombre visible en la card\r\n      var nombreEl = card.querySelector('.cdh-archivo-nombre');\r\n      if (nombreEl) nombreEl.textContent = texto || card.dataset.nombre;\r\n    }\r\n  })\r\n  .catch(function() {});\r\n}\r\n\r\n\/\/ \u2500\u2500 Subir archivos \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\/\/ \u2500\u2500 Sesion y nonce \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\/\/ El nonce de WordPress caduca a las 12-24 h. Si la cripta se queda abierta\r\n\/\/ en el movil y el usuario vuelve al dia siguiente, el nonce esta muerto\r\n\/\/ aunque la cookie de sesion siga viva: el servidor contesta 401\/403 y el\r\n\/\/ usuario solo ve \"no tienes permiso\" sin entender por que.\r\n\/\/ Aqui se distinguen los dos casos: nonce caducado (se renueva y se sigue)\r\n\/\/ y sesion cerrada de verdad (se avisa y se ofrece volver a entrar).\r\n\r\n\/\/ \u26a0 REVISAR: pagina donde vuelve a entrar el usuario.\r\nvar CDH_LOGIN_URL = '\/';\r\n\r\nvar cdhNonceUltimoRefresco = Date.now();\r\n\r\n\/\/ Pide a WordPress un nonce REST nuevo. Solo responde a usuarios con sesion\r\n\/\/ abierta, asi que un fallo aqui ya significa que la sesion esta cerrada.\r\nfunction cdhRefrescarNonce(cb) {\r\n  fetch('\/wp-admin\/admin-ajax.php?action=rest-nonce', { credentials: 'same-origin' })\r\n  .then(function(r) { return r.ok ? r.text() : ''; })\r\n  .then(function(t) {\r\n    t = String(t || '').trim();\r\n    \/\/ Un nonce de WordPress son 10 caracteres alfanumericos. Si llega\r\n    \/\/ cualquier otra cosa (HTML de login, 0, vacio) no vale.\r\n    if (\/^[a-z0-9]{10}$\/i.test(t)) {\r\n      window.cdhNonce = t;\r\n      cdhNonceUltimoRefresco = Date.now();\r\n      console.log('CDH: nonce renovado');\r\n      cb(true);\r\n    } else {\r\n      cb(false);\r\n    }\r\n  })\r\n  .catch(function() { cb(false); });\r\n}\r\n\r\n\/\/ Al volver a primer plano tras un rato (movil bloqueado, pestana de fondo)\r\n\/\/ se renueva el nonce por adelantado, para que la primera accion del usuario\r\n\/\/ no sea la que se coma el error.\r\ndocument.addEventListener('visibilitychange', function() {\r\n  if (document.hidden) return;\r\n  if (expModoLectura || !window.cdhNonce) return;\r\n  if (Date.now() - cdhNonceUltimoRefresco < 10 * 60 * 1000) return;\r\n  cdhRefrescarNonce(function() {});\r\n});\r\n\r\nfunction cdhAvisarSesionCaducada() {\r\n  cdhConfirm(\r\n    'Sesion caducada',\r\n    'Por seguridad tu sesion se ha cerrado y no se ha guardado nada.'\r\n      + '<br><br>Vuelve a entrar con tu usuario y podras continuar donde lo dejaste.',\r\n    '\ud83d\udd12', 'Volver a entrar',\r\n    function(ok) { if (ok) window.location.href = CDH_LOGIN_URL; }\r\n  );\r\n}\r\n\r\nfunction legSubirArchivos(carpetaId, files) {\r\n  if (!files || !files.length) return;\r\n  var progreso = document.getElementById('legProgreso');\r\n  var barra    = document.getElementById('legBarra');\r\n  var estado   = document.getElementById('legEstado');\r\n\r\n  progreso.classList.add('visible');\r\n  var total = files.length;\r\n  var done  = 0;\r\n  var errores = [];\r\n  var nonceRenovado = false; \/\/ un solo intento de renovacion por tanda\r\n\r\n  \/\/ Sesion muerta: cortar la tanda entera. Seguir con los archivos\r\n  \/\/ restantes solo produciria el mismo error repetido N veces.\r\n  function cortarPorSesion() {\r\n    barra.style.width = '0%';\r\n    progreso.classList.remove('visible');\r\n    console.log('CDH Legado: sesion caducada, tanda cancelada');\r\n    cdhAvisarSesionCaducada();\r\n  }\r\n\r\n  function subirUno(i) {\r\n    if (i >= total) {\r\n      barra.style.width = '100%';\r\n      if (errores.length) {\r\n        estado.textContent = '\u26a0 ' + errores.length + ' archivo(s) con error: ' + errores.join(', ');\r\n        estado.style.color = '#e08080';\r\n      } else {\r\n        estado.textContent = '\u2713 ' + total + ' archivo(s) subido(s) correctamente.';\r\n        estado.style.color = '#7ec89a';\r\n      }\r\n      setTimeout(function() {\r\n        \/\/ Si hubo errores el aviso se queda visible: en el movil 2 segundos\r\n        \/\/ no dan para leer el motivo. Se cierra al pulsarlo.\r\n        if (errores.length) {\r\n          progreso.onclick = function() {\r\n            progreso.classList.remove('visible');\r\n            barra.style.width = '0%';\r\n            progreso.onclick = null;\r\n          };\r\n          progreso.style.cursor = 'pointer';\r\n          estado.textContent += '  (pulsa para cerrar)';\r\n        } else {\r\n          progreso.classList.remove('visible');\r\n          barra.style.width = '0%';\r\n        }\r\n        legCargarArchivos(carpetaId);\r\n      }, 2000);\r\n      return;\r\n    }\r\n\r\n    var file = files[i];\r\n    estado.textContent = 'Subiendo ' + (i+1) + ' de ' + total + ': ' + file.name;\r\n    estado.style.color = 'rgba(200,160,60,0.7)';\r\n\r\n    var formData = new FormData();\r\n    formData.append('archivo', file);\r\n\r\n    var xhr = new XMLHttpRequest();\r\n    xhr.upload.onprogress = function(e) {\r\n      if (!e.lengthComputable) return;\r\n      var pct = ((i \/ total) + (e.loaded \/ e.total \/ total)) * 100;\r\n      barra.style.width = Math.min(98, pct) + '%';\r\n    };\r\n    xhr.onload = function() {\r\n      \/\/ 401\/403 = credencial rechazada. Antes de dar la sesion por perdida,\r\n      \/\/ probar si era solo el nonce: se renueva y se reintenta ESTE archivo.\r\n      if (xhr.status === 401 || xhr.status === 403) {\r\n        if (!nonceRenovado) {\r\n          nonceRenovado = true;\r\n          estado.textContent = 'Renovando la sesion...';\r\n          estado.style.color = 'rgba(200,160,60,0.7)';\r\n          cdhRefrescarNonce(function(ok) {\r\n            if (ok) { subirUno(i); } else { cortarPorSesion(); }\r\n          });\r\n        } else {\r\n          cortarPorSesion();\r\n        }\r\n        return;\r\n      }\r\n      done++;\r\n      \/\/ Diagnostico: guardar el motivo real, no solo el nombre del archivo.\r\n      \/\/ Si el servidor responde algo que no es JSON (413 de Nginx, error de\r\n      \/\/ PHP, pagina de error del hosting) se muestra el codigo HTTP y el\r\n      \/\/ principio del cuerpo, ya limpio de etiquetas.\r\n      var msg = '';\r\n      try {\r\n        var res = JSON.parse(xhr.responseText);\r\n        if (res.code) msg = res.message || res.code;\r\n      } catch(ex) {\r\n        msg = 'HTTP ' + xhr.status + ': ' + String(xhr.responseText || '(vacio)')\r\n                .replace(\/<[^>]*>\/g, ' ').replace(\/\\s+\/g, ' ').trim().slice(0, 140);\r\n      }\r\n      if (msg) {\r\n        errores.push(file.name + ' [' + legadoTamano(file.size) + '] -> ' + msg);\r\n        console.log('CDH Legado: fallo al subir', file.name, file.type, file.size, xhr.status, xhr.responseText);\r\n      }\r\n      subirUno(i + 1);\r\n    };\r\n    xhr.onerror = function() {\r\n      errores.push(file.name + ' [' + legadoTamano(file.size) + '] -> conexion interrumpida (HTTP ' + xhr.status + ')');\r\n      console.log('CDH Legado: error de red al subir', file.name, file.type, file.size, xhr.status);\r\n      subirUno(i + 1);\r\n    };\r\n    xhr.open('POST', '\/index.php\/wp-json\/cdh\/v1\/archivos\/' + carpetaId);\r\n    if (window.cdhNonce) xhr.setRequestHeader('X-WP-Nonce', window.cdhNonce);\r\n    xhr.send(formData);\r\n  }\r\n\r\n  subirUno(0);\r\n}\r\n\r\n\/\/ \u2500\u2500 Borrar archivo \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction legBorrarArchivo(id, carpetaId, e) {\r\n  if (e) e.stopPropagation();\r\n  cdhConfirm(\r\n    'Borrar archivo',\r\n    '\u00bfSeguro que quieres borrar este archivo?<br><br>Esta acci\u00f3n no se puede deshacer.',\r\n    '\ud83d\uddd1', 'Borrar',\r\n    function(ok) {\r\n      if (!ok) return;\r\n      fetch('\/index.php\/wp-json\/cdh\/v1\/archivo\/' + id, {\r\n        method: 'DELETE',\r\n        headers: { 'X-WP-Nonce': window.cdhNonce },\r\n        credentials: 'same-origin'\r\n      })\r\n      .then(function() { legCargarArchivos(carpetaId); })\r\n      .catch(function() { alert('Error al borrar el archivo.'); });\r\n    }\r\n  );\r\n}\r\n\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n\/\/ LIGHTBOX\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n\r\nfunction abrirLightbox(archivo, idx) {\r\n  if (idx !== undefined) lbIndice = idx;\r\n\r\n  var lb        = document.getElementById('cdhLightbox');\r\n  var contenido = document.getElementById('lbContenido');\r\n  var nombre    = document.getElementById('lbNombre');\r\n  var dlBtn     = document.getElementById('lbDescargaBtn');\r\n  var prevBtn   = document.getElementById('lbPrev');\r\n  var nextBtn   = document.getElementById('lbNext');\r\n  var contador  = document.getElementById('lbContador');\r\n\r\n  \/\/ Detener media anterior\r\n  lb.querySelectorAll('video, audio').forEach(function(m) { m.pause(); m.src = ''; });\r\n  contenido.innerHTML = '';\r\n\r\n  nombre.textContent = archivo.caption || archivo.nombre_original;\r\n  dlBtn.href         = archivo.url + (archivo.url.indexOf('?') > -1 ? '&dl=1' : '?dl=1');\r\n  dlBtn.download     = archivo.nombre_original;\r\n\r\n  \/\/ Flechas y contador\r\n  var total = lbArchivos.length;\r\n  if (total > 1) {\r\n    prevBtn.classList.toggle('hidden', lbIndice === 0);\r\n    nextBtn.classList.toggle('hidden', lbIndice === total - 1);\r\n    contador.textContent = (lbIndice + 1) + ' \/ ' + total;\r\n  } else {\r\n    prevBtn.classList.add('hidden');\r\n    nextBtn.classList.add('hidden');\r\n    contador.textContent = '';\r\n  }\r\n\r\n  switch (archivo.categoria) {\r\n    case 'imagen':\r\n      var img = document.createElement('img');\r\n      img.src = archivo.url;\r\n      img.alt = archivo.nombre_original;\r\n      contenido.appendChild(img);\r\n      break;\r\n\r\n    case 'video':\r\n      var vid = document.createElement('video');\r\n      vid.src = archivo.url;\r\n      vid.controls = true;\r\n      vid.autoplay = false;\r\n      vid.style.maxWidth = '90vw';\r\n      vid.style.maxHeight = '78vh';\r\n      vid.style.maxHeight = '78svh';   \/* si el navegador no conoce svh, ignora esta linea *\/\r\n      contenido.appendChild(vid);\r\n      break;\r\n\r\n    case 'audio':\r\n      var aud = document.createElement('div');\r\n      aud.style.cssText = 'text-align:center;padding:30px 20px;';\r\n      aud.innerHTML =\r\n        '<div style=\"font-size:64px;margin-bottom:20px;\">\ud83c\udfb5<\/div>'\r\n        + '<div style=\"font-family:Arial,sans-serif;font-size:14px;color:rgba(240,215,120,0.8);margin-bottom:20px;\">' + escapeHtml(archivo.nombre_original) + '<\/div>'\r\n        + '<audio controls autoplay style=\"width:min(400px,80vw);outline:none;\">'\r\n          + '<source src=\"' + archivo.url + '\" type=\"' + archivo.tipo_mime + '\">'\r\n        + '<\/audio>';\r\n      contenido.appendChild(aud);\r\n      break;\r\n\r\n    case 'pdf':\r\n      var frame = document.createElement('iframe');\r\n      frame.src = archivo.url;\r\n      frame.title = archivo.nombre_original;\r\n      contenido.appendChild(frame);\r\n      break;\r\n\r\n    case 'texto':\r\n      fetch(archivo.url, { credentials: 'same-origin' })\r\n        .then(function(r) { return r.text(); })\r\n        .then(function(txt) {\r\n          var pre = document.createElement('pre');\r\n          pre.textContent = txt;\r\n          contenido.appendChild(pre);\r\n        })\r\n        .catch(function() { legLightboxOtro(contenido, archivo); });\r\n      break;\r\n\r\n    default:\r\n      legLightboxOtro(contenido, archivo);\r\n      break;\r\n  }\r\n\r\n  lb.classList.add('open');\r\n}\r\n\r\nfunction lbNavegar(dir) {\r\n  var nuevoIdx = lbIndice + dir;\r\n  if (nuevoIdx < 0 || nuevoIdx >= lbArchivos.length) return;\r\n  var a = lbArchivos[nuevoIdx];\r\n  \/\/ Leer caption actualizado del grid si existe\r\n  var card = document.querySelector('.cdh-archivo-card[data-id=\"' + a.id + '\"]');\r\n  var captionActual = card ? (card.dataset.caption !== undefined ? card.dataset.caption : (a.caption || '')) : (a.caption || '');\r\n  abrirLightbox(Object.assign({}, a, { caption: captionActual }), nuevoIdx);\r\n}\r\n\r\nfunction legLightboxOtro(contenido, archivo) {\r\n  var div = document.createElement('div');\r\n  div.className = 'cdh-lb-otro';\r\n  div.innerHTML =\r\n    '<div class=\"cdh-lb-otro-ico\">' + legadoIcono(archivo.categoria, archivo.tipo_mime) + '<\/div>'\r\n    + '<div class=\"cdh-lb-otro-txt\">Este tipo de archivo no puede reproducirse en el navegador.<br>Desc\u00e1rgalo para abrirlo.<\/div>'\r\n    + '<a class=\"cdh-lb-btn-dl\" href=\"' + archivo.url + '\" download=\"' + escapeHtml(archivo.nombre_original) + '\" target=\"_blank\">\u2b07 &nbsp;Descargar<\/a>';\r\n  contenido.appendChild(div);\r\n}\r\n\r\nfunction cerrarLightbox() {\r\n  var lb = document.getElementById('cdhLightbox');\r\n  lb.classList.remove('open');\r\n  \/\/ Detener v\u00eddeo\/audio al cerrar\r\n  lb.querySelectorAll('video, audio').forEach(function(m) { m.pause(); m.src = ''; });\r\n  document.getElementById('lbContenido').innerHTML = '';\r\n}\r\n\r\ndocument.addEventListener('keydown', function(e) {\r\n  if (!document.getElementById('cdhLightbox').classList.contains('open')) return;\r\n  if (e.key === 'Escape')      cerrarLightbox();\r\n  if (e.key === 'ArrowLeft')   lbNavegar(-1);\r\n  if (e.key === 'ArrowRight')  lbNavegar(1);\r\n});\r\n\r\n\/\/ \u2500\u2500 Modal de confirmaci\u00f3n personalizado \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction cdhConfirm(titulo, mensaje, icono, labelOk, callback) {\r\n  var modal  = document.getElementById('cdhConfirmModal');\r\n  var title  = document.getElementById('cdhConfirmTitle');\r\n  var msg    = document.getElementById('cdhConfirmMsg');\r\n  var ico    = document.getElementById('cdhConfirmIcon');\r\n  var btnOk  = document.getElementById('cdhConfirmOk');\r\n  var btnCan = document.getElementById('cdhConfirmCancel');\r\n\r\n  title.textContent = titulo;\r\n  msg.innerHTML     = mensaje;\r\n  if (!icono || icono === '\ud83d\uddd1') {\r\n    ico.innerHTML = '<span class=\"cdh-confirm-basura\"><\/span>';\r\n  } else {\r\n    ico.textContent = icono;\r\n  }\r\n  btnOk.textContent = labelOk || 'Eliminar';\r\n\r\n  modal.style.display = 'flex';\r\n\r\n  \/\/ Limpiar listeners anteriores\r\n  var newOk  = btnOk.cloneNode(true);\r\n  var newCan = btnCan.cloneNode(true);\r\n  btnOk.parentNode.replaceChild(newOk, btnOk);\r\n  btnCan.parentNode.replaceChild(newCan, btnCan);\r\n\r\n  newOk.addEventListener('click', function() {\r\n    modal.style.display = 'none';\r\n    callback(true);\r\n  });\r\n  newCan.addEventListener('click', function() {\r\n    modal.style.display = 'none';\r\n    callback(false);\r\n  });\r\n\r\n  \/\/ Restaurar estilos hover despu\u00e9s del cloneNode\r\n  newOk.onmouseover  = function() { this.style.background='rgba(160,40,40,0.8)'; };\r\n  newOk.onmouseout   = function() { this.style.background='rgba(120,30,30,0.6)'; };\r\n  newCan.onmouseover = function() { this.style.borderColor='rgba(245,240,232,0.45)'; this.style.color='rgba(245,240,232,0.8)'; };\r\n  newCan.onmouseout  = function() { this.style.borderColor='rgba(245,240,232,0.2)';  this.style.color='rgba(245,240,232,0.5)'; };\r\n}\r\n\r\nfunction escapeHtml(str) {\r\n  return String(str).replace(\/&\/g,'&amp;').replace(\/<\/g,'&lt;').replace(\/>\/g,'&gt;').replace(\/\"\/g,'&quot;');\r\n}\r\n\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n\/\/ SISTEMA DE CARPETAS\r\n\/\/ \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n\r\nvar mcCarpetas      = [];       \/\/ Array de carpetas cargadas\r\nvar mcColorSel = 'verde';\r\n\r\n\/\/ Paleta de colores predefinidos\r\nvar mcPaleta = [\r\n  { key: 'verde',       c1: 'rgba(35,85,40,0.92)',   c2: 'rgba(65,140,70,0.55)',   hex: '#2d7a35' },\r\n  { key: 'verde-claro', c1: 'rgba(55,120,50,0.92)',  c2: 'rgba(90,180,80,0.55)',   hex: '#4aaa40' },\r\n  { key: 'azul',        c1: 'rgba(25,55,110,0.92)',  c2: 'rgba(50,100,200,0.55)',  hex: '#2855b8' },\r\n  { key: 'azul-claro',  c1: 'rgba(30,90,140,0.92)',  c2: 'rgba(60,150,220,0.55)',  hex: '#2880cc' },\r\n  { key: 'rojo',        c1: 'rgba(110,25,25,0.92)',  c2: 'rgba(200,55,55,0.55)',   hex: '#c43030' },\r\n  { key: 'naranja',     c1: 'rgba(130,65,10,0.92)',  c2: 'rgba(220,130,30,0.55)',  hex: '#d07010' },\r\n  { key: 'dorado',      c1: 'rgba(140,100,15,0.92)', c2: 'rgba(220,175,40,0.55)',  hex: '#c89018' },\r\n  { key: 'amarillo',      c1: 'rgba(120,115,10,0.92)', c2: 'rgba(215,210,30,0.55)',  hex: '#c8c015' },\r\n  { key: 'morado',      c1: 'rgba(70,25,100,0.92)',  c2: 'rgba(140,60,200,0.55)',  hex: '#7828c0' },\r\n  { key: 'rosa',        c1: 'rgba(120,30,80,0.92)',  c2: 'rgba(220,70,150,0.55)',  hex: '#d04090' },\r\n  { key: 'gris',        c1: 'rgba(60,60,65,0.92)',   c2: 'rgba(120,120,130,0.55)', hex: '#707080' },\r\n  { key: 'negro',       c1: 'rgba(18,18,20,0.95)',   c2: 'rgba(55,55,60,0.55)',    hex: '#1a1a1e' },\r\n  { key: 'blanco',      c1: 'rgba(235,232,225,0.97)', c2: 'rgba(255,252,245,0.65)', hex: '#ebe8e1' },\r\n  { key: 'amarillo-vivo', c1: 'rgba(200,170,0,0.97)', c2: 'rgba(255,235,0,0.80)',   hex: '#f0c800' },\r\n];\r\n\r\nfunction mcPaletaColores(key) {\r\n  var p = mcPaleta.find(function(x) { return x.key === key; });\r\n  return p ? [p.c1, p.c2] : [mcPaleta[0].c1, mcPaleta[0].c2];\r\n}\r\n\r\nfunction renderColorGrid(gridId, colorSelVar, onSelect) {\r\n  var grid = document.getElementById(gridId);\r\n  if (!grid) return;\r\n  grid.innerHTML = '';\r\n  mcPaleta.forEach(function(p) {\r\n    var div = document.createElement('div');\r\n    div.className = 'cdh-color-opt' + (colorSelVar === p.key ? ' sel' : '');\r\n    div.title = p.key.replace('-', ' ');\r\n    div.style.background = 'linear-gradient(135deg, ' + p.c1 + ', ' + p.c2.replace('0.55','0.9') + ')';\r\n    div.onclick = function() {\r\n      onSelect(p.key);\r\n      grid.querySelectorAll('.cdh-color-opt').forEach(function(el) { el.classList.remove('sel'); });\r\n      div.classList.add('sel');\r\n    };\r\n    grid.appendChild(div);\r\n  });\r\n}\r\n\r\nfunction mcCambiarTab(tab, btn) {\r\n  document.querySelectorAll('.cdh-tabs .cdh-tab').forEach(function(b) { b.classList.remove('sel'); });\r\n  btn.classList.add('sel');\r\n  var tc = document.getElementById('mcTabColor');\r\n  var ti = document.getElementById('mcTabIcono');\r\n  if (tc) tc.style.display = tab === 'color' ? '' : 'none';\r\n  if (ti) ti.style.display = tab === 'icono' ? '' : 'none';\r\n  \/\/ Show tipo toggle only on icono tab\r\n  var tt = document.getElementById('mcTipoToggle');\r\n  if (tt) tt.style.display = tab === 'icono' ? '' : 'none';\r\n}\r\n\r\nfunction mcToggleTipo(cb) {\r\n  mcTipoSel = cb.checked ? 'icono' : 'carpeta';\r\n}\r\n\r\nvar mcIconoSel      = 'carpeta-basica';\r\nvar mcTipoSel       = 'carpeta';\r\nvar mcEstadoSel     = 'abierta';\r\nvar mcModoEdicion   = null;     \/\/ null = nueva, id = editando\r\nvar mcIconosCat = {\r\n  'carpeta-basica': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#FFAC33' d='M36 30a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V12a4 4 0 0 1 4-4h13.833a4 4 0 0 1 2.829 1.172L21.828 10.343A2 2 0 0 0 23.242 11H32a4 4 0 0 1 4 4z'\/><path fill='#FFD983' d='M36 17v3H0v-3a4 4 0 0 1 4-4h28a4 4 0 0 1 4 4z'\/><\/svg>\", label: 'Carpeta' },\r\n  'reloj': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#FFE8B6' d='M21 18c0-2.001 3.246-3.369 5-6 2-3 2-10 2-10H8s0 7 2 10c1.754 2.631 5 3.999 5 6s-3.246 3.369-5 6c-2 3-2 10-2 10h20s0-7-2-10c-1.754-2.631-5-3.999-5-6z'\/><path fill='#FFAC33' d='M20.999 24c-.999 0-2.057-1-2.057-2C19 20.287 19 19.154 19 18c0-3.22 3.034-4.561 4.9-7H12.1c1.865 2.439 4.9 3.78 4.9 7 0 1.155 0 2.289.058 4 0 1-1.058 2-2.058 2-2 0-3.595 1.784-4 3-1 3-1 7-1 7h16s0-4-1-7c-.405-1.216-2.001-3-4.001-3z'\/><path fill='#3B88C3' d='M30 34c0 1.104-.896 2-2 2H8c-1.104 0-2-.896-2-2s.896-2 2-2h20c1.104 0 2 .896 2 2zm0-32c0 1.104-.896 2-2 2H8c-1.104 0-2-.896-2-2s.896-2 2-2h20c1.104 0 2 .896 2 2z'\/><\/svg>\", label: 'Reloj de arena' },\r\n  'candado': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#AAB8C2' d='M18 3C12.477 3 8 7.477 8 13v10h4V13c0-3.313 2.686-6 6-6s6 2.687 6 6v10h4V13c0-5.523-4.477-10-10-10z'\/><path fill='#FFAC33' d='M31 32c0 2.209-1.791 4-4 4H9c-2.209 0-4-1.791-4-4V20c0-2.209 1.791-4 4-4h18c2.209 0 4 1.791 4 4v12z'\/><\/svg>\", label: 'Candado' },\r\n  'calavera': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#CCD6DD' d='M34 16C34 6 26.837 0 18 0 9.164 0 2 6 2 16c0 5.574.002 10.388 6 12.64V33c0 1.657 1.343 3 3 3s3-1.343 3-3v-3.155c.324.027.659.05 1 .07V33c0 1.657 1.343 3 3 3s3-1.343 3-3v-3.085c.342-.021.676-.043 1-.07V33c0 1.657 1.344 3 3 3 1.657 0 3-1.343 3-3v-4.36c5.998-2.252 6-7.066 6-12.64z'\/><circle fill='#292F33' cx='11' cy='14' r='5'\/><circle fill='#292F33' cx='25' cy='14' r='5'\/><path fill='#292F33' d='M19.903 23.062C19.651 22.449 18.9 22 18 22s-1.652.449-1.903 1.062c-.632.176-1.097.75-1.097 1.438 0 .828.671 1.5 1.5 1.5.655 0 1.206-.422 1.41-1.007.03.001.059.007.09.007s.06-.006.09-.007c.205.585.756 1.007 1.41 1.007.828 0 1.5-.672 1.5-1.5 0-.688-.466-1.261-1.097-1.438z'\/><\/svg>\", label: 'Calavera' },\r\n  'Testamento': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#FFD983' d='M32 0H10C7.791 0 6 1.791 6 4v24H4c-2.209 0-4 1.791-4 4s1.791 4 4 4h24c2.209 0 4-1.791 4-4V8c2.209 0 4-1.791 4-4s-1.791-4-4-4z'\/><path fill='#E39F3D' d='M8 10h24V8H10L8 7z'\/><path fill='#FFE8B6' d='M10 0C7.791 0 6 1.791 6 4v24.555C5.41 28.211 4.732 28 4 28c-2.209 0-4 1.791-4 4s1.791 4 4 4 4-1.791 4-4V7.445C8.59 7.789 9.268 8 10 8c2.209 0 4-1.791 4-4s-1.791-4-4-4z'\/><path fill='#C1694F' d='M12 4c0 1.104-.896 2-2 2s-2-.896-2-2 .896-2 2-2 2 .896 2 2M6 32c0 1.104-.896 2-2 2s-2-.896-2-2 .896-2 2-2 2 .896 2 2m24-17c0 .552-.447 1-1 1H11c-.552 0-1-.448-1-1s.448-1 1-1h18c.553 0 1 .448 1 1m0 4c0 .553-.447 1-1 1H11c-.552 0-1-.447-1-1s.448-1 1-1h18c.553 0 1 .447 1 1m0 4c0 .553-.447 1-1 1H11c-.552 0-1-.447-1-1s.448-1 1-1h18c.553 0 1 .447 1 1m0 4c0 .553-.447 1-1 1H11c-.552 0-1-.447-1-1 0-.553.448-1 1-1h18c.553 0 1 .447 1 1'\/><\/svg>\", label: 'Testamento' },\r\n  'dinero': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#FDD888' d='M31.898 23.938C31.3 17.32 28 14 28 14l-6-8h-8l-6 8s-1.419 1.433-2.567 4.275C3.444 18.935 2 20.789 2 23c0 1.448.625 2.742 1.609 3.655C3.233 27.357 3 28.147 3 29c0 1.958 1.136 3.636 2.775 4.456C7.058 35.378 8.772 36 10 36h16c1.379 0 3.373-.779 4.678-3.31C32.609 31.999 34 30.17 34 28c0-1.678-.834-3.154-2.102-4.062zM18 6c.55 0 1.058-.158 1.5-.416.443.258.951.416 1.5.416 1.657 0 4-2.344 4-4 0 0 0-2-2-2-.788 0-1 1-2 1s-1-1-3-1-2 1-3 1-1.211-1-2-1c-2 0-2 2-2 2 0 1.656 2.344 4 4 4 .549 0 1.057-.158 1.5-.416.443.258.951.416 1.5.416z'\/><path fill='#BF6952' d='M24 6c0 .552-.447 1-1 1H13c-.552 0-1-.448-1-1s.448-1 1-1h10c.553 0 1 .448 1 1z'\/><path fill='#67757F' d='M23.901 24.542c0-4.477-8.581-4.185-8.581-6.886 0-1.308 1.301-1.947 2.811-1.947 2.538 0 2.99 1.569 4.139 1.569.813 0 1.205-.493 1.205-1.046 0-1.284-2.024-2.256-3.965-2.592V12.4c0-.773-.65-1.4-1.454-1.4-.805 0-1.456.627-1.456 1.4v1.283c-2.116.463-3.937 1.875-3.937 4.176 0 4.299 8.579 4.125 8.579 7.145 0 1.047-1.178 2.093-3.111 2.093-2.901 0-3.867-1.889-5.045-1.889-.574 0-1.087.464-1.087 1.164 0 1.113 1.938 2.451 4.603 2.824l-.001.01v1.398c0 .772.652 1.4 1.456 1.4.804 0 1.455-.628 1.455-1.4v-1.398c0-.017-.008-.03-.009-.045 2.398-.43 4.398-1.932 4.398-4.619z'\/><\/svg>\", label: 'Bolsa dinero' },\r\n  'empresa': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#DAC8B1' d='M34 13c0 1.104-.896 2-2 2h-6c-1.104 0-2-.896-2-2v-2c0-1.104.896-2 2-2h6c1.104 0 2 .896 2 2v2zm-22 0c0 1.104-.896 2-2 2H4c-1.104 0-2-.896-2-2v-2c0-1.104.896-2 2-2h6c1.104 0 2 .896 2 2v2z'\/><path fill='#F1DCC1' d='M36 34c0 1.104-.896 2-2 2H2c-1.104 0-2-.896-2-2V13c0-1.104.896-2 2-2h32c1.104 0 2 .896 2 2v21z'\/><path fill='#DAC8B1' d='M22 9V7c0-.738-.404-1.376-1-1.723V5c0-1.104-.896-2-2-2h-2c-1.104 0-2 .896-2 2v.277c-.595.347-1 .985-1 1.723v2h-1v27h10V9h-1z'\/><path fill='#55ACEE' d='M14 7h2v2h-2zm6 0h2v2h-2zm-3 0h2v2h-2z'\/><path fill='#3B88C3' d='M15 15h2v14h-2zm4 0h2v14h-2z'\/><path fill='#55ACEE' d='M24 17h2v12h-2zm4 0h2v12h-2zm4 0h2v12h-2zM2 17h2v12H2zm4 0h2v12H6zm4 0h2v12h-2zM2 30h2v2H2zm4 0h2v2H6zm4 0h2v2h-2z'\/><path fill='#3B88C3' d='M15 30h2v2h-2zm4 0h2v2h-2z'\/><path fill='#55ACEE' d='M24 30h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2z'\/><path fill='#66757F' d='M2 33h2v3H2zm4 0h2v3H6zm4 0h2v3h-2zm5 0h2v3h-2zm4 0h2v3h-2zm5 0h2v3h-2zm4 0h2v3h-2zm4 0h2v3h-2z'\/><\/svg>\", label: 'Empresa' },\r\n  'corazon': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#DD2E44' d='M35.885 11.833c0-5.45-4.418-9.868-9.867-9.868-3.308 0-6.227 1.633-8.018 4.129-1.791-2.496-4.71-4.129-8.017-4.129-5.45 0-9.868 4.417-9.868 9.868 0 .772.098 1.52.266 2.241C1.751 22.587 11.216 31.568 18 34.034c6.783-2.466 16.249-11.447 17.617-19.959.17-.721.268-1.469.268-2.242z'\/><\/svg>\", label: 'Coraz\u00f3n' },\r\n  'camara': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#66757F' d='M4 5s0-1 1-1h6s1 0 1 1v2H4V5z'\/><path fill='#31373D' d='M0 10s0-4 4-4h28s4 0 4 4v18s0 4-4 4H4s-4 0-4-4V10z'\/><circle fill='#CCD6DD' cx='21' cy='19' r='10'\/><circle fill='#31373D' cx='21' cy='19' r='8'\/><circle fill='#3B88C3' cx='21' cy='19' r='5'\/><circle fill='#FFF' cx='32.5' cy='9.5' r='1.5'\/><path fill='#F5F8FA' d='M12 9.5c0 .829-.671 1.5-1.5 1.5h-5C4.671 11 4 10.329 4 9.5S4.671 8 5.5 8h5c.829 0 1.5.671 1.5 1.5z'\/><\/svg>\", label: 'Fotos' },\r\n  'rosa': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#3E721D' d='M19.32 25.358c-.113 0-.217.003-.32.005v-.415c4.805-.479 8.548-4.264 8.548-7.301 0-3.249 0 1.47-9.562 1.47-9.558 0-9.558-4.719-9.558-1.47 0 3.043 3.757 6.838 8.572 7.305v.411c-.104-.002-.207-.005-.321-.005-2.553 0-6.603-2.05-6.603-1.32 0 .646 4.187 4.017 6.924 4.796V35c0 .553.447 1 1 1s1-.447 1-1v-6.166c2.738-.779 6.924-4.15 6.924-4.796 0-.729-4.05 1.32-6.604 1.32z'\/><path fill='#A0041E' d='M26.527 7.353c-3.887-4.412 1.506-5.882-2.592-5.882-.713 0-1.921.44-3.29 1.189C19.951 1.088 19.023 0 18 0c-2.05 0-3.726 4.342-3.873 8.269-1.108 1.543-1.855 3.235-1.855 4.966 0 6.092 2.591 8.823 6.479 8.823 7.776.001 13.644-8.047 7.776-14.705z'\/><path fill='#BE1931' d='M23.728 13.235c0 6.092-2.59 8.823-6.48 8.823-7.776 0-13.643-8.048-7.776-14.706C13.361 2.94 7.967 1.47 12.064 1.47c2.593.001 11.664 5.674 11.664 11.765z'\/><\/svg>\", label: 'Rosa' },\r\n  'carta': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><rect x='1' y='5' width='34' height='26' rx='3' fill='#E1E8ED' stroke='#99AAB5' stroke-width='0.8'\/><path d='M1 8 L18 19 L35 8' fill='none' stroke='#99AAB5' stroke-width='1.2'\/><path d='M1 5 L18 16 L35 5' fill='#CCD6DD'\/><defs><radialGradient id='lacreG' cx='40%' cy='35%'><stop offset='0%' stop-color='#cc2020'\/><stop offset='60%' stop-color='#8b0000'\/><stop offset='100%' stop-color='#4a0000'\/><\/radialGradient><\/defs><circle cx='18' cy='21' r='6.5' fill='url(#lacreG)' stroke='#600000' stroke-width='0.5'\/><ellipse cx='15.5' cy='18.5' rx='2' ry='1.2' fill='rgba(255,100,100,0.35)' transform='rotate(-20 15.5 18.5)'\/><\/svg>\", label: 'Carta sellada' },\r\n  'trofeo': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#FFAC33' d='M5.123 5h6C12.227 5 13 4.896 13 6V4c0-1.104-.773-2-1.877-2h-8c-2 0-3.583 2.125-3 5 0 0 1.791 9.375 1.917 9.958C2.373 18.5 4.164 20 6.081 20h6.958c1.105 0-.039-1.896-.039-3v-2c0 1.104-.773 2-1.877 2h-4c-1.104 0-1.833-1.042-2-2S3.539 7.667 3.539 7.667C3.206 5.75 4.018 5 5.123 5zm25.812 0h-6C23.831 5 22 4.896 22 6V4c0-1.104 1.831-2 2.935-2h8c2 0 3.584 2.125 3 5 0 0-1.633 9.419-1.771 10-.354 1.5-2.042 3-4 3h-7.146C21.914 20 22 18.104 22 17v-2c0 1.104 1.831 2 2.935 2h4c1.104 0 1.834-1.042 2-2s1.584-7.333 1.584-7.333C32.851 5.75 32.04 5 30.935 5zM20.832 22c0-6.958-2.709 0-2.709 0s-3-6.958-3 0-3.291 10-3.291 10h12.292c-.001 0-3.292-3.042-3.292-10z'\/><path fill='#FFCC4D' d='M29.123 6.577c0 6.775-6.77 18.192-11 18.192-4.231 0-11-11.417-11-18.192 0-5.195 1-6.319 3-6.319 1.374 0 6.025-.027 8-.027l7-.001c2.917-.001 4 .684 4 6.347z'\/><path fill='#C1694F' d='M27 33c0 1.104.227 2-.877 2h-16C9.018 35 9 34.104 9 33v-1c0-1.104 1.164-2 2.206-2h13.917c1.042 0 1.877.896 1.877 2v1z'\/><path fill='#C1694F' d='M29 34.625c0 .76.165 1.375-1.252 1.375H8.498C7.206 36 7 35.385 7 34.625v-.25C7 33.615 7.738 33 8.498 33h19.25c.759 0 1.252.615 1.252 1.375v.25z'\/><\/svg>\", label: 'Trofeo' },\r\n  'llave': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#C1694F' d='M32.614 3.414C28.31-.89 21.332-.89 17.027 3.414c-3.391 3.392-4.098 8.439-2.144 12.535l-3.916 3.915c-.64.641-.841 1.543-.625 2.359l-1.973 1.972c-.479-.48-1.252-.48-1.731 0l-1.731 1.732c-.479.479-.479 1.253 0 1.732l-.867.864c-.479-.478-1.253-.478-1.731 0l-.866.867c-.479.479-.479 1.253 0 1.732.015.016.036.02.051.033-.794 1.189-.668 2.812.382 3.863 1.195 1.195 3.134 1.195 4.329 0L20.08 21.144c4.097 1.955 9.144 1.247 12.535-2.146 4.302-4.302 4.302-11.28-.001-15.584zm-1.731 5.195c-.957.956-2.509.956-3.464 0-.956-.956-.956-2.507 0-3.464.955-.956 2.507-.956 3.464 0 .956.957.956 2.508 0 3.464z'\/><\/svg>\", label: 'Llave' },\r\n  'libro': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#553788' d='M15 31c0 2.209-.791 4-3 4H5c-4 0-4-14 0-14h7c2.209 0 3 1.791 3 4v6z'\/><path fill='#9266CC' d='M34 33h-1V23h1c.553 0 1-.447 1-1s-.447-1-1-1H10c-4 0-4 14 0 14h24c.553 0 1-.447 1-1s-.447-1-1-1z'\/><path fill='#CCD6DD' d='M34.172 33H11c-2 0-2-10 0-10h23.172c1.104 0 1.104 10 0 10z'\/><path fill='#99AAB5' d='M11.5 25h23.35c-.135-1.175-.36-2-.678-2H11c-1.651 0-1.938 6.808-.863 9.188C9.745 29.229 10.199 25 11.5 25z'\/><path fill='#269' d='M12 8c0 2.209-1.791 4-4 4H4C0 12 0 1 4 1h4c2.209 0 4 1.791 4 4v3z'\/><path fill='#55ACEE' d='M31 10h-1V3h1c.553 0 1-.447 1-1s-.447-1-1-1H7C3 1 3 12 7 12h24c.553 0 1-.447 1-1s-.447-1-1-1z'\/><path fill='#CCD6DD' d='M31.172 10H8c-2 0-2-7 0-7h23.172c1.104 0 1.104 7 0 7z'\/><path fill='#99AAB5' d='M8 5h23.925c-.114-1.125-.364-2-.753-2H8C6.807 3 6.331 5.489 6.562 7.5 6.718 6.142 7.193 5 8 5z'\/><path fill='#F4900C' d='M20 17c0 2.209-1.791 4-4 4H6c-4 0-4-9 0-9h10c2.209 0 4 1.791 4 4v1z'\/><path fill='#FFAC33' d='M35 19h-1v-5h1c.553 0 1-.447 1-1s-.447-1-1-1H15c-4 0-4 9 0 9h20c.553 0 1-.447 1-1s-.447-1-1-1z'\/><path fill='#CCD6DD' d='M35.172 19H16c-2 0-2-5 0-5h19.172c1.104 0 1.104 5 0 5z'\/><path fill='#99AAB5' d='M16 16h19.984c-.065-1.062-.334-2-.812-2H16c-1.274 0-1.733 2.027-1.383 3.5.198-.839.657-1.5 1.383-1.5z'\/><\/svg>\", label: 'Libro' },\r\n  'vela': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#67757F' d='M20 21.5c0 .828-.672 1.5-1.5 1.5-.829 0-1.5-.672-1.5-1.5v-3c0-.829.671-1.5 1.5-1.5.828 0 1.5.671 1.5 1.5v3z'\/><path fill='#E1E8ED' d='M27.138 33.817C27.183 35.022 26.206 36 25 36H12.183C10.977 36 10 35.022 10 33.817V21c0-1.205.115-2.183 2.183-2.183S15 23 25 21c1.091 0 2.183.978 2.138 2.183v10.634z'\/><path fill='#FCAB40' d='M18.687 18.538c-2.595 0-6.962-1.934-6.962-5.898 0-3.988 4.351-5.414 7.005-11.401.751-1.693.999-1.107 1.86-.076 2.06 2.463 5.058 7.483 5.058 11.574-.001 4.641-4.64 5.801-6.961 5.801z'\/><path fill='#FDCB58' d='M18.687 17.447c-4.184 0-3.482-5.802 0-9.283 2.321 1.16 5.801 9.283 0 9.283z'\/><path fill='#CCD6DD' d='M11 29c0 .553-.448 1-1 1s-1-.447-1-1v-7c0-.553.448-1 1-1s1 .447 1 1v7zm4 3c0 .553-.448 1-1 1s-1-.447-1-1v-7c0-.553.448-1 1-1s1 .447 1 1v7zm0-11c0 .553-.448 1-1 1s-1-.447-1-1v-1c0-.553.448-1 1-1s1 .447 1 1v1z'\/><\/svg>\", label: 'Vela' },\r\n  'cruz': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#9266CC' d='M36 32c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V4c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v28z'\/><path fill='#FFF' d='M26 10h-6V4c0-.552-.447-1-1-1h-2c-.552 0-1 .448-1 1v6h-6c-.552 0-1 .448-1 1v2c0 .552.448 1 1 1h6v18c0 .553.448 1 1 1h2c.553 0 1-.447 1-1V14h6c.553 0 1-.448 1-1v-2c0-.552-.447-1-1-1z'\/><\/svg>\", label: 'Cruz' },\r\n  'atardecer': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#FFCC4D' d='M32 0H4C1.791 0 0 1.791 0 4v28h36V4c0-2.209-1.791-4-4-4z'\/><path fill='#F4900C' d='M32.114 16.736c1.587-.451 1.587-1.147.001-1.599l-.559-.154L31 14.82v.005l-2.94-.891L30.383 12h-.014l.493-.322.497-.359c1.291-1.023 1.008-1.686-.629-1.498l-.636.089-.632.09h-.002l-2.979.339 1.77-3.18.309-.558c.802-1.44.281-1.963-1.158-1.163l-.558.282-.556.28h-.002L23.66 7.489 24 4.542v-.003l.08-.632.077-.638c.188-1.634-.492-1.915-1.516-.623l-.394.499-2.257 2.851-.819-2.881-.002-.005-.348-1.225c-.451-1.587-1.19-1.587-1.642 0l-.174.612-.174.613-.821 2.886-1.861-2.35-.001-.001-.395-.499-.397-.501c-1.023-1.29-1.704-1.007-1.515.629l.074.634.073.632v.001l.346 2.979-3.177-1.77-.557-.311c-1.441-.802-1.963-.28-1.161 1.161l.31.556 1.77 3.177-2.979-.346h-.001l-.632-.073-.635-.074c-1.636-.189-1.918.492-.629 1.515l.501.397.499.395.001.001 2.35 1.861-2.884.822-.612.174-.612.174c-1.587.452-1.587 1.19 0 1.642l1.225.348.004.002 2.881.819-2.851 2.258-.499.396c-1.292 1.023-1.011 1.705.623 1.517l.638-.08.632-.081h.002l2.948-.34L8 24.286v.002l-.28.556-.296.559c-.8 1.44-.271 1.96 1.169 1.158l.56-.309 3.185-1.77L12 27.46v.002l-.08.632-.077.635c-.189 1.637.491 1.918 1.514.627l.396-.5.395-.5 1.862-2.352.82 2.885v.001l.174.612.175.613c.452 1.586 1.105 1.586 1.557-.001L19 28.89v-.004l.905-2.882 1.905 2.352.416.5.407.5c1.022 1.29 1.71 1.01 1.521-.625l-.078-.637-.076-.633v-.003l-.34-2.947L26.284 26h.002l.557.28.558.295c1.44.803 1.963.273 1.16-1.167l-.28-.56L28 24.29v-.002l-1.489-2.628 2.947.34h.003l.633.08.637.077c1.635.188 1.915-.492.625-1.515l-.5-.395-.5-.395-2.352-1.947L30.886 17h.004l1.224-.264z'\/><circle fill='#FFE8B6' cx='18' cy='16' r='9.63'\/><path fill='#485359' d='M10 36V15l4-4h2l4 4v21zm23-17c0-1-1-1-1-1h-7s-1 0-1 1v17h9V19z'\/><path fill='#292F33' d='M28 25c0-1-1-1-1-1h-8c-1 0-1 1-1 1v11h10V25zm-17 2H6v-5s0-1-1-1H0v11c0 2.209 1.791 4 4 4h8v-8s0-1-1-1zm21 4c-1 0-1 1-1 1v4h1c2.209 0 4-1.791 4-4v-1h-4z'\/><path d='M8 29h2v2H8zm-2 4h2v2H6zm10-16h2v2h-2zm0 4h2v2h-2zm-2 4h2v2h-2zm10 1h2v2h-2zm-2 4h2v2h-2zm7-10h2v2h-2zm0 4h2v2h-2z' fill='#FFCC4D'\/><\/svg>\", label: 'Atardecer' },\r\n  'mar': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#FFCC4D' d='M32 0H4C1.791 0 0 1.791 0 4v19h36V4c0-2.209-1.791-4-4-4z'\/><path fill='#F4900C' d='M32.114 18.736c1.587-.451 1.587-1.147.001-1.599l-.559-.154L31 16.82v.005l-2.94-.891L30.383 14h-.014l.493-.322.497-.359c1.291-1.023 1.008-1.686-.629-1.498l-.636.089-.632.09h-.002l-2.979.339 1.77-3.18.309-.558c.802-1.44.281-1.963-1.158-1.163l-.558.282-.556.28h-.002L23.66 9.489 24 6.543V6.54l.08-.632.077-.638c.188-1.634-.492-1.915-1.516-.623l-.394.499-2.257 2.85-.819-2.881-.002-.005-.348-1.225c-.451-1.587-1.19-1.587-1.642 0l-.174.612-.174.613-.821 2.886-1.861-2.35-.001-.001-.395-.499-.397-.501c-1.023-1.29-1.704-1.007-1.515.629l.074.634.073.632v.001l.346 2.979-3.177-1.77-.557-.31c-1.441-.803-1.963-.281-1.161 1.16l.31.556 1.77 3.177-2.979-.346h-.001l-.632-.073-.635-.074c-1.636-.189-1.918.492-.629 1.515l.501.397.499.395.001.001 2.35 1.861-2.884.822-.612.174-.612.174c-1.587.452-1.587 1.19 0 1.642l1.225.348.004.002 2.881.819-2.851 2.258-.499.396c-1.292 1.023-1.011 1.705.623 1.517l.638-.08.632-.081h.002l2.948-.34L8 26.286v.002l-.28.556-.296.558c-.8 1.44-.271 1.96 1.169 1.158l.56-.309 3.185-1.77L12 29.46v.002l-.08.632-.077.635c-.189 1.637.491 1.918 1.514.627l.396-.5.395-.5 1.862-2.352.82 2.885v.001l.174.612.175.613c.452 1.586 1.105 1.586 1.557-.001L19 30.89v-.004l.905-2.882 1.905 2.352.416.5.407.5c1.022 1.29 1.71 1.01 1.521-.625l-.078-.637-.076-.633v-.003l-.34-2.947L26.284 28h.002l.557.28.558.295c1.44.803 1.963.272 1.16-1.167l-.28-.561L28 26.29v-.002l-1.489-2.628 2.947.34h.003l.633.08.637.077c1.635.189 1.915-.492.625-1.515l-.5-.396-.5-.395-2.352-1.947L30.886 19h.004l1.224-.264z'\/><circle fill='#FFE8B6' cx='18' cy='18' r='9.63'\/><path fill='#269' d='M0 22v10c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4V22H0z'\/><path d='M22 28c-1.979 0-3.25-.749-4-1.437-.75.688-2.021 1.437-4 1.437-3.577 0-4.842-2.448-4.895-2.553-.247-.494-.047-1.095.447-1.342.491-.244 1.086-.049 1.336.437.046.082.834 1.458 3.112 1.458 2.298 0 3.08-1.4 3.112-1.46.177-.328.503-.524.899-.533.373.006.716.212.883.546C18.92 24.6 19.701 26 22 26s3.08-1.4 3.112-1.46c.26-.481.859-.673 1.345-.42.485.251.682.839.438 1.327C26.843 25.552 25.577 28 22 28zm4 6c-1.979 0-3.25-.749-4-1.437-.75.688-2.021 1.437-4 1.437s-3.25-.749-4-1.437c-.75.688-2.021 1.437-4 1.437-3.577 0-4.842-2.448-4.895-2.553-.247-.494-.047-1.095.447-1.342.491-.243 1.086-.049 1.336.437C6.934 30.624 7.722 32 10 32c2.298 0 3.08-1.4 3.112-1.46.177-.328.523-.534.899-.533.373.006.716.212.883.546C14.92 30.6 15.702 32 18 32c2.299 0 3.08-1.4 3.112-1.46.177-.328.53-.541.899-.533.373.006.716.212.883.546C22.92 30.6 23.701 32 26 32s3.08-1.4 3.112-1.46c.26-.481.86-.673 1.345-.42.485.251.682.839.438 1.327C30.843 31.552 29.577 34 26 34z' fill='#3B88C3'\/><\/svg>\", label: 'Mar y sol' },\r\n  'montana': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#292F33' d='M19.083 35.5L12.25 12.292s-1.42.761-2.604 1.637c-.313.231-1.977 2.79-2.312 3.04-1.762 1.315-3.552 2.841-3.792 3.167C3.083 20.76 0 36 0 36l19.083-.5z'\/><path fill='#4B545D' d='M26.5 15.25l-7.312-9.212L18 2.25l-5.373 6.484-.971 1.172C11.25 10.688 10 15.25 10 15.25L8.75 20 3.252 30.054.917 34.791 32 35l-5.5-19.75z'\/><path fill='#292F33' d='M12 34h2l2-15.75 1.234-1.797 3.578-5.234.094-1.469-3.287 4.454L15 17.752l-2.388 7.362L12 27l-1.791 3.134L8 34zm12.059-17.616l-1.965 5.897L21 26l2.792 7.625 3.552-.062S23 26.625 23 26c0-.12.625-2.687.625-2.687l1.094-4.531L25 17.25l-.941-.866z'\/><path fill='#292F33' d='M36 36s-.384-3.845-.854-7.083c0 0-.146-3.885-1.271-5.167-1.049-1.195-2.624-1.875-2.833-1.962l-1.229-3.523L27.953 13l-2.422-2.125-1.844-1.626-.505-.621L18 2.25l2.289 7.299.524 1.67 3.246 5.165.66 2.397 1.438 2.281.774 2.701L28 27.5 26 34l10 2z'\/><path fill='#5C903F' d='M33.708 32.438c-1.345 0-4.958.562-5.458.562-2 0-4.25-1.75-5.25-1.75S19.406 33 17.406 33c-1.688 0-2.406-.812-4.719-.812-.748 0-4.096.871-4.812.781C6.052 32.741 5.115 32 4.656 32 2 32 0 36 0 36h36s-.875-3.562-2.292-3.562z'\/><\/svg>\", label: 'Monta\u00f1a' },\r\n  'paloma': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#5C913B' d='M.794 16.112c1 0 5.875 1.344 6.5 2.312L6.013 18.3s-3.906-1.25-4.906-1.25c-1.001 0-.313-.938-.313-.938z'\/><path fill='#99AAB5' d='M11 2c1 1 3 7 3 10s-2 6 2 8 5.001-1 5.001-5S20 7 19 5s-2 0-2 0-1-4-2-4-1 2-1 2-2-2-3-2 0 1 0 1z'\/><path fill='#CCD6DD' d='M10 15c3 0 4 4 6 4s1-3 3-3 10-5 10-11 3-3 3-1c1 0 2 1.586 2 3 0 1 0 2-1 3 1 0 2 2 1 3 1 3-1 6-3 7 0 1-2 3-4 2 0 0-1 3-3 2 0 0 3.052 1.684 4 2 3 1 7 1 7 1s0 1-2 2c0 0 1 1 0 2s-2 1-2 1 1 2-2 1-6-4-6-4-5 1-9-1-6-6-6-8-3-1-4-1 2-2 3-2c0 0 0-2 3-2z'\/><path fill='#5C913B' d='M6.95 18.019s5.438 2.625 7.938 6.656c1.9 3.064 2.782 8.656 2.782 8.656s.043.564-.907-2.281c-1-3-2.217-6.288-4.312-8.188-3.344-3.031-4.75-3.5-6.062-4.25-.332-.189.217-.687.561-.593z'\/><path fill='#5C913B' d='M16.198 28.54s2.038.103 3.107 2.139c1.068 2.036-.053 4.914-.053 4.914s-2.75-1.268-3.462-2.947c-.712-1.68.408-4.106.408-4.106zm-2.133-4.778s1.274 1.437 3.558 1.705c2.284.269 4.121-1.379 4.121-1.379s-2.144-1.97-3.968-2.033c-1.823-.065-3.711 1.707-3.711 1.707zm-4.047-3.148s-2.015.329-2.85 2.472.425 4.01.425 4.01 2.534-.848 3.055-2.597c.521-1.747-.63-3.885-.63-3.885z'\/><\/svg>\", label: 'Paloma paz' },\r\n  'yinyang': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#9266CC' d='M36 32c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V4c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v28z'\/><path fill='#FFF' d='M18.964 4.033C11.251 3.501 4.566 9.322 4.033 17.036s5.289 14.399 13.002 14.931c7.714.533 14.399-5.289 14.931-13.002.533-7.714-5.288-14.399-13.002-14.932zm-1.183 25.983c-3.317-.06-5.958-2.799-5.897-6.118C11.943 20.583 14.683 17.94 18 18c3.317.06 6.056-2.581 6.118-5.897.046-2.558-1.524-4.748-3.758-5.657l.151-.171c5.517 1.174 9.612 6.096 9.506 11.943-.122 6.639-5.597 11.919-12.236 11.798z'\/><circle fill='#FFF' cx='18' cy='24' r='2.5'\/><circle fill='#9266CC' cx='18' cy='12' r='2.5'\/><\/svg>\", label: 'Yin Yang' },\r\n  'familia': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#FFAC33' d='M31.72.302c-1.703-.551-5.71-.401-6.712.902-2.605.05-5.66 2.404-6.061 5.51-.397 3.074.487 4.501.801 6.812.356 2.618 1.828 3.456 3.005 3.807 1.693 2.237 3.493 2.141 6.516 2.141 3.043 0 5.258-1.057 6.73-2.993V2.834C34.925 1.737 33.487.873 31.72.302z'\/><path fill='#FFDC5D' d='M26.05 17.786h5.059v10H26.05z'\/><path fill='#FFDC5D' d='M35.248 9.103c-.571-.791-1.302-1.427-2.905-1.653.601.275 1.177 1.227 1.252 1.753.075.526.15.952-.326.426-1.906-2.107-3.982-1.277-6.039-2.564-1.437-.899-1.875-1.893-1.875-1.893s-.175 1.327-2.354 2.68c-.632.392-1.385 1.265-1.803 2.554-.301.927-.207 1.753-.207 3.165 0 1.145.27 2.235.738 3.219 1.218 2.558 3.823 4.37 6.85 4.37 2.587 0 4.869-1.335 6.239-3.317.561-.812.97-1.733 1.181-2.717v-4.138c-.144-.83-.385-1.378-.751-1.885z'\/><path fill='#C1694F' d='M31.952 17.786h-6.746s.843 1.686 3.373 1.686 3.373-1.686 3.373-1.686zm-2.529-2.107h-1.686c-.233 0-.422-.189-.422-.422 0-.233.189-.422.422-.422h1.686c.233 0 .422.189.422.422-.001.233-.189.422-.422.422z'\/><path fill='#662113' d='M25.207 12.728c-.466 0-.843-.378-.843-.843v-.843c0-.466.378-.843.843-.843.466 0 .843.378.843.843v.843c0 .465-.377.843-.843.843zm6.745 0c-.466 0-.843-.378-.843-.843v-.843c0-.466.378-.843.843-.843.466 0 .843.378.843.843v.843c.001.465-.377.843-.843.843z'\/><path fill='#FA743E' d='M21 22h5s.198 4.773 2.472 4.773S31.084 22 31.084 22H36v14H18V24.973C18 23 19 22 21 22z'\/><path fill='#DD551F' d='M20.986 26h1.028v10h-1.028z'\/><path fill='#FFAC33' d='M8.27 19.473c5.902 0 8.713-3.949 8.962-10.656.15-4.057-2.23-7.13-6.511-8.515-1.704-.551-5.711-.401-6.713.901-1.362.026-2.844.686-4.008 1.751v13.375c.548.544 1.185.834 1.754 1.003 1.694 2.237 3.494 2.141 6.516 2.141z'\/><path fill='#FFDC5D' d='M4.897 17.786h5.059v10H4.897z'\/><path fill='#FFDC5D' d='M14.095 9.103c-.571-.791-1.302-1.427-2.905-1.653.601.275 1.177 1.227 1.252 1.753.075.526.15.952-.326.426-1.906-2.107-3.982-1.277-6.039-2.564-1.436-.899-1.874-1.894-1.874-1.894s-.175 1.327-2.354 2.68C1.217 8.243.464 9.116.046 10.405c-.022.067-.028.132-.046.198v4.506c.124.587.323 1.148.577 1.68 1.218 2.558 3.823 4.37 6.85 4.37 2.587 0 4.869-1.335 6.239-3.317.849-1.229 1.349-2.705 1.349-4.271 0-2.565-.268-3.566-.92-4.468z'\/><path fill='#C1694F' d='M10.799 17.786H4.053s.843 1.686 3.373 1.686 3.373-1.686 3.373-1.686zM8.27 15.679H6.584c-.233 0-.422-.189-.422-.422 0-.233.189-.422.422-.422H8.27c.233 0 .422.189.422.422 0 .233-.189.422-.422.422z'\/><path fill='#662113' d='M4.054 12.728c-.466 0-.843-.378-.843-.843v-.843c0-.466.378-.843.843-.843.466 0 .843.378.843.843v.843c0 .465-.377.843-.843.843zm6.745 0c-.466 0-.843-.378-.843-.843v-.843c0-.466.378-.843.843-.843.466 0 .843.378.843.843v.843c.001.465-.377.843-.843.843z'\/><path fill='#99AAB5' d='M15 22h-5s-.198 4.773-2.472 4.773S4.897 22 4.897 22H0v14h18V24.973C18 23 17 22 15 22z'\/><path fill='#66757F' d='M13.986 26h1.028v10h-1.028z'\/><path fill='#FFAC33' d='M20.959 15.053c-1.464-.474-4.909-.345-5.771.775-2.239.043-4.866 2.067-5.211 4.737-.341 2.643.419 3.87.689 5.857.306 2.251 1.572 2.971 2.584 3.273 1.456 1.923 3.003 1.841 5.602 1.841 5.074 0 7.491-3.395 7.705-9.162.129-3.489-1.917-6.13-5.598-7.321z'\/><path fill='#FFDC5D' d='M16.053 30.085h4.148V36h-4.148z'\/><path fill='#FFDC5D' d='M23.861 22.62c-.491-.68-1.12-1.227-2.498-1.421.517.237 1.012 1.055 1.077 1.507.065.452.129.818-.28.366-1.639-1.811-3.424-1.098-5.192-2.205-1.235-.773-1.612-1.628-1.612-1.628s-.151 1.141-2.024 2.304c-.543.337-1.191 1.088-1.55 2.196-.258.797-.178 1.507-.178 2.721 0 3.544 2.921 6.524 6.524 6.524s6.524-3.006 6.524-6.524c-.001-2.204-.232-3.065-.791-3.84z'\/><path fill='#C1694F' d='M21.027 30.085h-5.8s.725 1.45 2.9 1.45 2.9-1.45 2.9-1.45zm-2.175-1.449h-1.45c-.2 0-.362-.162-.362-.362s.162-.362.362-.362h1.45c.2 0 .362.162.362.362s-.162.362-.362.362z'\/><path fill='#662113' d='M15.091 26.764c-.466 0-.843-.377-.843-.843v-.843c0-.466.377-.843.843-.843.465 0 .843.377.843.843v.843c0 .466-.377.843-.843.843zm6 0c-.466 0-.843-.377-.843-.843v-.843c0-.466.377-.843.843-.843.466 0 .843.377.843.843v.843c0 .466-.377.843-.843.843z'\/><path fill='#5C913B' d='M23.091 33h-2.89s-.705 3-2.074 3c-1.368 0-2.074-3-2.074-3h-1.962c-.368 0-.719.032-1.055.088-1.941.326-3.301 1.535-3.759 2.912h17.632c-.518-1.602-2.159-3-3.818-3z'\/><\/svg>\", label: 'Familia' },\r\n  'cajafuerte': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#AAB8C2' d='M13 3C7.477 3 3 7.477 3 13v10h4V13c0-3.313 2.687-6 6-6s6 2.687 6 6v10h4V13c0-5.523-4.477-10-10-10z'\/><path fill='#FFAC33' d='M26 32c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V20c0-2.209 1.791-4 4-4h18c2.209 0 4 1.791 4 4v12z'\/><path fill='#C1694F' d='M35 9c0-4.971-4.029-9-9-9s-9 4.029-9 9c0 3.917 2.507 7.24 6 8.477V33.5c0 1.381 1.119 2.5 2.5 2.5 1.213 0 2.223-.864 2.45-2.01.018.001.032.01.05.01.553 0 1-.447 1-1v-1c0-.553-.447-1-1-1v-1c.553 0 1-.447 1-1v-2c0-.553-.447-1-1-1v-2.277c.596-.347 1-.984 1-1.723v-4.523c3.493-1.236 6-4.559 6-8.477zm-9-7c1.104 0 2 .896 2 2s-.896 2-2 2-2-.896-2-2 .896-2 2-2z'\/><\/svg>\", label: 'Caja fuerte' },\r\n  'velero': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 36 36'><path fill='#A7A9AC' d='M20 26c0 .553-.447 1-1 1-.552 0-1-.447-1-1V1c0-.552.448-1 1-1 .553 0 1 .448 1 1v25z'\/><path fill='#D1D3D4' d='M3 24h31v8H12c-6 0-9-8-9-8z'\/><path fill='#55ACEE' d='M0 30h36v6H0z'\/><path fill='#FFAC33' d='M5 22s2-5 5-9 8-8 8-8-1 11-1 16v1s-3-1-6-1-6 1-6 1z'\/><path fill='#F4900C' d='M20 2s6 6 9 11c2.771 4.618 4 9 4 9s-3-1-6-1-6 1-6 1v-1c0-9-1-19-1-19z'\/><path fill='#E6E7E8' d='M2 24c-.552 0-1 .447-1 1s.448 1 1 1h33v-2H2z'\/><\/svg>\", label: 'Velero' },\r\n  'partitura': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 80 80'><rect width='80' height='80' rx='8' fill='#f5edc8'\/><line x1='8' y1='36' x2='72' y2='36' stroke='#8b6020' stroke-width='1'\/><line x1='8' y1='42' x2='72' y2='42' stroke='#8b6020' stroke-width='1'\/><line x1='8' y1='48' x2='72' y2='48' stroke='#8b6020' stroke-width='1'\/><line x1='8' y1='54' x2='72' y2='54' stroke='#8b6020' stroke-width='1'\/><line x1='8' y1='60' x2='72' y2='60' stroke='#8b6020' stroke-width='1'\/><text x='16' y='62' font-family='Georgia,serif' font-size='52' fill='#3a1a05' font-style='italic'>&#119070;<\/text><ellipse cx='54' cy='59' rx='7' ry='5' fill='#3a1a05' transform='rotate(-15 54 59)'\/><line x1='61' y1='57' x2='61' y2='36' stroke='#3a1a05' stroke-width='2'\/><\/svg>\", label: 'Partituras' },\r\n  'esvastica': { svg: \"<svg xmlns='http:\/\/www.w3.org\/2000\/svg' viewBox='0 0 100 100'><rect width='100' height='100' rx='6' fill='#cc1010'\/><path d='M50 18 L50 50 L82 50 L82 36 M50 82 L50 50 L18 50 L18 64 M18 50 L50 50 L50 18 L64 18 M82 50 L50 50 L50 82 L36 82' fill='none' stroke='#f0e060' stroke-width='8' stroke-linecap='square'\/><\/svg>\", label: 'Sv\u00e1stica hind\u00fa' },\r\n};\r\n\/\/ Mapas SVG de colores de carpeta seg\u00fan categor\u00eda de icono\r\nfunction carpetaSVG(color1, color2, w, h) {\r\n  w = w || 100; h = h || 88;\r\n  return '<svg viewBox=\"0 0 100 92\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"c-carpeta-svg\">'\r\n    \/\/ Sombra base\r\n    + '<ellipse cx=\"50\" cy=\"90\" rx=\"38\" ry=\"3.5\" fill=\"rgba(0,0,0,0.35)\"\/>'\r\n    \/\/ Cuerpo principal de la carpeta (m\u00e1s alto para el emoji)\r\n    + '<path d=\"M4,26 L4,80 Q4,87 11,87 L89,87 Q96,87 96,80 L96,36 Q96,29 89,29 L51,29 L43,22 L14,22 Q4,22 4,26 Z\"'\r\n    + ' fill=\"' + color1 + '\" stroke=\"rgba(210,165,55,0.5)\" stroke-width=\"1.5\"\/>'\r\n    \/\/ Pesta\u00f1a superior\r\n    + '<path d=\"M4,26 L4,32 L96,32 L96,36 Q96,29 89,29 L51,29 L43,22 L14,22 Q4,22 4,26 Z\"'\r\n    + ' fill=\"' + color2.replace('0.4','0.55').replace('0.45','0.6') + '\"\/>'\r\n    \/\/ L\u00ednea divisoria\r\n    + '<line x1=\"4\" y1=\"32\" x2=\"96\" y2=\"32\" stroke=\"' + color2 + '\" stroke-width=\"1.2\"\/>'\r\n    + '<\/svg>';\r\n}\r\n\r\n\/\/ Color de carpeta seg\u00fan estado\r\n\/\/ Color de carpeta \u2014 usa el color personalizado si existe, sino verde por defecto\r\nfunction carpetaColores(estado, colorKey) {\r\n  var base = mcPaletaColores(colorKey || 'verde');\r\n  \/\/ Para cerrada\/oculta oscurecemos el tono base\r\n  if (estado === 'cerrada') {\r\n    return [base[0].replace(\/[\\d.]+\\)$\/, '0.75)'), base[1].replace(\/[\\d.]+\\)$\/, '0.4)')];\r\n  }\r\n  if (estado === 'oculta') {\r\n    \/\/ Tono azulado oscuro independientemente del color base\r\n    return ['rgba(20,50,55,0.92)', 'rgba(40,100,110,0.5)'];\r\n  }\r\n  return base;\r\n}\r\n\r\n\/\/ Formatear fecha para mostrar\r\nfunction formatFecha(fechaStr) {\r\n  if (!fechaStr) return '';\r\n  var d = new Date(fechaStr);\r\n  var dia = ('0' + d.getDate()).slice(-2);\r\n  var mes = ('0' + (d.getMonth()+1)).slice(-2);\r\n  var anio = d.getFullYear();\r\n  return dia + '\/' + mes + '\/' + anio;\r\n}\r\n\r\n\/\/ \u2500\u2500 Cargar y renderizar carpetas en la cripta \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction cargarCarpetas() {\r\n  if (!cdhSepId) return;\r\n  var headers = {};\r\n  if (window.cdhNonce) headers['X-WP-Nonce'] = window.cdhNonce;\r\n  fetch('\/index.php\/wp-json\/cdh\/v1\/carpetas?sep_id=' + cdhSepId, {\r\n    headers: headers,\r\n    credentials: 'same-origin'\r\n  })\r\n  .then(function(r) { return r.json(); })\r\n  .then(function(data) {\r\n    mcCarpetas = Array.isArray(data) ? data : [];\r\n    mapaHtmlCache = null;\r\n    mapaPrecarga();\r\n    renderCarpetasCripta();\r\n    renderListaCarpetasModal();\r\n    actualizarLimite();\r\n  })\r\n  .catch(function() {});\r\n}\r\n\r\ndocument.addEventListener('DOMContentLoaded', function() {\r\n  \/\/ cargarCarpetas se llama directamente desde cargarDatos() una vez disponible cdhSepId\r\n});\r\n\r\n\/\/ \u2500\u2500 Encajar iconos y modulos dentro de la pantalla \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\/\/ Las posiciones se guardan en pixeles absolutos, medidos en la pantalla\r\n\/\/ donde el propietario coloco cada cosa. En un movil, cualquiera que caiga\r\n\/\/ mas alla del ancho o del alto se queda fuera y el visitante no la ve.\r\n\/\/ Aqui se traen dentro SIN guardar nada: la disposicion original del\r\n\/\/ propietario no se toca, solo se corrige lo que se pinta en esta pantalla.\r\nfunction criptaFijarOrigen(el, x, y) {\r\n  if (!el) return;\r\n  el.dataset.cdhOrigX = x;\r\n  el.dataset.cdhOrigY = y;\r\n}\r\n\r\nfunction criptaEncajarEnPantalla() {\r\n  var MARGEN = 8;\r\n  var maxW = window.innerWidth, maxH = window.innerHeight;\r\n  var elems = [];\r\n  var zona = document.getElementById('carpetasZona');\r\n  if (zona) {\r\n    Array.prototype.forEach.call(zona.querySelectorAll('.c-carpeta-item'), function(el) {\r\n      elems.push(el);\r\n    });\r\n  }\r\n  ['criptaArbol', 'criptaBiografia'].forEach(function(id) {\r\n    var el = document.getElementById(id);\r\n    if (el && el.style.display !== 'none') elems.push(el);\r\n  });\r\n\r\n  \/\/ Los que hay que rescatar de fuera se apuntan aqui, para no amontonarlos\r\n  \/\/ todos en el mismo borde.\r\n  var rescatados = [];\r\n  function ocupado(x, y, w, h) {\r\n    for (var i = 0; i < rescatados.length; i++) {\r\n      var r = rescatados[i];\r\n      if (x < r.x + r.w && x + w > r.x && y < r.y + r.h && y + h > r.y) return true;\r\n    }\r\n    return false;\r\n  }\r\n\r\n  elems.forEach(function(el) {\r\n    var w = el.offsetWidth  || 80;\r\n    var h = el.offsetHeight || 80;\r\n\r\n    \/\/ Origen = el sitio que le puso el propietario. Se recuerda en el propio\r\n    \/\/ elemento para que al volver a una pantalla ancha (girar el telefono)\r\n    \/\/ cada icono regrese a donde estaba, en vez de quedarse encogido.\r\n    if (el.dataset.cdhOrigX === undefined || el.dataset.cdhOrigY === undefined) {\r\n      criptaFijarOrigen(el, parseFloat(el.style.left) || 0, parseFloat(el.style.top) || 0);\r\n    }\r\n    var ox = parseFloat(el.dataset.cdhOrigX);\r\n    var oy = parseFloat(el.dataset.cdhOrigY);\r\n    if (isNaN(ox) || isNaN(oy)) return;\r\n\r\n    var topeX = Math.max(MARGEN, maxW - w - MARGEN);\r\n    var topeY = Math.max(MARGEN, maxH - h - MARGEN);\r\n    var x = Math.min(Math.max(ox, MARGEN), topeX);\r\n    var y = Math.min(Math.max(oy, MARGEN), topeY);\r\n\r\n    if (x !== ox || y !== oy) {\r\n      var paso = w + 12, vueltas = 0;\r\n      while (ocupado(x, y, w, h) && vueltas < 40) {\r\n        x -= paso;\r\n        if (x < MARGEN) { x = topeX; y -= h + 14; }\r\n        if (y < MARGEN) { y = topeY; }\r\n        vueltas++;\r\n      }\r\n      rescatados.push({ x: x, y: y, w: w, h: h });\r\n    }\r\n\r\n    el.style.left = Math.round(x) + 'px';\r\n    el.style.top  = Math.round(y) + 'px';\r\n  });\r\n}\r\n\r\n\/\/ Al girar el telefono o cambiar el tamano de la ventana hay que repasarlo.\r\n(function() {\r\n  var temporizador = null;\r\n  function alCambiarTamano() {\r\n    clearTimeout(temporizador);\r\n    temporizador = setTimeout(criptaEncajarEnPantalla, 160);\r\n  }\r\n  window.addEventListener('resize', alCambiarTamano);\r\n  window.addEventListener('orientationchange', alCambiarTamano);\r\n})();\r\n\r\n\/\/ Renderiza las carpetas flotantes en la cripta\r\nfunction renderCarpetasCripta() {\r\n  var zona = document.getElementById('carpetasZona');\r\n  if (!zona) return;\r\n  zona.innerHTML = '';\r\n  if (!mcCarpetas.length) { zona.classList.add('vacia'); return; }\r\n\r\n  var ahora = new Date();\r\n  var hayVisibles = false;\r\n  var positions = criptaLoadPos();\r\n  var autoX = 30;\r\n  var autoY = Math.max(100, window.innerHeight - 180);\r\n\r\n  mcCarpetas.forEach(function(c) {\r\n    if (expModoLectura && c.estado === 'oculta') {\r\n      if (!c.fecha_apertura) return;\r\n      if (new Date(c.fecha_apertura) > ahora) return;\r\n    }\r\n    hayVisibles = true;\r\n\r\n    var colores = carpetaColores(c.estado, c.color);\r\n    var icoData = (c.icono && mcIconosCat[c.icono]) ? mcIconosCat[c.icono] : null;\r\n    var esIcono = (c.tipo === 'icono') && icoData;\r\n    var item = document.createElement('div');\r\n    item.className = 'c-carpeta-item';\r\n    item.dataset.id = c.id;\r\n    \/\/ El propietario sigue viendo el candado y la fecha (le dicen c\u00f3mo tiene\r\n    \/\/ marcada la carpeta); al visitante, en cambio, se le quitan en cuanto la\r\n    \/\/ fecha llega, porque ya puede entrar.\r\n    var liberada = cdhCarpetaLiberada(c);\r\n    var lock = '';\r\n    if (!liberada && c.estado === 'cerrada') lock = '<span class=\"' + (esIcono ? 'c-icono-grande-lock' : 'c-carpeta-lock') + '\">\ud83d\udd12<\/span>';\r\n    if (!liberada && c.estado === 'oculta')  lock = '<span class=\"' + (esIcono ? 'c-icono-grande-lock' : 'c-carpeta-lock') + '\">\u23f3<\/span>';\r\n    var fechaHtml = '';\r\n    if (!liberada && c.estado === 'cerrada' && c.fecha_apertura) {\r\n      fechaHtml = '<div class=\"c-carpeta-fecha\">Se abre el ' + formatFecha(c.fecha_apertura) + '<\/div>';\r\n    }\r\n    var iconoWrap;\r\n    if (esIcono) {\r\n      iconoWrap = '<div class=\"c-icono-grande\" style=\"position:relative;\">' + icoData.svg + lock + '<\/div>';\r\n    } else {\r\n      var emSvg = (icoData && c.icono !== 'carpeta-basica') ? icoData.svg : '';\r\n      iconoWrap = '<div class=\"c-carpeta-icono-wrap\">' + carpetaSVG(colores[0], colores[1]) + (emSvg ? '<span class=\"c-carpeta-emoji\">' + emSvg + '<\/span>' : '') + lock + '<\/div>';\r\n    }\r\n    var accionesHtml = expModoLectura ? '' :\r\n      '<div class=\"c-carpeta-acciones\">'\r\n        + '<div class=\"c-carpeta-accion\" title=\"A\u00f1adir contenido\" onclick=\"abrirExplorador(' + c.id + ',\\'' + escapeHtml(c.nombre) + '\\',\\'' + c.estado + '\\',\\'' + (c.fecha_apertura||'') + '\\',\\'' + (c.icono||'') + '\\',\\'' + (c.tipo||'') + '\\');event.stopPropagation();\">+<\/div>'\r\n        + '<div class=\"c-carpeta-accion\" title=\"Editar\" onclick=\"editarCarpeta(' + c.id + ',event)\">\u270f\ufe0f<\/div>'\r\n        + '<div class=\"c-carpeta-accion\" title=\"Borrar\" onclick=\"borrarCarpeta(' + c.id + ',event)\">\ud83d\uddd1<\/div>'\r\n      + '<\/div>';\r\n    item.innerHTML = iconoWrap\r\n      + '<div class=\"c-carpeta-nombre\">' + escapeHtml(c.nombre) + '<\/div>'\r\n      + fechaHtml\r\n      + accionesHtml;\r\n    \/\/ Posici\u00f3n: guardada en servidor (todos la ven igual) > localStorage local (legado) > auto en fila inferior\r\n    var tienePosServidor = (c.pos_x !== null && c.pos_x !== undefined && c.pos_y !== null && c.pos_y !== undefined);\r\n    var saved = positions[c.id];\r\n    if (tienePosServidor) {\r\n      item.style.left = c.pos_x + 'px';\r\n      item.style.top  = c.pos_y + 'px';\r\n    } else if (saved) {\r\n      item.style.left = saved.x + 'px';\r\n      item.style.top  = saved.y + 'px';\r\n      \/\/ Migraci\u00f3n autom\u00e1tica: posici\u00f3n guardada solo en este navegador (de\r\n      \/\/ antes de existir el guardado en servidor) \u2014 la subimos una vez.\r\n      if (!expModoLectura && window.cdhNonce) {\r\n        fetch('\/index.php\/wp-json\/cdh\/v1\/carpetas\/' + c.id, {\r\n          method: 'PUT',\r\n          headers: { 'Content-Type': 'application\/json', 'X-WP-Nonce': window.cdhNonce },\r\n          credentials: 'same-origin',\r\n          body: JSON.stringify({ pos_x: saved.x, pos_y: saved.y })\r\n        }).catch(function(){});\r\n      }\r\n    } else {\r\n      item.style.left = autoX + 'px';\r\n      item.style.top  = autoY + 'px';\r\n      autoX += Math.min(140, Math.round(window.innerWidth * 0.10));\r\n      if (autoX > window.innerWidth - 120) { autoX = 30; autoY -= 130; }\r\n    }\r\n\r\n    zona.appendChild(item);\r\n\r\n    \/\/ Drag libre + click\r\n    (function(el, cId, cData) {\r\n      var ox=0,oy=0,sx=0,sy=0,moved=false,dragging=false,desdeAccion=false;\r\n      function guardarPosCarpeta(x, y) {\r\n        criptaFijarOrigen(el, x, y);   \/\/ lo que acaba de elegir manda\r\n        criptaSavePos(cId, x, y); \/\/ cach\u00e9 local instant\u00e1nea\r\n        if (expModoLectura || !window.cdhNonce) return;\r\n        fetch('\/index.php\/wp-json\/cdh\/v1\/carpetas\/' + cId, {\r\n          method: 'PUT',\r\n          headers: { 'Content-Type': 'application\/json', 'X-WP-Nonce': window.cdhNonce },\r\n          credentials: 'same-origin',\r\n          body: JSON.stringify({ pos_x: x, pos_y: y })\r\n        }).catch(function(){});\r\n      }\r\n      el.addEventListener('mousedown', function(e) {\r\n        if (expModoLectura) return;\r\n        if (e.button!==0 || e.target.closest('.c-carpeta-accion')) return;\r\n        e.preventDefault(); dragging=true; moved=false;\r\n        ox=el.offsetLeft; oy=el.offsetTop; sx=e.clientX; sy=e.clientY;\r\n        el.classList.add('dragging'); el.style.transition='none';\r\n      });\r\n      document.addEventListener('mousemove', function(e) {\r\n        if (!dragging) return;\r\n        var dx=e.clientX-sx, dy=e.clientY-sy;\r\n        if (Math.abs(dx)>5||Math.abs(dy)>5) moved=true;\r\n        el.style.left=Math.max(0,Math.min(ox+dx,window.innerWidth -el.offsetWidth ))+'px';\r\n        el.style.top =Math.max(0,Math.min(oy+dy,window.innerHeight-el.offsetHeight))+'px';\r\n      });\r\n      document.addEventListener('mouseup', function() {\r\n        if (!dragging) return; dragging=false; el.classList.remove('dragging');\r\n        if (moved) guardarPosCarpeta(el.offsetLeft, el.offsetTop);\r\n        else if (!el.querySelector('.c-carpeta-accion:hover'))\r\n          abrirExplorador(cData.id, cData.nombre, cData.estado, cData.fecha_apertura, cData.icono, cData.tipo);\r\n      });\r\n      el.addEventListener('touchstart',function(e){if(expModoLectura){return;}desdeAccion=!!(e.target&&e.target.closest&&e.target.closest('.c-carpeta-accion'));if(desdeAccion){dragging=false;return;}var t=e.touches[0];ox=el.offsetLeft;oy=el.offsetTop;sx=t.clientX;sy=t.clientY;dragging=true;moved=false;el.classList.add('dragging');},{passive:true});\r\n      el.addEventListener('touchmove',function(e){if(!dragging)return;e.preventDefault();var t=e.touches[0];var dx=t.clientX-sx,dy=t.clientY-sy;if(Math.abs(dx)>5||Math.abs(dy)>5)moved=true;el.style.left=Math.max(0,Math.min(ox+dx,window.innerWidth-el.offsetWidth))+'px';el.style.top=Math.max(0,Math.min(oy+dy,window.innerHeight-el.offsetHeight))+'px';},{passive:false});\r\n      \/\/ Visitante: no hay arrastre, asi que la carpeta se abre con un click\r\n      \/\/ normal. Sirve para raton y para el toque (el navegador dispara click\r\n      \/\/ despues de touchend). En modo edicion no hace nada: ahi abren mouseup\r\n      \/\/ y touchend, y disparar aqui tambien abriria la carpeta dos veces.\r\n      el.addEventListener('click', function(e) {\r\n        if (!criptaSoloLectura) return;\r\n        if (e.target && e.target.closest && e.target.closest('.c-carpeta-accion')) return;\r\n        abrirExplorador(cData.id, cData.nombre, cData.estado, cData.fecha_apertura, cData.icono, cData.tipo);\r\n      });\r\n      el.addEventListener('touchend',function(){if(criptaSoloLectura){return;}if(desdeAccion){desdeAccion=false;dragging=false;el.classList.remove('dragging');return;}dragging=false;el.classList.remove('dragging');if(moved)guardarPosCarpeta(el.offsetLeft,el.offsetTop);else abrirExplorador(cData.id,cData.nombre,cData.estado,cData.fecha_apertura,cData.icono,cData.tipo);});\r\n    })(item, c.id, c);\r\n  });\r\n\r\n  criptaEncajarEnPantalla();\r\n\r\n  if (hayVisibles) {\r\n    zona.classList.remove('vacia');\r\n  } else {\r\n    zona.classList.add('vacia');\r\n  }\r\n}\r\n\r\n\/\/ \u2500\u2500 Modal gestor de carpetas \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\nfunction abrirModalCarpetas() {\r\n  document.getElementById('panel').classList.remove('open');\r\n  renderGridIconos();\r\n  renderColorGrid('mcColorGrid', mcColorSel, function(k) { mcColorSel = k; });\r\n  \/\/ No llamamos cargarCarpetas() aqu\u00ed para evitar que una respuesta\r\n  \/\/ tard\u00eda sobreescriba mcCarpetas y haga desaparecer carpetas reci\u00e9n creadas.\r\n  \/\/ Las carpetas ya est\u00e1n en mcCarpetas desde la carga inicial.\r\n  renderListaCarpetasModal();\r\n  mcResetForm();\r\n  actualizarLimite();\r\n  document.getElementById('modalCarpetas').classList.add('open');\r\n}\r\n\r\nfunction cerrarModalCarpetas() {\r\n  document.getElementById('modalCarpetas').classList.remove('open');\r\n  mcResetForm();\r\n}\r\n\r\ndocument.addEventListener('keydown', function(e) {\r\n  if (e.key === 'Escape') cerrarModalCarpetas();\r\n});\r\n\r\n\/\/ Renderiza el grid de iconos\r\nfunction renderGridIconos() {\r\n  var grid = document.getElementById('mcIconosGrid');\r\n  if (!grid) return;\r\n  grid.innerHTML = '';\r\n  Object.entries(mcIconosCat).forEach(function(entry) {\r\n    var key = entry[0], ico = entry[1];\r\n    var div = document.createElement('div');\r\n    div.className = 'cdh-mc-icono-opt' + (key === mcIconoSel ? ' sel' : '');\r\n    div.dataset.key = key;\r\n    div.innerHTML = '<span class=\"cdh-icono-img\">' + (ico.svg||'') + '<\/span><span>' + ico.label + '<\/span>';\r\n    div.onclick = function() {\r\n      mcIconoSel = key;\r\n      document.querySelectorAll('.cdh-mc-icono-opt').forEach(function(el) { el.classList.remove('sel'); });\r\n      div.classList.add('sel');\r\n      \/\/ Auto-activar modo icono al seleccionar uno\r\n      mcTipoSel = 'icono';\r\n      var ck = document.getElementById('mcTipoCheck');\r\n      if (ck) ck.checked = true;\r\n    };\r\n    grid.appendChild(div);\r\n  });\r\n}\r\n\r\n\/\/ Renderiza la lista de carpetas en el modal\r\nfunction renderListaCarpetasModal() {\r\n  var lista = document.getElementById('mcListaCarpetas');\r\n  if (!lista) return;\r\n  if (!mcCarpetas.length) {\r\n    lista.innerHTML = '<div class=\"cdh-mc-vacia\">A\u00fan no has creado ninguna carpeta.<\/div>';\r\n    return;\r\n  }\r\n  lista.innerHTML = '';\r\n  var ahora = new Date();\r\n  mcCarpetas.forEach(function(c) {\r\n    var emoji = (c.icono && c.icono !== 'carpeta-basica' && mcIconosCat[c.icono]) ? mcIconosCat[c.icono].svg : '';\r\n    var estadoTexto = { abierta:'\ud83d\udd13 Abierta', cerrada:'\ud83d\udd12 Cerrada', oculta:'\u23f3 Oculta' }[c.estado] || c.estado;\r\n    var fechaTexto = (c.estado !== 'abierta' && c.fecha_apertura) ? ' \u00b7 ' + formatFecha(c.fecha_apertura) : '';\r\n\r\n    var fila = document.createElement('div');\r\n    fila.className = 'cdh-mc-carpeta-fila';\r\n    fila.innerHTML =\r\n      '<div class=\"cdh-mc-carpeta-emoji\">' + emoji + '<\/div>'\r\n      + '<div class=\"cdh-mc-carpeta-info\">'\r\n        + '<div class=\"cdh-mc-carpeta-nombre\">' + escapeHtml(c.nombre) + '<\/div>'\r\n        + '<div class=\"cdh-mc-carpeta-meta\">' + estadoTexto + fechaTexto + '<\/div>'\r\n      + '<\/div>'\r\n      + '<div class=\"cdh-mc-carpeta-btns\">'\r\n        + '<div class=\"cdh-mc-btn-ico\" title=\"Editar\" onclick=\"editarCarpeta(' + c.id + ')\">\u270f\ufe0f<\/div>'\r\n        + '<div class=\"cdh-mc-btn-ico danger\" title=\"Borrar\" onclick=\"borrarCarpeta(' + c.id + ')\">\ud83d\uddd1<\/div>'\r\n      + '<\/div>';\r\n    lista.appendChild(fila);\r\n  });\r\n}\r\n\r\nfunction actualizarLimite() {\r\n  var n = mcCarpetas.length;\r\n  var el = document.getElementById('mcLimite');\r\n  if (!el) return;\r\n  el.textContent = n + ' \/ 5 carpetas ra\u00edz';\r\n  el.className = 'cdh-mc-limite' + (n >= 5 ? ' lleno' : '');\r\n\r\n  \/\/ Mostrar\/ocultar formulario si l\u00edmite alcanzado\r\n  var formWrap = document.getElementById('mcFormWrap');\r\n  if (formWrap) formWrap.style.display = (n >= 5 && !mcModoEdicion) ? 'none' : 'block';\r\n}\r\n\r\n\/\/ Estado selector\r\nfunction selEstado(estado, el) {\r\n  mcEstadoSel = estado;\r\n  document.querySelectorAll('.cdh-mc-estado-opt').forEach(function(e) { e.classList.remove('sel'); });\r\n  el.classList.add('sel');\r\n  var fechaWrap = document.getElementById('mcFechaWrap');\r\n  var label     = document.getElementById('mcFechaLabel');\r\n  if (estado === 'abierta') {\r\n    fechaWrap.classList.remove('visible');\r\n  } else {\r\n    fechaWrap.classList.add('visible');\r\n    label.textContent = estado === 'oculta'\r\n      ? 'Fecha en que aparecer\u00e1 la carpeta'\r\n      : 'Fecha de apertura (visible para los visitantes)';\r\n  }\r\n}\r\n\r\n\/\/ Reset formulario\r\nfunction mcResetForm() {\r\n  mcModoEdicion = null;\r\n  mcIconoSel    = 'carpeta-basica';\r\n  mcColorSel    = 'verde';\r\n  mcEstadoSel   = 'abierta';\r\n  var n = document.getElementById('mcNombre');\r\n  var f = document.getElementById('mcFechaApertura');\r\n  var b = document.getElementById('mcBtnGuardar');\r\n  var t = document.getElementById('mcFormTitulo');\r\n  var a = document.getElementById('mcAviso');\r\n  if (n) n.value = '';\r\n  if (f) f.value = '';\r\n  if (b) b.textContent = 'Crear carpeta';\r\n  if (t) t.textContent = 'Nueva carpeta';\r\n  if (a) { a.className = 'cdh-mc-aviso'; a.textContent = ''; }\r\n  \/\/ Reset estado visual\r\n  document.querySelectorAll('.cdh-mc-estado-opt').forEach(function(e) {\r\n    e.classList.toggle('sel', e.dataset.estado === 'abierta');\r\n  });\r\n  document.getElementById('mcFechaWrap').classList.remove('visible');\r\n  \/\/ Reset icono\r\n  document.querySelectorAll('.cdh-mc-icono-opt').forEach(function(e) {\r\n    e.classList.toggle('sel', e.dataset.key === 'carpeta-basica');\r\n  });\r\n  \/\/ Reset color grid\r\n  renderColorGrid('mcColorGrid', mcColorSel, function(k) { mcColorSel = k; });\r\n  \/\/ Volver a pesta\u00f1a color\r\n  mcTipoSel = 'carpeta';\r\n  var tabs = document.querySelectorAll('.cdh-tabs .cdh-tab');\r\n  if (tabs.length) { tabs[0].classList.add('sel'); tabs[1].classList.remove('sel'); }\r\n  var tc = document.getElementById('mcTabColor');\r\n  var ti = document.getElementById('mcTabIcono');\r\n  var tt = document.getElementById('mcTipoToggle');\r\n  var ck = document.getElementById('mcTipoCheck');\r\n  if (tc) tc.style.display = '';\r\n  if (ti) ti.style.display = 'none';\r\n  if (tt) tt.style.display = 'none';\r\n  if (ck) ck.checked = false;\r\n  actualizarLimite();\r\n}\r\n\r\nfunction mcCancelarEdicion() {\r\n  mcResetForm();\r\n  cerrarModalCarpetas();\r\n}\r\n\r\n\/\/ Editar carpeta\r\nfunction editarCarpeta(id, e) {\r\n  if (e) e.stopPropagation();\r\n  var c = mcCarpetas.find(function(x) { return x.id == id; });\r\n  if (!c) return;\r\n\r\n  mcModoEdicion = id;\r\n  mcIconoSel    = c.icono;\r\n  mcColorSel    = c.color || 'verde';\r\n  mcEstadoSel   = c.estado;\r\n\r\n  document.getElementById('mcNombre').value = c.nombre;\r\n  document.getElementById('mcBtnGuardar').textContent = 'Guardar cambios';\r\n  document.getElementById('mcFormTitulo').textContent = 'Editar carpeta';\r\n\r\n  \/\/ Marcar icono\r\n  document.querySelectorAll('.cdh-mc-icono-opt').forEach(function(el) {\r\n    el.classList.toggle('sel', el.dataset.key === c.icono);\r\n  });\r\n\r\n  \/\/ Marcar color\r\n  renderColorGrid('mcColorGrid', mcColorSel, function(k) { mcColorSel = k; });\r\n\r\n  \/\/ Marcar estado\r\n  document.querySelectorAll('.cdh-mc-estado-opt').forEach(function(el) {\r\n    el.classList.toggle('sel', el.dataset.estado === c.estado);\r\n  });\r\n\r\n  \/\/ Fecha\r\n  var fechaWrap = document.getElementById('mcFechaWrap');\r\n  var label     = document.getElementById('mcFechaLabel');\r\n  if (c.estado !== 'abierta') {\r\n    fechaWrap.classList.add('visible');\r\n    label.textContent = c.estado === 'oculta'\r\n      ? 'Fecha en que aparecer\u00e1 la carpeta'\r\n      : 'Fecha de apertura (visible para los visitantes)';\r\n    if (c.fecha_apertura) {\r\n      document.getElementById('mcFechaApertura').value = c.fecha_apertura.split(' ')[0];\r\n    }\r\n  } else {\r\n    fechaWrap.classList.remove('visible');\r\n  }\r\n\r\n  \/\/ Abrir modal y mostrar pesta\u00f1a color\r\n  document.getElementById('modalCarpetas').classList.add('open');\r\n  renderGridIconos();  \/\/ poblar el grid antes de marcar el icono seleccionado\r\n  var tabs = document.querySelectorAll('.cdh-tabs .cdh-tab');\r\n  if (tabs.length) { tabs[0].classList.add('sel'); tabs[1].classList.remove('sel'); }\r\n  var tc = document.getElementById('mcTabColor'); var ti = document.getElementById('mcTabIcono');\r\n  if (tc) tc.style.display = ''; if (ti) ti.style.display = 'none';\r\n  actualizarLimite();\r\n  document.getElementById('mcNombre').focus();\r\n}\r\n\r\n\/\/ Guardar (crear o editar)\r\nfunction mcGuardar() {\r\n  var nombre = document.getElementById('mcNombre').value.trim();\r\n  var fecha  = document.getElementById('mcFechaApertura').value;\r\n  var aviso  = document.getElementById('mcAviso');\r\n  aviso.className = 'cdh-mc-aviso';\r\n\r\n  if (!nombre) {\r\n    aviso.textContent = 'El nombre de la carpeta es obligatorio.';\r\n    aviso.className = 'cdh-mc-aviso error';\r\n    return;\r\n  }\r\n\r\n  var body = {\r\n    sep_id:         cdhSepId,\r\n    nombre:         nombre,\r\n    icono:          mcIconoSel,\r\n    color:          mcColorSel,\r\n    tipo:           mcTipoSel,\r\n    estado:         mcEstadoSel,\r\n    \/\/ Cadena vac\u00eda = \"borra la fecha\" (ver cdh_editar_carpeta, m\u00f3dulo 03)\r\n    fecha_apertura: (mcEstadoSel !== 'abierta' && fecha) ? fecha : '',\r\n  };\r\n\r\n  var url    = mcModoEdicion\r\n    ? '\/index.php\/wp-json\/cdh\/v1\/carpetas\/' + mcModoEdicion\r\n    : '\/index.php\/wp-json\/cdh\/v1\/carpetas';\r\n  var method = mcModoEdicion ? 'PUT' : 'POST';\r\n\r\n  document.getElementById('mcBtnGuardar').disabled = true;\r\n\r\n  fetch(url, {\r\n    method: method,\r\n    headers: { 'Content-Type': 'application\/json', 'X-WP-Nonce': window.cdhNonce },\r\n    credentials: 'same-origin',\r\n    body: JSON.stringify(body)\r\n  })\r\n  .then(function(r) { return r.json(); })\r\n  .then(function(data) {\r\n    document.getElementById('mcBtnGuardar').disabled = false;\r\n    if (data.code) {\r\n      aviso.textContent = data.message || 'Error al guardar.';\r\n      aviso.className = 'cdh-mc-aviso error';\r\n      return;\r\n    }\r\n    \/\/ Actualizar array local\r\n    if (mcModoEdicion) {\r\n      mcCarpetas = mcCarpetas.map(function(c) { return c.id == mcModoEdicion ? data : c; });\r\n    } else {\r\n      mcCarpetas.push(data);\r\n    }\r\n    mapaHtmlCache = null;\r\n    mapaPrecarga();\r\n    renderListaCarpetasModal();\r\n    renderCarpetasCripta();\r\n    actualizarLimite();\r\n    \/\/ Tanto al crear como al editar: cerrar modal y volver a la cripta\r\n    mcResetForm();\r\n    setTimeout(function() {\r\n      cerrarModalCarpetas();\r\n      var hintCripta = document.getElementById('criptaHint');\r\n      if (hintCripta) {\r\n        hintCripta.style.display = 'block'; hintCripta.classList.remove('hide');\r\n        clearTimeout(window._criptaHintTimer);\r\n        window._criptaHintTimer = setTimeout(function() {\r\n          hintCripta.classList.add('hide');\r\n          setTimeout(function() { hintCripta.style.display = 'none'; }, 500);\r\n        }, 4000);\r\n      }\r\n    }, 300);\r\n  })\r\n  .catch(function() {\r\n    document.getElementById('mcBtnGuardar').disabled = false;\r\n    aviso.textContent = 'Error de conexi\u00f3n. Int\u00e9ntalo de nuevo.';\r\n    aviso.className = 'cdh-mc-aviso error';\r\n  });\r\n}\r\n\r\n\/\/ Borrar carpeta\r\nfunction borrarCarpeta(id, e) {\r\n  if (e) e.stopPropagation();\r\n  var c = mcCarpetas.find(function(x) { return x.id == id; });\r\n  var nombre = c ? c.nombre : 'esta carpeta';\r\n\r\n  cdhConfirm(\r\n    'Borrar carpeta',\r\n    '\u00bfBorrar <strong>\"' + escapeHtml(nombre) + '\"<\/strong>?<br><br>Se eliminar\u00e1n tambi\u00e9n todas sus subcarpetas y contenido.',\r\n    '\ud83d\uddd1', 'Borrar',\r\n    function(ok) {\r\n      if (!ok) return;\r\n      fetch('\/index.php\/wp-json\/cdh\/v1\/carpetas\/' + id, {\r\n        method: 'DELETE',\r\n        headers: { 'X-WP-Nonce': window.cdhNonce },\r\n        credentials: 'same-origin'\r\n      })\r\n      .then(function(r) { return r.json(); })\r\n      .then(function() {\r\n        mcCarpetas = mcCarpetas.filter(function(x) { return x.id != id; });\r\n        mapaHtmlCache = null;\r\n        mapaPrecarga();\r\n        renderListaCarpetasModal();\r\n        renderCarpetasCripta();\r\n        actualizarLimite();\r\n        if (mcModoEdicion == id) mcResetForm();\r\n      })\r\n      .catch(function() { alert('Error al borrar la carpeta.'); });\r\n    }\r\n  );\r\n}\r\n\r\n\/\/ Previsualizar carpeta (abre el preview con esa carpeta destacada)\r\nfunction previewCarpeta(id, e) {\r\n  if (e) e.stopPropagation();\r\n  \/\/ Por ahora abre la preview general \u2014 cuando implementemos el contenido\r\n  \/\/ se abrir\u00e1 directamente en esa carpeta\r\n  document.getElementById('previewBtn').click();\r\n}\r\n\r\n\/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\r\n   PANTALLA COMPLETA\r\n   Oculta la barra del navegador y, en movil, intenta ademas fijar\r\n   el apaisado. Si el navegador no lo admite (iPhone), el boton no\r\n   llega a mostrarse.\r\n   \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 *\/\r\nfunction cdhFsActivo() {\r\n  return document.fullscreenElement || document.webkitFullscreenElement || null;\r\n}\r\n\r\nfunction cdhPantallaCompleta() {\r\n  var raiz = document.documentElement;\r\n  if (cdhFsActivo()) {\r\n    try { if (screen.orientation && screen.orientation.unlock) screen.orientation.unlock(); } catch (e) {}\r\n    if (document.exitFullscreen)            document.exitFullscreen();\r\n    else if (document.webkitExitFullscreen) document.webkitExitFullscreen();\r\n  } else {\r\n    var p = null;\r\n    if (raiz.requestFullscreen)            p = raiz.requestFullscreen();\r\n    else if (raiz.webkitRequestFullscreen) p = raiz.webkitRequestFullscreen();\r\n    \/\/ Solo tiene sentido fijar el apaisado en pantallas pequenas\r\n    if (p && p.then && window.innerWidth < 1000) {\r\n      p.then(function () {\r\n        try {\r\n          if (screen.orientation && screen.orientation.lock) {\r\n            var l = screen.orientation.lock('landscape');\r\n            if (l && l.catch) l.catch(function () {});\r\n          }\r\n        } catch (e) {}\r\n      }).catch(function () {});\r\n    }\r\n  }\r\n}\r\n\r\n\/* Entrada a pantalla completa desde el aviso de girar el telefono.\r\n   El toque del visitante es el gesto de usuario que exige la API, asi que\r\n   desde aqui si se puede pedir. cdhPantallaCompleta() intenta ademas fijar\r\n   el apaisado por debajo de 1000 px de ancho. Cerramos el aviso a mano por\r\n   si el giro no llega a producirse (movil con la rotacion bloqueada). *\/\r\nfunction cdhGiraPantallaCompleta() {\r\n  if (!cdhFsActivo()) cdhPantallaCompleta();\r\n  var ov = document.getElementById('cdhGiraOverlay');\r\n  if (ov) ov.classList.add('cdh-gira-ok');\r\n}\r\n\r\n(function cdhFsInit() {\r\n  var btn = document.getElementById('fsBtn');\r\n  var ov  = document.getElementById('cdhGiraOverlay');\r\n  var raiz = document.documentElement;\r\n  \/\/ Si el navegador no admite pantalla completa, no ensuciamos la esquina\r\n  \/\/ ni prometemos en el aviso algo que no vamos a poder darle.\r\n  if (!raiz.requestFullscreen && !raiz.webkitRequestFullscreen) {\r\n    if (btn) btn.style.display = 'none';\r\n    if (ov) {\r\n      ov.classList.add('cdh-sin-fs');\r\n      var txt = ov.querySelector('.cdh-gira-txt');\r\n      if (txt) txt.textContent = 'La Cripta se contempla mejor con el telefono en horizontal.';\r\n    }\r\n    return;\r\n  }\r\n  if (!btn) return;\r\n  function pinta() {\r\n    var on = !!cdhFsActivo();\r\n    btn.classList.toggle('activo', on);\r\n  }\r\n  document.addEventListener('fullscreenchange', pinta);\r\n  document.addEventListener('webkitfullscreenchange', pinta);\r\n  pinta();\r\n})();\r\n<\/script>\r\n\r\n<!-- \u2500\u2500 Modal confirmaci\u00f3n personalizado \u2500\u2500 -->\r\n<div id=\"cdhConfirmModal\" style=\"\r\n  display:none; position:fixed; inset:0; z-index:100060;\r\n  background:rgba(0,0,0,0.75); backdrop-filter:blur(5px);\r\n  align-items:center; justify-content:center; padding:20px;\r\n\">\r\n  <div style=\"\r\n    background:linear-gradient(160deg,rgba(55,22,8,0.98) 0%,rgba(18,42,28,0.98) 100%);\r\n    border:1px solid rgba(201,169,110,0.35); border-radius:8px;\r\n    padding:36px 32px; max-width:420px; width:100%;\r\n    box-shadow:0 20px 60px rgba(0,0,0,0.85);\r\n    font-family:Arial,sans-serif; text-align:center;\r\n  \">\r\n    <div id=\"cdhConfirmIcon\" style=\"font-size:42px; margin-bottom:14px;\"><span class=\"cdh-confirm-basura\"><\/span><\/div>\r\n    <div id=\"cdhConfirmTitle\" style=\"\r\n      font-family:'Cinzel',serif; font-size:14px; letter-spacing:3px;\r\n      text-transform:uppercase; color:#e08080; margin-bottom:14px;\r\n    \"><\/div>\r\n    <div id=\"cdhConfirmMsg\" style=\"\r\n      font-size:13px; line-height:1.7; color:rgba(245,240,232,0.72);\r\n      margin-bottom:28px;\r\n    \"><\/div>\r\n    <div style=\"display:flex; gap:12px; justify-content:center;\">\r\n      <button id=\"cdhConfirmCancel\" style=\"\r\n        padding:11px 28px; background:transparent;\r\n        border:1px solid rgba(245,240,232,0.2); border-radius:4px;\r\n        color:rgba(245,240,232,0.5); font-family:'Cinzel',serif;\r\n        font-size:11px; letter-spacing:2px; text-transform:uppercase;\r\n        cursor:pointer; transition:all 0.2s;\r\n      \" onmouseover=\"this.style.borderColor='rgba(245,240,232,0.45)';this.style.color='rgba(245,240,232,0.8)'\"\r\n         onmouseout=\"this.style.borderColor='rgba(245,240,232,0.2)';this.style.color='rgba(245,240,232,0.5)'\">\r\n        Cancelar\r\n      <\/button>\r\n      <button id=\"cdhConfirmOk\" style=\"\r\n        padding:11px 28px; background:rgba(120,30,30,0.6);\r\n        border:1px solid rgba(200,80,80,0.45); border-radius:4px;\r\n        color:#e08080; font-family:'Cinzel',serif;\r\n        font-size:11px; letter-spacing:2px; text-transform:uppercase;\r\n        cursor:pointer; transition:all 0.2s;\r\n      \" onmouseover=\"this.style.background='rgba(160,40,40,0.8)'\"\r\n         onmouseout=\"this.style.background='rgba(120,30,30,0.6)'\">\r\n        Eliminar\r\n      <\/button>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<!-- Modal eliminar cuenta -->\r\n<div id=\"modalEliminar\" class=\"cdh-modal-overlay\">\r\n  <div class=\"cdh-modal\">\r\n    <h3>\u26a0 Eliminar cuenta<\/h3>\r\n    <p>Si elimina su cuenta, eliminar\u00e1 tambi\u00e9n todas las sepulturas y datos vinculados a ella. Descargue antes, si lo desea, toda la informaci\u00f3n aportada a nuestra Web.<\/p>\r\n    <div id=\"cdh-eliminar-aviso\" class=\"cdh-aviso\"><\/div>\r\n    <p style=\"font-size:13px;color:rgba(245,240,232,0.5);\">Escriba <strong style=\"color:#e08080;\">ELIMINAR<\/strong> para confirmar:<\/p>\r\n    <input type=\"text\" id=\"cdh-confirmar-texto\" class=\"cdh-confirmar-input\" placeholder=\"ELIMINAR\" autocomplete=\"off\"\r\n      oninput=\"document.getElementById('cdh-btn-eliminar-final').disabled=this.value.trim()!=='ELIMINAR'; document.getElementById('cdh-btn-eliminar-final').style.opacity=this.value.trim()==='ELIMINAR'?'1':'0.4';\">\r\n    <p class=\"cdh-confirmar-nota\">Esta acci\u00f3n es irreversible y no puede deshacerse.<\/p>\r\n    <div class=\"cdh-modal-btns\">\r\n      <button id=\"cdh-btn-descargar\" class=\"cdh-btn-descargar\" onclick=\"descargarMisDatos()\">\u2b07 &nbsp;Descargar mis datos antes de salir<\/button>\r\n      <button id=\"cdh-btn-eliminar-final\" class=\"cdh-btn-eliminar-final\" onclick=\"eliminarCuentaFinal()\" disabled style=\"opacity:0.4\">Eliminar mi cuenta definitivamente<\/button>\r\n      <button class=\"cdh-btn-cancelar-modal\" onclick=\"cerrarModalEliminar()\">Cancelar<\/button>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n<!-- \u2500\u2500 Lightbox \u2500\u2500 -->\r\n<div class=\"cdh-lightbox\" id=\"cdhLightbox\">\r\n  <button class=\"cdh-lb-cerrar\" onclick=\"cerrarLightbox()\">\u2715<\/button>\r\n  <a class=\"cdh-lb-descargar\" id=\"lbDescargaBtn\" href=\"#\" download target=\"_blank\">\u2b07 Descargar<\/a>\r\n  <div class=\"cdh-lb-contador\" id=\"lbContador\"><\/div>\r\n  <button class=\"cdh-lb-nav prev\" id=\"lbPrev\" onclick=\"lbNavegar(-1)\">\u2039<\/button>\r\n  <div class=\"cdh-lb-contenido\" id=\"lbContenido\"><\/div>\r\n  <button class=\"cdh-lb-nav next\" id=\"lbNext\" onclick=\"lbNavegar(1)\">\u203a<\/button>\r\n  <div class=\"cdh-lb-nombre\" id=\"lbNombre\"><\/div>\r\n<\/div>\r\n\r\n<\/body>\r\n<\/html>\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>La Cripta Gira el telefono La Cripta se contempla en horizontal, a pantalla completa. Ver a pantalla completa Continuar asi \ud83d\uddfa\ufe0f Mapa de la Cripta Cargando&#8230; \u270f\ufe0f &nbsp;Editar mis datos \ud83d\udd11 &nbsp;Cambiar contrase\u00f1a \ud83e\udea6 &nbsp;Crear nueva Sepultura o Glosar monumento funerario \ud83d\udeaa &nbsp;Cerrar sesi\u00f3n \u26a0\ufe0f &nbsp;Eliminar mi cuenta \ud83c\udfe0 &nbsp;Salir \ud83d\udc41\ufe0f \u2699 &nbsp;OPCIONES \ud83c\udfdb &nbsp;Temas [&hellip;]<\/p>\n","protected":false},"author":33,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"footnotes":""},"class_list":["post-632","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/cementeriodigitalhispano.com\/index.php\/wp-json\/wp\/v2\/pages\/632","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cementeriodigitalhispano.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/cementeriodigitalhispano.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/cementeriodigitalhispano.com\/index.php\/wp-json\/wp\/v2\/users\/33"}],"replies":[{"embeddable":true,"href":"https:\/\/cementeriodigitalhispano.com\/index.php\/wp-json\/wp\/v2\/comments?post=632"}],"version-history":[{"count":688,"href":"https:\/\/cementeriodigitalhispano.com\/index.php\/wp-json\/wp\/v2\/pages\/632\/revisions"}],"predecessor-version":[{"id":2202,"href":"https:\/\/cementeriodigitalhispano.com\/index.php\/wp-json\/wp\/v2\/pages\/632\/revisions\/2202"}],"wp:attachment":[{"href":"https:\/\/cementeriodigitalhispano.com\/index.php\/wp-json\/wp\/v2\/media?parent=632"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}