Snippets Collections
Blitzvorschau (Schnellste Methode)

Angenommen, Ihre Daten stehen in Spalte A1 ("Test1234").
Schreiben Sie in Zelle B1 das gewünschte Ergebnis ohne Zahlen ("Test").
Schreiben Sie in Zelle B2 das Ergebnis für die nächste Zeile.
Drücken Sie Strg + E (oder gehen Sie auf Daten -> Blitzvorschau). Excel erkennt das Muster und entfernt alle Zahlen. 
 function footerNavTracking() {
        const footerWrapper = document.querySelector(".footer__wrapper");
        if (!footerWrapper) return;

        footerWrapper.addEventListener("click", (e) => {
            // Find the closest relevant link
            const link = e.target.closest(
                ".footer__col-second-button_wrapper a, .footer__logo-link",
            );
            if (!link) return;

            // Get the URL from the <a> tag
            const url = link.getAttribute("href") || "";

            // Social links
            if (link.matches(".footer__col-second-button_wrapper a")) {
                gtmPush({
                    event: "navigation_click",
                    navigation_type: "footer_nav",
                    click_text: "Social",
                    click_url: url,
                    nav_level: 1,
                });
            }

            // Logo links
            if (link.matches(".footer__logo-link")) {
                gtmPush({
                    event: "navigation_click",
                    navigation_type: "footer_nav",
                    click_text: "logo",
                    click_url: url,
                    nav_level: 1,
                });
            }
        });
    }
 function navigationTracking() {
        const mainNav = document.querySelector(".main-navigation__main");
        if (!mainNav) return;

        const navItems = [
            {
                selector: ".main-navigation__control-link",
                type: "nav-links",
                handler: (e, el) => {
                    const btnTextRaw = el.textContent || "";
                    const btnText = btnTextRaw.replace(/\s+/g, " ").trim();
                    const isPressed =
                        el.getAttribute("aria-pressed") === "true";
                    const navState = isPressed ? "closed" : "open";

                    navigationClickTracking(btnText, null, 1, navState);
                },
            },
            {
                selector: "#main-nav-bookmarks",
                type: "nav-bookmark",
                handler: (e, el) => {
                    const btnText = el.innerText.trim();
                    navigationClickTracking(btnText, "/sruh/bookmarks", 1);
                },
            },
            {
                selector: "#main-nav-close",
                type: "nav-search",
                handler: (e, el) => {
                    const btnText = el.outerText.trim();
                    navigationClickTracking(btnText, null, 1);
                },
            },
            {
                selector: "#main-nav-quiz",
                type: "nav-quiz",
                handler: () => {
                    navigationClickTracking(
                        "Senior Road User Quiz",
                        "/sruh/quiz",
                        1,
                    );
                },
            },
        ];

        navItems.forEach((item) => {
            const elements = mainNav.querySelectorAll(item.selector);

            elements.forEach((el) => {
                if (el.dataset.navTracked) return;
                el.dataset.navTracked = "true";

                el.addEventListener("click", (e) => {
                    item.handler(e, el);
                });
            });
        });

        /*  SUB MENU LINK TRACKING */

        const subNavWrapper = document.querySelector(".main-navigation__aside");
        if (!subNavWrapper) return;

        // Use event delegation to catch all subnav link clicks
        // This works regardless of when the subnav is opened
        if (subNavWrapper.dataset.subNavTrackingSetup) return;
        subNavWrapper.dataset.subNavTrackingSetup = "true";

        subNavWrapper.addEventListener("click", (e) => {
            // Find the clicked link
            const link = e.target.closest(
                ".main-navigation__content-list li a",
            );
            if (!link) return;

            // Only track if the link is within an active menu
            const activeMenu = link.closest(".main-navigation__content.active");
            if (!activeMenu) return;

            const linkText = link.textContent.replace(/\s+/g, " ").trim();
            const linkUrl = link.getAttribute("href") || "";

            navigationClickTracking(linkText, linkUrl, 2);
        });
    }
const TEST_MODE = true; // true = preventDefault for testing, false = production
    function maybePreventDefault(e) {
        if (TEST_MODE) e.preventDefault();
    }
     // usage: maybePreventDefault(e);


