<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flor de Plutchik - Competencias Emocionales</title>
<style>
  :root { --bg:#f4f7fb; --card:#fff; --text:#1a1a1a; --muted:#555; --accent:#2b6cb0; --border:#d0d7de; --radius:12px; }
  * { box-sizing: border-box; }
  body { margin:0; font-family:system-ui,-apple-system,'Segoe UI',Roboto,sans-serif; background:var(--bg); color:var(--text); font-size:18px; line-height:1.5; }
  header { background:var(--card); border-bottom:1px solid var(--border); padding:1rem 1.5rem; display:flex; align-items:center; justify-content:space-between; flex-wrap:wrap; gap:1rem; }
  header h1 { font-size:1.4rem; margin:0; }
  nav { display:flex; flex-wrap:wrap; gap:0.5rem; background:var(--card); padding:0.75rem 1.5rem; border-bottom:1px solid var(--border); position:sticky; top:0; z-index:10; }
  nav button { background:#eef2f7; border:1px solid var(--border); border-radius:999px; padding:0.5rem 1rem; font-size:1rem; cursor:pointer; color:var(--text); font-weight:500; }
  nav button.active { background:var(--accent); color:#fff; border-color:var(--accent); }
  main { padding:1.5rem; max-width:1200px; margin:0 auto; }
  .tab-pane { display:none; } .tab-pane.active { display:block; }
  .card { background:var(--card); border:1px solid var(--border); border-radius:var(--radius); padding:1.25rem; margin-bottom:1rem; box-shadow:0 1px 3px rgba(0,0,0,0.05); }
  h2 { font-size:1.3rem; margin-top:0; } h3 { font-size:1.1rem; }
  button.primary { background:var(--accent); color:#fff; border:none; border-radius:8px; padding:0.75rem 1.25rem; font-size:1rem; cursor:pointer; font-weight:600; }
  button.primary:hover { background:#1f4f82; }
  button.secondary { background:#eef2f7; border:1px solid var(--border); border-radius:8px; padding:0.6rem 1rem; font-size:0.95rem; cursor:pointer; }
  button.secondary:hover { background:#dde5ee; }
  textarea,select,input[type="text"] { width:100%; padding:0.6rem; border:1px solid var(--border); border-radius:8px; font-size:1rem; font-family:inherit; margin-top:0.4rem; }
  textarea { min-height:90px; resize:vertical; }
  label { font-weight:600; display:block; margin-top:0.75rem; }
  .flower-container { display:flex; justify-content:center; margin:1rem 0; }
  .flower-container svg { max-width:100%; height:auto; }
  .info-panel { background:#f8fafc; border:1px solid var(--border); border-radius:var(--radius); padding:1rem; min-height:120px; }
  .badge { display:inline-flex; align-items:center; gap:0.4rem; padding:0.25rem 0.6rem; border-radius:999px; font-size:0.9rem; font-weight:500; margin:0.2rem; background:#eef2f7; border:1px solid var(--border); }
  .badge .dot { width:12px; height:12px; border-radius:50%; display:inline-block; }
  .journey-list { display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); gap:1rem; }
  .journey-card { background:var(--card); border:1px solid var(--border); border-radius:var(--radius); padding:1rem; cursor:pointer; transition:box-shadow 0.2s; }
  .journey-card:hover { box-shadow:0 4px 12px rgba(0,0,0,0.1); }
  .journey-card h3 { margin:0 0 0.4rem 0; }
  .journey-card p { margin:0.2rem 0; color:var(--muted); font-size:0.95rem; }
  .log { background:#f8fafc; border:1px solid var(--border); border-radius:8px; padding:0.75rem; max-height:320px; overflow-y:auto; font-size:0.95rem; margin:0.75rem 0; }
  .log-entry { margin:0.6rem 0; padding-bottom:0.6rem; border-bottom:1px dashed var(--border); }
  .log-entry:last-child { border-bottom:none; }
  .log-entry .log-action { font-weight:600; }
  .log-entry .log-consequence { color:var(--muted); font-style:italic; margin:0.2rem 0 0.2rem 1rem; }
  .log-entry .log-result { margin-left:1rem; }
  .situation-panel { background:#eef6ff; border:1px solid #b3d4fc; border-left:4px solid var(--accent); border-radius:8px; padding:0.75rem 1rem; margin:0.75rem 0; }
  .situation-panel p { margin:0.2rem 0; }
  .situation-panel .situation-label { font-size:0.8rem; text-transform:uppercase; letter-spacing:0.5px; color:var(--accent); font-weight:700; }
  .quick-actions { display:flex; flex-wrap:wrap; gap:0.5rem; margin:0.75rem 0; }
  .quick-actions button { font-size:0.95rem; }
  .fallback { background:#fff8e1; border:1px solid #f0c36d; border-radius:8px; padding:0.75rem; margin:0.75rem 0; }
  .fallback p { margin:0 0 0.5rem 0; font-weight:600; }
  .progress { font-weight:600; color:var(--muted); margin-bottom:0.5rem; }
  .summary { background:#e8f5e9; border:1px solid #a5d6a7; border-radius:var(--radius); padding:1rem; }
  .summary h3 { margin-top:0; }
  .bar-chart { margin:1rem 0; }
  .bar-row { display:flex; align-items:center; gap:0.5rem; margin:0.3rem 0; }
  .bar-label { width:120px; font-size:0.9rem; }
  .bar-track { flex:1; background:#eef2f7; border-radius:6px; height:22px; overflow:hidden; }
  .bar-fill { height:100%; border-radius:6px; }
  .bar-value { width:40px; text-align:right; font-size:0.9rem; }
  .teacher-guide { max-width:800px; }
  .teacher-guide h2 { margin-top:0; } .teacher-guide ul { padding-left:1.2rem; } .teacher-guide li { margin:0.4rem 0; }
  .tech-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); gap:1rem; margin-top:1rem; }
  .tech-card { border:1px solid var(--border); border-radius:var(--radius); padding:1rem; background:var(--card); }
  .tech-card h3 { margin:0 0 0.4rem 0; font-size:1.1rem; } .tech-card p { margin:0.3rem 0; font-size:0.95rem; }
  .tech-card .tech-level { display:inline-block; padding:0.15rem 0.5rem; border-radius:999px; font-size:0.8rem; font-weight:600; margin-bottom:0.5rem; }
  .tech-level.alta { background:#ffcdd2; color:#b71c1c; } .tech-level.media { background:#ffe0b2; color:#e65100; } .tech-level.baja { background:#c8e6c9; color:#1b5e20; }
  @media (max-width:600px) { body { font-size:16px; } main { padding:1rem; } nav { padding:0.5rem 1rem; } }
</style>
</head>
<body>
<header>
  <h1>🌸 Flor de Plutchik · Competencias Emocionales</h1>
  <span style="font-size:0.9rem;color:var(--muted)">Formación para la empleabilidad</span>
</header>
<nav id="tabs">
  <button data-tab="tutorial" class="active">Tutorial</button>
  <button data-tab="explorador">Explorador</button>
  <button data-tab="constructor">Constructor</button>
  <button data-tab="termometro">Mi termómetro</button>
  <button data-tab="recorridos">Recorridos</button>
  <button data-tab="tecnicas">Técnicas</button>
  <button data-tab="guia">Guía docente</button>
</nav>
<main>
  <section id="tutorial" class="tab-pane active">
    <div class="card">
      <h2>Bienvenido/a a la Flor de Plutchik</h2>
      <p>Esta herramienta te ayuda a <strong>reconocer tus emociones</strong> y a entender que <strong>no podemos pasar de una emoción muy intensa a la calma de golpe</strong>. Como cuando llueve muy fuerte: primero escampa, luego sale el sol.</p>
      <p>La flor tiene 8 emociones básicas. Cada una tiene <strong>tres niveles de intensidad</strong>:</p>
      <ul>
        <li><strong>Centro:</strong> intensidad muy alta (por ejemplo, Furia).</li>
        <li><strong>Zona media:</strong> intensidad media (por ejemplo, Enfado).</li>
        <li><strong>Borde:</strong> intensidad baja (por ejemplo, Irritación).</li>
      </ul>
      <p>Para bajar de Furia a Irritación hay que recorrer un camino: Furia → Enfado → Irritación. No se puede saltar.</p>
      <p>En esta web puedes:</p>
      <ul>
        <li><strong>Explorar</strong> la flor y sus combinaciones.</li>
        <li><strong>Construir</strong> emociones combinando dos básicas.</li>
        <li><strong>Registrar</strong> cómo te sientes en tu termómetro.</li>
        <li><strong>Hacer recorridos</strong> con situaciones de la vida diaria y practicar el camino de vuelta.</li>
        <li><strong>Consultar técnicas</strong> sencillas para regularte cuando lo necesites.</li>
      </ul>
    </div>
    <div class="card">
      <h2>Cómo funcionan los recorridos</h2>
      <p>En cada recorrido hay una situación y tú decides qué hacer. Hay <strong>dos momentos por paso</strong>:</p>
      <ol>
        <li><strong>Qué haces:</strong> eliges una acción concreta. Puede <strong>subir</strong> la intensidad, <strong>bajarla</strong> o <strong>mantenerla</strong>.</li>
        <li><strong>Qué haces ya más tranquilo:</strong> solo aparece si estás en nivel 2 o menos. Eliges otra acción concreta, como <em>"pido hablar al terminar"</em> (cambias de enfoque) o <em>"sigo esperando mi turno"</em> (te quedas).</li>
      </ol>
      <p><strong>Regla importante:</strong> no puedes cambiar de enfoque mientras estás en máxima intensidad. Primero hay que bajar la intensidad paso a paso.</p>
      <p>Cada decisión tiene una <strong>consecuencia</strong>: la situación cambia, y también cambia el estado de los personajes. En todo momento verás una descripción actualizada de lo que está pasando.</p>
    </div>
  </section>

  <section id="explorador" class="tab-pane">
    <div class="card">
      <h2>Explorador de la flor</h2>
      <p>Haz clic en cualquier parte de la flor para ver el nombre de la emoción, su intensidad y sus combinaciones.</p>
      <div class="flower-container" id="flowerExplorer"></div>
      <div class="info-panel" id="explorerInfo"><p>Selecciona una emoción en la flor para ver la información.</p></div>
    </div>
  </section>

  <section id="constructor" class="tab-pane">
    <div class="card">
      <h2>Constructor de emociones</h2>
      <p>Las emociones complejas surgen de la mezcla de dos emociones básicas. Elige la primera y después la segunda: solo aparecerán las emociones que pueden combinarse con ella.</p>
      <div style="display:flex; gap:1rem; flex-wrap:wrap;">
        <div style="flex:1; min-width:200px;"><label for="emo1">Primera emoción</label><select id="emo1"></select></div>
        <div style="flex:1; min-width:200px;"><label for="emo2">Segunda emoción (solo combinaciones válidas)</label><select id="emo2"></select></div>
      </div>
      <div id="dyadResult" class="info-panel" style="margin-top:1rem;"><p>Elige dos emociones diferentes para ver su combinación.</p></div>
    </div>
  </section>

  <section id="termometro" class="tab-pane">
    <div class="card">
      <h2>Mi termómetro emocional</h2>
      <p>Registra cómo te sientes en un momento concreto. Puedes comparar tus registros a lo largo del tiempo.</p>
      <label for="thermoEmotion">Emoción</label><select id="thermoEmotion"></select>
      <label for="thermoLevel">Intensidad</label>
      <input type="range" id="thermoLevel" min="1" max="3" value="2" step="1" style="width:100%;">
      <div style="display:flex; justify-content:space-between; font-size:0.9rem; color:var(--muted);"><span>Baja</span><span>Media</span><span>Alta</span></div>
      <label for="thermoNote">Nota (opcional)</label>
      <textarea id="thermoNote" placeholder="¿Qué ha pasado? ¿Dónde estabas?"></textarea>
      <button class="primary" id="saveRecord" style="margin-top:0.75rem;">Guardar registro</button>
    </div>
    <div class="card"><h2>Mis registros</h2><div id="recordsList"><p>No hay registros todavía.</p></div></div>
    <div class="card"><h2>Comparación</h2><div id="comparisonChart"><p>Guarda algún registro para ver la comparación.</p></div></div>
  </section>

  <section id="recorridos" class="tab-pane">
    <div id="journeyList">
      <div class="card">
        <h2>Recorridos emocionales</h2>
        <p>Elige una situación. Practicarás cómo pasar de una emoción muy intensa a una de menor intensidad, paso a paso. En cada paso tomarás dos decisiones: qué haces y, si ya estás más tranquilo, si cambias de enfoque con una acción concreta.</p>
      </div>
      <div class="journey-list" id="scenarioList"></div>
    </div>
    <div id="journeyActive" style="display:none;"></div>
  </section>

  <section id="tecnicas" class="tab-pane">
    <div class="card">
      <h2>Técnicas de regulación emocional</h2>
      <p>Trucos sencillos que puedes usar en muchas situaciones. No todos funcionan para todo el mundo: pruébalos y quédate con los que te ayuden.</p>
      <p><strong>Importante:</strong> según la intensidad, conviene empezar por unas u otras. Si estás en nivel 3 (máxima intensidad), primero baja el cuerpo; si estás en nivel 2, puedes pensar y hablar; si estás en nivel 1, puedes planificar.</p>
    </div>
    <h3 style="margin-left:0.25rem;">Para intensidad alta (nivel 3)</h3>
    <div class="tech-grid" id="techAlta"></div>
    <h3 style="margin-left:0.25rem;">Para intensidad media (nivel 2)</h3>
    <div class="tech-grid" id="techMedia"></div>
    <h3 style="margin-left:0.25rem;">Para intensidad baja (nivel 1)</h3>
    <div class="tech-grid" id="techBaja"></div>
  </section>

  <section id="guia" class="tab-pane">
    <div class="card teacher-guide">
      <h2>Guía para el docente</h2>
      <p><strong>Objetivo:</strong> que el alumnado reconozca sus emociones, comprenda que la intensidad emocional cambia gradualmente y practique el “camino de vuelta” desde una emoción muy intensa hasta una de menor intensidad, aplicándolo a situaciones cotidianas.</p>
      <h3>Competencias trabajadas</h3>
      <ul>
        <li>Conciencia emocional: identificar y nombrar emociones con precisión.</li>
        <li>Autorregulación: reconocer que no se puede pasar de una emoción intensa a la calma de golpe.</li>
        <li>Habilidades sociales: anticipar consecuencias de las propias acciones y regular la expresión emocional.</li>
        <li>Pensamiento alternativo: explorar distintas respuestas ante una misma situación.</li>
        <li>Transferencia: disponer de un repertorio de técnicas aplicables a la vida diaria.</li>
      </ul>
      <h3>Cómo funcionan los recorridos</h3>
      <p>Cada paso tiene <strong>dos momentos</strong>:</p>
      <ol>
        <li><strong>Intensidad:</strong> el alumno elige una acción concreta que sube, baja o mantiene la intensidad. Los personajes reaccionan a esa acción con emociones coherentes y la situación se actualiza.</li>
        <li><strong>Foco:</strong> solo si el nivel resultante es 2 o menos, el alumno elige otra acción concreta. Unas acciones implican <strong>cambiar de enfoque</strong> y otras implican <strong>quedarse</strong>. Cambiar de enfoque baja un nivel adicional.</li>
      </ol>
      <p>En cada paso se muestran tres cosas:</p>
      <ul>
        <li><strong>La situación actualizada</strong> arriba: descripción del estado del mundo, del alumno y del personaje.</li>
        <li><strong>La consecuencia inmediata</strong> en el registro: qué ha pasado y cómo ha reaccionado el personaje.</li>
        <li><strong>El estado del personaje</strong>: emoción y nivel actualizados con cada decisión.</li>
      </ul>
      <h3>Cómo usar la narrativa en clase</h3>
      <ul>
        <li><strong>Leer las consecuencias en voz alta:</strong> después de cada decisión, pide a un alumno que lea la consecuencia. Pregunta: "¿Os esperabais esta reacción? ¿Por qué?".</li>
        <li><strong>Comparar situación inicial y actual:</strong> al final del recorrido, comparad el párrafo de situación inicial con el panel de situación actual.</li>
        <li><strong>Fijarse en los personajes:</strong> los personajes cambian de emoción con las decisiones. Pregunta: "¿Cómo está ahora el compañero? ¿Por qué ha cambiado de esta manera y no de otra?".</li>
        <li><strong>Reflexionar sobre la coherencia:</strong> cuando el alumno haga algo que provoque una reacción del personaje, pregúntale si le parece lógica esa reacción. Esto entrena la teoría de la mente.</li>
      </ul>
      <h3>Cómo usar la pestaña "Técnicas"</h3>
      <ul>
        <li><strong>Antes:</strong> como vocabulario previo. "¿Cuáles de estas técnicas conocíais?".</li>
        <li><strong>Durante:</strong> cuando un alumno se atasque, anímale a consultar las técnicas de su nivel actual.</li>
        <li><strong>Después:</strong> como transferencia. "¿Cuál crees que te serviría en tu día a día?".</li>
      </ul>
      <h3>Sugerencias de sesión</h3>
      <ul>
        <li><strong>Duración:</strong> 45-60 minutos.</li>
        <li><strong>Agrupamiento:</strong> parejas o pequeño grupo. Un alumno maneja la herramienta, otro observa; luego intercambian.</li>
        <li><strong>Evaluación:</strong> valora la reflexión, la coherencia entre acción y reacción, y la capacidad de explicar el camino recorrido.</li>
        <li><strong>Transferencia:</strong> al final de cada recorrido, pide una situación real y una técnica que probarían.</li>
      </ul>
      <h3>Adaptaciones</h3>
      <ul>
        <li>Si la escritura supone una barrera, usen los botones de acción rápida.</li>
        <li>Lean las situaciones y las consecuencias en voz alta si es necesario.</li>
        <li>Refuercen cada avance: "Has bajado de Furia a Enfado. ¡Eso es un paso!".</li>
      </ul>
      <h3>Nota sobre el modelo</h3>
      <p>La Flor de Plutchik es una simplificación didáctica. Las emociones reales son más complejas y personales. Úsala como un mapa para conversar, no como una verdad absoluta.</p>
    </div>
  </section>
</main>
<script>
const EMOTION_ORDER = ['alegria','confianza','miedo','sorpresa','tristeza','disgusto','ira','anticipacion'];
const EMOTIONS = {
  alegria:{name:'Alegría',color:'#FFD700',opposite:'tristeza',def:'Sensación de bienestar y satisfacción.',levels:['Serenidad','Alegría','Éxtasis']},
  confianza:{name:'Confianza',color:'#A8E05F',opposite:'disgusto',def:'Sentimiento de seguridad y creencia en alguien o algo.',levels:['Aceptación','Confianza','Admiración']},
  miedo:{name:'Miedo',color:'#4CAF50',opposite:'ira',def:'Respuesta ante un peligro real o imaginario.',levels:['Aprensión','Miedo','Terror']},
  sorpresa:{name:'Sorpresa',color:'#5BC8FF',opposite:'anticipacion',def:'Reacción ante algo inesperado.',levels:['Distracción','Sorpresa','Asombro']},
  tristeza:{name:'Tristeza',color:'#3B6FD4',opposite:'alegria',def:'Respuesta ante una pérdida o decepción.',levels:['Melancolía','Tristeza','Aflicción']},
  disgusto:{name:'Disgusto',color:'#9C27B0',opposite:'confianza',def:'Rechazo hacia algo desagradable.',levels:['Aburrimiento','Disgusto','Aversión']},
  ira:{name:'Ira',color:'#E53935',opposite:'miedo',def:'Respuesta ante una injusticia u obstáculo.',levels:['Irritación','Enfado','Furia']},
  anticipacion:{name:'Anticipación',color:'#FF9800',opposite:'sorpresa',def:'Preparación ante un evento futuro.',levels:['Interés','Anticipación','Vigilancia']}
};
const DYADS = {
  'alegria+confianza':{name:'Amor',desc:'Alegría y confianza juntas generan amor.'},
  'confianza+miedo':{name:'Sumisión',desc:'Confianza y miedo generan sumisión.'},
  'miedo+sorpresa':{name:'Sobresalto',desc:'Miedo y sorpresa generan sobresalto o alarma.'},
  'sorpresa+tristeza':{name:'Decepción',desc:'Sorpresa y tristeza generan decepción.'},
  'tristeza+disgusto':{name:'Remordimiento',desc:'Tristeza y disgusto generan remordimiento.'},
  'disgusto+ira':{name:'Desprecio',desc:'Disgusto e ira generan desprecio.'},
  'ira+anticipacion':{name:'Agresividad',desc:'Ira y anticipación generan agresividad.'},
  'anticipacion+alegria':{name:'Optimismo',desc:'Anticipación y alegría generan optimismo.'}
};

const BASE_LEXICON = {
  escalar:['grit','insult','pego','empujo','rompo','lloro','me voy','callate','idiota','tonto','estupido','bobo','harto','basta','ya esta bien','patada','portazo','enfad','furios','rabia','cabread','molest','atac','defend','pele','discut','falta de respeto'],
  desescalar:['respiro','calma','tranquil','espero','cuento','pienso','agua','paseo','me alejo','hablo','explico','pido','perdon','disculpa','escucho','entiendo','reflexion','consider','comprendo','acepto'],
  mantener:['nada','silencio','callado','aguanto','no digo','no hago','me quedo','igual','sin hacer','sin decir'],
  contiguo:['cambio','tema','otra cosa','propongo','plan','luego','despues','solo','aparte','amigo','ayuda','alternativa','conversar','dialog','aclar','charl']
};

const SCENARIOS = [
  {
    id:'clase_interrumpe', title:'En clase: tu compañero te interrumpe',
    context:'Estás en clase presentando un trabajo. Un compañero te interrumpe varias veces.',
    situationLevels:{
      3:'La presentación se ha interrumpido. La clase entera os mira y la tensión es máxima.',
      2:'Tu compañero sigue hablando, aunque la tensión ha bajado algo. La clase sigue con atención.',
      1:'Tu compañero está callado. Puedes terminar la presentación con tranquilidad.'
    },
    origin:{emotion:'ira',level:3},
    targetMain:{emotion:'ira',level:1},
    targetAlt:{emotion:'anticipacion',level:1},
    contiguoEmotion:'anticipacion',
    maxSteps:6,
    characters:[{name:'Tu compañero',emotion:'ira',level:2}],
    actions:{
      subir:[
        {label:'Le grito que se calle',charReaction:{emotion:'ira',level:3},consequence:'Gritas. Tu compañero se gira y te grita también. La clase entera os mira en silencio.'},
        {label:'Le insulto',charReaction:{emotion:'ira',level:3},consequence:'Le insultas. Tu compañero se levanta de la silla, muy alterado. El profesor interviene.'}
      ],
      bajar:[
        {label:'Respiro hondo y espero mi turno',charReaction:{emotion:'ira',level:1},consequence:'Respiras hondo y esperas tu turno. Tu compañero sigue hablando, pero notas que la tensión baja.'},
        {label:'Cuento hasta diez y sigo con calma',charReaction:{emotion:'ira',level:1},consequence:'Cuentas hasta diez y sigues con calma. Tu compañero se extraña de tu reacción y baja el tono.'}
      ],
      mantener:[
        {label:'No digo nada y aguanto',charReaction:{emotion:'ira',level:2},consequence:'Te callas. Tu compañero sigue interrumpiendo. La tensión sigue ahí, atascada.'}
      ]
    },
    focusActions:[
      {label:'Le pido hablar al terminar, con calma',type:'cambiar',charReaction:{emotion:'sorpresa',level:2},consequence:'Le pides hablar al terminar. Tu compañero asiente, sorprendido por tu calma. Te concentras en la presentación.'},
      {label:'Sigo esperando mi turno sin decir nada',type:'quedarse',charReaction:null,consequence:'Sigues esperando sin decir nada. La emoción se mantiene, pero no sube.'},
      {label:'Anoto lo que quiero decirle luego',type:'cambiar',charReaction:{emotion:'sorpresa',level:1},consequence:'Anotas lo que quieres decirle. Te concentras en la presentación y la mente se te despeja.'}
    ]
  },
  {
    id:'clase_profesor', title:'En clase: el profesor te corrige delante de todos',
    context:'Estás en clase y el profesor te corrige un error delante de todos.',
    situationLevels:{
      3:'La corrección ha sido delante de todos. El silencio en clase es total y tú no sabes dónde meterte.',
      2:'El profesor ha terminado la corrección. La clase sigue, aunque tú aún estás afectado.',
      1:'La corrección ha quedado atrás. Puedes seguir la clase con normalidad.'
    },
    origin:{emotion:'tristeza',level:3},
    targetMain:{emotion:'tristeza',level:1},
    targetAlt:{emotion:'sorpresa',level:1},
    contiguoEmotion:'sorpresa',
    maxSteps:6,
    characters:[{name:'El profesor',emotion:'confianza',level:2}],
    actions:{
      subir:[
        {label:'Me pongo a llorar',charReaction:{emotion:'sorpresa',level:2},consequence:'Te pones a llorar. El profesor se queda callado, incómodo, y la clase entera te mira.'},
        {label:'Me hundo y no digo nada',charReaction:{emotion:'sorpresa',level:1},consequence:'Te hundes en la silla y no dices nada. El silencio se hace muy largo y la tristeza crece.'}
      ],
      bajar:[
        {label:'Respiro y escucho con calma',charReaction:{emotion:'confianza',level:2},consequence:'Respiras y escuchas con calma. El profesor termina la corrección. Notas que la tristeza baja un poco.'},
        {label:'Pienso que es una corrección, no un ataque',charReaction:{emotion:'confianza',level:2},consequence:'Piensas que es una corrección, no un ataque. El profesor sigue con la clase. Te sientes algo mejor.'}
      ],
      mantener:[
        {label:'Me quedo en blanco',charReaction:{emotion:'sorpresa',level:2},consequence:'Te quedas en blanco. El profesor espera. La tristeza sigue ahí, sin moverse.'}
      ]
    },
    focusActions:[
      {label:'Pido hablar con el profesor al terminar',type:'cambiar',charReaction:{emotion:'confianza',level:3},consequence:'Pides hablar con el profesor al terminar. Él asiente, complacido. Ahora piensas en qué le vas a decir.'},
      {label:'Acepto la corrección y sigo la clase',type:'quedarse',charReaction:{emotion:'confianza',level:2},consequence:'Aceptas la corrección y sigues la clase. La tristeza se queda contigo, pero ya no te paraliza.'},
      {label:'Me pregunto qué ha pasado para que me corrija así',type:'cambiar',charReaction:{emotion:'confianza',level:2},consequence:'Te preguntas qué ha pasado. La curiosidad sustituye poco a poco a la tristeza.'}
    ]
  },
  {
    id:'casa_ropa', title:'En casa: tu hermano usa tu ropa sin permiso',
    context:'Llegas a casa y ves que tu hermano lleva puesta tu ropa favorita sin pedirte permiso.',
    situationLevels:{
      3:'El conflicto con tu hermano está en su punto más alto. La casa está tensa.',
      2:'Tu hermano se ha dado cuenta de que estás molesto. La tensión ha bajado algo, pero sigue ahí.',
      1:'Tu hermano está dispuesto a hablar. La situación está más tranquila.'
    },
    origin:{emotion:'ira',level:3},
    targetMain:{emotion:'ira',level:1},
    targetAlt:{emotion:'anticipacion',level:1},
    contiguoEmotion:'anticipacion',
    maxSteps:6,
    characters:[{name:'Tu hermano',emotion:'sorpresa',level:2}],
    actions:{
      subir:[
        {label:'Le grito',charReaction:{emotion:'ira',level:2},consequence:'Le gritas. Tu hermano se sobresalta y te responde a gritos. La casa se llena de tensión.'},
        {label:'Le insulto',charReaction:{emotion:'ira',level:3},consequence:'Le insultas. Tu hermano se pone a la defensiva y empezáis a discutir.'}
      ],
      bajar:[
        {label:'Respiro y le explico cómo me siento',charReaction:{emotion:'confianza',level:2},consequence:'Respiras y le explicas cómo te sientes. Tu hermano se queda callado, escuchando. La tensión baja.'},
        {label:'Cuento hasta diez antes de hablar',charReaction:{emotion:'confianza',level:1},consequence:'Cuentas hasta diez antes de hablar. Tu hermano espera. La furia baja un poco antes de que digas nada.'}
      ],
      mantener:[
        {label:'Me callo y me voy sin decir nada',charReaction:{emotion:'sorpresa',level:1},consequence:'Te callas y te vas. Tu hermano se queda con la ropa puesta. La furia sigue ahí, atascada.'}
      ]
    },
    focusActions:[
      {label:'Le propongo hablar luego con calma',type:'cambiar',charReaction:{emotion:'confianza',level:2},consequence:'Le propones hablar luego con calma. Tu hermano acepta. Ahora piensas en cómo plantearlo.'},
      {label:'Me voy a mi cuarto a calmarme',type:'quedarse',charReaction:null,consequence:'Te vas a tu cuarto a calmarte. La emoción se queda contigo, pero en un espacio más tranquilo.'},
      {label:'Pienso cómo decírselo sin gritar',type:'cambiar',charReaction:null,consequence:'Piensas cómo decírselo sin gritar. Las ideas se ordenan y la cabeza se te despeja.'}
    ]
  },
  {
    id:'casa_salir', title:'En casa: tus padres no te dejan salir el sábado',
    context:'Tus padres te dicen que no puedes salir el sábado con tus amigos.',
    situationLevels:{
      3:'La conversación con tus padres ha terminado mal. La tensión en casa es muy alta.',
      2:'La conversación con tus padres ha terminado. La tristeza sigue presente.',
      1:'La conversación con tus padres ha terminado. Puedes pensar con más claridad.'
    },
    origin:{emotion:'tristeza',level:2},
    targetMain:{emotion:'tristeza',level:1},
    targetAlt:{emotion:'sorpresa',level:1},
    contiguoEmotion:'sorpresa',
    maxSteps:6,
    characters:[{name:'Tus padres',emotion:'confianza',level:2}],
    actions:{
      subir:[
        {label:'Me encierro en mi cuarto',charReaction:{emotion:'tristeza',level:2},consequence:'Te encierras en tu cuarto. Tus padres se quedan preocupados en el salón. La tristeza sube.'},
        {label:'Les grito',charReaction:{emotion:'tristeza',level:2},consequence:'Les gritas. Tus padres se quedan dolidos y en silencio. La conversación se rompe.'}
      ],
      bajar:[
        {label:'Respiro y les escucho',charReaction:{emotion:'confianza',level:2},consequence:'Respiras y les escuchas. Tus padres te explican sus razones. La tristeza baja.'},
        {label:'Pienso en sus razones',charReaction:{emotion:'confianza',level:2},consequence:'Piensas en sus razones. Entiendes algo más. La tristeza baja un poco.'}
      ],
      mantener:[
        {label:'No digo nada',charReaction:{emotion:'confianza',level:1},consequence:'No dices nada. Tus padres esperan. La tristeza se queda contigo.'}
      ]
    },
    focusActions:[
      {label:'Les pregunto por qué no me dejan',type:'cambiar',charReaction:{emotion:'confianza',level:2},consequence:'Les preguntas por qué no te dejan. Tus padres te lo explican. La tristeza se transforma en curiosidad.'},
      {label:'Me quedo en mi cuarto pero pensando',type:'quedarse',charReaction:null,consequence:'Te quedas en tu cuarto, pero pensando. La tristeza sigue, aunque ya no es tan intensa.'},
      {label:'Les propongo otro plan',type:'cambiar',charReaction:{emotion:'anticipacion',level:1},consequence:'Les propones otro plan. Tus padres lo piensan. Te sorprendes a ti mismo proponiendo.'}
    ]
  },
  {
    id:'amigos_cancela', title:'Con amigos: un amigo cancela el plan a última hora',
    context:'Un amigo te cancela el plan que teníais a última hora. Te quedas sin hacer nada.',
    situationLevels:{
      3:'El plan se ha cancelado y no hay alternativa. La tristeza es muy intensa.',
      2:'El plan se ha cancelado. La tristeza está presente, pero puedes hacer otras cosas.',
      1:'El plan se ha cancelado. Ya puedes pensar en qué hacer sin que la tristeza te bloquee.'
    },
    origin:{emotion:'tristeza',level:2},
    targetMain:{emotion:'tristeza',level:1},
    targetAlt:{emotion:'sorpresa',level:1},
    contiguoEmotion:'sorpresa',
    maxSteps:6,
    characters:[{name:'Tu amigo',emotion:'disgusto',level:2}],
    actions:{
      subir:[
        {label:'Le escribo enfadado',charReaction:{emotion:'ira',level:2},consequence:'Le escribes enfadado. Tu amigo responde a la defensiva. La tristeza se mezcla con rabia.'},
        {label:'Le insulto por mensaje',charReaction:{emotion:'ira',level:3},consequence:'Le insultas por mensaje. Tu amigo no contesta. La tristeza se hace más grande.'}
      ],
      bajar:[
        {label:'Respiro y busco otra cosa que hacer',charReaction:{emotion:'disgusto',level:1},consequence:'Respiras y buscas otra cosa que hacer. Te distraes. La tristeza baja.'},
        {label:'Pienso que le habrá surgido algo',charReaction:{emotion:'disgusto',level:1},consequence:'Piensas que le habrá surgido algo. La tristeza baja un poco.'}
      ],
      mantener:[
        {label:'Me quedo en casa sin hacer nada',charReaction:{emotion:'disgusto',level:2},consequence:'Te quedas en casa sin hacer nada. La tristeza sigue ahí.'}
      ]
    },
    focusActions:[
      {label:'Le pregunto qué ha pasado',type:'cambiar',charReaction:{emotion:'confianza',level:2},consequence:'Le preguntas qué ha pasado. Te contesta. La tristeza se transforma en curiosidad.'},
      {label:'Me quedo en casa pero buscando algo que hacer',type:'quedarse',charReaction:null,consequence:'Te quedas en casa, pero buscas algo que hacer. La tristeza sigue, aunque se hace más llevadera.'},
      {label:'Pienso en proponer otro plan mañana',type:'cambiar',charReaction:{emotion:'anticipacion',level:1},consequence:'Piensas en proponer otro plan mañana. Te animas. La tristeza se transforma en interés.'}
    ]
  },
  {
    id:'ocio_cine', title:'En el cine: alguien habla y no te deja oír',
    context:'Estás en el cine y la persona de al lado habla en voz alta durante la película.',
    situationLevels:{
      3:'La persona de al lado sigue hablando. La irritación es máxima y no puedes concentrarte.',
      2:'La persona de al lado sigue hablando, aunque tú estás más centrado en la película.',
      1:'La persona de al lado ha bajado la voz. Puedes seguir la película.'
    },
    origin:{emotion:'ira',level:2},
    targetMain:{emotion:'ira',level:1},
    targetAlt:{emotion:'anticipacion',level:1},
    contiguoEmotion:'anticipacion',
    maxSteps:6,
    characters:[{name:'La persona de al lado',emotion:'sorpresa',level:2}],
    actions:{
      subir:[
        {label:'Le grito que se calle',charReaction:{emotion:'ira',level:2},consequence:'Le gritas que se calle. La persona te mira sorprendida y la sala entera se gira. La tensión sube.'},
        {label:'Le insulto',charReaction:{emotion:'ira',level:3},consequence:'Le insultas. La persona se levanta. La película se interrumpe. La tensión sube.'}
      ],
      bajar:[
        {label:'Respiro y me concentro en la película',charReaction:{emotion:'sorpresa',level:1},consequence:'Respiras y te concentras en la película. La voz de al lado sigue, pero tú estás más tranquilo.'},
        {label:'Pienso que quizá no se da cuenta',charReaction:{emotion:'sorpresa',level:1},consequence:'Piensas que quizá no se da cuenta. La irritación baja.'}
      ],
      mantener:[
        {label:'Aguanto sin decir nada',charReaction:{emotion:'sorpresa',level:2},consequence:'Aguantas sin decir nada. La persona sigue hablando. La irritación se queda.'}
      ]
    },
    focusActions:[
      {label:'Me cambio de sitio y sigo la película',type:'cambiar',charReaction:null,consequence:'Te cambias de sitio. Encuentras un hueco mejor. La película se disfruta más.'},
      {label:'Me quedo en mi sitio pero concentrado',type:'quedarse',charReaction:null,consequence:'Te quedas en tu sitio, concentrado. La irritación sigue, pero no te impide ver la película.'},
      {label:'Pienso en decírselo al salir',type:'cambiar',charReaction:null,consequence:'Piensas en decírselo al salir. Ahora piensas en cómo abordarlo sin gritar.'}
    ]
  },
  {
    id:'amigos_rien', title:'Con amigos: se ríen de algo que dijiste',
    context:'Estás con amigos y se ríen de algo que has dicho. No sabes si es una broma o se están burlando.',
    situationLevels:{
      3:'Tus amigos siguen riéndose. No sabes si es broma o burla. La tristeza es muy intensa.',
      2:'Tus amigos siguen riéndose. La tristeza está presente, pero puedes pensar con más claridad.',
      1:'Tus amigos han parado de reírse. La tristeza ha bajado y puedes hablar con ellos.'
    },
    origin:{emotion:'tristeza',level:2},
    targetMain:{emotion:'tristeza',level:1},
    targetAlt:{emotion:'sorpresa',level:1},
    contiguoEmotion:'sorpresa',
    maxSteps:6,
    characters:[{name:'Tus amigos',emotion:'alegria',level:2}],
    actions:{
      subir:[
        {label:'Me pongo a llorar',charReaction:{emotion:'sorpresa',level:2},consequence:'Te pones a llorar. Tus amigos se quedan en silencio, sin saber qué hacer. La tristeza sube.'},
        {label:'Me enfado y les grito',charReaction:{emotion:'sorpresa',level:2},consequence:'Te enfadas y les gritas. Tus amigos se sorprenden. La tristeza se mezcla con rabia.'}
      ],
      bajar:[
        {label:'Respiro y pienso que no es para tanto',charReaction:{emotion:'alegria',level:2},consequence:'Respiras y piensas que no es para tanto. La tristeza baja un poco.'},
        {label:'Pienso que es una broma sin mala intención',charReaction:{emotion:'alegria',level:2},consequence:'Piensas que es una broma sin mala intención. Te tranquilizas.'}
      ],
      mantener:[
        {label:'Me quedo callado',charReaction:{emotion:'alegria',level:1},consequence:'Te quedas callado. Tus amigos siguen. La tristeza se queda contigo.'}
      ]
    },
    focusActions:[
      {label:'Les pregunto si es una broma',type:'cambiar',charReaction:{emotion:'confianza',level:2},consequence:'Les preguntas si es una broma. Te dicen que sí, que era sin mala intención. La tristeza se transforma en alivio.'},
      {label:'Me quedo callado pero escuchando',type:'quedarse',charReaction:null,consequence:'Te quedas callado, pero escuchando. La tristeza sigue, aunque ya no te aísla.'},
      {label:'Pienso que no es para tanto y me río',type:'cambiar',charReaction:{emotion:'alegria',level:2},consequence:'Piensas que no es para tanto y te ríes con ellos. La tristeza se transforma en alegría compartida.'}
    ]
  },
  {
    id:'casa_tareas', title:'En casa: las tareas no están repartidas',
    context:'Ves que nadie ha hecho las tareas de la casa y todo está desordenado. Otra vez.',
    situationLevels:{
      3:'La casa está desordenada y nadie ha hecho su parte. La tensión es máxima.',
      2:'La casa sigue desordenada, pero puedes hablar con calma.',
      1:'La casa sigue desordenada, pero estás tranquilo para proponer soluciones.'
    },
    origin:{emotion:'ira',level:2},
    targetMain:{emotion:'ira',level:1},
    targetAlt:{emotion:'anticipacion',level:1},
    contiguoEmotion:'anticipacion',
    maxSteps:6,
    characters:[{name:'Tu familia',emotion:'disgusto',level:2}],
    actions:{
      subir:[
        {label:'Grito y me quejo',charReaction:{emotion:'ira',level:2},consequence:'Gritas y te quejas. Tu familia reacciona a la defensiva. La tensión sube.'},
        {label:'Insulto a todos',charReaction:{emotion:'ira',level:3},consequence:'Insultas a todos. El ambiente se vuelve muy tenso.'}
      ],
      bajar:[
        {label:'Respiro y hablo con calma',charReaction:{emotion:'disgusto',level:1},consequence:'Respiras y hablas con calma. Tu familia escucha. La tensión baja.'},
        {label:'Pienso en cómo repartir mejor',charReaction:{emotion:'disgusto',level:1},consequence:'Piensas en cómo repartir mejor. Las ideas te calman.'}
      ],
      mantener:[
        {label:'No hago nada',charReaction:{emotion:'disgusto',level:2},consequence:'No haces nada. El desorden sigue. La tensión se queda.'}
      ]
    },
    focusActions:[
      {label:'Propongo un reparto de tareas',type:'cambiar',charReaction:{emotion:'confianza',level:2},consequence:'Propones un reparto de tareas. Tu familia lo acepta. La irritación se transforma en interés.'},
      {label:'Hago mi parte sin decir nada',type:'quedarse',charReaction:null,consequence:'Haces tu parte sin decir nada. La irritación sigue, pero al menos avanzas.'},
      {label:'Pienso cómo plantearlo esta noche',type:'cambiar',charReaction:null,consequence:'Piensas cómo plantearlo esta noche. Las ideas se ordenan y la cabeza se te despeja.'}
    ]
  },
  {
    id:'transporte_empuja', title:'En el autobús: alguien te empuja',
    context:'Vas en el autobús lleno y alguien te empuja para pasar. Casi te caes.',
    situationLevels:{
      3:'La persona que te ha empujado sigue cerca. La irritación es máxima.',
      2:'La persona se ha alejado un poco. La irritación está presente, pero puedes pensar.',
      1:'El autobús sigue lleno, pero estás tranquilo.'
    },
    origin:{emotion:'ira',level:2},
    targetMain:{emotion:'ira',level:1},
    targetAlt:{emotion:'anticipacion',level:1},
    contiguoEmotion:'anticipacion',
    maxSteps:6,
    characters:[{name:'La persona que te empuja',emotion:'sorpresa',level:2}],
    actions:{
      subir:[
        {label:'Le empujo también',charReaction:{emotion:'ira',level:2},consequence:'Le empujas también. La persona se gira enfadada. La tensión sube en el autobús.'},
        {label:'Le grito e insulto',charReaction:{emotion:'ira',level:3},consequence:'Le gritas e insultas. La gente del autobús os mira. La tensión sube.'}
      ],
      bajar:[
        {label:'Respiro y me agarro fuerte',charReaction:{emotion:'sorpresa',level:1},consequence:'Respiras y te agarras fuerte. La persona sigue su camino. La tensión baja.'},
        {label:'Pienso que no lo ha hecho a propósito',charReaction:{emotion:'sorpresa',level:1},consequence:'Piensas que no lo ha hecho a propósito. La irritación baja.'}
      ],
      mantener:[
        {label:'Me callo',charReaction:{emotion:'sorpresa',level:2},consequence:'Te callas. La persona se aleja. La irritación se queda contigo.'}
      ]
    },
    focusActions:[
      {label:'Me aparto y busco otro sitio',type:'cambiar',charReaction:null,consequence:'Te apartas y buscas otro sitio. Encuentras un hueco más tranquilo.'},
      {label:'Me quedo donde estoy pero agarrado',type:'quedarse',charReaction:null,consequence:'Te quedas donde estás, agarrado. La irritación sigue, pero no sube.'},
      {label:'Pienso que no ha sido a propósito',type:'cambiar',charReaction:null,consequence:'Piensas que no ha sido a propósito. La irritación se transforma en comprensión.'}
    ]
  },
  {
    id:'clase_grupo', title:'En clase: trabajo en grupo y alguien no hace su parte',
    context:'Estáis haciendo un trabajo en grupo y un compañero no ha hecho su parte. El plazo termina mañana.',
    situationLevels:{
      3:'Tu compañero no ha hecho su parte y el plazo termina mañana. La tensión es máxima.',
      2:'Tu compañero sigue sin hacer su parte, pero puedes hablar con él.',
      1:'Tu compañero escucha. Estás tranquilo para proponer soluciones.'
    },
    origin:{emotion:'ira',level:2},
    targetMain:{emotion:'ira',level:1},
    targetAlt:{emotion:'anticipacion',level:1},
    contiguoEmotion:'anticipacion',
    maxSteps:6,
    characters:[{name:'Tu compañero',emotion:'disgusto',level:2}],
    actions:{
      subir:[
        {label:'Le grito',charReaction:{emotion:'ira',level:2},consequence:'Le gritas. Tu compañero se pone a la defensiva. El grupo se tensa.'},
        {label:'Le insulto',charReaction:{emotion:'ira',level:3},consequence:'Le insultas. Tu compañero se levanta. El trabajo se para.'}
      ],
      bajar:[
        {label:'Respiro y le pregunto qué ha pasado',charReaction:{emotion:'confianza',level:1},consequence:'Respiras y le preguntas qué ha pasado. Te explica que ha tenido un problema. La tensión baja.'},
        {label:'Pienso que quizá ha tenido un problema',charReaction:{emotion:'disgusto',level:1},consequence:'Piensas que quizá ha tenido un problema. La irritación baja.'}
      ],
      mantener:[
        {label:'Lo hago yo todo sin decir nada',charReaction:{emotion:'disgusto',level:2},consequence:'Haces su parte sin decir nada. El trabajo avanza, pero tú estás agotado y molesto.'}
      ]
    },
    focusActions:[
      {label:'Le pregunto qué ha pasado con su parte',type:'cambiar',charReaction:{emotion:'confianza',level:2},consequence:'Le preguntas qué ha pasado. Te lo cuenta. La irritación se transforma en comprensión.'},
      {label:'Hago yo su parte sin decir nada',type:'quedarse',charReaction:null,consequence:'Haces su parte sin decir nada. La irritación sigue, pero el trabajo termina.'},
      {label:'Propongo repartir de nuevo',type:'cambiar',charReaction:{emotion:'anticipacion',level:1},consequence:'Propones repartir de nuevo. Tu compañero acepta. La irritación se transforma en interés.'}
    ]
  }
];

const TECHNIQUES = {
  alta:[
    {name:'Respiración 4-7-8',level:'alta',desc:'Para bajar muy rápido el nivel de activación.',how:'Inspira contando 4. Aguanta contando 7. Espira contando 8. Repite 3 o 4 veces.',when:'Cuando notas el cuerpo muy revolucionado: corazón rápido, puños apretados, calor en la cara.'},
    {name:'Contar hasta 10',level:'alta',desc:'Para darte tiempo antes de reaccionar.',how:'Cuenta despacio, en voz baja o mentalmente. Si hace falta, cuenta hasta 20.',when:'Cuando sientes que vas a decir o hacer algo de lo que luego te arrepentirás.'},
    {name:'Agua fría en la cara o las muñecas',level:'alta',desc:'Para enfriar el cuerpo y la cabeza.',how:'Moja la cara o las muñecas con agua fría. Si no hay agua, aprieta un cubito o una lata fría.',when:'Cuando la emoción es tan fuerte que no puedes pensar con claridad.'},
    {name:'Apretar los puños y soltar',level:'alta',desc:'Para descargar la tensión física.',how:'Aprieta los puños 5 segundos y suelta. Repite 3 veces. Acompaña con una respiración lenta.',when:'Cuando sientes que la rabia o el miedo te tensan los músculos.'},
    {name:'Salir a caminar un momento',level:'alta',desc:'Para cambiar de escenario y bajar el ritmo.',how:'Levanta el brazo y pide permiso para salir un momento. Camina 5 minutos. Vuelve cuando estés más tranquilo.',when:'Cuando el ambiente está muy caliente y necesitas distancia.'}
  ],
  media:[
    {name:'Decir "necesito un momento"',level:'media',desc:'Para ganar tiempo sin huir.',how:'Di con calma: "Necesito un momento, ahora vuelvo". Y cúmplelo: vuelve en pocos minutos.',when:'Cuando estás en nivel 2 y no quieres que la situación escale.'},
    {name:'Escribir lo que sientes',level:'media',desc:'Para ordenar la cabeza y descargar.',how:'Escribe 3 o 4 frases en una libreta o en el móvil: qué ha pasado, qué has sentido y qué te gustaría hacer.',when:'Cuando la emoción te da vueltas en la cabeza y no te deja pensar.'},
    {name:'Hablar con alguien de confianza',level:'media',desc:'Para no estar solo con la emoción.',how:'Cuéntale a alguien de confianza lo que te ha pasado y cómo te sientes. No hace falta que te dé la razón; solo que te escuche.',when:'Cuando la emoción se hace grande y necesitas apoyo.'},
    {name:'Pensar "esto pasará"',level:'media',desc:'Para relativizar sin negar lo que sientes.',how:'Dite a ti mismo: "Esto es desagradable, pero pasará. Ya me ha pasado otras veces y lo he superado".',when:'Cuando sientes que la emoción va a durar siempre.'}
  ],
  baja:[
    {name:'Escuchar música',level:'baja',desc:'Para cambiar el ánimo de fondo.',how:'Ponte una canción que te guste. Si puedes, elige una que vaya con cómo quieres sentirte, no con cómo te sientes ahora.',when:'Cuando estás en nivel 1 y quieres terminar de regularte.'},
    {name:'Cambiar de tarea',level:'baja',desc:'Para salir del bucle de pensamiento.',how:'Deja lo que estás haciendo y haz otra cosa 10 minutos: ordenar, dibujar, caminar, llamar a alguien.',when:'Cuando notes que le estás dando vueltas a lo mismo.'},
    {name:'Visualizar un lugar seguro',level:'baja',desc:'Para relajarte y darte calma.',how:'Cierra los ojos e imagina un lugar donde te sientas bien. Fíjate en los detalles: colores, sonidos, olores. Quédate ahí un minuto.',when:'Cuando necesitas un respiro mental sin moverte del sitio.'}
  ]
};

function normalize(text){return text.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g,'').replace(/[^a-z0-9\s]/g,' ').replace(/\s+/g,' ').trim();}
function levenshtein(a,b){const m=a.length,n=b.length;const dp=Array.from({length:m+1},()=>Array(n+1).fill(0));for(let i=0;i<=m;i++)dp[i][0]=i;for(let j=0;j<=n;j++)dp[0][j]=j;for(let i=1;i<=m;i++)for(let j=1;j<=n;j++){dp[i][j]=Math.min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i-1][j-1]+(a[i-1]===b[j-1]?0:1));}return dp[m][n];}

function matchLexicon(text, lexicon){
  const normText = normalize(text);
  const words = normText.split(' ');
  const scores = {};
  for (const [outcome, keywords] of Object.entries(lexicon)) {
    scores[outcome] = 0;
    for (const kw of keywords) {
      const nkw = normalize(kw);
      if (!nkw) continue;
      let matched = false;
      if (normText.includes(nkw)) { scores[outcome] += 1; matched = true; }
      else if (nkw.length >= 4) {
        const root = nkw.slice(0, Math.min(5, nkw.length));
        if (normText.includes(root)) { scores[outcome] += 0.5; matched = true; }
      }
      if (!matched) {
        for (const w of words) {
          if (w.length > 2 && Math.abs(w.length - nkw.length) <= 2 && levenshtein(w, nkw) <= 1) {
            scores[outcome] += 0.5;
            break;
          }
        }
      }
    }
  }
  let best = null, bestScore = 0;
  for (const [outcome, score] of Object.entries(scores)) {
    if (score > bestScore) { bestScore = score; best = outcome; }
  }
  return bestScore > 0 ? best : null;
}

function analyzeText(text, scenario){
  const sc = matchLexicon(text, scenario.lexicon);
  const base = matchLexicon(text, BASE_LEXICON);
  if (!sc && !base) return null;
  if (!sc) return base;
  if (!base) return sc;
  const scNorm = sc === 'escalar' ? 'escalar' : sc === 'desescalar' ? 'desescalar' : sc === 'mantener' ? 'mantener' : 'contiguo';
  if (scNorm === base) return sc;
  return sc;
}

function lighten(hex, percent){
  const num = parseInt(hex.slice(1),16);
  const r = (num>>16)&0xff, g = (num>>8)&0xff, b = num&0xff;
  const nr = Math.round(r+(255-r)*percent), ng = Math.round(g+(255-g)*percent), nb = Math.round(b+(255-b)*percent);
  return '#'+((1<<24)+(nr<<16)+(ng<<8)+nb).toString(16).slice(1);
}

function annularSector(cx,cy,r1,r2,startAngle,endAngle){
  const rad = Math.PI/180;
  const x1=cx+r1*Math.cos(startAngle*rad), y1=cy+r1*Math.sin(startAngle*rad);
  const x2=cx+r2*Math.cos(startAngle*rad), y2=cy+r2*Math.sin(startAngle*rad);
  const x3=cx+r2*Math.cos(endAngle*rad), y3=cy+r2*Math.sin(endAngle*rad);
  const x4=cx+r1*Math.cos(endAngle*rad), y4=cy+r1*Math.sin(endAngle*rad);
  const largeArc = (endAngle-startAngle)>180?1:0;
  return `M ${x1} ${y1} L ${x2} ${y2} A ${r2} ${r2} 0 ${largeArc} 1 ${x3} ${y3} L ${x4} ${y4} A ${r1} ${r1} 0 ${largeArc} 0 ${x1} ${y1} Z`;
}

function drawFlower(container, size, showMarker, showLabels=true, labelEmotions=null){
  const ns = 'http://www.w3.org/2000/svg';
  const svg = document.createElementNS(ns,'svg');
  svg.setAttribute('viewBox','0 0 500 500');
  svg.setAttribute('width',size); svg.setAttribute('height',size); svg.style.maxWidth='100%';
  const cx=250, cy=250;
  const rings=[{level:3,r1:30,r2:90},{level:2,r1:90,r2:160},{level:1,r1:160,r2:230}];
  EMOTION_ORDER.forEach((emo,i)=>{
    const centerAngle = -90 + i*45;
    const start = centerAngle - 22.5, end = centerAngle + 22.5;
    const color = EMOTIONS[emo].color;
    rings.forEach(ring=>{
      const path = document.createElementNS(ns,'path');
      path.setAttribute('d', annularSector(cx,cy,ring.r1,ring.r2,start,end));
      const lightness = ring.level===3?0:ring.level===2?0.35:0.6;
      path.setAttribute('fill', lighten(color, lightness));
      path.setAttribute('stroke','#fff'); path.setAttribute('stroke-width','1.5');
      path.setAttribute('data-emotion',emo); path.setAttribute('data-level',ring.level);
      path.style.cursor='pointer';
      path.addEventListener('click',()=>showEmotionInfo(emo,ring.level));
      svg.appendChild(path);
    });
  });
  const center = document.createElementNS(ns,'circle');
  center.setAttribute('cx',cx); center.setAttribute('cy',cy); center.setAttribute('r','30');
  center.setAttribute('fill','#f4f7fb'); center.setAttribute('stroke','#fff'); center.setAttribute('stroke-width','2');
  svg.appendChild(center);
  if (showLabels) {
    const labelRings = [{level:3,r:60,fontSize:9,weight:'normal'},{level:2,r:125,fontSize:11,weight:'bold'},{level:1,r:195,fontSize:9,weight:'normal'}];
    EMOTION_ORDER.forEach((emo,i)=>{
      if (labelEmotions && !labelEmotions.includes(emo)) return;
      const angle = -90 + i*45;
      const rad = angle*Math.PI/180;
      const e = EMOTIONS[emo];
      labelRings.forEach(lr=>{
        const x = cx + lr.r*Math.cos(rad), y = cy + lr.r*Math.sin(rad);
        let rotation = angle;
        if (angle > 90 || angle < -90) rotation += 180;
        const text = document.createElementNS(ns,'text');
        text.setAttribute('x',x); text.setAttribute('y',y);
        text.setAttribute('text-anchor','middle'); text.setAttribute('dominant-baseline','middle');
        text.setAttribute('fill','#fff'); text.setAttribute('stroke','#1a1a1a');
        text.setAttribute('stroke-width','2'); text.setAttribute('stroke-linejoin','round');
        text.setAttribute('paint-order','stroke');
        text.setAttribute('font-size',lr.fontSize); text.setAttribute('font-weight',lr.weight);
        text.setAttribute('transform',`rotate(${rotation}, ${x}, ${y})`);
        text.textContent = e.levels[lr.level-1];
        text.style.pointerEvents='none';
        svg.appendChild(text);
      });
    });
  }
  if (showMarker) {
    const marker = document.createElementNS(ns,'circle');
    marker.setAttribute('id','marker'); marker.setAttribute('r','10');
    marker.setAttribute('fill','#111'); marker.setAttribute('stroke','#fff'); marker.setAttribute('stroke-width','3');
    marker.style.pointerEvents='none';
    svg.appendChild(marker);
  }
  container.innerHTML=''; container.appendChild(svg);
  return svg;
}

function updateMarker(svg, emotion, level){
  const marker = svg.querySelector('#marker');
  if (!marker) return;
  const idx = EMOTION_ORDER.indexOf(emotion);
  const angle = (-90 + idx*45)*Math.PI/180;
  let radius;
  if (level===3) radius=60; else if (level===2) radius=125; else radius=195;
  const offset = 24;
  const perpAngle = angle + Math.PI/2;
  const x = 250 + radius*Math.cos(angle) + offset*Math.cos(perpAngle);
  const y = 250 + radius*Math.sin(angle) + offset*Math.sin(perpAngle);
  marker.setAttribute('cx',x); marker.setAttribute('cy',y);
}

function showEmotionInfo(emotion, level){
  const e = EMOTIONS[emotion];
  const levelName = e.levels[level-1];
  const intensityText = level===3?'Alta intensidad':level===2?'Intensidad media':'Baja intensidad';
  const dyads = [];
  EMOTION_ORDER.forEach(other=>{
    if (other===emotion) return;
    const dyad = DYADS[emotion+'+'+other] || DYADS[other+'+'+emotion];
    if (dyad) dyads.push(`${dyad.name} (con ${EMOTIONS[other].name})`);
  });
  document.getElementById('explorerInfo').innerHTML = `
    <h3 style="margin-top:0;color:${e.color}">${e.name} · ${levelName}</h3>
    <p><strong>${intensityText}</strong></p>
    <p>${e.def}</p>
    <p><strong>Emoción opuesta:</strong> ${EMOTIONS[e.opposite].name}</p>
    <p><strong>Combinaciones:</strong> ${dyads.length?dyads.join(', '):'Ninguna díada primaria'}</p>
  `;
}

function initConstructor(){
  const sel1 = document.getElementById('emo1'), sel2 = document.getElementById('emo2');
  sel1.innerHTML = EMOTION_ORDER.map(e=>`<option value="${e}">${EMOTIONS[e].name}</option>`).join('');
  function getPartners(emotion){
    return EMOTION_ORDER.filter(other=>other!==emotion && (DYADS[emotion+'+'+other] || DYADS[other+'+'+emotion]));
  }
  function updateSecond(){
    const first = sel1.value;
    const partners = getPartners(first);
    sel2.innerHTML = partners.map(p=>`<option value="${p}">${EMOTIONS[p].name}</option>`).join('');
    if (partners.length>0) sel2.value = partners[0];
    updateDyad();
  }
  function updateDyad(){
    const a=sel1.value, b=sel2.value;
    const result = document.getElementById('dyadResult');
    if (!a||!b||a===b){ result.innerHTML='<p>Elige dos emociones diferentes.</p>'; return; }
    const dyad = DYADS[a+'+'+b] || DYADS[b+'+'+a];
    if (dyad) result.innerHTML = `<h3 style="margin-top:0;">${dyad.name}</h3><p>${dyad.desc}</p><p><strong>${EMOTIONS[a].name} + ${EMOTIONS[b].name} = ${dyad.name}</strong></p>`;
    else result.innerHTML = `<p>${EMOTIONS[a].name} y ${EMOTIONS[b].name} no forman una díada primaria en este modelo.</p>`;
  }
  sel1.addEventListener('change',updateSecond);
  sel2.addEventListener('change',updateDyad);
  updateSecond();
}

function getRecords(){try{return JSON.parse(localStorage.getItem('plutchik_records')||'[]');}catch{return[];}}
function saveRecords(records){localStorage.setItem('plutchik_records',JSON.stringify(records));}
function renderRecords(){
  const records = getRecords();
  const list = document.getElementById('recordsList');
  const chart = document.getElementById('comparisonChart');
  if (records.length===0){
    list.innerHTML='<p>No hay registros todavía.</p>';
    chart.innerHTML='<p>Guarda algún registro para ver la comparación.</p>';
    return;
  }
  list.innerHTML = records.slice().reverse().map(r=>{
    const e = EMOTIONS[r.emotion];
    const levelName = e.levels[r.level-1];
    return `<div class="badge" style="display:flex;justify-content:space-between;width:100%;margin:0.3rem 0;">
      <span><span class="dot" style="background:${e.color}"></span> <strong>${e.name}</strong> · ${levelName}</span>
      <span style="color:var(--muted);font-size:0.85rem;">${r.date}</span>
    </div>${r.note?`<p style="margin:0.2rem 0 0.5rem 1.5rem;font-size:0.9rem;color:var(--muted);">${r.note}</p>`:''}`;
  }).join('');
  const counts={}, sums={};
  EMOTION_ORDER.forEach(e=>{counts[e]=0;sums[e]=0;});
  records.forEach(r=>{if(counts[r.emotion]!==undefined){counts[r.emotion]++;sums[r.emotion]+=r.level;}});
  const maxCount = Math.max(1,...Object.values(counts));
  chart.innerHTML = '<div class="bar-chart">' + EMOTION_ORDER.map(e=>{
    const c=counts[e]; const avg = c?(sums[e]/c).toFixed(1):'0'; const width=(c/maxCount)*100;
    return `<div class="bar-row"><div class="bar-label">${EMOTIONS[e].name}</div><div class="bar-track"><div class="bar-fill" style="width:${width}%;background:${EMOTIONS[e].color};"></div></div><div class="bar-value">${c} (${avg})</div></div>`;
  }).join('') + '</div><p style="font-size:0.9rem;color:var(--muted);">Número de registros (y media de intensidad 1-3).</p>';
}
function initThermometer(){
  const sel = document.getElementById('thermoEmotion');
  sel.innerHTML = EMOTION_ORDER.map(e=>`<option value="${e}">${EMOTIONS[e].name}</option>`).join('');
  document.getElementById('saveRecord').addEventListener('click',()=>{
    const emotion = sel.value;
    const level = parseInt(document.getElementById('thermoLevel').value,10);
    const note = document.getElementById('thermoNote').value.trim();
    const date = new Date().toLocaleString('es-ES',{day:'2-digit',month:'2-digit',year:'numeric',hour:'2-digit',minute:'2-digit'});
    const records = getRecords();
    records.push({emotion,level,note,date});
    saveRecords(records);
    document.getElementById('thermoNote').value='';
    renderRecords();
  });
  renderRecords();
}

function initTechniques(){
  const card = t => `<div class="tech-card">
    <span class="tech-level ${t.level}">Intensidad ${t.level}</span>
    <h3>${t.name}</h3>
    <p><strong>Para qué sirve:</strong> ${t.desc}</p>
    <p><strong>Cómo se hace:</strong> ${t.how}</p>
    <p><strong>Cuándo usarla:</strong> ${t.when}</p>
  </div>`;
  document.getElementById('techAlta').innerHTML = TECHNIQUES.alta.map(card).join('');
  document.getElementById('techMedia').innerHTML = TECHNIQUES.media.map(card).join('');
  document.getElementById('techBaja').innerHTML = TECHNIQUES.baja.map(card).join('');
}

let journey = null;

function initScenarios(){
  const list = document.getElementById('scenarioList');
  list.innerHTML = SCENARIOS.map(s=>`
    <div class="journey-card" data-id="${s.id}">
      <h3>${s.title}</h3>
      <p>${s.context}</p>
      <p style="margin-top:0.5rem;font-size:0.85rem;color:var(--muted);">Desde ${EMOTIONS[s.origin.emotion].name} (${EMOTIONS[s.origin.emotion].levels[s.origin.level-1]}) hasta ${EMOTIONS[s.targetMain.emotion].name} (${EMOTIONS[s.targetMain.emotion].levels[s.targetMain.level-1]}) o ${EMOTIONS[s.targetAlt.emotion].name} (${EMOTIONS[s.targetAlt.emotion].levels[s.targetAlt.level-1]})</p>
    </div>`).join('');
  list.querySelectorAll('.journey-card').forEach(card=>card.addEventListener('click',()=>startJourney(card.dataset.id)));
}

function startJourney(id){
  const scenario = SCENARIOS.find(s=>s.id===id);
  if (!scenario) return;
  journey = {
    scenario,
    currentNode:{...scenario.origin},
    characters: scenario.characters.map(c=>({...c})),
    phase:'intensity',
    step:0,
    maxSteps: scenario.maxSteps||6,
    log:[],
    finished:false,
    endReason:null
  };
  document.getElementById('journeyList').style.display='none';
  document.getElementById('journeyActive').style.display='block';
  renderJourney();
}

function endJourney(){
  journey = null;
  document.getElementById('journeyList').style.display='block';
  document.getElementById('journeyActive').style.display='none';
  document.getElementById('journeyActive').innerHTML='';
}

function getCurrentSituation(j){
  const s = j.scenario;
  if (j.step===0) return s.context;
  const e = EMOTIONS[j.currentNode.emotion];
  const ln = e.levels[j.currentNode.level-1];
  const char = j.characters[0];
  const charE = EMOTIONS[char.emotion];
  const charLn = charE.levels[char.level-1];
  if (j.currentNode.emotion===s.contiguoEmotion) {
    return `Has cambiado de enfoque. Ahora estás en ${e.name} · ${ln}. ${char.name} está en ${charE.name} · ${charLn}. La situación ha tomado otro rumbo.`;
  }
  const worldDesc = (s.situationLevels && s.situationLevels[j.currentNode.level]) || '';
  return `${worldDesc} Tú estás en ${e.name} · ${ln}. ${char.name} está en ${charE.name} · ${charLn}.`;
}

function logEntryHtml(entry){
  const e = EMOTIONS[entry.result.emotion];
  const ln = e.levels[entry.result.level-1];
  const tag = entry.type==='focus' ? (entry.focusType==='cambiar' ? ' <em style="color:var(--accent);font-size:0.85rem;">[cambio de enfoque]</em>' : ' <em style="color:var(--muted);font-size:0.85rem;">[te quedas]</em>') : '';
  const consequence = entry.consequence ? `<p class="log-consequence">${entry.consequence}</p>` : '';
  let charLine = '';
  if (entry.charResult) {
    const ce = EMOTIONS[entry.charResult.emotion];
    const cln = ce.levels[entry.charResult.level-1];
    charLine = `<p class="log-result"><span class="badge"><span class="dot" style="background:${ce.color}"></span>Personaje: ${ce.name} · ${cln}</span></p>`;
  }
  return `<div class="log-entry">
    <p class="log-action">${entry.action}${tag}</p>
    ${consequence}
    <p class="log-result"><span class="badge"><span class="dot" style="background:${e.color}"></span>Tú: ${e.name} · ${ln}</span></p>
    ${charLine}
  </div>`;
}

function applyCharReaction(charReaction){
  if (!charReaction) return null;
  journey.characters.forEach(c=>{
    c.emotion = charReaction.emotion;
    c.level = charReaction.level;
  });
  return {...charReaction};
}

function applyIntensityAction(actionType, actionLabel, charReaction, consequence){
  if (actionType==='subir') journey.currentNode.level = Math.min(3, journey.currentNode.level+1);
  else if (actionType==='bajar') journey.currentNode.level = Math.max(1, journey.currentNode.level-1);
  const charResult = applyCharReaction(charReaction);
  journey.log.push({
    type:'intensity',
    action: actionLabel||'Acción',
    consequence: consequence||'',
    result:{...journey.currentNode},
    charResult
  });
  if (journey.currentNode.level<=2) journey.phase='focus';
  else advanceStep();
  renderJourney();
}

function applyFocus(focusType, actionLabel, charReaction, consequence){
  if (focusType==='cambiar') {
    journey.currentNode.emotion = journey.scenario.contiguoEmotion;
    journey.currentNode.level = Math.max(1, journey.currentNode.level-1);
  }
  const charResult = applyCharReaction(charReaction);
  journey.log.push({
    type:'focus',
    focusType,
    action: actionLabel,
    consequence: consequence||'',
    result:{...journey.currentNode},
    charResult
  });
  advanceStep();
  renderJourney();
}

function advanceStep(){
  journey.step++;
  const c = journey.currentNode;
  const tm = journey.scenario.targetMain;
  const ta = journey.scenario.targetAlt;
  if (c.emotion===tm.emotion && c.level===tm.level){ journey.finished=true; journey.endReason='main'; journey.phase='finished'; return; }
  if (c.emotion===ta.emotion && c.level===ta.level){ journey.finished=true; journey.endReason='alt'; journey.phase='finished'; return; }
  if (journey.step>=journey.maxSteps){ journey.finished=true; journey.endReason='maxSteps'; journey.phase='finished'; return; }
  journey.phase='intensity';
}

function renderIntensityPhase(s, j){
  const buttons = [];
  ['subir','bajar','mantener'].forEach(type=>{
    s.actions[type].forEach((a,i)=>{
      buttons.push(`<button class="secondary action-btn" data-type="${type}" data-index="${i}">${a.label}</button>`);
    });
  });
  return `
    <p>¿Qué haces?</p>
    <div class="quick-actions">${buttons.join('')}</div>
    <p style="font-size:0.9rem;color:var(--muted);">O escribe lo que harías:</p>
    <textarea id="journeyInput" placeholder="Escribe lo que harías o dirías..."></textarea>
    <button class="primary" id="journeySubmit" style="margin-top:0.5rem;">Enviar respuesta</button>
    <div id="fallbackArea" class="fallback" style="display:none;">
      <p>No estoy seguro de cómo encaja eso. ¿Qué tipo de acción describes?</p>
      <div class="quick-actions">
        <button class="secondary fallback-btn" data-type="subir">Aumenta mi emoción</button>
        <button class="secondary fallback-btn" data-type="bajar">Reduce mi emoción</button>
        <button class="secondary fallback-btn" data-type="mantener">Se mantiene igual</button>
      </div>
    </div>`;
}

function renderFocusPhase(s, j){
  const buttons = s.focusActions.map((a,i)=>{
    const hint = a.type==='cambiar' ? ' (cambia de enfoque)' : ' (te quedas)';
    return `<button class="secondary focus-btn" data-index="${i}">${a.label}<span style="font-weight:normal;color:var(--muted);font-size:0.85rem;">${hint}</span></button>`;
  }).join('');
  return `
    <p>Ya estás más tranquilo (nivel ${j.currentNode.level}). ¿Qué haces ahora?</p>
    <div class="quick-actions">${buttons}</div>
    <p style="font-size:0.9rem;color:var(--muted);">Las acciones que dicen "cambia de enfoque" te llevan a otra emoción parecida y bajan un poco más la intensidad. Las que dicen "te quedas" mantienen la emoción actual.</p>`;
}

function renderSummary(container, j){
  const s = j.scenario;
  const finalEmo = EMOTIONS[j.currentNode.emotion];
  const finalLevel = finalEmo.levels[j.currentNode.level-1];
  let title, message;
  if (j.endReason==='main'){ title='¡Has llegado al objetivo principal!'; message='Has recorrido el camino de vuelta paso a paso, bajando la intensidad hasta '+finalEmo.name+' · '+finalLevel+'.'; }
  else if (j.endReason==='alt'){ title='¡Has llegado al objetivo alternativo!'; message='Has cambiado de enfoque con una acción concreta y has llegado a '+finalEmo.name+' · '+finalLevel+'. Es otra forma válida de regular la emoción.'; }
  else { title='Fin del recorrido'; message='No has llegado al objetivo en los pasos disponibles. Puedes intentarlo de nuevo eligiendo acciones que bajen la intensidad poco a poco.'; }
  const charFinal = j.characters.map(c=>{
    const e = EMOTIONS[c.emotion];
    return `${c.name}: ${e.name} · ${e.levels[c.level-1]}`;
  }).join('<br>');
  container.innerHTML = `
    <div class="card">
      <h2>Resumen del viaje: ${s.title}</h2>
      <div class="summary">
        <h3>${title}</h3>
        <p>${message}</p>
        <p><strong>Emoción final:</strong> ${finalEmo.name} · ${finalLevel}</p>
        <p><strong>Objetivo principal:</strong> ${EMOTIONS[s.targetMain.emotion].name} · ${EMOTIONS[s.targetMain.emotion].levels[s.targetMain.level-1]}</p>
        <p><strong>Objetivo alternativo:</strong> ${EMOTIONS[s.targetAlt.emotion].name} · ${EMOTIONS[s.targetAlt.emotion].levels[s.targetAlt.level-1]}</p>
        <h3 style="margin-top:1rem;">Lo que ha pasado paso a paso</h3>
        <div class="log">${j.log.map(logEntryHtml).join('')}</div>
        <p><strong>Situación final:</strong> ${getCurrentSituation(j)}</p>
        <p><strong>Estado final de los personajes:</strong><br>${charFinal}</p>
        <p><em>Piensa en una situación de tu vida real parecida a esta. ¿Qué harías? ¿Qué técnica de la pestaña "Técnicas" probarías?</em></p>
      </div>
      <button class="primary" onclick="endJourney()" style="margin-top:1rem;">Volver a los recorridos</button>
    </div>`;
}

function renderJourney(){
  const container = document.getElementById('journeyActive');
  const j = journey;
  if (!j){ container.innerHTML=''; return; }
  if (j.phase==='finished'){ renderSummary(container,j); return; }
  const s = j.scenario;
  const curEmo = EMOTIONS[j.currentNode.emotion];
  const curLevelName = curEmo.levels[j.currentNode.level-1];
  const charBadges = j.characters.map(c=>{
    const e = EMOTIONS[c.emotion];
    const ln = e.levels[c.level-1];
    return `<span class="badge"><span class="dot" style="background:${e.color}"></span>${c.name}: ${e.name} · ${ln}</span>`;
  }).join('');
  let phaseContent = '';
  if (j.phase==='intensity') phaseContent = renderIntensityPhase(s,j);
  else if (j.phase==='focus') phaseContent = renderFocusPhase(s,j);
  const situation = getCurrentSituation(j);
  container.innerHTML = `
    <div class="card">
      <div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:0.5rem;">
        <h2 style="margin:0;">${s.title}</h2>
        <span class="progress">Paso ${j.step+1} de ${j.maxSteps}</span>
      </div>
      <div class="situation-panel">
        <p class="situation-label">Situación actual</p>
        <p>${situation}</p>
      </div>
      <div class="flower-container" id="journeyFlower"></div>
      <div style="margin:0.5rem 0;">${charBadges}</div>
      <p><strong>Ahora sientes: ${curEmo.name} · ${curLevelName}.</strong></p>
      ${phaseContent}
      <h3 style="margin-top:1.5rem;">Lo que ha pasado hasta ahora</h3>
      <div class="log" id="journeyLog">
        ${j.log.length?j.log.map(logEntryHtml).join(''):'<p style="color:var(--muted);">La situación acaba de empezar. Elige tu primera acción.</p>'}
      </div>
      <button class="secondary" onclick="endJourney()" style="margin-top:1rem;">Abandonar recorrido</button>
    </div>`;
  const svg = drawFlower(document.getElementById('journeyFlower'),380,true,true,[j.currentNode.emotion,s.contiguoEmotion]);
  updateMarker(svg,j.currentNode.emotion,j.currentNode.level);
  if (j.phase==='intensity') {
    document.querySelectorAll('.action-btn').forEach(btn=>{
      btn.addEventListener('click',()=>{
        const type = btn.dataset.type;
        const index = parseInt(btn.dataset.index);
        const action = s.actions[type][index];
        applyIntensityAction(type, action.label, action.charReaction||null, action.consequence||'');
      });
    });
    document.getElementById('journeySubmit').addEventListener('click',()=>{
      const text = document.getElementById('journeyInput').value.trim();
      if (!text){ alert('Escribe algo o elige una acción.'); return; }
      let outcome = analyzeText(text,s);
      if (!outcome){ document.getElementById('fallbackArea').style.display='block'; return; }
      if (outcome==='contiguo') outcome='desescalar';
      const type = outcome==='escalar'?'subir':outcome==='desescalar'?'bajar':'mantener';
      const template = s.actions[type][0];
      const charReaction = template ? (template.charReaction||null) : null;
      let charDesc = '';
      if (charReaction) {
        const ce = EMOTIONS[charReaction.emotion];
        charDesc = ` ${j.characters[0].name} reacciona: ${ce.name} · ${ce.levels[charReaction.level-1]}.`;
      }
      const consequence = `Has escrito: "${text}".${charDesc}`;
      applyIntensityAction(type, '"'+text+'"', charReaction, consequence);
    });
    document.querySelectorAll('.fallback-btn').forEach(btn=>{
      btn.addEventListener('click',()=>{
        document.getElementById('fallbackArea').style.display='none';
        const type = btn.dataset.type;
        const text = document.getElementById('journeyInput').value.trim();
        const template = s.actions[type][0];
        const charReaction = template ? (template.charReaction||null) : null;
        let charDesc = '';
        if (charReaction) {
          const ce = EMOTIONS[charReaction.emotion];
          charDesc = ` ${j.characters[0].name} reacciona: ${ce.name} · ${ce.levels[charReaction.level-1]}.`;
        }
        const consequence = `Has escrito: "${text}".${charDesc}`;
        applyIntensityAction(type, '"'+text+'"', charReaction, consequence);
      });
    });
  } else if (j.phase==='focus') {
    document.querySelectorAll('.focus-btn').forEach(btn=>{
      btn.addEventListener('click',()=>{
        const index = parseInt(btn.dataset.index);
        const fa = s.focusActions[index];
        applyFocus(fa.type, fa.label, fa.charReaction||null, fa.consequence||'');
      });
    });
  }
  const logDiv = document.getElementById('journeyLog');
  if (logDiv) logDiv.scrollTop = logDiv.scrollHeight;
}

function switchTab(tabId){
  document.querySelectorAll('.tab-pane').forEach(p=>p.classList.remove('active'));
  document.querySelectorAll('#tabs button').forEach(b=>b.classList.remove('active'));
  const pane = document.getElementById(tabId);
  if (pane) pane.classList.add('active');
  const btn = document.querySelector(`#tabs button[data-tab="${tabId}"]`);
  if (btn) btn.classList.add('active');
  if (tabId==='explorador') {
    if (!document.querySelector('#flowerExplorer svg')) drawFlower(document.getElementById('flowerExplorer'),500,false);
  }
  if (tabId==='recorridos') {
    if (!journey) {
      document.getElementById('journeyList').style.display='block';
      document.getElementById('journeyActive').style.display='none';
    }
  }
}

document.addEventListener('DOMContentLoaded',()=>{
  document.querySelectorAll('#tabs button').forEach(btn=>btn.addEventListener('click',()=>switchTab(btn.dataset.tab)));
  drawFlower(document.getElementById('flowerExplorer'),500,false);
  initConstructor();
  initThermometer();
  initScenarios();
  initTechniques();
  window.switchTab = switchTab;
  window.endJourney = endJourney;
});
</script>
</body>
</html>