DIgital Content

Postulaciones Bibliotecas Transformadoras

<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;600;700&family=DM+Sans:wght@300;400;500;600&display=swap" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>
<style>

  :root {
    --gold: #C9A84C;
    --gold-light: #E8C97A;
    --gold-pale: #FBF4E3;
    --dark: #1A1A2E;
    --dark2: #16213E;
    --ink: #2C2C3E;
    --muted: #7A7A9A;
    --border: #E2D9C5;
    --white: #FDFCF9;
    --green: #2D6A4F;
    --red: #C0392B;
    --blue: #1B4F8A;
  }

  * { box-sizing: border-box; margin: 0; padding: 0; }

  /* HEADER */
  .header {
    background: linear-gradient(135deg, var(--dark) 0%, var(--dark2) 60%, #0F3460 100%);
    padding: 40px 48px 32px;
    border-bottom: 2px solid var(--gold);
    position: relative;
    overflow: hidden;
  }
  .header::before {
    content: '';
    position: absolute;
    top: -60px; right: -60px;
    width: 300px; height: 300px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(201,168,76,0.15) 0%, transparent 70%);
  }
  .header-badge {
    display: inline-block;
    background: var(--gold);
    color: var(--dark);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 2px;
    text-transform: uppercase;
    padding: 5px 14px;
    border-radius: 2px;
    margin-bottom: 14px;
  }
  .header h1 {
    font-family: 'Playfair Display', serif;
    color: var(--white);
    font-size: 30px;
    font-weight: 700;
    line-height: 1.2;
    margin-bottom: 6px;
  }
  .header h1 span { color: var(--gold-light); }
  .header p {
    color: rgba(255,255,255,0.55);
    font-size: 13px;
    letter-spacing: 0.5px;
  }

  /* MAIN LAYOUT */
  .container {
    max-width: 960px;
    margin: 0 auto;
    padding: 36px 24px 80px;
  }

  /* STEPS */
  .steps {
    display: flex;
    gap: 0;
    margin-bottom: 36px;
    background: rgba(255,255,255,0.04);
    border: 1px solid rgba(201,168,76,0.25);
    border-radius: 8px;
    overflow: hidden;
  }
  .step {
    flex: 1;
    padding: 14px 18px;
    text-align: center;
    cursor: pointer;
    border-right: 1px solid rgba(201,168,76,0.15);
    transition: all 0.2s;
    position: relative;
  }
  .step:last-child { border-right: none; }
  .step .step-num {
    font-size: 10px;
    color: var(--muted);
    letter-spacing: 1.5px;
    text-transform: uppercase;
    margin-bottom: 3px;
  }
  .step .step-label {
    font-size: 12px;
    color: rgba(255,255,255,0.5);
    font-weight: 500;
  }
  .step.active { background: rgba(201,168,76,0.12); }
  .step.active .step-num { color: var(--gold); }
  .step.active .step-label { color: var(--white); }
  .step.done .step-label { color: rgba(255,255,255,0.35); }
  .step.done::after {
    content: '✓';
    position: absolute;
    top: 8px; right: 10px;
    color: var(--gold);
    font-size: 10px;
  }

  /* PANELS */
  .panel { display: none; animation: fadeIn 0.3s ease; }
  .panel.visible { display: block; }
  @keyframes fadeIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }

  /* CARD */
  .card {
    background: var(--white);
    border-radius: 10px;
    padding: 32px 36px;
    margin-bottom: 24px;
    box-shadow: 0 4px 24px rgba(0,0,0,0.18);
  }
  .card-title {
    font-family: 'Playfair Display', serif;
    font-size: 18px;
    color: var(--dark);
    margin-bottom: 6px;
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .card-title .icon {
    width: 28px; height: 28px;
    background: var(--gold);
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: 13px;
    flex-shrink: 0;
  }
  .card-sub {
    font-size: 12px;
    color: var(--muted);
    margin-bottom: 24px;
    padding-left: 38px;
  }

  /* FORM ELEMENTS */
  label {
    display: block;
    font-size: 12px;
    font-weight: 600;
    color: var(--ink);
    letter-spacing: 0.5px;
    text-transform: uppercase;
    margin-bottom: 6px;
  }
  input[type="text"], input[type="email"], select, textarea {
    width: 100%;
    padding: 11px 14px;
    border: 1.5px solid var(--border);
    border-radius: 6px;
    font-family: 'DM Sans', sans-serif;
    font-size: 14px;
    color: var(--ink);
    background: var(--white);
    transition: border-color 0.2s;
    outline: none;
    margin-bottom: 18px;
  }
  input:focus, select:focus, textarea:focus {
    border-color: var(--gold);
    box-shadow: 0 0 0 3px rgba(201,168,76,0.12);
  }
  textarea { resize: vertical; min-height: 80px; }

  .form-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
  }

  /* CATEGORY SELECTOR */
  .cat-cards {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    margin-bottom: 8px;
  }
  .cat-card {
    border: 2px solid var(--border);
    border-radius: 8px;
    padding: 20px;
    cursor: pointer;
    transition: all 0.2s;
    text-align: center;
  }
  .cat-card:hover { border-color: var(--gold); background: var(--gold-pale); }
  .cat-card.selected { border-color: var(--gold); background: var(--gold-pale); }
  .cat-card .cat-icon { font-size: 28px; margin-bottom: 10px; }
  .cat-card .cat-name {
    font-family: 'Playfair Display', serif;
    font-size: 14px;
    font-weight: 600;
    color: var(--dark);
    margin-bottom: 6px;
  }
  .cat-card .cat-desc { font-size: 11px; color: var(--muted); line-height: 1.4; }

  /* SUBCATEGORY */
  .subcat-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-bottom: 8px;
  }
  .subcat-item {
    border: 1.5px solid var(--border);
    border-radius: 6px;
    padding: 12px 14px;
    cursor: pointer;
    transition: all 0.2s;
    display: flex;
    align-items: center;
    gap: 10px;
  }
  .subcat-item:hover { border-color: var(--gold); background: var(--gold-pale); }
  .subcat-item.selected { border-color: var(--gold); background: var(--gold-pale); }
  .subcat-item .num {
    width: 22px; height: 22px;
    background: var(--gold);
    border-radius: 50%;
    font-size: 10px;
    font-weight: 700;
    color: var(--dark);
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
  }
  .subcat-item.selected .num { background: var(--dark); color: var(--gold); }
  .subcat-label { font-size: 12px; font-weight: 500; color: var(--ink); line-height: 1.3; }

  /* RUBRIC TABLE */
  .rubric-section { margin-bottom: 28px; }
  .rubric-section-title {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    color: var(--muted);
    margin-bottom: 14px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border);
  }
  .criterion-row {
    display: grid;
    grid-template-columns: 1fr auto;
    gap: 20px;
    align-items: start;
    padding: 16px 0;
    border-bottom: 1px solid #f0ede6;
  }
  .criterion-row:last-child { border-bottom: none; }
  .criterion-info .crit-name {
    font-size: 14px;
    font-weight: 600;
    color: var(--dark);
    margin-bottom: 3px;
  }
  .criterion-info .crit-desc { font-size: 12px; color: var(--muted); line-height: 1.4; }
  .criterion-info .crit-weight {
    display: inline-block;
    background: var(--gold-pale);
    border: 1px solid var(--gold);
    color: var(--dark);
    font-size: 10px;
    font-weight: 700;
    padding: 2px 8px;
    border-radius: 20px;
    margin-top: 6px;
    letter-spacing: 0.5px;
  }
  .score-buttons {
    display: flex;
    gap: 6px;
    flex-shrink: 0;
  }
  .score-btn {
    width: 38px; height: 38px;
    border: 1.5px solid var(--border);
    border-radius: 6px;
    background: white;
    font-size: 14px;
    font-weight: 700;
    color: var(--muted);
    cursor: pointer;
    transition: all 0.15s;
    display: flex; align-items: center; justify-content: center;
  }
  .score-btn:hover { border-color: var(--gold); color: var(--dark); }
  .score-btn.active { background: var(--gold); border-color: var(--gold); color: var(--dark); }

  /* SCORE LEGEND */
  .score-legend {
    background: #f8f6f0;
    border-radius: 8px;
    padding: 16px 20px;
    margin-bottom: 24px;
  }
  .score-legend-title { font-size: 11px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; color: var(--muted); margin-bottom: 10px; }
  .legend-items { display: flex; gap: 10px; flex-wrap: wrap; }
  .legend-item { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--ink); }
  .legend-dot {
    width: 22px; height: 22px;
    background: var(--gold);
    border-radius: 4px;
    display: flex; align-items: center; justify-content: center;
    font-size: 11px; font-weight: 700; color: var(--dark);
  }

  /* RESULT BOX */
  .result-box {
    background: linear-gradient(135deg, var(--dark) 0%, var(--dark2) 100%);
    border: 1px solid var(--gold);
    border-radius: 10px;
    padding: 24px 28px;
    margin-top: 24px;
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
  .result-box .score-display {
    font-family: 'Playfair Display', serif;
    font-size: 48px;
    font-weight: 700;
    color: var(--gold-light);
  }
  .result-box .score-label { font-size: 12px; color: rgba(255,255,255,0.5); margin-top: 2px; }
  .result-box .score-bar-wrap { flex: 1; margin: 0 32px; }
  .score-bar-bg { height: 8px; background: rgba(255,255,255,0.1); border-radius: 4px; overflow: hidden; }
  .score-bar-fill { height: 100%; background: linear-gradient(90deg, var(--gold), var(--gold-light)); border-radius: 4px; transition: width 0.6s cubic-bezier(0.4,0,0.2,1); }
  .score-level { font-size: 13px; color: var(--gold-light); font-weight: 600; margin-top: 8px; }

  /* BUTTONS */
  .btn {
    padding: 13px 28px;
    border-radius: 7px;
    font-family: 'DM Sans', sans-serif;
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    border: none;
    transition: all 0.2s;
    letter-spacing: 0.3px;
  }
  .btn-primary {
    background: var(--gold);
    color: var(--dark);
  }
  .btn-primary:hover { background: var(--gold-light); transform: translateY(-1px); box-shadow: 0 4px 16px rgba(201,168,76,0.4); }
  .btn-secondary {
    background: transparent;
    color: rgba(255,255,255,0.7);
    border: 1.5px solid rgba(255,255,255,0.2);
  }
  .btn-secondary:hover { border-color: var(--gold); color: var(--gold); }
  .btn-export {
    background: var(--green);
    color: white;
  }
  .btn-export:hover { background: #1e4d38; transform: translateY(-1px); }
  .btn-add {
    background: var(--blue);
    color: white;
  }
  .btn-add:hover { background: #123666; }

  .btn-row {
    display: flex;
    gap: 12px;
    justify-content: flex-end;
    margin-top: 28px;
  }

  /* EVALUATIONS LIST */
  .eval-list { margin-bottom: 20px; }
  .eval-item {
    background: var(--white);
    border-radius: 8px;
    padding: 16px 20px;
    margin-bottom: 10px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  }
  .eval-item-info { display: flex; flex-direction: column; gap: 3px; }
  .eval-item-title { font-size: 14px; font-weight: 600; color: var(--dark); }
  .eval-item-meta { font-size: 11px; color: var(--muted); }
  .eval-score-badge {
    background: var(--gold);
    color: var(--dark);
    font-weight: 700;
    font-size: 14px;
    padding: 6px 14px;
    border-radius: 20px;
    min-width: 60px;
    text-align: center;
  }
  .eval-delete {
    background: none;
    border: none;
    color: var(--muted);
    cursor: pointer;
    font-size: 16px;
    padding: 4px 8px;
    transition: color 0.2s;
  }
  .eval-delete:hover { color: var(--red); }

  /* SUMMARY TABLE */
  .summary-table {
    width: 100%;
    border-collapse: collapse;
    margin-top: 16px;
    font-size: 13px;
  }
  .summary-table th {
    background: var(--dark);
    color: var(--gold);
    padding: 10px 14px;
    text-align: left;
    font-size: 11px;
    letter-spacing: 0.8px;
    text-transform: uppercase;
  }
  .summary-table td {
    padding: 10px 14px;
    border-bottom: 1px solid var(--border);
    color: var(--ink);
  }
  .summary-table tr:hover td { background: var(--gold-pale); }
  .tag {
    display: inline-block;
    font-size: 10px;
    padding: 2px 8px;
    border-radius: 20px;
    font-weight: 600;
    letter-spacing: 0.5px;
  }
  .tag-transform { background: #E8F4FD; color: var(--blue); }
  .tag-vida { background: #FEF9E7; color: #856404; border: 1px solid var(--gold); }

  /* CONFLICT SECTION */
  .conflict-box {
    border: 1.5px dashed var(--border);
    border-radius: 8px;
    padding: 16px 20px;
    margin-top: 20px;
  }
  .conflict-box label { text-transform: none; font-size: 13px; font-weight: 500; letter-spacing: 0; display: flex; align-items: center; gap: 8px; cursor: pointer; }
  .conflict-box input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--gold); }

  /* EMPTY STATE */
  .empty-state {
    text-align: center;
    padding: 48px 20px;
    color: rgba(255,255,255,0.4);
  }
  .empty-state .empty-icon { font-size: 40px; margin-bottom: 12px; opacity: 0.5; }
  .empty-state p { font-size: 14px; }

  /* TOAST */
  .toast {
    position: absolute;
    bottom: 24px;
    right: 24px;
    background: var(--dark);
    border: 1px solid var(--gold);
    color: var(--white);
    padding: 14px 20px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 500;
    transform: translateY(80px);
    opacity: 0;
    transition: all 0.3s ease;
    z-index: 1000;
    max-width: 300px;
  }
  .toast.show { transform: translateY(0); opacity: 1; }

  /* RESPONSIVE */
  @media (max-width: 620px) {
    .form-row, .cat-cards, .subcat-grid { grid-template-columns: 1fr; }
    .score-buttons { flex-wrap: wrap; }
    .card { padding: 20px; }
    .container { padding: 20px 14px 60px; }
    .header { padding: 28px 20px 22px; }
  }

</style>
<div class="header">
  <div class="header-badge">II Jornada · 2026</div>
  <h1>Reconocimientos a <span>Bibliotecas Transformadoras</span></h1>
  <p>Sistema de Evaluación para Jurados · 10 al 31 de marzo de 2026</p>
</div>

<div class="container">

  <!-- STEPS -->
  <div class="steps">
    <div class="step active" id="step1" onclick="goToStep(1)">
      <div class="step-num">Paso 1</div>
      <div class="step-label">Identificación</div>
    </div>
    <div class="step" id="step2" onclick="goToStep(2)">
      <div class="step-num">Paso 2</div>
      <div class="step-label">Categoría</div>
    </div>
    <div class="step" id="step3" onclick="goToStep(3)">
      <div class="step-num">Paso 3</div>
      <div class="step-label">Calificación</div>
    </div>
    <div class="step" id="step4" onclick="goToStep(4)">
      <div class="step-num">Paso 4</div>
      <div class="step-label">Resumen</div>
    </div>
  </div>

  <!-- PANEL 1: IDENTIFICACIÓN -->
  <div class="panel visible" id="panel1">
    <div class="card">
      <div class="card-title"><div class="icon">👤</div> Identificación del Jurado</div>
      <div class="card-sub">Complete sus datos antes de iniciar las evaluaciones.</div>

      <div class="form-row">
        <div>
          <label>Nombre completo *</label>
          <input type="text" id="juradoNombre" placeholder="Ej. Dra. María González">
        </div>
        <div>
          <label>Código / Identificador</label>
          <input type="text" id="juradoCodigo" placeholder="Ej. JUR-001">
        </div>
      </div>
      <div class="form-row">
        <div>
          <label>Institución</label>
          <input type="text" id="juradoInstitucion" placeholder="Ej. Universidad Nacional">
        </div>
        <div>
          <label>Correo electrónico</label>
          <input type="email" id="juradoEmail" placeholder="correo@institucion.edu.co">
        </div>
      </div>

      <div class="conflict-box">
        <label>
          <input type="checkbox" id="conflictoInteres">
          Declaro que conozco y no tengo conflicto de interés con los proyectos/postulantes que evaluaré.
        </label>
      </div>

      <div class="btn-row">
        <button class="btn btn-primary" onclick="continueToStep2()">Continuar →</button>
      </div>
    </div>
  </div>

  <!-- PANEL 2: CATEGORÍA -->
  <div class="panel" id="panel2">
    <div class="card">
      <div class="card-title"><div class="icon">📂</div> Seleccionar Categoría</div>
      <div class="card-sub">Elija la categoría del proyecto o postulación a evaluar.</div>

      <div class="cat-cards">
        <div class="cat-card" id="cat-transform" onclick="selectCategory('transformadores')">
          <div class="cat-icon">🏛️</div>
          <div class="cat-name">Proyectos Transformadores</div>
          <div class="cat-desc">10 subcategorías · Evaluación de proyectos institucionales</div>
        </div>
        <div class="cat-card" id="cat-vida" onclick="selectCategory('vida')">
          <div class="cat-icon">🌟</div>
          <div class="cat-name">Reconocimiento a Toda una Vida</div>
          <div class="cat-desc">Trayectoria profesional sostenida en el sector bibliotecario</div>
        </div>
      </div>

      <!-- SUBCATEGORIES (for transformadores) -->
      <div id="subcatSection" style="display:none; margin-top:24px;">
        <label style="text-transform:none; font-size:13px; font-weight:600; letter-spacing:0; margin-bottom:12px; display:block;">Seleccione la subcategoría:</label>
        <div class="subcat-grid" id="subcatGrid"></div>
      </div>

      <!-- POSTULANT INFO -->
      <div style="margin-top:24px;">
        <label>Nombre del proyecto / postulante *</label>
        <input type="text" id="postulanteName" placeholder="Ej. Biblioteca Central UNAL / Nombre del profesional">
        <label>Institución postulante</label>
        <input type="text" id="postulanteInstitucion" placeholder="Ej. Universidad de Antioquia">
      </div>

      <div class="btn-row">
        <button class="btn btn-secondary" onclick="goToStep(1)">← Atrás</button>
        <button class="btn btn-primary" onclick="continueToStep3()">Calificar →</button>
      </div>
    </div>
  </div>

  <!-- PANEL 3: CALIFICACIÓN -->
  <div class="panel" id="panel3">
    <div class="card">
      <div class="card-title"><div class="icon">⭐</div> Rúbrica de Evaluación</div>
      <div class="card-sub" id="panel3Sub"></div>

      <div class="score-legend">
        <div class="score-legend-title">Escala de calificación</div>
        <div class="legend-items">
          <div class="legend-item"><div class="legend-dot">1</div> Muy bajo / Sin evidencia</div>
          <div class="legend-item"><div class="legend-dot">2</div> Bajo / Limitado</div>
          <div class="legend-item"><div class="legend-dot">3</div> Aceptable / Parcial</div>
          <div class="legend-item"><div class="legend-dot">4</div> Alto / Cumple</div>
          <div class="legend-item"><div class="legend-dot">5</div> Sobresaliente</div>
        </div>
      </div>

      <div id="rubricContainer"></div>

      <!-- QUALITATIVE (Vida) -->
      <div id="qualitativeSection" style="display:none;">
        <div class="rubric-section-title" style="margin-top:24px;">Evaluación Cualitativa</div>
        <label>¿Cuál considera que es la principal contribución de este(a) profesional?</label>
        <textarea id="q1" placeholder="Escriba su respuesta..."></textarea>
        <label>¿Por qué su trayectoria merece reconocimiento público?</label>
        <textarea id="q2" placeholder="Escriba su respuesta..."></textarea>
      </div>

      <!-- OBSERVATIONS -->
      <div style="margin-top:16px;">
        <label style="text-transform:none; font-size:13px; font-weight:500; letter-spacing:0;">Observaciones adicionales (opcional)</label>
        <textarea id="observaciones" placeholder="Comentarios generales del jurado..."></textarea>
      </div>

      <!-- RESULT -->
      <div class="result-box">
        <div>
          <div class="score-display" id="scoreDisplay">—</div>
          <div class="score-label">Puntaje total</div>
        </div>
        <div class="score-bar-wrap">
          <div class="score-bar-bg">
            <div class="score-bar-fill" id="scoreBar" style="width:0%"></div>
          </div>
          <div class="score-level" id="scoreLevel">Complete todos los criterios</div>
        </div>
      </div>

      <div class="btn-row">
        <button class="btn btn-secondary" onclick="goToStep(2)">← Atrás</button>
        <button class="btn btn-primary" onclick="saveEvaluation()">💾 Guardar Evaluación</button>
      </div>
    </div>
  </div>

  <!-- PANEL 4: RESUMEN -->
  <div class="panel" id="panel4">
    <div class="card">
      <div class="card-title"><div class="icon">📊</div> Resumen de Evaluaciones</div>
      <div class="card-sub" id="panel4Sub"></div>

      <div id="evalListContainer"></div>

      <div id="emptyState" class="empty-state" style="display:none;">
        <div class="empty-icon">📋</div>
        <p>No hay evaluaciones registradas aún.</p>
      </div>

      <div id="summaryTableWrap" style="display:none; overflow-x:auto;">
        <table class="summary-table">
          <thead>
            <tr>
              <th>#</th>
              <th>Proyecto / Postulante</th>
              <th>Categoría</th>
              <th>Institución</th>
              <th>Puntaje</th>
              <th>Nivel</th>
            </tr>
          </thead>
          <tbody id="summaryBody"></tbody>
        </table>
      </div>

      <div class="btn-row" style="margin-top:24px; justify-content:space-between; flex-wrap:wrap; gap:10px;">
        <button class="btn btn-add" onclick="newEvaluation()">+ Nueva Evaluación</button>
        <div style="display:flex; gap:12px;">
          <button class="btn btn-export" onclick="exportToExcel()">⬇ Exportar Excel</button>
        </div>
      </div>
    </div>
  </div>

</div>

<!-- TOAST -->
<div class="toast" id="toast"></div>

<script>
// ============================================================
// DATA
// ============================================================
const SUBCATEGORIES = [
  { id: 1, name: "Innovación Tecnológica" },
  { id: 2, name: "Fomento a la Lectura Lúdica" },
  { id: 3, name: "Colaboración Interinstitucional" },
  { id: 4, name: "Impacto Social" },
  { id: 5, name: "Impacto Ambiental" },
  { id: 6, name: "Inclusión y Accesibilidad" },
  { id: 7, name: "Alfabetización Informacional" },
  { id: 8, name: "Diseño de Espacios Físicos" },
  { id: 9, name: "Uso Creativo de Recursos Bibliográficos" },
  { id: 10, name: "Red de Colaboración de Bibliotecas Universitarias" }
];

const CRITERIA_TRANSFORM = [
  { id: "c1", name: "Claridad del problema identificado", weight: 0.15, desc: "¿El proyecto identifica claramente el problema o necesidad que busca resolver?" },
  { id: "c2", name: "Innovación y diferenciación", weight: 0.20, desc: "¿Propone soluciones novedosas o enfoques diferenciadores respecto a prácticas tradicionales?" },
  { id: "c3", name: "Impacto medible", weight: 0.25, desc: "¿Se presentan evidencias cuantitativas o cualitativas del impacto generado?" },
  { id: "c4", name: "Sostenibilidad y escalabilidad", weight: 0.20, desc: "¿El proyecto puede mantenerse en el tiempo y replicarse en otros contextos?" },
  { id: "c5", name: "Gestión y ejecución del proyecto", weight: 0.20, desc: "¿Muestra evidencias de planificación, ejecución eficiente y logro de resultados?" },
];

const CRITERIA_VIDA = [
  { id: "v1", name: "Trayectoria y permanencia en el sector", weight: 0.20, desc: "Años de dedicación, continuidad y liderazgo sostenido en el ámbito bibliotecario o académico." },
  { id: "v2", name: "Impacto institucional y comunitario", weight: 0.25, desc: "Transformaciones generadas en bibliotecas o instituciones; influencia directa en comunidades académicas." },
  { id: "v3", name: "Aporte al desarrollo del sector", weight: 0.25, desc: "Participación en redes, producción académica, incidencia en políticas o modelos de gestión." },
  { id: "v4", name: "Innovación y legado profesional", weight: 0.30, desc: "Prácticas pioneras, modelos replicables, creación de metodologías o enfoques diferenciadores." },
];

// ============================================================
// STATE
// ============================================================
let state = {
  currentStep: 1,
  jurado: {},
  currentCategory: null,
  currentSubcat: null,
  scores: {},
  evaluations: [],
};

// ============================================================
// NAVIGATION
// ============================================================
function goToStep(n) {
  for (let i = 1; i <= 4; i++) {
    document.getElementById('panel' + i).classList.remove('visible');
    const s = document.getElementById('step' + i);
    s.classList.remove('active', 'done');
    if (i < n) s.classList.add('done');
  }
  document.getElementById('panel' + n).classList.add('visible');
  document.getElementById('step' + n).classList.add('active');
  state.currentStep = n;
  window.scrollTo({ top: 0, behavior: 'smooth' });
}

function continueToStep2() {
  const nombre = document.getElementById('juradoNombre').value.trim();
  if (!nombre) { showToast('⚠️ Ingrese su nombre completo.'); return; }
  if (!document.getElementById('conflictoInteres').checked) { showToast('⚠️ Debe declarar el conflicto de interés.'); return; }
  state.jurado = {
    nombre,
    codigo: document.getElementById('juradoCodigo').value.trim(),
    institucion: document.getElementById('juradoInstitucion').value.trim(),
    email: document.getElementById('juradoEmail').value.trim(),
  };
  updatePanel4Header();
  goToStep(2);
}

function continueToStep3() {
  if (!state.currentCategory) { showToast('⚠️ Seleccione una categoría.'); return; }
  if (state.currentCategory === 'transformadores' && !state.currentSubcat) { showToast('⚠️ Seleccione la subcategoría.'); return; }
  const name = document.getElementById('postulanteName').value.trim();
  if (!name) { showToast('⚠️ Ingrese el nombre del proyecto o postulante.'); return; }
  state.scores = {};
  buildRubric();
  goToStep(3);
}

// ============================================================
// CATEGORY SELECTION
// ============================================================
function selectCategory(cat) {
  state.currentCategory = cat;
  state.currentSubcat = null;
  document.getElementById('cat-transform').classList.toggle('selected', cat === 'transformadores');
  document.getElementById('cat-vida').classList.toggle('selected', cat === 'vida');
  const subcatSection = document.getElementById('subcatSection');
  if (cat === 'transformadores') {
    subcatSection.style.display = 'block';
    buildSubcatGrid();
  } else {
    subcatSection.style.display = 'none';
  }
}

function buildSubcatGrid() {
  const grid = document.getElementById('subcatGrid');
  grid.innerHTML = SUBCATEGORIES.map(s => `
    <div class="subcat-item" id="subcat-${s.id}" onclick="selectSubcat(${s.id})">
      <div class="num">${s.id}</div>
      <div class="subcat-label">${s.name}</div>
    </div>
  `).join('');
}

function selectSubcat(id) {
  state.currentSubcat = id;
  document.querySelectorAll('.subcat-item').forEach(el => el.classList.remove('selected'));
  document.getElementById('subcat-' + id).classList.add('selected');
}

// ============================================================
// RUBRIC
// ============================================================
function buildRubric() {
  const criteria = state.currentCategory === 'transformadores' ? CRITERIA_TRANSFORM : CRITERIA_VIDA;
  const container = document.getElementById('rubricContainer');
  const sub = state.currentCategory === 'transformadores'
    ? `Proyecto: <strong>${document.getElementById('postulanteName').value}</strong> · Subcategoría: <strong>${SUBCATEGORIES.find(s=>s.id===state.currentSubcat).name}</strong>`
    : `Postulante: <strong>${document.getElementById('postulanteName').value}</strong>`;
  document.getElementById('panel3Sub').innerHTML = sub;

  container.innerHTML = `<div class="rubric-section">
    <div class="rubric-section-title">Criterios de evaluación</div>
    ${criteria.map(c => `
      <div class="criterion-row">
        <div class="criterion-info">
          <div class="crit-name">${c.name}</div>
          <div class="crit-desc">${c.desc}</div>
          <span class="crit-weight">Peso: ${Math.round(c.weight*100)}%</span>
        </div>
        <div class="score-buttons">
          ${[1,2,3,4,5].map(n => `
            <button class="score-btn" id="btn-${c.id}-${n}" onclick="setScore('${c.id}', ${n})">${n}</button>
          `).join('')}
        </div>
      </div>
    `).join('')}
  </div>`;

  document.getElementById('qualitativeSection').style.display =
    state.currentCategory === 'vida' ? 'block' : 'none';
  document.getElementById('q1').value = '';
  document.getElementById('q2').value = '';
  document.getElementById('observaciones').value = '';
  updateScore();
}

function setScore(criterionId, score) {
  state.scores[criterionId] = score;
  const criteria = state.currentCategory === 'transformadores' ? CRITERIA_TRANSFORM : CRITERIA_VIDA;
  const c = criteria.find(x => x.id === criterionId);
  [1,2,3,4,5].forEach(n => {
    const btn = document.getElementById(`btn-${criterionId}-${n}`);
    if (btn) btn.classList.toggle('active', n === score);
  });
  updateScore();
}

function updateScore() {
  const criteria = state.currentCategory === 'transformadores' ? CRITERIA_TRANSFORM : CRITERIA_VIDA;
  let total = 0;
  let filled = 0;
  criteria.forEach(c => {
    if (state.scores[c.id]) {
      total += state.scores[c.id] * c.weight * 20; // scale to 100
      filled++;
    }
  });
  const display = document.getElementById('scoreDisplay');
  const bar = document.getElementById('scoreBar');
  const level = document.getElementById('scoreLevel');
  if (filled === 0) {
    display.textContent = '—';
    bar.style.width = '0%';
    level.textContent = 'Complete todos los criterios';
    return;
  }
  const pct = filled === criteria.length ? total : (total / filled * criteria.reduce((a,c)=>a+(state.scores[c.id]?c.weight:0),0)) ;
  // recalculate properly
  let realTotal = 0;
  criteria.forEach(c => { if (state.scores[c.id]) realTotal += state.scores[c.id] * c.weight * 20; });
  const rounded = Math.round(realTotal * 10) / 10;
  display.textContent = filled === criteria.length ? rounded : '...';
  bar.style.width = (filled === criteria.length ? realTotal : 0) + '%';
  const lvlText = realTotal >= 90 ? '🏆 Sobresaliente' : realTotal >= 75 ? '⭐ Alto' : realTotal >= 60 ? '✅ Aceptable' : realTotal >= 40 ? '⚠️ Bajo' : '❌ Muy bajo';
  level.textContent = filled === criteria.length ? lvlText : `${filled}/${criteria.length} criterios calificados`;
}

// ============================================================
// SAVE
// ============================================================
function saveEvaluation() {
  const criteria = state.currentCategory === 'transformadores' ? CRITERIA_TRANSFORM : CRITERIA_VIDA;
  if (criteria.some(c => !state.scores[c.id])) { showToast('⚠️ Califique todos los criterios antes de guardar.'); return; }

  let total = 0;
  criteria.forEach(c => { total += state.scores[c.id] * c.weight * 20; });
  total = Math.round(total * 10) / 10;

  const evalObj = {
    id: Date.now(),
    fecha: new Date().toLocaleDateString('es-CO'),
    hora: new Date().toLocaleTimeString('es-CO', { hour: '2-digit', minute: '2-digit' }),
    jurado: { ...state.jurado },
    categoria: state.currentCategory,
    subcategoria: state.currentCategory === 'transformadores'
      ? SUBCATEGORIES.find(s => s.id === state.currentSubcat).name : 'Reconocimiento a Toda una Vida',
    postulante: document.getElementById('postulanteName').value.trim(),
    institucion: document.getElementById('postulanteInstitucion').value.trim(),
    scores: { ...state.scores },
    total,
    nivel: total >= 90 ? 'Sobresaliente' : total >= 75 ? 'Alto' : total >= 60 ? 'Aceptable' : total >= 40 ? 'Bajo' : 'Muy bajo',
    q1: document.getElementById('q1').value,
    q2: document.getElementById('q2').value,
    observaciones: document.getElementById('observaciones').value,
  };
  state.evaluations.push(evalObj);
  showToast('✅ Evaluación guardada correctamente');
  goToStep(4);
  renderSummary();
}

// ============================================================
// SUMMARY
// ============================================================
function renderSummary() {
  const container = document.getElementById('evalListContainer');
  const empty = document.getElementById('emptyState');
  const tableWrap = document.getElementById('summaryTableWrap');
  if (state.evaluations.length === 0) {
    empty.style.display = 'block';
    tableWrap.style.display = 'none';
    container.innerHTML = '';
    return;
  }
  empty.style.display = 'none';
  tableWrap.style.display = 'block';
  const tbody = document.getElementById('summaryBody');
  tbody.innerHTML = state.evaluations.map((e, i) => `
    <tr>
      <td>${i + 1}</td>
      <td><strong>${e.postulante}</strong></td>
      <td>
        <span class="tag ${e.categoria === 'transformadores' ? 'tag-transform' : 'tag-vida'}">
          ${e.categoria === 'transformadores' ? e.subcategoria : 'Toda una Vida'}
        </span>
      </td>
      <td>${e.institucion || '—'}</td>
      <td><strong>${e.total}</strong>/100</td>
      <td>${e.nivel}</td>
    </tr>
  `).join('');
}

function updatePanel4Header() {
  document.getElementById('panel4Sub').textContent =
    `Jurado: ${state.jurado.nombre || '—'} · ${state.evaluations.length} evaluaciones registradas`;
}

function newEvaluation() {
  state.currentCategory = null;
  state.currentSubcat = null;
  state.scores = {};
  document.getElementById('postulanteName').value = '';
  document.getElementById('postulanteInstitucion').value = '';
  document.getElementById('cat-transform').classList.remove('selected');
  document.getElementById('cat-vida').classList.remove('selected');
  document.getElementById('subcatSection').style.display = 'none';
  goToStep(2);
}

// ============================================================
// EXPORT TO EXCEL
// ============================================================
function exportToExcel() {
  if (state.evaluations.length === 0) { showToast('⚠️ No hay evaluaciones para exportar.'); return; }

  const wb = XLSX.utils.book_new();

  // ---- Sheet 1: Resumen ----
  const resumenData = [
    ['II JORNADA DE RECONOCIMIENTOS A BIBLIOTECAS TRANSFORMADORAS 2026'],
    ['Reporte de Evaluaciones de Jurado'],
    ['Generado:', new Date().toLocaleString('es-CO')],
    ['Jurado:', state.jurado.nombre, 'Código:', state.jurado.codigo],
    ['Institución:', state.jurado.institucion, 'Email:', state.jurado.email],
    [],
    ['#', 'Fecha', 'Hora', 'Postulante / Proyecto', 'Institución', 'Categoría', 'Subcategoría',
      'C1 Claridad Problema', 'C2 Innovación', 'C3 Impacto', 'C4 Sostenibilidad', 'C5 Gestión',
      'V1 Trayectoria', 'V2 Impacto Inst.', 'V3 Aporte Sector', 'V4 Innovación/Legado',
      'Puntaje Total (100)', 'Nivel', 'Q1 Contribución Principal', 'Q2 Justificación', 'Observaciones']
  ];

  state.evaluations.forEach((e, i) => {
    resumenData.push([
      i + 1,
      e.fecha,
      e.hora,
      e.postulante,
      e.institucion,
      e.categoria === 'transformadores' ? 'Proyectos Transformadores' : 'Reconocimiento a Toda una Vida',
      e.subcategoria,
      e.scores['c1'] || '',
      e.scores['c2'] || '',
      e.scores['c3'] || '',
      e.scores['c4'] || '',
      e.scores['c5'] || '',
      e.scores['v1'] || '',
      e.scores['v2'] || '',
      e.scores['v3'] || '',
      e.scores['v4'] || '',
      e.total,
      e.nivel,
      e.q1 || '',
      e.q2 || '',
      e.observaciones || ''
    ]);
  });

  const ws1 = XLSX.utils.aoa_to_sheet(resumenData);
  ws1['!cols'] = [
    {wch:4},{wch:10},{wch:8},{wch:28},{wch:22},{wch:24},{wch:30},
    {wch:8},{wch:10},{wch:8},{wch:12},{wch:10},
    {wch:10},{wch:12},{wch:14},{wch:16},
    {wch:14},{wch:12},{wch:35},{wch:35},{wch:30}
  ];
  XLSX.utils.book_append_sheet(wb, ws1, 'Evaluaciones');

  // ---- Sheet 2: Métricas ----
  const transformEvals = state.evaluations.filter(e => e.categoria === 'transformadores');
  const vidaEvals = state.evaluations.filter(e => e.categoria === 'vida');

  const metricasData = [
    ['MÉTRICAS Y ESTADÍSTICAS'],
    [],
    ['RESUMEN GENERAL'],
    ['Total evaluaciones', state.evaluations.length],
    ['Proyectos Transformadores', transformEvals.length],
    ['Reconocimiento Toda una Vida', vidaEvals.length],
    [],
  ];

  if (transformEvals.length > 0) {
    const totales = transformEvals.map(e => e.total);
    metricasData.push(['PROYECTOS TRANSFORMADORES — MÉTRICAS']);
    metricasData.push(['Puntaje promedio', promedio(totales)]);
    metricasData.push(['Puntaje máximo', Math.max(...totales)]);
    metricasData.push(['Puntaje mínimo', Math.min(...totales)]);
    metricasData.push([]);
    metricasData.push(['Desglose por criterio (promedios)']);
    metricasData.push(['Claridad del problema (15%)', promedioCol(transformEvals, 'c1')]);
    metricasData.push(['Innovación y diferenciación (20%)', promedioCol(transformEvals, 'c2')]);
    metricasData.push(['Impacto medible (25%)', promedioCol(transformEvals, 'c3')]);
    metricasData.push(['Sostenibilidad y escalabilidad (20%)', promedioCol(transformEvals, 'c4')]);
    metricasData.push(['Gestión y ejecución (20%)', promedioCol(transformEvals, 'c5')]);
    metricasData.push([]);
    metricasData.push(['Ranking Proyectos Transformadores']);
    metricasData.push(['#', 'Postulante', 'Subcategoría', 'Institución', 'Puntaje', 'Nivel']);
    [...transformEvals].sort((a,b) => b.total - a.total).forEach((e, i) =>
      metricasData.push([i+1, e.postulante, e.subcategoria, e.institucion, e.total, e.nivel])
    );
    metricasData.push([]);
  }

  if (vidaEvals.length > 0) {
    const totales = vidaEvals.map(e => e.total);
    metricasData.push(['RECONOCIMIENTO TODA UNA VIDA — MÉTRICAS']);
    metricasData.push(['Puntaje promedio', promedio(totales)]);
    metricasData.push(['Puntaje máximo', Math.max(...totales)]);
    metricasData.push(['Puntaje mínimo', Math.min(...totales)]);
    metricasData.push([]);
    metricasData.push(['Desglose por criterio (promedios)']);
    metricasData.push(['Trayectoria y permanencia (20%)', promedioCol(vidaEvals, 'v1')]);
    metricasData.push(['Impacto institucional y comunitario (25%)', promedioCol(vidaEvals, 'v2')]);
    metricasData.push(['Aporte al desarrollo del sector (25%)', promedioCol(vidaEvals, 'v3')]);
    metricasData.push(['Innovación y legado profesional (30%)', promedioCol(vidaEvals, 'v4')]);
    metricasData.push([]);
    metricasData.push(['Ranking Reconocimiento Toda una Vida']);
    metricasData.push(['#', 'Postulante', 'Institución', 'Puntaje', 'Nivel']);
    [...vidaEvals].sort((a,b) => b.total - a.total).forEach((e, i) =>
      metricasData.push([i+1, e.postulante, e.institucion, e.total, e.nivel])
    );
  }

  const ws2 = XLSX.utils.aoa_to_sheet(metricasData);
  ws2['!cols'] = [{wch:40},{wch:20},{wch:25},{wch:22},{wch:12},{wch:15}];
  XLSX.utils.book_append_sheet(wb, ws2, 'Métricas');

  // ---- Export ----
  const fecha = new Date().toISOString().slice(0,10);
  const juradoSlug = (state.jurado.codigo || state.jurado.nombre || 'jurado').replace(/\s+/g,'-').toLowerCase();
  XLSX.writeFile(wb, `evaluaciones-jurado-${juradoSlug}-${fecha}.xlsx`);
  showToast('📥 Excel exportado exitosamente');
}

function promedio(arr) {
  if (!arr.length) return 0;
  return Math.round(arr.reduce((a,b)=>a+b,0)/arr.length * 10)/10;
}
function promedioCol(evals, key) {
  const vals = evals.map(e => e.scores[key]).filter(Boolean);
  return vals.length ? promedio(vals) : '—';
}

// ============================================================
// TOAST
// ============================================================
function showToast(msg) {
  const t = document.getElementById('toast');
  t.textContent = msg;
  t.classList.add('show');
  setTimeout(() => t.classList.remove('show'), 3000);
}
</script>
<script>
const SHEETS_URL = 'https://script.google.com/macros/s/AKfycbzIXGNogOSxI-TK5y8OeZeuXkh6OT1YTMK2AaXY1FQ_m5gShovL-rAsxLnUuyVMBZMd/exec';

// ============================================================
// DATA
// ============================================================
const SUBCATEGORIES = [
  { id: 1, name: "Innovación Tecnológica" },
  { id: 2, name: "Fomento a la Lectura Lúdica" },
  { id: 3, name: "Colaboración Interinstitucional" },
  { id: 4, name: "Impacto Social" },
  { id: 5, name: "Impacto Ambiental" },
  { id: 6, name: "Inclusión y Accesibilidad" },
  { id: 7, name: "Alfabetización Informacional" },
  { id: 8, name: "Diseño de Espacios Físicos" },
  { id: 9, name: "Uso Creativo de Recursos Bibliográficos" },
  { id: 10, name: "Red de Colaboración de Bibliotecas Universitarias" }
];

const CRITERIA_TRANSFORM = [
  { id: "c1", name: "Claridad del problema identificado", weight: 0.15, desc: "¿El proyecto identifica claramente el problema o necesidad que busca resolver?" },
  { id: "c2", name: "Innovación y diferenciación", weight: 0.20, desc: "¿Propone soluciones novedosas o enfoques diferenciadores respecto a prácticas tradicionales?" },
  { id: "c3", name: "Impacto medible", weight: 0.25, desc: "¿Se presentan evidencias cuantitativas o cualitativas del impacto generado?" },
  { id: "c4", name: "Sostenibilidad y escalabilidad", weight: 0.20, desc: "¿El proyecto puede mantenerse en el tiempo y replicarse en otros contextos?" },
  { id: "c5", name: "Gestión y ejecución del proyecto", weight: 0.20, desc: "¿Muestra evidencias de planificación, ejecución eficiente y logro de resultados?" },
];

const CRITERIA_VIDA = [
  { id: "v1", name: "Trayectoria y permanencia en el sector", weight: 0.20, desc: "Años de dedicación, continuidad y liderazgo sostenido en el ámbito bibliotecario o académico." },
  { id: "v2", name: "Impacto institucional y comunitario", weight: 0.25, desc: "Transformaciones generadas en bibliotecas o instituciones; influencia directa en comunidades académicas." },
  { id: "v3", name: "Aporte al desarrollo del sector", weight: 0.25, desc: "Participación en redes, producción académica, incidencia en políticas o modelos de gestión." },
  { id: "v4", name: "Innovación y legado profesional", weight: 0.30, desc: "Prácticas pioneras, modelos replicables, creación de metodologías o enfoques diferenciadores." },
];

// ============================================================
// STATE
// ============================================================
let state = {
  currentStep: 1,
  jurado: {},
  currentCategory: null,
  currentSubcat: null,
  scores: {},
  evaluations: [],
};

// ============================================================
// NAVIGATION
// ============================================================
function goToStep(n) {
  for (let i = 1; i <= 4; i++) {
    document.getElementById('panel' + i).classList.remove('visible');
    const s = document.getElementById('step' + i);
    s.classList.remove('active', 'done');
    if (i < n) s.classList.add('done');
  }
  document.getElementById('panel' + n).classList.add('visible');
  document.getElementById('step' + n).classList.add('active');
  state.currentStep = n;
  window.scrollTo({ top: 0, behavior: 'smooth' });
}

function continueToStep2() {
  const nombre = document.getElementById('juradoNombre').value.trim();
  if (!nombre) { showToast('⚠️ Ingrese su nombre completo.'); return; }
  if (!document.getElementById('conflictoInteres').checked) { showToast('⚠️ Debe declarar el conflicto de interés.'); return; }
  state.jurado = {
    nombre,
    codigo: document.getElementById('juradoCodigo').value.trim(),
    institucion: document.getElementById('juradoInstitucion').value.trim(),
    email: document.getElementById('juradoEmail').value.trim(),
  };
  updatePanel4Header();
  goToStep(2);
}

function continueToStep3() {
  if (!state.currentCategory) { showToast('⚠️ Seleccione una categoría.'); return; }
  if (state.currentCategory === 'transformadores' && !state.currentSubcat) { showToast('⚠️ Seleccione la subcategoría.'); return; }
  const name = document.getElementById('postulanteName').value.trim();
  if (!name) { showToast('⚠️ Ingrese el nombre del proyecto o postulante.'); return; }
  state.scores = {};
  buildRubric();
  goToStep(3);
}

// ============================================================
// CATEGORY SELECTION
// ============================================================
function selectCategory(cat) {
  state.currentCategory = cat;
  state.currentSubcat = null;
  document.getElementById('cat-transform').classList.toggle('selected', cat === 'transformadores');
  document.getElementById('cat-vida').classList.toggle('selected', cat === 'vida');
  const subcatSection = document.getElementById('subcatSection');
  if (cat === 'transformadores') {
    subcatSection.style.display = 'block';
    buildSubcatGrid();
  } else {
    subcatSection.style.display = 'none';
  }
}

function buildSubcatGrid() {
  const grid = document.getElementById('subcatGrid');
  grid.innerHTML = SUBCATEGORIES.map(s => `
    <div class="subcat-item" id="subcat-${s.id}" onclick="selectSubcat(${s.id})">
      <div class="num">${s.id}</div>
      <div class="subcat-label">${s.name}</div>
    </div>
  `).join('');
}

function selectSubcat(id) {
  state.currentSubcat = id;
  document.querySelectorAll('.subcat-item').forEach(el => el.classList.remove('selected'));
  document.getElementById('subcat-' + id).classList.add('selected');
}

// ============================================================
// RUBRIC
// ============================================================
function buildRubric() {
  const criteria = state.currentCategory === 'transformadores' ? CRITERIA_TRANSFORM : CRITERIA_VIDA;
  const container = document.getElementById('rubricContainer');
  const sub = state.currentCategory === 'transformadores'
    ? `Proyecto: <strong>${document.getElementById('postulanteName').value}</strong> · Subcategoría: <strong>${SUBCATEGORIES.find(s=>s.id===state.currentSubcat).name}</strong>`
    : `Postulante: <strong>${document.getElementById('postulanteName').value}</strong>`;
  document.getElementById('panel3Sub').innerHTML = sub;

  container.innerHTML = `<div class="rubric-section">
    <div class="rubric-section-title">Criterios de evaluación</div>
    ${criteria.map(c => `
      <div class="criterion-row">
        <div class="criterion-info">
          <div class="crit-name">${c.name}</div>
          <div class="crit-desc">${c.desc}</div>
          <span class="crit-weight">Peso: ${Math.round(c.weight*100)}%</span>
        </div>
        <div class="score-buttons">
          ${[1,2,3,4,5].map(n => `
            <button class="score-btn" id="btn-${c.id}-${n}" onclick="setScore('${c.id}', ${n})">${n}</button>
          `).join('')}
        </div>
      </div>
    `).join('')}
  </div>`;

  document.getElementById('qualitativeSection').style.display =
    state.currentCategory === 'vida' ? 'block' : 'none';
  document.getElementById('q1').value = '';
  document.getElementById('q2').value = '';
  document.getElementById('observaciones').value = '';
  updateScore();
}

function setScore(criterionId, score) {
  state.scores[criterionId] = score;
  const criteria = state.currentCategory === 'transformadores' ? CRITERIA_TRANSFORM : CRITERIA_VIDA;
  const c = criteria.find(x => x.id === criterionId);
  [1,2,3,4,5].forEach(n => {
    const btn = document.getElementById(`btn-${criterionId}-${n}`);
    if (btn) btn.classList.toggle('active', n === score);
  });
  updateScore();
}

function updateScore() {
  const criteria = state.currentCategory === 'transformadores' ? CRITERIA_TRANSFORM : CRITERIA_VIDA;
  let total = 0;
  let filled = 0;
  criteria.forEach(c => {
    if (state.scores[c.id]) {
      total += state.scores[c.id] * c.weight * 20; // scale to 100
      filled++;
    }
  });
  const display = document.getElementById('scoreDisplay');
  const bar = document.getElementById('scoreBar');
  const level = document.getElementById('scoreLevel');
  if (filled === 0) {
    display.textContent = '—';
    bar.style.width = '0%';
    level.textContent = 'Complete todos los criterios';
    return;
  }
  const pct = filled === criteria.length ? total : (total / filled * criteria.reduce((a,c)=>a+(state.scores[c.id]?c.weight:0),0)) ;
  // recalculate properly
  let realTotal = 0;
  criteria.forEach(c => { if (state.scores[c.id]) realTotal += state.scores[c.id] * c.weight * 20; });
  const rounded = Math.round(realTotal * 10) / 10;
  display.textContent = filled === criteria.length ? rounded : '...';
  bar.style.width = (filled === criteria.length ? realTotal : 0) + '%';
  const lvlText = realTotal >= 90 ? '🏆 Sobresaliente' : realTotal >= 75 ? '⭐ Alto' : realTotal >= 60 ? '✅ Aceptable' : realTotal >= 40 ? '⚠️ Bajo' : '❌ Muy bajo';
  level.textContent = filled === criteria.length ? lvlText : `${filled}/${criteria.length} criterios calificados`;
}

// ============================================================
// SAVE
// ============================================================
function saveEvaluation() {
  const criteria = state.currentCategory === 'transformadores' ? CRITERIA_TRANSFORM : CRITERIA_VIDA;
  if (criteria.some(c => !state.scores[c.id])) { showToast('⚠️ Califique todos los criterios antes de guardar.'); return; }

  let total = 0;
  criteria.forEach(c => { total += state.scores[c.id] * c.weight * 20; });
  total = Math.round(total * 10) / 10;

  const evalObj = {
    id: Date.now(),
    fecha: new Date().toLocaleDateString('es-CO'),
    hora: new Date().toLocaleTimeString('es-CO', { hour: '2-digit', minute: '2-digit' }),
    jurado: { ...state.jurado },
    categoria: state.currentCategory,
    subcategoria: state.currentCategory === 'transformadores'
      ? SUBCATEGORIES.find(s => s.id === state.currentSubcat).name : 'Reconocimiento a Toda una Vida',
    postulante: document.getElementById('postulanteName').value.trim(),
    institucion: document.getElementById('postulanteInstitucion').value.trim(),
    scores: { ...state.scores },
    total,
    nivel: total >= 90 ? 'Sobresaliente' : total >= 75 ? 'Alto' : total >= 60 ? 'Aceptable' : total >= 40 ? 'Bajo' : 'Muy bajo',
    q1: document.getElementById('q1').value,
    q2: document.getElementById('q2').value,
    observaciones: document.getElementById('observaciones').value,
  };
  const row = {
    'Fecha': evalObj.fecha, 'Hora': evalObj.hora,
    'Jurado': evalObj.jurado.nombre, 'Código Jurado': evalObj.jurado.codigo,
    'Institución Jurado': evalObj.jurado.institucion, 'Email Jurado': evalObj.jurado.email,
    'Categoría': evalObj.categoria === 'transformadores' ? 'Proyectos Transformadores' : 'Reconocimiento a Toda una Vida',
    'Subcategoría': evalObj.subcategoria,
    'Postulante / Proyecto': evalObj.postulante, 'Institución Postulante': evalObj.institucion,
    'C1 Claridad del problema (15%)': evalObj.scores['c1'] || '',
    'C2 Innovación y diferenciación (20%)': evalObj.scores['c2'] || '',
    'C3 Impacto medible (25%)': evalObj.scores['c3'] || '',
    'C4 Sostenibilidad y escalabilidad (20%)': evalObj.scores['c4'] || '',
    'C5 Gestión y ejecución (20%)': evalObj.scores['c5'] || '',
    'V1 Trayectoria y permanencia (20%)': evalObj.scores['v1'] || '',
    'V2 Impacto institucional y comunitario (25%)': evalObj.scores['v2'] || '',
    'V3 Aporte al desarrollo del sector (25%)': evalObj.scores['v3'] || '',
    'V4 Innovación y legado profesional (30%)': evalObj.scores['v4'] || '',
    'Puntaje Total (100)': evalObj.total, 'Nivel': evalObj.nivel,
    'Q1 - Contribución principal': evalObj.q1 || '',
    'Q2 - Justificación reconocimiento': evalObj.q2 || '',
    'Observaciones': evalObj.observaciones || '',
  };
  // Build GET query string
  const params = Object.entries(row)
    .map(([k, v]) => encodeURIComponent(k) + '=' + encodeURIComponent(v))
    .join('&');
  const url = SHEETS_URL + '?' + params;

  showToast('⏳ Enviando a Google Sheets...');

  // Method 1: fetch no-cors
  try {
    fetch(url, { method: 'GET', mode: 'no-cors' })
      .then(() => showToast('✅ Evaluación guardada en Google Sheets'))
      .catch(() => {});
  } catch(e) {}

  // Method 2: fetch cors
  try {
    fetch(url, { method: 'GET', mode: 'cors' })
      .then(() => {})
      .catch(() => {});
  } catch(e) {}

  // Method 3: Image tag
  try {
    const img = new Image();
    img.src = url;
  } catch(e) {}

  // Method 4: XMLHttpRequest
  try {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.send();
  } catch(e) {}

  // Method 5: script tag injection (most iframe-friendly)
  try {
    const script = document.createElement('script');
    script.src = url + '&callback=_gsCallback';
    document.head.appendChild(script);
    setTimeout(() => { try { document.head.removeChild(script); } catch(e){} }, 3000);
  } catch(e) {}

  // Method 6: sendBeacon if available
  try {
    if (navigator.sendBeacon) {
      navigator.sendBeacon(url);
    }
  } catch(e) {}

  setTimeout(() => showToast('✅ Evaluación guardada en Google Sheets'), 1500);
  state.evaluations.push(evalObj);
  goToStep(4);
  renderSummary();
}

// ============================================================
// SUMMARY
// ============================================================
function renderSummary() {
  const container = document.getElementById('evalListContainer');
  const empty = document.getElementById('emptyState');
  const tableWrap = document.getElementById('summaryTableWrap');
  if (state.evaluations.length === 0) {
    empty.style.display = 'block';
    tableWrap.style.display = 'none';
    container.innerHTML = '';
    return;
  }
  empty.style.display = 'none';
  tableWrap.style.display = 'block';
  const tbody = document.getElementById('summaryBody');
  tbody.innerHTML = state.evaluations.map((e, i) => `
    <tr>
      <td>${i + 1}</td>
      <td><strong>${e.postulante}</strong></td>
      <td>
        <span class="tag ${e.categoria === 'transformadores' ? 'tag-transform' : 'tag-vida'}">
          ${e.categoria === 'transformadores' ? e.subcategoria : 'Toda una Vida'}
        </span>
      </td>
      <td>${e.institucion || '—'}</td>
      <td><strong>${e.total}</strong>/100</td>
      <td>${e.nivel}</td>
    </tr>
  `).join('');
}

function updatePanel4Header() {
  document.getElementById('panel4Sub').textContent =
    `Jurado: ${state.jurado.nombre || '—'} · ${state.evaluations.length} evaluaciones registradas`;
}

function newEvaluation() {
  state.currentCategory = null;
  state.currentSubcat = null;
  state.scores = {};
  document.getElementById('postulanteName').value = '';
  document.getElementById('postulanteInstitucion').value = '';
  document.getElementById('cat-transform').classList.remove('selected');
  document.getElementById('cat-vida').classList.remove('selected');
  document.getElementById('subcatSection').style.display = 'none';
  goToStep(2);
}

// ============================================================
// EXPORT TO EXCEL
// ============================================================
function exportToExcel() {
  if (state.evaluations.length === 0) { showToast('⚠️ No hay evaluaciones para exportar.'); return; }

  const wb = XLSX.utils.book_new();

  // ---- Sheet 1: Resumen ----
  const resumenData = [
    ['II JORNADA DE RECONOCIMIENTOS A BIBLIOTECAS TRANSFORMADORAS 2026'],
    ['Reporte de Evaluaciones de Jurado'],
    ['Generado:', new Date().toLocaleString('es-CO')],
    ['Jurado:', state.jurado.nombre, 'Código:', state.jurado.codigo],
    ['Institución:', state.jurado.institucion, 'Email:', state.jurado.email],
    [],
    ['#', 'Fecha', 'Hora', 'Postulante / Proyecto', 'Institución', 'Categoría', 'Subcategoría',
      'C1 Claridad Problema', 'C2 Innovación', 'C3 Impacto', 'C4 Sostenibilidad', 'C5 Gestión',
      'V1 Trayectoria', 'V2 Impacto Inst.', 'V3 Aporte Sector', 'V4 Innovación/Legado',
      'Puntaje Total (100)', 'Nivel', 'Q1 Contribución Principal', 'Q2 Justificación', 'Observaciones']
  ];

  state.evaluations.forEach((e, i) => {
    resumenData.push([
      i + 1,
      e.fecha,
      e.hora,
      e.postulante,
      e.institucion,
      e.categoria === 'transformadores' ? 'Proyectos Transformadores' : 'Reconocimiento a Toda una Vida',
      e.subcategoria,
      e.scores['c1'] || '',
      e.scores['c2'] || '',
      e.scores['c3'] || '',
      e.scores['c4'] || '',
      e.scores['c5'] || '',
      e.scores['v1'] || '',
      e.scores['v2'] || '',
      e.scores['v3'] || '',
      e.scores['v4'] || '',
      e.total,
      e.nivel,
      e.q1 || '',
      e.q2 || '',
      e.observaciones || ''
    ]);
  });

  const ws1 = XLSX.utils.aoa_to_sheet(resumenData);
  ws1['!cols'] = [
    {wch:4},{wch:10},{wch:8},{wch:28},{wch:22},{wch:24},{wch:30},
    {wch:8},{wch:10},{wch:8},{wch:12},{wch:10},
    {wch:10},{wch:12},{wch:14},{wch:16},
    {wch:14},{wch:12},{wch:35},{wch:35},{wch:30}
  ];
  XLSX.utils.book_append_sheet(wb, ws1, 'Evaluaciones');

  // ---- Sheet 2: Métricas ----
  const transformEvals = state.evaluations.filter(e => e.categoria === 'transformadores');
  const vidaEvals = state.evaluations.filter(e => e.categoria === 'vida');

  const metricasData = [
    ['MÉTRICAS Y ESTADÍSTICAS'],
    [],
    ['RESUMEN GENERAL'],
    ['Total evaluaciones', state.evaluations.length],
    ['Proyectos Transformadores', transformEvals.length],
    ['Reconocimiento Toda una Vida', vidaEvals.length],
    [],
  ];

  if (transformEvals.length > 0) {
    const totales = transformEvals.map(e => e.total);
    metricasData.push(['PROYECTOS TRANSFORMADORES — MÉTRICAS']);
    metricasData.push(['Puntaje promedio', promedio(totales)]);
    metricasData.push(['Puntaje máximo', Math.max(...totales)]);
    metricasData.push(['Puntaje mínimo', Math.min(...totales)]);
    metricasData.push([]);
    metricasData.push(['Desglose por criterio (promedios)']);
    metricasData.push(['Claridad del problema (15%)', promedioCol(transformEvals, 'c1')]);
    metricasData.push(['Innovación y diferenciación (20%)', promedioCol(transformEvals, 'c2')]);
    metricasData.push(['Impacto medible (25%)', promedioCol(transformEvals, 'c3')]);
    metricasData.push(['Sostenibilidad y escalabilidad (20%)', promedioCol(transformEvals, 'c4')]);
    metricasData.push(['Gestión y ejecución (20%)', promedioCol(transformEvals, 'c5')]);
    metricasData.push([]);
    metricasData.push(['Ranking Proyectos Transformadores']);
    metricasData.push(['#', 'Postulante', 'Subcategoría', 'Institución', 'Puntaje', 'Nivel']);
    [...transformEvals].sort((a,b) => b.total - a.total).forEach((e, i) =>
      metricasData.push([i+1, e.postulante, e.subcategoria, e.institucion, e.total, e.nivel])
    );
    metricasData.push([]);
  }

  if (vidaEvals.length > 0) {
    const totales = vidaEvals.map(e => e.total);
    metricasData.push(['RECONOCIMIENTO TODA UNA VIDA — MÉTRICAS']);
    metricasData.push(['Puntaje promedio', promedio(totales)]);
    metricasData.push(['Puntaje máximo', Math.max(...totales)]);
    metricasData.push(['Puntaje mínimo', Math.min(...totales)]);
    metricasData.push([]);
    metricasData.push(['Desglose por criterio (promedios)']);
    metricasData.push(['Trayectoria y permanencia (20%)', promedioCol(vidaEvals, 'v1')]);
    metricasData.push(['Impacto institucional y comunitario (25%)', promedioCol(vidaEvals, 'v2')]);
    metricasData.push(['Aporte al desarrollo del sector (25%)', promedioCol(vidaEvals, 'v3')]);
    metricasData.push(['Innovación y legado profesional (30%)', promedioCol(vidaEvals, 'v4')]);
    metricasData.push([]);
    metricasData.push(['Ranking Reconocimiento Toda una Vida']);
    metricasData.push(['#', 'Postulante', 'Institución', 'Puntaje', 'Nivel']);
    [...vidaEvals].sort((a,b) => b.total - a.total).forEach((e, i) =>
      metricasData.push([i+1, e.postulante, e.institucion, e.total, e.nivel])
    );
  }

  const ws2 = XLSX.utils.aoa_to_sheet(metricasData);
  ws2['!cols'] = [{wch:40},{wch:20},{wch:25},{wch:22},{wch:12},{wch:15}];
  XLSX.utils.book_append_sheet(wb, ws2, 'Métricas');

  // ---- Export ----
  const fecha = new Date().toISOString().slice(0,10);
  const juradoSlug = (state.jurado.codigo || state.jurado.nombre || 'jurado').replace(/\s+/g,'-').toLowerCase();
  XLSX.writeFile(wb, `evaluaciones-jurado-${juradoSlug}-${fecha}.xlsx`);
  showToast('📥 Excel exportado exitosamente');
}

function promedio(arr) {
  if (!arr.length) return 0;
  return Math.round(arr.reduce((a,b)=>a+b,0)/arr.length * 10)/10;
}
function promedioCol(evals, key) {
  const vals = evals.map(e => e.scores[key]).filter(Boolean);
  return vals.length ? promedio(vals) : '—';
}

// ============================================================
// TOAST
// ============================================================
function showToast(msg) {
  const t = document.getElementById('toast');
  t.textContent = msg;
  t.classList.add('show');
  setTimeout(() => t.classList.remove('show'), 3000);
}

</script>