//example

   function footerNavTracking() {
        const footerWrapper = document.querySelector(".footer");
        if (!footerWrapper) return;

        footerWrapper.addEventListener("click", (e) => {
            maybePreventDefault(e);
            const { target } = e;

            const link = target.closest(`
                .footer-content__partners-link,
                .footer-content__navigation-link,
                .footer__copyright-section a,
                .footer-site-logo__link
            `);
            if (!link) return;

            const linkurl = link.getAttribute('href') || "";
            const linkTextRaw = link.textContent.trim();
            const linkText = linkTextRaw.replace(/\s+/g, " ").trim() || "";

            if(link.matches('.footer-content__partners-link')){
                gtmPush({
                    event: "navigation_click",
                    navigation_type: "footer_nav",
                    click_text: "our partners",
                    click_url: linkurl,
                    nav_level: 1,
                });
            }

            if(link.matches('.footer-content__navigation-link, .footer__copyright-section a, .footer-site-logo__link')){
                gtmPush({
                    event: "navigation_click",
                    navigation_type: "footer_nav",
                    click_text: linkText,
                    click_url: linkurl,
                    nav_level: 1,
                });
            }
        });
    }
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Creador de Currículum Vitae</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background-color: #f5f7fa;
            color: #333;
            line-height: 1.6;
            padding-bottom: 40px;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            padding: 20px;
        }
        
        header {
            text-align: center;
            padding: 30px 0;
            background: linear-gradient(135deg, #2c3e50, #4a6491);
            color: white;
            border-radius: 10px;
            margin-bottom: 30px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
        }
        
        h1 {
            font-size: 2.5rem;
            margin-bottom: 10px;
        }
        
        .subtitle {
            font-size: 1.1rem;
            opacity: 0.9;
        }
        
        .app-container {
            display: flex;
            flex-wrap: wrap;
            gap: 30px;
        }
        
        .form-section {
            flex: 1;
            min-width: 300px;
            background-color: white;
            border-radius: 10px;
            padding: 25px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
        }
        
        .preview-section {
            flex: 1;
            min-width: 300px;
            background-color: white;
            border-radius: 10px;
            padding: 25px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
        }
        
        h2 {
            color: #2c3e50;
            margin-bottom: 20px;
            padding-bottom: 10px;
            border-bottom: 2px solid #4a6491;
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        h2 i {
            color: #4a6491;
        }
        
        .form-group {
            margin-bottom: 20px;
        }
        
        label {
            display: block;
            margin-bottom: 8px;
            font-weight: 600;
            color: #2c3e50;
        }
        
        input, textarea {
            width: 100%;
            padding: 12px 15px;
            border: 1px solid #ddd;
            border-radius: 6px;
            font-size: 1rem;
            transition: border-color 0.3s;
        }
        
        input:focus, textarea:focus {
            outline: none;
            border-color: #4a6491;
        }
        
        textarea {
            min-height: 100px;
            resize: vertical;
        }
        
        .skills-container {
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
            margin-top: 10px;
        }
        
        .skill-tag {
            background-color: #eef2f7;
            padding: 6px 12px;
            border-radius: 20px;
            display: flex;
            align-items: center;
            gap: 5px;
            font-size: 0.9rem;
        }
        
        .skill-tag .remove-skill {
            cursor: pointer;
            color: #e74c3c;
            font-weight: bold;
        }
        
        .add-skill {
            display: flex;
            gap: 10px;
        }
        
        .add-skill input {
            flex: 1;
        }
        
        .btn {
            background-color: #4a6491;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 6px;
            cursor: pointer;
            font-size: 1rem;
            font-weight: 600;
            transition: background-color 0.3s;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 8px;
        }
        
        .btn:hover {
            background-color: #3a5379;
        }
        
        .btn-primary {
            background-color: #2c3e50;
        }
        
        .btn-primary:hover {
            background-color: #1a252f;
        }
        
        .btn-secondary {
            background-color: #3498db;
        }
        
        .btn-secondary:hover {
            background-color: #2980b9;
        }
        
        .btn-danger {
            background-color: #e74c3c;
        }
        
        .btn-danger:hover {
            background-color: #c0392b;
        }
        
        .btn-success {
            background-color: #27ae60;
        }
        
        .btn-success:hover {
            background-color: #219653;
        }
        
        .btn-block {
            display: block;
            width: 100%;
            margin-top: 20px;
            padding: 12px;
        }
        
        .btn-sm {
            padding: 6px 12px;
            font-size: 0.9rem;
        }
        
        /* Estilos para la foto */
        .photo-upload-container {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 15px;
            margin-bottom: 20px;
        }
        
        .photo-preview {
            width: 150px;
            height: 180px;
            border-radius: 8px;
            border: 3px solid #4a6491;
            overflow: hidden;
            background-color: #f8f9fa;
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
        }
        
        .photo-preview img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        
        .photo-placeholder {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            color: #7f8c8d;
            text-align: center;
            padding: 20px;
        }
        
        .photo-placeholder i {
            font-size: 48px;
            margin-bottom: 10px;
            color: #bdc3c7;
        }
        
        .photo-upload-btn {
            position: relative;
            overflow: hidden;
        }
        
        .photo-upload-btn input[type="file"] {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            opacity: 0;
            cursor: pointer;
        }
        
        .photo-actions {
            display: flex;
            gap: 10px;
            margin-top: 10px;
        }
        
        .photo-instructions {
            font-size: 0.85rem;
            color: #666;
            text-align: center;
            margin-top: 5px;
        }
        
        .cv-preview {
            background-color: white;
            min-height: 800px;
            padding: 30px;
            border: 1px solid #eee;
            border-radius: 8px;
            font-size: 0.95rem;
            line-height: 1.5;
        }
        
        /* Encabezado SIN foto (versión anterior) */
        .cv-header-no-photo {
            background-color: #2c3e50;
            color: white;
            padding: 30px;
            border-radius: 8px;
            margin-bottom: 30px;
        }
        
        /* Encabezado CON foto (nueva versión) */
        .cv-header-with-photo {
            background-color: #2c3e50;
            color: white;
            padding: 30px;
            border-radius: 8px;
            margin-bottom: 30px;
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
            position: relative;
            min-height: 180px;
        }
        
        .cv-header-content {
            flex: 1;
        }
        
        .cv-photo-container {
            width: 140px;
            height: 160px;
            border-radius: 8px;
            overflow: hidden;
            border: 3px solid rgba(255, 255, 255, 0.3);
            background-color: rgba(255, 255, 255, 0.1);
            display: flex;
            align-items: center;
            justify-content: center;
            margin-left: 20px;
            flex-shrink: 0;
        }
        
        .cv-photo {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        
        .cv-photo-placeholder {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            color: rgba(255, 255, 255, 0.7);
            text-align: center;
            padding: 20px;
            font-size: 0.9rem;
        }
        
        .cv-photo-placeholder i {
            font-size: 36px;
            margin-bottom: 8px;
        }
        
        .cv-name {
            font-size: 2.2rem;
            margin-bottom: 5px;
        }
        
        .cv-title {
            font-size: 1.4rem;
            opacity: 0.9;
            margin-bottom: 15px;
        }
        
        .cv-contact {
            display: flex;
            flex-wrap: wrap;
            gap: 20px;
            margin-top: 15px;
        }
        
        .cv-contact-item {
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 0.95rem;
        }
        
        .cv-section {
            margin-bottom: 25px;
        }
        
        .cv-section-title {
            color: #2c3e50;
            border-bottom: 2px solid #4a6491;
            padding-bottom: 5px;
            margin-bottom: 15px;
            font-size: 1.3rem;
        }
        
        .cv-item {
            margin-bottom: 20px;
            padding-bottom: 15px;
            border-bottom: 1px solid #eee;
        }
        
        .cv-item:last-child {
            border-bottom: none;
        }
        
        .cv-item-title {
            font-weight: 600;
            color: #333;
            margin-bottom: 5px;
            font-size: 1.1rem;
        }
        
        .cv-item-subtitle {
            color: #4a6491;
            font-style: italic;
            margin-bottom: 5px;
        }
        
        .cv-item-dates {
            color: #666;
            font-size: 0.9rem;
            margin-bottom: 8px;
            display: flex;
            align-items: center;
            gap: 5px;
        }
        
        .current-badge {
            background-color: #27ae60;
            color: white;
            padding: 2px 8px;
            border-radius: 12px;
            font-size: 0.8rem;
            font-weight: 600;
        }
        
        .cv-skills {
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
        }
        
        .cv-skill {
            background-color: #eef2f7;
            padding: 6px 12px;
            border-radius: 4px;
            font-size: 0.9rem;
        }
        
        .actions {
            display: flex;
            justify-content: center;
            gap: 20px;
            margin-top: 30px;
            flex-wrap: wrap;
        }
        
        .instructions {
            background-color: #eef2f7;
            padding: 20px;
            border-radius: 8px;
            margin-top: 30px;
            font-size: 0.95rem;
        }
        
        .instructions h3 {
            margin-bottom: 10px;
            color: #2c3e50;
        }
        
        .instructions ul {
            padding-left: 20px;
        }
        
        .instructions li {
            margin-bottom: 8px;
        }
        
        /* Estilos para la experiencia laboral dinámica */
        .job-entry {
            background-color: #f8f9fa;
            padding: 20px;
            border-radius: 8px;
            margin-bottom: 20px;
            border-left: 4px solid #4a6491;
        }
        
        .job-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
        }
        
        .job-title {
            font-weight: 600;
            color: #2c3e50;
        }
        
        .current-job-toggle {
            display: flex;
            align-items: center;
            gap: 8px;
            margin-bottom: 15px;
        }
        
        .toggle-label {
            font-size: 0.9rem;
            color: #666;
        }
        
        .toggle-switch {
            position: relative;
            display: inline-block;
            width: 50px;
            height: 24px;
        }
        
        .toggle-switch input {
            opacity: 0;
            width: 0;
            height: 0;
        }
        
        .toggle-slider {
            position: absolute;
            cursor: pointer;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: #ccc;
            transition: .4s;
            border-radius: 24px;
        }
        
        .toggle-slider:before {
            position: absolute;
            content: "";
            height: 16px;
            width: 16px;
            left: 4px;
            bottom: 4px;
            background-color: white;
            transition: .4s;
            border-radius: 50%;
        }
        
        input:checked + .toggle-slider {
            background-color: #27ae60;
        }
        
        input:checked + .toggle-slider:before {
            transform: translateX(26px);
        }
        
        .remove-job {
            background-color: transparent;
            border: none;
            color: #e74c3c;
            cursor: pointer;
            font-size: 1.2rem;
            padding: 5px;
        }
        
        .add-job-btn {
            margin-top: 10px;
        }
        
        /* Estilos para el pie de página del PDF */
        .pdf-footer {
            position: fixed;
            bottom: 0;
            left: 0;
            right: 0;
            text-align: center;
            font-size: 10pt;
            color: #666;
            padding: 10px;
            background-color: white;
            border-top: 1px solid #eee;
        }
        
        .page-number {
            font-family: Arial, sans-serif;
        }
        
        @media (max-width: 768px) {
            .app-container {
                flex-direction: column;
            }
            
            .cv-preview {
                min-height: auto;
            }
            
            .actions {
                flex-direction: column;
            }
            
            .job-header {
                flex-direction: column;
                align-items: flex-start;
                gap: 10px;
            }
            
            .cv-header-with-photo {
                flex-direction: column;
                align-items: center;
                text-align: center;
                min-height: auto;
            }
            
            .cv-photo-container {
                margin-left: 0;
                margin-bottom: 20px;
                order: -1;
            }
            
            .cv-header-content {
                width: 100%;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1><i class="fas fa-file-alt"></i> Creador de Currículum Vitae</h1>
            <p class="subtitle">Completa el formulario y genera tu CV profesional en minutos</p>
        </header>
        
        <div class="app-container">
            <!-- Sección del formulario -->
            <section class="form-section">
                <h2><i class="fas fa-edit"></i> Información Personal</h2>
                
                <!-- Subida de foto -->
                <div class="form-group">
                    <label>Foto de Perfil (Opcional)</label>
                    <div class="photo-upload-container">
                        <div class="photo-preview" id="photo-preview">
                            <div class="photo-placeholder" id="photo-placeholder">
                                <i class="fas fa-user-circle"></i>
                                <span>Sin foto</span>
                            </div>
                            <img id="photo-preview-img" style="display: none;">
                        </div>
                        
                        <div class="photo-actions">
                            <button class="btn btn-secondary photo-upload-btn" id="upload-photo-btn">
                                <i class="fas fa-upload"></i> Subir Foto
                                <input type="file" id="photo-input" accept="image/*" style="display: none;">
                            </button>
                            <button class="btn btn-danger" id="remove-photo-btn" style="display: none;">
                                <i class="fas fa-trash"></i> Eliminar
                            </button>
                        </div>
                        
                        <div class="photo-instructions">
                            <p><strong>Opcional:</strong> JPG o PNG, máximo 2MB</p>
                            <p>Con foto: CV moderno | Sin foto: CV clásico</p>
                        </div>
                    </div>
                </div>
                
                <div class="form-group">
                    <label for="name">Nombre Completo</label>
                    <input type="text" id="name" placeholder="Ej: Juan Pérez González">
                </div>
                
                <div class="form-group">
                    <label for="title">Título Profesional</label>
                    <input type="text" id="title" placeholder="Ej: Desarrollador Web Frontend">
                </div>
                
                <div class="form-group">
                    <label for="email">Correo Electrónico</label>
                    <input type="email" id="email" placeholder="Ej: juan.perez@email.com">
                </div>
                
                <div class="form-group">
                    <label for="phone">Teléfono</label>
                    <input type="text" id="phone" placeholder="Ej: +34 612 345 678">
                </div>
                
                <div class="form-group">
                    <label for="location">Ubicación</label>
                    <input type="text" id="location" placeholder="Ej: Madrid, España">
                </div>
                
                <div class="form-group">
                    <label for="summary">Resumen Profesional</label>
                    <textarea id="summary" placeholder="Breve descripción de tu experiencia, habilidades y objetivos profesionales..."></textarea>
                </div>
                
                <h2><i class="fas fa-briefcase"></i> Experiencia Laboral</h2>
                <div id="jobs-container">
                    <!-- Las experiencias laborales se agregarán aquí dinámicamente -->
                </div>
                
                <div class="form-group">
                    <button class="btn btn-secondary add-job-btn" id="add-job-btn">
                        <i class="fas fa-plus"></i> Agregar Experiencia Laboral
                    </button>
                </div>
                
                <h2><i class="fas fa-graduation-cap"></i> Educación</h2>
                
                <div class="form-group">
                    <label for="education1-degree">Título Académico</label>
                    <input type="text" id="education1-degree" placeholder="Ej: Grado en Ingeniería Informática">
                </div>
                
                <div class="form-group">
                    <label for="education1-school">Institución</label>
                    <input type="text" id="education1-school" placeholder="Ej: Universidad Complutense de Madrid">
                </div>
                
                <div class="form-group">
                    <label for="education1-dates">Fechas</label>
                    <input type="text" id="education1-dates" placeholder="Ej: 2016 - 2020">
                </div>
                
                <h2><i class="fas fa-star"></i> Habilidades</h2>
                
                <div class="form-group">
                    <div class="skills-container" id="skills-container">
                        <!-- Las habilidades se agregarán aquí dinámicamente -->
                    </div>
                    <div class="add-skill">
                        <input type="text" id="new-skill" placeholder="Ej: JavaScript, React, HTML/CSS">
                        <button class="btn btn-sm" id="add-skill-btn">Agregar</button>
                    </div>
                </div>
                
                <button class="btn btn-primary btn-block" id="generate-pdf">
                    <i class="fas fa-download"></i> Descargar CV en PDF
                </button>
            </section>
            
            <!-- Sección de vista previa -->
            <section class="preview-section">
                <h2><i class="fas fa-eye"></i> Vista Previa del CV</h2>
                
                <div class="cv-preview" id="cv-preview">
                    <!-- El encabezado se actualizará dinámicamente según si hay foto o no -->
                    <div id="cv-header-container">
                        <!-- Se llenará dinámicamente con JavaScript -->
                    </div>
                    
                    <div class="cv-section">
                        <div class="cv-section-title">Resumen Profesional</div>
                        <div id="cv-summary">Breve descripción de tu experiencia, habilidades y objetivos profesionales.</div>
                    </div>
                    
                    <div class="cv-section">
                        <div class="cv-section-title">Experiencia Laboral</div>
                        <div id="cv-jobs-container">
                            <!-- Las experiencias laborales se mostrarán aquí -->
                            <div class="cv-item">
                                <div class="cv-item-title">Puesto de Trabajo</div>
                                <div class="cv-item-subtitle">Empresa</div>
                                <div class="cv-item-dates">
                                    Fechas
                                    <span class="current-badge">Actual</span>
                                </div>
                                <div>Descripción de responsabilidades y logros en este puesto.</div>
                            </div>
                        </div>
                    </div>
                    
                    <div class="cv-section">
                        <div class="cv-section-title">Educación</div>
                        <div class="cv-item">
                            <div class="cv-item-title" id="cv-education1-degree">Título Académico</div>
                            <div class="cv-item-subtitle" id="cv-education1-school">Institución</div>
                            <div class="cv-item-dates" id="cv-education1-dates">Fechas</div>
                        </div>
                    </div>
                    
                    <div class="cv-section">
                        <div class="cv-section-title">Habilidades</div>
                        <div class="cv-skills" id="cv-skills">
                            <div class="cv-skill">Ejemplo de habilidad</div>
                            <div class="cv-skill">Otra habilidad</div>
                            <div class="cv-skill">Habilidad técnica</div>
                        </div>
                    </div>
                </div>
                
                <div class="actions">
                    <button class="btn" id="reset-form">
                        <i class="fas fa-redo"></i> Reiniciar Formulario
                    </button>
                    <button class="btn" id="print-cv">
                        <i class="fas fa-print"></i> Imprimir CV
                    </button>
                </div>
                
                <div class="instructions">
                    <h3>Instrucciones:</h3>
                    <ul>
                        <li><strong>Foto opcional:</strong> Con foto tendrás un CV moderno, sin foto un CV clásico.</li>
                        <li>Completa todos los campos del formulario.</li>
                        <li>Agrega tus experiencias laborales con el botón "Agregar Experiencia Laboral".</li>
                        <li>Marca como "Trabajo Actual" si es tu empleo actual.</li>
                        <li>La vista previa se actualizará automáticamente.</li>
                        <li>Agrega tus habilidades una por una.</li>
                        <li>Haz clic en "Descargar CV en PDF" para guardar tu currículum.</li>
                        <li>Usa "Imprimir CV" si prefieres imprimirlo directamente.</li>
                    </ul>
                </div>
            </section>
        </div>
    </div>

    <!-- Incluir html2pdf -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
    
    <script>
        // Elementos del formulario
        const formInputs = {
            name: document.getElementById('name'),
            title: document.getElementById('title'),
            email: document.getElementById('email'),
            phone: document.getElementById('phone'),
            location: document.getElementById('location'),
            summary: document.getElementById('summary'),
            education1Degree: document.getElementById('education1-degree'),
            education1School: document.getElementById('education1-school'),
            education1Dates: document.getElementById('education1-dates'),
            newSkill: document.getElementById('new-skill')
        };
        
        // Elementos de vista previa
        const previewElements = {
            name: document.getElementById('cv-name'),
            title: document.getElementById('cv-title'),
            email: document.getElementById('cv-email'),
            phone: document.getElementById('cv-phone'),
            location: document.getElementById('cv-location'),
            summary: document.getElementById('cv-summary'),
            education1Degree: document.getElementById('cv-education1-degree'),
            education1School: document.getElementById('cv-education1-school'),
            education1Dates: document.getElementById('cv-education1-dates'),
            skills: document.getElementById('cv-skills'),
            jobsContainer: document.getElementById('cv-jobs-container'),
            headerContainer: document.getElementById('cv-header-container')
        };
        
        // Elementos de foto
        const photoInput = document.getElementById('photo-input');
        const photoPreview = document.getElementById('photo-preview-img');
        const photoPlaceholder = document.getElementById('photo-placeholder');
        const uploadPhotoBtn = document.getElementById('upload-photo-btn');
        const removePhotoBtn = document.getElementById('remove-photo-btn');
        
        // Elementos de habilidades
        const skillsContainer = document.getElementById('skills-container');
        const addSkillBtn = document.getElementById('add-skill-btn');
        const cvSkillsContainer = document.getElementById('cv-skills');
        
        // Elementos de experiencia laboral
        const jobsContainer = document.getElementById('jobs-container');
        const addJobBtn = document.getElementById('add-job-btn');
        
        // Botones de acción
        const generatePdfBtn = document.getElementById('generate-pdf');
        const resetFormBtn = document.getElementById('reset-form');
        const printCvBtn = document.getElementById('print-cv');
        
        // Almacenar habilidades
        let skills = ['JavaScript', 'HTML/CSS', 'React', 'Git'];
        
        // Almacenar experiencias laborales
        let jobs = [
            {
                id: 1,
                title: 'Desarrollador Frontend',
                company: 'Tech Solutions S.A.',
                dates: 'Enero 2020 - Presente',
                description: 'Desarrollo de aplicaciones web utilizando React, HTML5 y CSS3. Colaboración en equipos ágiles.',
                current: true
            },
            {
                id: 2,
                title: 'Desarrollador Web Junior',
                company: 'Digital Agency',
                dates: 'Junio 2018 - Diciembre 2019',
                description: 'Creación de sitios web responsivos y mantenimiento de sitios existentes.',
                current: false
            }
        ];
        
        // Almacenar foto (como Data URL)
        let userPhoto = null;
        
        // Función para actualizar el encabezado según si hay foto o no
        function updateCVHeader() {
            if (userPhoto) {
                // Con foto: usar diseño con foto
                previewElements.headerContainer.innerHTML = `
                    <div class="cv-header-with-photo">
                        <div class="cv-header-content">
                            <div class="cv-name">${formInputs.name.value || 'Nombre Completo'}</div>
                            <div class="cv-title">${formInputs.title.value || 'Título Profesional'}</div>
                            <div class="cv-contact">
                                <div class="cv-contact-item">
                                    <i class="fas fa-envelope"></i> ${formInputs.email.value || 'correo@ejemplo.com'}
                                </div>
                                <div class="cv-contact-item">
                                    <i class="fas fa-phone"></i> ${formInputs.phone.value || '+34 612 345 678'}
                                </div>
                                <div class="cv-contact-item">
                                    <i class="fas fa-map-marker-alt"></i> ${formInputs.location.value || 'Ciudad, País'}
                                </div>
                            </div>
                        </div>
                        
                        <div class="cv-photo-container">
                            <img src="${userPhoto}" class="cv-photo">
                        </div>
                    </div>
                `;
            } else {
                // Sin foto: usar diseño clásico (como la versión anterior)
                previewElements.headerContainer.innerHTML = `
                    <div class="cv-header-no-photo">
                        <div class="cv-name">${formInputs.name.value || 'Nombre Completo'}</div>
                        <div class="cv-title">${formInputs.title.value || 'Título Profesional'}</div>
                        <div class="cv-contact">
                            <div class="cv-contact-item">
                                <i class="fas fa-envelope"></i> ${formInputs.email.value || 'correo@ejemplo.com'}
                            </div>
                            <div class="cv-contact-item">
                                <i class="fas fa-phone"></i> ${formInputs.phone.value || '+34 612 345 678'}
                            </div>
                            <div class="cv-contact-item">
                                <i class="fas fa-map-marker-alt"></i> ${formInputs.location.value || 'Ciudad, País'}
                            </div>
                        </div>
                    </div>
                `;
            }
        }
        
        // Inicializar foto
        function initializePhoto() {
            // Agregar evento al botón de subida personalizado
            uploadPhotoBtn.addEventListener('click', function() {
                photoInput.click();
            });
            
            // Manejar selección de archivo
            photoInput.addEventListener('change', handlePhotoUpload);
            
            // Manejar eliminación de foto
            removePhotoBtn.addEventListener('click', removePhoto);
        }
        
        // Manejar subida de foto
        function handlePhotoUpload(event) {
            const file = event.target.files[0];
            if (!file) return;
            
            // Validar tipo de archivo
            if (!file.type.match('image.*')) {
                alert('Por favor, selecciona un archivo de imagen (JPG, PNG, etc.)');
                return;
            }
            
            // Validar tamaño (máximo 2MB)
            if (file.size > 2 * 1024 * 1024) {
                alert('La imagen es demasiado grande. El tamaño máximo es 2MB.');
                return;
            }
            
            const reader = new FileReader();
            
            reader.onload = function(e) {
                userPhoto = e.target.result;
                
                // Mostrar vista previa en el formulario
                photoPreview.src = userPhoto;
                photoPreview.style.display = 'block';
                photoPlaceholder.style.display = 'none';
                
                // Mostrar botón de eliminar
                removePhotoBtn.style.display = 'block';
                
                // Actualizar encabezado del CV
                updateCVHeader();
            };
            
            reader.readAsDataURL(file);
        }
        
        // Eliminar foto
        function removePhoto() {
            userPhoto = null;
            
            // Ocultar vista previa en el formulario
            photoPreview.style.display = 'none';
            photoPlaceholder.style.display = 'flex';
            
            // Ocultar botón de eliminar
            removePhotoBtn.style.display = 'none';
            
            // Limpiar input de archivo
            photoInput.value = '';
            
            // Actualizar encabezado del CV
            updateCVHeader();
        }
        
        // Inicializar experiencias laborales
        function initializeJobs() {
            jobsContainer.innerHTML = '';
            jobs.forEach(job => {
                addJobToForm(job);
            });
            updateJobsPreview();
        }
        
        // Agregar experiencia laboral al formulario
        function addJobToForm(job = null) {
            const jobId = job ? job.id : Date.now();
            const jobTitle = job ? job.title : '';
            const jobCompany = job ? job.company : '';
            const jobDates = job ? job.dates : '';
            const jobDescription = job ? job.description : '';
            const isCurrent = job ? job.current : false;
            
            const jobEntry = document.createElement('div');
            jobEntry.className = 'job-entry';
            jobEntry.id = `job-${jobId}`;
            
            jobEntry.innerHTML = `
                <div class="job-header">
                    <div class="job-title">Experiencia Laboral</div>
                    <button type="button" class="remove-job" data-job-id="${jobId}">
                        <i class="fas fa-times"></i>
                    </button>
                </div>
                
                <div class="current-job-toggle">
                    <span class="toggle-label">¿Es tu trabajo actual?</span>
                    <label class="toggle-switch">
                        <input type="checkbox" class="current-job-checkbox" ${isCurrent ? 'checked' : ''} data-job-id="${jobId}">
                        <span class="toggle-slider"></span>
                    </label>
                </div>
                
                <div class="form-group">
                    <label for="job-title-${jobId}">Puesto de Trabajo</label>
                    <input type="text" id="job-title-${jobId}" class="job-title-input" 
                           placeholder="Ej: Desarrollador Frontend" value="${jobTitle}">
                </div>
                
                <div class="form-group">
                    <label for="job-company-${jobId}">Empresa</label>
                    <input type="text" id="job-company-${jobId}" class="job-company-input" 
                           placeholder="Ej: Tech Solutions S.A." value="${jobCompany}">
                </div>
                
                <div class="form-group">
                    <label for="job-dates-${jobId}">Fechas</label>
                    <input type="text" id="job-dates-${jobId}" class="job-dates-input" 
                           placeholder="Ej: Enero 2020 - Presente" value="${jobDates}">
                </div>
                
                <div class="form-group">
                    <label for="job-description-${jobId}">Descripción</label>
                    <textarea id="job-description-${jobId}" class="job-description-input" 
                              placeholder="Describe tus responsabilidades y logros en este puesto...">${jobDescription}</textarea>
                </div>
            `;
            
            jobsContainer.appendChild(jobEntry);
            
            // Añadir eventos a los campos de este trabajo
            const titleInput = jobEntry.querySelector('.job-title-input');
            const companyInput = jobEntry.querySelector('.job-company-input');
            const datesInput = jobEntry.querySelector('.job-dates-input');
            const descriptionInput = jobEntry.querySelector('.job-description-input');
            const currentCheckbox = jobEntry.querySelector('.current-job-checkbox');
            const removeBtn = jobEntry.querySelector('.remove-job');
            
            // Actualizar el array de trabajos cuando cambien los inputs
            const updateJobInArray = () => {
                const jobIndex = jobs.findIndex(j => j.id === jobId);
                
                if (jobIndex === -1) {
                    // Nuevo trabajo
                    jobs.push({
                        id: jobId,
                        title: titleInput.value,
                        company: companyInput.value,
                        dates: datesInput.value,
                        description: descriptionInput.value,
                        current: currentCheckbox.checked
                    });
                } else {
                    // Actualizar trabajo existente
                    jobs[jobIndex] = {
                        ...jobs[jobIndex],
                        title: titleInput.value,
                        company: companyInput.value,
                        dates: datesInput.value,
                        description: descriptionInput.value,
                        current: currentCheckbox.checked
                    };
                }
                
                updateJobsPreview();
            };
            
            titleInput.addEventListener('input', updateJobInArray);
            companyInput.addEventListener('input', updateJobInArray);
            datesInput.addEventListener('input', updateJobInArray);
            descriptionInput.addEventListener('input', updateJobInArray);
            currentCheckbox.addEventListener('change', updateJobInArray);
            
            // Eliminar trabajo
            removeBtn.addEventListener('click', function() {
                if (jobs.length <= 1) {
                    alert('Debes tener al menos una experiencia laboral.');
                    return;
                }
                
                if (confirm('¿Estás seguro de que quieres eliminar esta experiencia laboral?')) {
                    jobs = jobs.filter(j => j.id !== jobId);
                    jobEntry.remove();
                    updateJobsPreview();
                }
            });
            
            // Si es un trabajo nuevo, agregarlo al array
            if (!job) {
                jobs.push({
                    id: jobId,
                    title: '',
                    company: '',
                    dates: '',
                    description: '',
                    current: false
                });
            }
        }
        
        // Actualizar vista previa de experiencias laborales
        function updateJobsPreview() {
            previewElements.jobsContainer.innerHTML = '';
            
            // Ordenar trabajos: primero los actuales, luego los anteriores
            const sortedJobs = [...jobs].sort((a, b) => {
                if (a.current && !b.current) return -1;
                if (!a.current && b.current) return 1;
                return 0;
            });
            
            sortedJobs.forEach(job => {
                if (job.title || job.company || job.dates || job.description) {
                    const jobElement = document.createElement('div');
                    jobElement.className = 'cv-item';
                    
                    jobElement.innerHTML = `
                        <div class="cv-item-title">${job.title || 'Puesto de Trabajo'}</div>
                        <div class="cv-item-subtitle">${job.company || 'Empresa'}</div>
                        <div class="cv-item-dates">
                            ${job.dates || 'Fechas'}
                            ${job.current ? '<span class="current-badge">Actual</span>' : ''}
                        </div>
                        <div>${job.description || 'Descripción de responsabilidades y logros en este puesto.'}</div>
                    `;
                    
                    previewElements.jobsContainer.appendChild(jobElement);
                }
            });
            
            // Si no hay trabajos, mostrar un placeholder
            if (previewElements.jobsContainer.children.length === 0) {
                const placeholder = document.createElement('div');
                placeholder.className = 'cv-item';
                placeholder.innerHTML = `
                    <div class="cv-item-title">Puesto de Trabajo</div>
                    <div class="cv-item-subtitle">Empresa</div>
                    <div class="cv-item-dates">
                        Fechas
                        <span class="current-badge">Actual</span>
                    </div>
                    <div>Descripción de responsabilidades y logros en este puesto.</div>
                `;
                previewElements.jobsContainer.appendChild(placeholder);
            }
        }
        
        // Inicializar habilidades
        function initializeSkills() {
            skills.forEach(skill => addSkillToContainers(skill));
        }
        
        // Agregar habilidad a ambos contenedores
        function addSkillToContainers(skill) {
            // Agregar al formulario
            const skillTag = document.createElement('div');
            skillTag.className = 'skill-tag';
            skillTag.innerHTML = `
                ${skill}
                <span class="remove-skill" data-skill="${skill}">×</span>
            `;
            skillsContainer.appendChild(skillTag);
            
            // Agregar a la vista previa
            const cvSkill = document.createElement('div');
            cvSkill.className = 'cv-skill';
            cvSkill.textContent = skill;
            cvSkillsContainer.appendChild(cvSkill);
            
            // Añadir evento para eliminar habilidad
            skillTag.querySelector('.remove-skill').addEventListener('click', function() {
                const skillToRemove = this.getAttribute('data-skill');
                skills = skills.filter(s => s !== skillToRemove);
                updateSkillsDisplay();
            });
        }
        
        // Actualizar visualización de habilidades
        function updateSkillsDisplay() {
            // Limpiar contenedores
            skillsContainer.innerHTML = '';
            cvSkillsContainer.innerHTML = '';
            
            // Volver a agregar todas las habilidades
            skills.forEach(skill => addSkillToContainers(skill));
        }
        
        // Actualizar vista previa en tiempo real
        function updatePreview() {
            // Información personal
            updateCVHeader(); // Actualizar encabezado según si hay foto o no
            
            previewElements.summary.textContent = formInputs.summary.value || 'Breve descripción de tu experiencia, habilidades y objetivos profesionales.';
            
            // Educación
            previewElements.education1Degree.textContent = formInputs.education1Degree.value || 'Título Académico';
            previewElements.education1School.textContent = formInputs.education1School.value || 'Institución';
            previewElements.education1Dates.textContent = formInputs.education1Dates.value || 'Fechas';
            
            // Experiencias laborales ya se actualizan por separado
        }
        
        // Añadir eventos de entrada a todos los campos del formulario
        Object.values(formInputs).forEach(input => {
            if (input && input.tagName !== 'BUTTON') {
                input.addEventListener('input', updatePreview);
            }
        });
        
        // Añadir nueva habilidad
        addSkillBtn.addEventListener('click', function() {
            const newSkill = formInputs.newSkill.value.trim();
            if (newSkill && !skills.includes(newSkill)) {
                skills.push(newSkill);
                updateSkillsDisplay();
                formInputs.newSkill.value = '';
            }
        });
        
        // Permitir agregar habilidad con Enter
        formInputs.newSkill.addEventListener('keypress', function(e) {
            if (e.key === 'Enter') {
                addSkillBtn.click();
            }
        });
        
        // Añadir nueva experiencia laboral
        addJobBtn.addEventListener('click', function() {
            addJobToForm();
        });
        
        // Crear CV limpio para PDF con pie de página personalizado
        function createCleanCVForPDF() {
            const cleanCV = document.createElement('div');
            cleanCV.className = 'cv-pdf-clean';
            
            // Ordenar trabajos: primero los actuales, luego los anteriores
            const sortedJobs = [...jobs].sort((a, b) => {
                if (a.current && !b.current) return -1;
                if (!a.current && b.current) return 1;
                return 0;
            });
            
            // Filtrar trabajos que tengan al menos un campo completado
            const filteredJobs = sortedJobs.filter(job => 
                job.title || job.company || job.dates || job.description
            );
            
            // Crear encabezado según si hay foto o no
            let headerHTML = '';
            if (userPhoto) {
                // Con foto: diseño moderno
                headerHTML = `
                    <div style="background-color: #2c3e50; color: white; padding: 30px; border-radius: 8px; margin-bottom: 30px; display: flex; justify-content: space-between; align-items: flex-start;">
                        <div style="flex: 1;">
                            <div style="font-size: 28pt; font-weight: bold; margin-bottom: 5px;">${formInputs.name.value || 'Nombre Completo'}</div>
                            <div style="font-size: 18pt; opacity: 0.9; margin-bottom: 15px;">${formInputs.title.value || 'Título Profesional'}</div>
                            <div style="display: flex; flex-wrap: wrap; gap: 20px; margin-top: 15px;">
                                <div style="display: flex; align-items: center; gap: 8px; font-size: 11pt;">
                                    <i class="fas fa-envelope"></i> ${formInputs.email.value || 'correo@ejemplo.com'}
                                </div>
                                <div style="display: flex; align-items: center; gap: 8px; font-size: 11pt;">
                                    <i class="fas fa-phone"></i> ${formInputs.phone.value || '+34 612 345 678'}
                                </div>
                                <div style="display: flex; align-items: center; gap: 8px; font-size: 11pt;">
                                    <i class="fas fa-map-marker-alt"></i> ${formInputs.location.value || 'Ciudad, País'}
                                </div>
                            </div>
                        </div>
                        
                        <div style="width: 120px; height: 150px; border-radius: 8px; overflow: hidden; border: 3px solid rgba(255, 255, 255, 0.3); margin-left: 20px; flex-shrink: 0;">
                            <img src="${userPhoto}" style="width: 100%; height: 100%; object-fit: cover;">
                        </div>
                    </div>
                `;
            } else {
                // Sin foto: diseño clásico (como versión anterior)
                headerHTML = `
                    <div style="background-color: #2c3e50; color: white; padding: 30px; border-radius: 8px; margin-bottom: 30px;">
                        <div style="font-size: 28pt; font-weight: bold; margin-bottom: 5px;">${formInputs.name.value || 'Nombre Completo'}</div>
                        <div style="font-size: 18pt; opacity: 0.9; margin-bottom: 15px;">${formInputs.title.value || 'Título Profesional'}</div>
                        <div style="display: flex; flex-wrap: wrap; gap: 20px; margin-top: 15px;">
                            <div style="display: flex; align-items: center; gap: 8px; font-size: 11pt;">
                                <i class="fas fa-envelope"></i> ${formInputs.email.value || 'correo@ejemplo.com'}
                            </div>
                            <div style="display: flex; align-items: center; gap: 8px; font-size: 11pt;">
                                <i class="fas fa-phone"></i> ${formInputs.phone.value || '+34 612 345 678'}
                            </div>
                            <div style="display: flex; align-items: center; gap: 8px; font-size: 11pt;">
                                <i class="fas fa-map-marker-alt"></i> ${formInputs.location.value || 'Ciudad, País'}
                            </div>
                        </div>
                    </div>
                `;
            }
            
            cleanCV.innerHTML = `
                ${headerHTML}
                
                <div class="cv-pdf-section">
                    <div class="cv-pdf-section-title">Resumen Profesional</div>
                    <div>${formInputs.summary.value || 'Breve descripción de tu experiencia, habilidades y objetivos profesionales.'}</div>
                </div>
                
                <div class="cv-pdf-section">
                    <div class="cv-pdf-section-title">Experiencia Laboral</div>
                    ${filteredJobs.map(job => `
                        <div class="cv-pdf-item">
                            <div class="cv-pdf-item-title">${job.title || 'Puesto de Trabajo'}</div>
                            <div class="cv-pdf-item-subtitle">${job.company || 'Empresa'}</div>
                            <div class="cv-pdf-item-dates">
                                ${job.dates || 'Fechas'}
                                ${job.current ? '<span style="background-color: #27ae60; color: white; padding: 2px 8px; border-radius: 12px; font-size: 0.8rem; margin-left: 8px;">Actual</span>' : ''}
                            </div>
                            <div>${job.description || 'Descripción de responsabilidades y logros en este puesto.'}</div>
                        </div>
                    `).join('')}
                </div>
                
                <div class="cv-pdf-section">
                    <div class="cv-pdf-section-title">Educación</div>
                    <div class="cv-pdf-item">
                        <div class="cv-pdf-item-title">${formInputs.education1Degree.value || 'Título Académico'}</div>
                        <div class="cv-pdf-item-subtitle">${formInputs.education1School.value || 'Institución'}</div>
                        <div class="cv-pdf-item-dates">${formInputs.education1Dates.value || 'Fechas'}</div>
                    </div>
                </div>
                
                <div class="cv-pdf-section">
                    <div class="cv-pdf-section-title">Habilidades</div>
                    <div class="cv-pdf-skills">
                        ${skills.map(skill => `<div class="cv-pdf-skill">${skill}</div>`).join('')}
                    </div>
                </div>
                
                <!-- Pie de página para el PDF -->
                <div class="pdf-footer">
                    <div class="page-number">Página <span class="page"></span> de <span class="total"></span></div>
                </div>
            `;
            
            // Agregar estilos CSS para el PDF
            const style = document.createElement('style');
            style.textContent = `
                .cv-pdf-clean {
                    width: 100%;
                    background-color: white;
                    padding: 40px;
                    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
                    color: #333;
                    line-height: 1.6;
                    position: relative;
                    min-height: 100vh;
                }
                
                .cv-pdf-section {
                    margin-bottom: 25px;
                }
                
                .cv-pdf-section-title {
                    color: #2c3e50;
                    border-bottom: 2px solid #4a6491;
                    padding-bottom: 5px;
                    margin-bottom: 15px;
                    font-size: 16pt;
                    font-weight: bold;
                }
                
                .cv-pdf-item {
                    margin-bottom: 15px;
                    padding-bottom: 15px;
                    border-bottom: 1px solid #eee;
                }
                
                .cv-pdf-item:last-child {
                    border-bottom: none;
                }
                
                .cv-pdf-item-title {
                    font-weight: 600;
                    color: #333;
                    margin-bottom: 5px;
                    font-size: 12pt;
                }
                
                .cv-pdf-item-subtitle {
                    color: #4a6491;
                    font-style: italic;
                    margin-bottom: 5px;
                    font-size: 11pt;
                }
                
                .cv-pdf-item-dates {
                    color: #666;
                    font-size: 10pt;
                    margin-bottom: 8px;
                    display: flex;
                    align-items: center;
                }
                
                .cv-pdf-skills {
                    display: flex;
                    flex-wrap: wrap;
                    gap: 10px;
                    margin-bottom: 60px;
                }
                
                .cv-pdf-skill {
                    background-color: #eef2f7;
                    padding: 6px 12px;
                    border-radius: 4px;
                    font-size: 10pt;
                }
                
                .pdf-footer {
                    position: fixed;
                    bottom: 0;
                    left: 0;
                    right: 0;
                    text-align: center;
                    font-size: 10pt;
                    color: #666;
                    padding: 10px;
                    background-color: white;
                    border-top: 1px solid #eee;
                    height: 40px;
                }
                
                .page-number {
                    font-family: Arial, sans-serif;
                }
            `;
            
            cleanCV.appendChild(style);
            return cleanCV;
        }
        
        // Generar PDF limpio con numeración de páginas personalizada
        generatePdfBtn.addEventListener('click', async function() {
            const cleanCV = createCleanCVForPDF();
            
            // Opciones para html2pdf
            const options = {
                margin: [0.5, 0.8, 0.5, 0.8], // [top, right, bottom, left]
                filename: `CV_${formInputs.name.value || 'Mi_CV'}.pdf`,
                image: { type: 'jpeg', quality: 0.98 },
                html2canvas: { 
                    scale: 2,
                    useCORS: true,
                    logging: false,
                    windowWidth: 794,
                    windowHeight: 1123
                },
                jsPDF: { 
                    unit: 'mm', 
                    format: 'a4', 
                    orientation: 'portrait',
                    putTotalPages: '{total_pages_count_string}'
                },
                pagebreak: { mode: ['avoid-all', 'css', 'legacy'] }
            };
            
            // Configurar el pie de página con números de página
            const worker = html2pdf().set(options).from(cleanCV);
            
            worker.toPdf().get('pdf').then(function(pdf) {
                const totalPages = pdf.internal.getNumberOfPages();
                
                for (let i = 1; i <= totalPages; i++) {
                    pdf.setPage(i);
                    pdf.setFontSize(10);
                    pdf.setFont("helvetica", "normal");
                    pdf.text(`Página ${i} de ${totalPages}`, pdf.internal.pageSize.width / 2, 
                            pdf.internal.pageSize.height - 10, {align: 'center'});
                }
            }).save();
        });
        
        // Imprimir CV limpio
        printCvBtn.addEventListener('click', function() {
            const cleanCV = createCleanCVForPDF();
            
            // Crear ventana de impresión
            const printWindow = window.open('', '_blank');
            printWindow.document.write(`
                <!DOCTYPE html>
                <html>
                <head>
                    <title>Curriculum Vitae - ${formInputs.name.value || 'Mi CV'}</title>
                    <style>
                        body {
                            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
                            color: #333;
                            line-height: 1.6;
                            margin: 0;
                            padding: 20px;
                        }
                        
                        .cv-pdf-header {
                            background-color: #2c3e50;
                            color: white;
                            padding: 30px;
                            border-radius: 8px;
                            margin-bottom: 30px;
                        }
                        
                        .cv-pdf-header-with-photo {
                            display: flex;
                            justify-content: space-between;
                            align-items: flex-start;
                        }
                        
                        .cv-pdf-name {
                            font-size: 28pt;
                            margin-bottom: 5px;
                            font-weight: bold;
                        }
                        
                        .cv-pdf-title {
                            font-size: 18pt;
                            opacity: 0.9;
                            margin-bottom: 15px;
                        }
                        
                        .cv-pdf-contact {
                            display: flex;
                            flex-wrap: wrap;
                            gap: 20px;
                            margin-top: 15px;
                        }
                        
                        .cv-pdf-contact-item {
                            display: flex;
                            align-items: center;
                            gap: 8px;
                            font-size: 11pt;
                        }
                        
                        .cv-photo-container {
                            width: 120px;
                            height: 150px;
                            border-radius: 8px;
                            overflow: hidden;
                            border: 3px solid rgba(255, 255, 255, 0.3);
                            margin-left: 20px;
                        }
                        
                        .cv-photo-container img {
                            width: 100%;
                            height: 100%;
                            object-fit: cover;
                        }
                        
                        .cv-pdf-section {
                            margin-bottom: 25px;
                        }
                        
                        .cv-pdf-section-title {
                            color: #2c3e50;
                            border-bottom: 2px solid #4a6491;
                            padding-bottom: 5px;
                            margin-bottom: 15px;
                            font-size: 16pt;
                            font-weight: bold;
                        }
                        
                        .cv-pdf-item {
                            margin-bottom: 15px;
                            padding-bottom: 15px;
                            border-bottom: 1px solid #eee;
                        }
                        
                        .cv-pdf-item:last-child {
                            border-bottom: none;
                        }
                        
                        .cv-pdf-item-title {
                            font-weight: 600;
                            color: #333;
                            margin-bottom: 5px;
                            font-size: 12pt;
                        }
                        
                        .cv-pdf-item-subtitle {
                            color: #4a6491;
                            font-style: italic;
                            margin-bottom: 5px;
                            font-size: 11pt;
                        }
                        
                        .cv-pdf-item-dates {
                            color: #666;
                            font-size: 10pt;
                            margin-bottom: 8px;
                            display: flex;
                            align-items: center;
                        }
                        
                        .cv-pdf-skills {
                            display: flex;
                            flex-wrap: wrap;
                            gap: 10px;
                        }
                        
                        .cv-pdf-skill {
                            background-color: #eef2f7;
                            padding: 6px 12px;
                            border-radius: 4px;
                            font-size: 10pt;
                        }
                        
                        @media print {
                            body {
                                padding: 0;
                            }
                            
                            @page {
                                margin: 20mm;
                                @bottom-center {
                                    content: "Página " counter(page) " de " counter(pages);
                                    font-family: Arial, sans-serif;
                                    font-size: 10pt;
                                    color: #666;
                                }
                            }
                        }
                    </style>
                </head>
                <body>
                    ${cleanCV.innerHTML}
                </body>
                </html>
            `);
            
            printWindow.document.close();
            printWindow.focus();
            
            setTimeout(() => {
                printWindow.print();
                setTimeout(() => {
                    printWindow.close();
                }, 500);
            }, 500);
        });
        
        // Reiniciar formulario
        resetFormBtn.addEventListener('click', function() {
            if (confirm('¿Estás seguro de que quieres reiniciar el formulario? Se perderán todos los datos.')) {
                // Limpiar campos del formulario
                Object.values(formInputs).forEach(input => {
                    if (input && input.tagName !== 'BUTTON') {
                        input.value = '';
                    }
                });
                
                // Restablecer habilidades
                skills = ['JavaScript', 'HTML/CSS', 'React', 'Git'];
                updateSkillsDisplay();
                
                // Restablecer experiencias laborales
                jobs = [
                    {
                        id: 1,
                        title: '',
                        company: '',
                        dates: '',
                        description: '',
                        current: false
                    }
                ];
                initializeJobs();
                
                // Eliminar foto si existe
                if (userPhoto) {
                    removePhoto();
                }
                
                // Actualizar vista previa
                updatePreview();
            }
        });
        
        // Datos de ejemplo para probar
        function loadSampleData() {
            // Solo cargar si no hay datos en el formulario
            if (!formInputs.name.value) {
                formInputs.name.value = 'María López García';
                formInputs.title.value = 'Desarrolladora Full Stack';
                formInputs.email.value = 'maria.lopez@email.com';
                formInputs.phone.value = '+34 634 567 890';
                formInputs.location.value = 'Barcelona, España';
                formInputs.summary.value = 'Desarrolladora con 5 años de experiencia en el desarrollo de aplicaciones web. Especializada en JavaScript, React y Node.js. Apasionada por crear soluciones eficientes y escalables.';
                formInputs.education1Degree.value = 'Grado en Ingeniería Informática';
                formInputs.education1School.value = 'Universidad Politécnica de Cataluña';
                formInputs.education1Dates.value = '2015 - 2019';
                
                // Actualizar vista previa
                updatePreview();
            }
        }
        
        // Inicializar la aplicación
        function init() {
            initializePhoto();
            initializeSkills();
            initializeJobs();
            updatePreview();
            loadSampleData();
        }
        
        // Iniciar cuando el DOM esté listo
        document.addEventListener('DOMContentLoaded', init);
    </script>
</body>
</html>
=SI(ESTVIDE(A1); "ta formule"; A1)
{
	"blocks": [
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":sunshine: :x-connect: Boost Days: What's on this week :x-connect: :sunshine:"
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "Good morning Melbourne and hope you all had a fab weekend! :sunshine: \n\n Please see below for what's on this week! "
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":calendar-date-21: Wednesday, 21st January",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n:coffee:  :donutss: *Xero Café* – A selection of Donuts \n :coffee:*Barista Special* – Rod Laver Latte :tennis: \n :spaghetti:Join us at *12.00pm* for some * Delicious Pasta from Pasta Prego* in the Wominjeka Breakout Space on Level 3. Check out the:thread:"
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":calendar-date-22: Thursday, 22nd January",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": ":coffee: *Xero Cafe*: A selection of Donuts \n :coffee: *Barista Special* – Rod Laver Latte \n :Breakfast: Join us at *8.30am -10.30am* for a * Breakfast Buffet* in the Wominjeka Breakout Space in the Level 3 breakout space."
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": " What else? :heart:  \n\nStay tuned to this channel, and make sure you’re subscribed to the <https://calendar.google.com/calendar/u/0/r?cid=Y19xczkyMjk5ZGlsODJzMjA4aGt1b3RnM2t1MEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t /|*Melbourne Social Calendar*> for all upcoming events. \n\n :tennis: :pingpong: In celebration of the Australian Open, On *Friday 30th January*, we are inviting 20 teams to compete in our own Xero Melbourne Open :melbourne:. Yes, we are hosting a Ping Pong competition during our Social at 4pm in the Wominjeka Breakout Space. Please sign up in the :thread: for a chance to win some official AO merchandise. \n\n DON'T MISS OUT! :yay:\t\t"
			}
		}
	]
}
 // page view counter
        function incrementPageViewCount() {
            const key = "page_view_count";
            const count = Number(sessionStorage.getItem(key)) || 0;
            const newCount = count + 1;
            sessionStorage.setItem(key, newCount);
            return newCount;
        }
import $, { contains } from 'jquery';

class Property {
  constructor(element) {
    this.$element = $(element);
    this.$tabs = this.$element.find(".property--tab li");
    this.$tabsContent = this.$element.find(".property--main-row");
    this.init();
  }

  init() {
    this.$tabs.first().addClass("active");
    this.$tabsContent.hide();
    this.$tabsContent.first().show();

    this.$tabs.click((e) => {
      e.preventDefault();
      if ($(e.currentTarget).hasClass("active")) {
        return;
      }
      this.$tabs.removeClass("active");
      $(e.currentTarget).addClass("active");
      this.$tabsContent.hide();

      var activeTab = $(e.currentTarget).find("a").attr("href");
      $(activeTab).fadeIn(700);
      return false;
    });
  }
}

$('[data-property]').each((index, element) => new Property(element));
A reliable approach is to work with a development team that delivers cryptocurrency exchange software built for security, speed, and operational stability. The right solution should support centralized, decentralized, or hybrid exchange models and adapt to specific business and market requirements. Features such as robust security controls, fast transaction processing, real-time updates, and comprehensive management tools are essential for serving both beginner and professional traders. Softean’s cryptocurrency exchange development follow this approach, enabling businesses to scale confidently while maintaining trust, performance, and long-term reliability >> https://www.softean.com/cryptocurrency-exchange-development  
function getRandomChar(charset: string) {
  const index = Math.floor(Math.random() * charset.length);
  return charset[index] ?? "";
}

function generateRandomString(length: number, charset: string) {
  let result = "";
  for (let i = 0; i < length; i += 1) {
    result += getRandomChar(charset);
  }
  return result;
}
// px -> rem 转换
const pxToRem = (px: number, base: number) => {
  if (base === 0) return "0";
  return (px / base).toFixed(4).replace(/\.?0+$/, "");
};

// rem -> px 转换
const remToPx = (rem: number, base: number) => {
  return (rem * base).toFixed(2).replace(/\.?0+$/, "");
};
Within the vast body of industry, where structures stand on the shoulders of strength and machinery operates on the foundation of reliability, small components play a key role that might go unnoticed at first glance. Among these silent heroes, the Grade 8.8 bolt holds a lofty and unparalleled position. This name, familiar in the Iranian market vernacular, in fact narrates a story of steel, carbon, and tireless resistance. But the fundamental question is: What differentiates this seemingly simple piece from ordinary bolts? Why has purchasing  <a href="https://screw.full-design.com/grade-8-8-bolt-the-steel-elixir-in-the-fastening-industry-81814969" onclick="window.open(this.href, '', 'resizable=no,status=no,location=no,toolbar=no,menubar=no,fullscreen=no,scrollbars=no,dependent=no'); return false;">Grade 8.8 bolts</a>
{
	"blocks": [
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":sunshine: :x-connect: Boost Days: What's on this week :x-connect: :sunshine:"
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "Good morning Brisbane and hope you all had a fab weekend! :sunshine: \n\n Please see below for what's on this week! :yay: Due to the low attendance last week in the office, we have changes to the boost program this week. "
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":calendar-date-12: Monday, 12th January",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n:coffee: *Café Partnership*: Enjoy free coffee and café-style beverages from our Cafe partner *Industry Beans*.\n\n :croissant: Morning tea from 9am in the kitchen. \n:Lunch: Delicious *Greenstreat salads* provided in the kitchen from *12pm* in the kitchen."
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":calendar-date-14: Wednesday, 14th January",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": ":coffee: *Café Partnership*: Enjoy free coffee and café-style beverages from our Cafe partner *Industry Beans*. \n\n:lunch: *Morning Tea*:from *9am* in the kitchen!"
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":calendar-date-16:Friday, 16th January ",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": ":cheers-9743: :cheese: *Happy Hour & Happy Friday:* from 3pm - 4pm in the kitchen! Wind down for the week over some drinks and nibbles."
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "Stay tuned to this channel for more details, check out the <https://calendar.google.com/calendar/u/0?cid=Y19uY2M4cDN1NDRsdTdhczE0MDhvYjZhNnRjb0Bncm91cC5jYWxlbmRhci5nb29nbGUuY29t|*Brisbane Social Calendar*>, and get ready to Boost your workdays!\n\nLove,\nWX Team :party-wx:"
			}
		}
	]
}
{
	"blocks": [
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":sunshine: :x-connect: Boost Days: What's on this week :x-connect: :sunshine:"
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "Good morning Melbourne and hope you all had a fab weekend! :sunshine: \n\n Please see below for what's on this week! "
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":calendar-date-14: Wednesday, 14th January",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": "\n:coffee: :strawberry: :muffin: *Xero Café* – Cookies \n :coffee::gingerman: *Barista Special* – Lavender iced Latte \n :Lunch:Join us at *12.00pm* for some Mexican in the Wominjeka Breakout Space on Level 3. Check out the :thread:"
			}
		},
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": ":calendar-date-15: Thursday, 15th January",
				"emoji": true
			}
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": ":coffee: *Xero Cafe*: Cookies \n :coffee: *Barista Special* – Lavender iced latte \n :Breakfast: Join us at *8.30am -10.30am* for a * Breakfast Buffet* in the Wominjeka Breakout Space in the Level 3 breakout space. \n :pizza::party: Join us at *4.00pm* in the Level 3 breakout space for some cheese and drinks"
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "section",
			"text": {
				"type": "mrkdwn",
				"text": " What else?  \n\nStay tuned to this channel, and make sure you’re subscribed to the <https://calendar.google.com/calendar/u/0/r?cid=Y19xczkyMjk5ZGlsODJzMjA4aGt1b3RnM2t1MEBncm91cC5jYWxlbmRhci5nb29nbGUuY29t /|*Melbourne Social Calendar*> for all upcoming events."
			}
		}
	]
}
function footerNavTracking() {
        const footerWrapper = document.querySelector(".footer__wrapper");
        if (!footerWrapper) return;

        footerWrapper.addEventListener("click", (e) => {
            // Find the closest relevant link
            const link = e.target.closest(
                ".footer__col-second-button_wrapper a, .footer__logo-link",
            );
            if (!link) return;

            e.preventDefault();

            // Get the URL from the <a> tag
            const url = link.getAttribute("href") || "";

            // Social links
            if (link.matches(".footer__col-second-button_wrapper a")) {
                // Get the visible text (after the span/SVG)
                const linkTextRaw = link.lastChild.textContent.trim();
                const linkText = linkTextRaw.replace(/\s+/g, " ").trim() || "";

                gtmPush({
                    event: "navigation_click",
                    navigation_type: "footer_nav",
                    click_text: linkText,
                    click_url: url,
                    level: 1,
                });
            }

            // Logo links
            if (link.matches(".footer__logo-link")) {
                const linkTextRaw =
                    link.querySelector("svg title")?.textContent || "";
                const linkText = linkTextRaw.replace(/\s+/g, " ").trim() || "";
                const url = link.getAttribute("href") || "";

                gtmPush({
                    event: "navigation_click",
                    navigation_type: "footer_nav",
                    click_text: linkText,
                    click_url: url,
                    level: 1,
                });
            }
        });
    }
function navigationTracking() {
        const mainNav = document.querySelector(".main-navigation__main");
        if (!mainNav) return;

        const navItems = [
            {
                selector: ".main-navigation__control-link",
                type: "nav-links",
                handler: (e, el) => {
                    const btnText = el.textContent.trim() || "";
                    const isPressed =
                        el.getAttribute("aria-pressed") === "true";

                    navigationClickTracking(btnText, null, 1, isPressed);
                },
            },
            {
                selector: "#main-nav-bookmarks",
                type: "nav-bookmark",
                handler: (e, el) => {
                    const btnText = el.innerText.trim();
                    navigationClickTracking(btnText, "/sruh/bookmarks", 1);
                },
            },
            {
                selector: "#main-nav-close",
                type: "nav-search",
                handler: (e, el) => {
                    const btnText = el.outerText.trim();
                    navigationClickTracking(btnText, null, 1);
                },
            },
            {
                selector: "#main-nav-quiz",
                type: "nav-quiz",
                handler: (e, el) => {
                    const cleanText = el.textContent
                        .replace(/\s+/g, " ")
                        .trim();

                    navigationClickTracking(cleanText, "/sruh/quiz", 1);
                },
            },
        ];

        navItems.forEach((item) => {
            const elements = mainNav.querySelectorAll(item.selector);

            elements.forEach((el) => {
                // ✅ prevent duplicate listeners
                if (el.dataset.navTracked) return;
                el.dataset.navTracked = "true";

                el.addEventListener("click", (e) => {
                    e.preventDefault();
                    item.handler(e, el);
                });
            });
        });

        /*  SUB MENU LINK TRACKING */

        const subNavButtons = document.querySelectorAll(
            ".main-navigation__control-link",
        );
        if (!subNavButtons.length) return;

        subNavButtons.forEach((button) => {
            // prevent duplicate listeners
            if (button.dataset.subNavTracked) return;
            button.dataset.subNavTracked = "true";

            button.addEventListener("click", (e) => {
                e.preventDefault();

                const isActive = button.classList.contains("active");
                if (!isActive) return;

                const subNavWrapper = document.querySelector(
                    ".main-navigation__aside",
                );
                if (!subNavWrapper) return;

                const contentMenus = subNavWrapper.querySelectorAll(
                    ".main-navigation__content",
                );

                // wait for active class toggle
                setTimeout(() => {
                    contentMenus.forEach((menu) => {
                        if (!menu.classList.contains("active")) return;

                        const links = menu.querySelectorAll(
                            ".main-navigation__content-list li a",
                        );

                        links.forEach((link) => {
                            // ✅ prevent duplicate listeners
                            if (link.dataset.subNavLinkTracked) return;
                            link.dataset.subNavLinkTracked = "true";

                            link.addEventListener("click", (e) => {
                                e.preventDefault();

                                const linkText = link.textContent
                                    .replace(/\s+/g, " ")
                                    .trim();

                                const linkUrl = link.getAttribute("href") || "";

                                navigationClickTracking(linkText, linkUrl, 2);
                            });
                        });
                    });
                }, 100);
            });
        });
    }
A P2P crypto exchange allows users to trade directly with each other in a secure and transparent environment. At Beleaf Technologies, we make this process simple and reliable by building user-friendly P2P exchange platforms designed around real trading needs. Our solutions include trusted escrow systems, multiple payment options, and strong security measures to protect every transaction. Whether you’re a startup or a growing business, Beleaf Technologies supports you from idea to launch, helping you create a scalable P2P exchange that builds trust and grows with your users.

Visit Our Website >> https://beleaftechnologies.com/p2p-cryptocurrency-exchange-development-company

Reach Now 

Whatsapp : +91 8056786622

Email id : business@beleaftechnologies.com 


// Get selected Sales Offer
var salesOffer = ZDK.Page.getField("Sales_Offer").getValue();
if (salesOffer == null) {
	ZDK.Page.getField("Project_Name").setValue(null);
	ZDK.Page.getField("Unit").setValue(null);
	ZDK.Page.getField("Office_Location").setValue("");
	return;
}

// Fetch Sales Offer (Quote) details
var quote = ZDK.Apps.CRM.Quotes.fetchById(salesOffer.id);
// ---------------- Project ----------------
var project = null;
var projectID = quote._Projects.id;
var projectName = quote._Projects.name;
// var = proj = quote.Project;
var proj = ZDK.Page.getField('Project_Name');
proj.setValue({
	id: projectID,
	name: projectName
});

if (quote.Projects != null) {
	projectID = quote.Projects;
	project = {
		id: quote._Projects.id
	};
}

var projectID = quote._Unit_Name.id;
var projectName = quote._Unit_Name.name;
var unit = ZDK.Page.getField('Unit');
unit.setValue({
	id: projectID,
	name: projectName
});
console.log(unit);
console.log(project);
// ---------------- Office Location ----------------
var officeLocation = "";
if (quote.Office_Location != null) {
	officeLocation = quote.Office_Location;
}

ZDK.Page.getField("Office_Location").setValue(officeLocation);
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Sebagai bentuk komitmen BCA Insurance untuk memberikan pelayanan terbaik, anda dapat menyampaikan pengaduan terhadap layanan kepada kami melalui; Whatsap :(+62)08174772812) Untuk informasi layanan bantuan sentiasa disisi anda 24Jam.
Ya , Nasabah yang terhormat , Berikut WhatsApp , + 62 ( O8174772812 ) informasi jam layanan Dari BCA life call center halo bca I5OO8 & 8 Melalui tlpn ( EXT .I .6.I ) & Aplikasi halo bca ( Menu BcA Live ) 24jam . Layanan O6 ; OO - 22.OO WlB .              
Ya, Nasabah yang terhormat, Berikut WhatsApp, +62 (O8174772812) informasi jam layanan Dari BCa life call center halo bca I5OO8&8 Melalui tlpn (EXT. I.6.I) & Aplikasi halo bca (Menu BcA Live) 24jam. Layanan O6;OO-22.OO WlB.
Yoga Teacher Training in Rishikesh has gained global recognition as a trusted path for learning authentic yoga. As yoga continues to grow worldwide, many practitioners are seeking education that is rooted in tradition, discipline, and deeper understanding. Rishikesh, widely known as the Yoga Capital of the World, offers a learning environment that reflects the true spirit and purpose of yoga.

Rishikesh as a Center for Authentic Yoga Learning

Rishikesh is not just a popular destination for yoga; it is a place where yoga has been practiced and preserved for generations. Located along the sacred Ganges River and surrounded by the Himalayan foothills, the city provides an atmosphere that naturally supports meditation, self-study, and mindful living. This spiritual setting plays a significant role in enhancing the overall yoga teacher training experience.

Well-Designed Teacher Training Programs

Yoga teacher training programs in Rishikesh are carefully structured to meet international standards while maintaining traditional values. Courses typically include comprehensive training in yoga asanas, alignment, pranayama, meditation, yoga philosophy, anatomy, and teaching methodology. This well-rounded approach helps students develop confidence, clarity, and competence as yoga practitioners and teachers.

Learning Beyond Physical Practice

Unlike short-term workshops or fitness-based certifications, yoga teacher training in Rishikesh emphasizes yoga as a complete system. Students learn about ethical principles, yogic lifestyle practices, and the mental and spiritual aspects of yoga. This broader perspective allows students to understand yoga as a lifelong practice rather than a physical routine.

Guidance from Knowledgeable Instructors

One of the key advantages of training in Rishikesh is the opportunity to learn from experienced teachers. Many instructors have studied under traditional lineages and bring years of practical and philosophical knowledge to their teaching. Their guidance helps students develop a strong foundation and a respectful approach to sharing yoga with others.

Immersion in a Yogic Lifestyle

Yoga teacher training in Rishikesh often includes a disciplined daily schedule that supports holistic growth. Early morning practices, meditation sessions, and simple vegetarian meals are commonly part of the training experience. This immersive lifestyle encourages mental clarity, physical balance, and emotional stability.

Exposure to a Global Yoga Community

Students from different countries and backgrounds come together in Rishikesh to pursue yoga teacher training. This diverse learning environment encourages cultural exchange and shared understanding. Training within an international community also prepares students to teach yoga to people from various walks of life.

Long-Term Benefits of Training in Rishikesh

The impact of yoga teacher training in Rishikesh often extends far beyond certification. Many students experience increased self-awareness, improved discipline, and a stronger connection to their personal values. These benefits support both professional development and overall well-being.
This Workato recipe runs on a scheduled trigger every 5 minutes. When triggered, it sends an HTTP request to an external endpoint and processes the returned results. For each item in the HTTP response, the recipe evaluates a conditional rule based on the Gender field. If the condition is met, the recipe upserts a Lead record in Salesforce, ensuring the record is either created or updated as needed. This design supports near-real-time ingestion of external data into Salesforce using polling, conditional logic, and bulk-safe iteration.
This is an after-save, record-triggered Flow on Task that runs when a Task is updated. The flow retrieves the related Quote (via the Task’s related record), then retrieves the associated Contact. A decision element evaluates whether the Task outcome indicates Approved or Rejected.

If Approved, the flow updates fields on the related Quote to reflect approval status and sends a notification to the sales rep indicating approval.

If Rejected, the flow updates the related Quote with rejection status and sends a rejection notification to the sales rep.

If neither condition is met, the flow exits without making changes.

The flow is optimized for Actions and Related Records, ensuring updates occur after the Task is committed, and separates approval and rejection logic to avoid unnecessary updates or notifications.
How the Interview Started
How the Interview Started
Omni Fiber Integration (005Uh00000BDCxt) started the flow interview.
API Version for Running the Flow: 65
Some of this flow's variables were set when the interview started.
recordId = 001VG00000ieqL9YAI
versionId:301VG00000lnI7B
Flow start time: December 25, 2025 at 12:02 PM.


Get Records: Get $Record - Account
One or more  Account  records were retrieved.
Find all Account records where:
Id Equals {!recordId} (001VG00000ieqL9YAI)
Store the values of these fields in Get_Record_Account: OwnerId, Id
Result
Successfully found records.


Transaction Committed
Any records that the flow was ready to create, update, or delete were committed to the database.


Screen: Update Account Ownership
Selected Navigation Button: NEXT
Screen Component: Account_Lookup
Lightning component: flowruntime:lookup
Inputs:
fieldApiName = OwnerId
label = Ownership Change
objectApiName = Account
required = true
Outputs:
recordId = 0058b00000G9C26AAF
recordIds = [0058b00000G9C26AAF]
recordName = Bryant McAfee


Assignment: Update Account Ownership
1 variable was updated.
{!Get_Record_Account.OwnerId} Equals {!Account_Lookup.recordId}
Result
{!Get_Record_Account.OwnerId} = "0058b00000G9C26AAF"


Get Records: Get All Related Contacts
One or more  Contact  records were retrieved.
Find all Contact records where:
AccountId Equals {!Get_Record_Account.Id} (001VG00000ieqL9YAI)
Store the values of these fields in Get_All_Related_Contacts: OwnerId, Id
Result
Successfully found records.


Loop: Loop Over Contacts
Iteration  0  of the loop through the  Get_All_Related_Contacts  collection occurred.
$$:LoopNext:
Loop Through: [003VG0000124Y6HYAU,003VG0000166qBHYAY,003VG0000166rYkYAI,003VG0000166vKbYAI]
Iteration: 0
Current iteration item: 003VG0000124Y6HYAU


Assignment: Update Contact Ownership
1 variable was updated.
{!Loop_Over_Contacts.OwnerId} Equals {!Account_Lookup.recordId}
Result
{!Loop_Over_Contacts.OwnerId} = "0058b00000G9C26AAF"


Assignment: Add Contact To Collection
1 variable was updated.
{!NewContactCollection} Add {!Loop_Over_Contacts}
Result
{!NewContactCollection} = "[Contact (003VG0000124Y6HYAU)]"


Loop: Loop Over Contacts
Iteration  1  of the loop through the  Get_All_Related_Contacts  collection occurred.
$$:LoopNext:
Loop Through: [003VG0000124Y6HYAU,003VG0000166qBHYAY,003VG0000166rYkYAI,003VG0000166vKbYAI]
Iteration: 1
Current iteration item: 003VG0000166qBHYAY


Assignment: Update Contact Ownership
1 variable was updated.
{!Loop_Over_Contacts.OwnerId} Equals {!Account_Lookup.recordId}
Result
{!Loop_Over_Contacts.OwnerId} = "0058b00000G9C26AAF"


Assignment: Add Contact To Collection
1 variable was updated.
{!NewContactCollection} Add {!Loop_Over_Contacts}
Result
{!NewContactCollection} = "[Contact (003VG0000124Y6HYAU),Contact (003VG0000166qBHYAY)]"


Loop: Loop Over Contacts
Iteration  2  of the loop through the  Get_All_Related_Contacts  collection occurred.
$$:LoopNext:
Loop Through: [003VG0000124Y6HYAU,003VG0000166qBHYAY,003VG0000166rYkYAI,003VG0000166vKbYAI]
Iteration: 2
Current iteration item: 003VG0000166rYkYAI


Assignment: Update Contact Ownership
1 variable was updated.
{!Loop_Over_Contacts.OwnerId} Equals {!Account_Lookup.recordId}
Result
{!Loop_Over_Contacts.OwnerId} = "0058b00000G9C26AAF"


Assignment: Add Contact To Collection
1 variable was updated.
{!NewContactCollection} Add {!Loop_Over_Contacts}
Result
{!NewContactCollection} = "[Contact (003VG0000124Y6HYAU),Contact (003VG0000166qBHYAY),Contact (003VG0000166rYkYAI)]"


Loop: Loop Over Contacts
Iteration  3  of the loop through the  Get_All_Related_Contacts  collection occurred.
$$:LoopNext:
Loop Through: [003VG0000124Y6HYAU,003VG0000166qBHYAY,003VG0000166rYkYAI,003VG0000166vKbYAI]
Iteration: 3
Current iteration item: 003VG0000166vKbYAI


Assignment: Update Contact Ownership
1 variable was updated.
{!Loop_Over_Contacts.OwnerId} Equals {!Account_Lookup.recordId}
Result
{!Loop_Over_Contacts.OwnerId} = "0058b00000G9C26AAF"


Assignment: Add Contact To Collection
1 variable was updated.
{!NewContactCollection} Add {!Loop_Over_Contacts}
Result
{!NewContactCollection} = "[Contact (003VG0000124Y6HYAU),Contact (003VG0000166qBHYAY),Contact (003VG0000166rYkYAI),Contact (003VG0000166vKbYAI)]"


Loop: Loop Over Contacts
Loop was completed.
$$:LoopEnd:
End Loop.


Update Records: Update Related Contacts
One or more  Contact  records are ready to be updated.
Update Contact records whose IDs are stored in {!NewContactCollection}.
Variable Values
[
  {
    "OwnerId": "0058b00000G9C26AAF",
    "Id": "003VG0000124Y6HYAU"
  },
  {
    "OwnerId": "0058b00000G9C26AAF",
    "Id": "003VG0000166qBHYAY"
  },
  {
    "OwnerId": "0058b00000G9C26AAF",
    "Id": "003VG0000166rYkYAI"
  },
  {
    "OwnerId": "0058b00000G9C26AAF",
    "Id": "003VG0000166vKbYAI"
  }
]
Result
All records whose IDs are in {!NewContactCollection} are ready to be updated when the next screen, pause, or local action is executed or when the interview finishes.


Update Records: Update $Account Record
One or more  Account  records are ready to be updated.
Update Account records whose IDs are stored in {!Get_Record_Account}.
Variable Values
{
  "OwnerId": "0058b00000G9C26AAF",
  "Id": "001VG00000ieqL9YAI"
}
Result
All records whose IDs are in {!Get_Record_Account} are ready to be updated when the next screen, pause, or local action is executed or when the interview finishes.


Transaction Committed
Any records that the flow was ready to create, update, or delete were committed to the database.


How the Interview Finished
The flow interview ran for 10.07 seconds and finished on December 25, 2025 at 12:02 PM.
/lightning/o/Opportunity/new?
recordTypeId=012Uh00000HlNozIAF
&defaultFieldValues=
AccountId={!Account.Id},
ContactId={!Contact.Id},
StageName=Prospecting,
Opportunity_Entered_Date__c={!TEXT(TODAY())},
CloseDate={!TEXT(TODAY() + 30)}
DirPersonUserEx::worker2UserId(hcmworker)
def check_password(password):
    if len(password) < 8:
        return "Weak"
    elif len(password) <= 11:
        return "Medium"
    else:
        return "Strong"

num = int(input("How many passwords? "))
strong_count = 0

for i in range(num):
    pwd = input("Enter password: ")
    result = check_password(pwd)
    print(result)
    if result == "Strong":
        strong_count += 1

print("Number of strong passwords:", strong_count)
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>OpenCharacter AI</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      background: #0f172a;
      color: #e5e7eb;
      margin: 0;
      padding: 0;
    }
    header {
      background: #020617;
      padding: 20px;
      text-align: center;
    }
    header h1 {
      margin: 0;
      font-size: 28px;
    }
    header p {
      color: #94a3b8;
      margin-top: 8px;
    }
    .container {
      max-width: 900px;
      margin: 30px auto;
      padding: 20px;
    }
    .chat-box {
      background: #020617;
      border-radius: 10px;
      padding: 20px;
      height: 350px;
      overflow-y: auto;
      margin-bottom: 15px;
    }
    .message {
      margin-bottom: 12px;
    }
    .user {
      text-align: right;
      color: #38bdf8;
    }
    .ai {
      text-align: left;
      color: #a7f3d0;
    }
    .input-area {
      display: flex;
      gap: 10px;
    }
    input {
      flex: 1;
      padding: 12px;
      border-radius: 6px;
      border: none;
      outline: none;
    }
    button {
      padding: 12px 18px;
      background: #38bdf8;
      border: none;
      border-radius: 6px;
      cursor: pointer;
      font-weight: bold;
    }
    button:hover {
      background: #0ea5e9;
    }
    footer {
      text-align: center;
      padding: 20px;
      color: #64748b;
      font-size: 14px;
    }
  </style>
</head>
<body>

<header>
  <h1>OpenCharacter AI</h1>
  <p>Create and chat with custom AI characters</p>
</header>

<div class="container">
  <div class="chat-box" id="chatBox">
    <div class="message ai">Hello! I’m your AI character. How can I talk with you today?</div>
  </div>

  <div class="input-area">
    <input type="text" id="userInput" placeholder="Type your message..." />
    <button onclick="sendMessage()">Send</button>
  </div>
</div>

<footer>
  © OpenCharacter AI — Interactive AI Characters for Chat & Creativity
</footer>

<script>
  function sendMessage() {
    const input = document.getElementById("userInput");
    const chatBox = document.getElementById("chatBox");

    if (input.value.trim() === "") return;

    const userMessage = document.createElement("div");
    userMessage.className = "message user";
    userMessage.innerText = input.value;
    chatBox.appendChild(userMessage);

    const aiMessage = document.createElement("div");
    aiMessage.className = "message ai";
    aiMessage.innerText = "I’m listening. Tell me more.";
    chatBox.appendChild(aiMessage);

    input.value = "";
    chatBox.scrollTop = chatBox.scrollHeight;
  }
</script>

</body>
</html>
star

Fri Jan 16 2026 08:19:25 GMT+0000 (Coordinated Universal Time) https://www.nativeassignmenthelp.co.uk/

@jamesstone

star

Fri Jan 16 2026 07:48:22 GMT+0000 (Coordinated Universal Time)

@2late #excel

star

Thu Jan 15 2026 03:59:56 GMT+0000 (Coordinated Universal Time)

@davidmchale #closest

star

Thu Jan 15 2026 03:58:28 GMT+0000 (Coordinated Universal Time)

@davidmchale #preventdefault #testing

star

Thu Jan 15 2026 03:56:34 GMT+0000 (Coordinated Universal Time)

@davidmchale #preventdefault #testing

star

Wed Jan 14 2026 16:15:27 GMT+0000 (Coordinated Universal Time)

@jrg_300i #javascript

star

Wed Jan 14 2026 13:54:25 GMT+0000 (Coordinated Universal Time) https://chat.mistral.ai/chat

@teressider

star

Wed Jan 14 2026 06:36:01 GMT+0000 (Coordinated Universal Time) https://www.coinsclone.com/top-centralized-exchange-clone-scripts/

@Emmawoods

star

Wed Jan 14 2026 06:13:23 GMT+0000 (Coordinated Universal Time) https://medium.com/cryptocurrency-scripts/how-does-opensea-make-money-f443b0bc8794

@LilianAnderson #opensearevenue #nftmarketplacegrowth #howopenseamakesmoney #nftbusinessmodel #openseamarketvalue

star

Wed Jan 14 2026 03:40:17 GMT+0000 (Coordinated Universal Time)

@FOHWellington

star

Tue Jan 13 2026 23:36:38 GMT+0000 (Coordinated Universal Time)

@davidmchale #sessionstorage

star

Tue Jan 13 2026 13:26:20 GMT+0000 (Coordinated Universal Time)

@divyasoni23 #javascript #jquery

star

Mon Jan 12 2026 05:59:18 GMT+0000 (Coordinated Universal Time) https://www.softean.com/cryptocurrency-exchange-development

@Amybonbo

star

Sun Jan 11 2026 15:13:56 GMT+0000 (Coordinated Universal Time) https://stringart.online/

@SoulDee

star

Sun Jan 11 2026 15:13:03 GMT+0000 (Coordinated Universal Time) https://stringart.online/random-string/

@SoulDee #typescript

star

Sun Jan 11 2026 15:08:37 GMT+0000 (Coordinated Universal Time) https://px2rem.com/

@SoulDee

star

Sun Jan 11 2026 15:03:15 GMT+0000 (Coordinated Universal Time) https://px2rem.com/

@SoulDee #typescript

star

Thu Jan 08 2026 13:08:51 GMT+0000 (Coordinated Universal Time) https://screw.full-design.com/grade-8-8-bolt-the-steel-elixir-in-the-fastening-industry-81814969

@hamilton222

star

Thu Jan 08 2026 00:27:13 GMT+0000 (Coordinated Universal Time)

@FOHWellington

star

Thu Jan 08 2026 00:09:04 GMT+0000 (Coordinated Universal Time)

@FOHWellington

star

Wed Jan 07 2026 05:48:40 GMT+0000 (Coordinated Universal Time)

@davidmchale #matches() #click #event

star

Wed Jan 07 2026 05:46:55 GMT+0000 (Coordinated Universal Time)

@davidmchale #map #selectors #tracking

star

Tue Jan 06 2026 08:02:30 GMT+0000 (Coordinated Universal Time) https://www.thecryptoape.com/pancakeswap-clone-script

@nancywheeler

star

Tue Jan 06 2026 05:27:03 GMT+0000 (Coordinated Universal Time) https://www.nextwisi.com/blockchain-development-company-germany

@nextwisi #blockchain

star

Mon Jan 05 2026 13:41:41 GMT+0000 (Coordinated Universal Time)

@usman13

star

Mon Jan 05 2026 12:54:20 GMT+0000 (Coordinated Universal Time) https://github.com/pages-themes

@milliedavidson

star

Mon Jan 05 2026 12:41:45 GMT+0000 (Coordinated Universal Time) https://jekyllrb.com/docs/installation/macos/

@milliedavidson #ruby

star

Mon Jan 05 2026 12:40:20 GMT+0000 (Coordinated Universal Time) https://www.moncefbelyamani.com/which-shell-am-i-using-how-can-i-switch/

@milliedavidson

star

Mon Jan 05 2026 12:31:55 GMT+0000 (Coordinated Universal Time) https://brew.sh/

@milliedavidson #mac #terminal #ruby

star

Mon Jan 05 2026 06:39:32 GMT+0000 (Coordinated Universal Time) https://medium.com/cryptocurrency-scripts/top-white-label-nft-marketplace-development-companies-e99911482a72

@LilianAnderson #whitelabelnftmarketplace #nftmarketplacedevelopment #nftstartupsolutions #securenftdevelopment #nftbusinessgrowth

star

Sat Jan 03 2026 07:06:33 GMT+0000 (Coordinated Universal Time)

@Pusat123

star

Sat Jan 03 2026 03:49:29 GMT+0000 (Coordinated Universal Time)

@Pusat123

star

Wed Dec 31 2025 12:57:27 GMT+0000 (Coordinated Universal Time)

@Bisniskita #haskell

star

Wed Dec 31 2025 10:02:21 GMT+0000 (Coordinated Universal Time) https://mirayogashala.com/

@mirayogalshala ##fitness #health #yoga

star

Fri Dec 26 2025 09:20:23 GMT+0000 (Coordinated Universal Time) https://www.coinsclone.com/best-crypto-exchanges-with-lowest-fees/

@Emmawoods

star

Thu Dec 25 2025 17:26:05 GMT+0000 (Coordinated Universal Time) https://app.trial.workato.com/recipes/109103/edit?step=0e239fa3-b891-44b0-8c34-4df78d4559d4

@Davis249

star

Thu Dec 25 2025 17:15:49 GMT+0000 (Coordinated Universal Time) https://omnifiber2--austindev3.sandbox.lightning.force.com/builder_platform_interaction/flowBuilder.app?flowId=301Uh00000hez5gIAA

@Davis249

star

Thu Dec 25 2025 17:06:30 GMT+0000 (Coordinated Universal Time) https://omnifiber2--austindev3.sandbox.lightning.force.com/builder_platform_interaction/flowBuilder.app?flowId=301VG00000lnI7BYAU

@Davis249

star

Thu Dec 25 2025 16:42:46 GMT+0000 (Coordinated Universal Time) https://omnifiber2--austindev3.sandbox.my.salesforce-setup.com/lightning/setup/ObjectManager/Opportunity/ButtonsLinksActions/00bUh00000AYVy5IAH/view

@Davis249

star

Thu Dec 25 2025 16:38:20 GMT+0000 (Coordinated Universal Time) https://omnifiber2--austindev3.sandbox.lightning.force.com/builder_platform_interaction/flowBuilder.app?flowId=301VG00000lmxKVYAY

@Davis249

star

Tue Dec 23 2025 11:29:54 GMT+0000 (Coordinated Universal Time)

@MinaTimo

star

Tue Dec 23 2025 05:28:25 GMT+0000 (Coordinated Universal Time) https://cryptiecraft.com/ico-software-development/

@monroealex17 #icosoftwaredevelopment #icoscriptsoftware #fundraisingplatform #cryptofundraising

star

Sun Dec 21 2025 15:06:56 GMT+0000 (Coordinated Universal Time)

@ieewijif98

star

Fri Dec 19 2025 09:21:09 GMT+0000 (Coordinated Universal Time) https://www.coinsclone.com/how-long-does-it-take-to-develop-a-cryptocurrency-exchange/

@Emmawoods

star

Fri Dec 19 2025 06:55:57 GMT+0000 (Coordinated Universal Time) https://opencharacter.org/

@opencharacterai

star

Thu Dec 18 2025 13:19:01 GMT+0000 (Coordinated Universal Time) https://www.firebeetechnoservices.com/blog/binary-options-trading-bot

@aanaethan #binary #blockchain

Save snippets that work with our extensions

Available in the Chrome Web Store Get Firefox Add-on Get VS Code extension