// game.jsx — interactive prediction game for SIATA forecast.
// 5 screens: Welcome → Round 1 (blind) → Round 2 (ingredients) →
// Round 3 (decisions on 72h forecast) → Round 4 (why it matters).

const STEPS = [
  'Bienvenida',
  'N1 · Las fuentes',
  'N2 · Significados',
  'N3 · Matemáticas',
  'N4 · Comprensión',
  'N5a · A ciegas',
  'N5b · Suma datos',
  'N5c · Decide',
  'N5d · Cierre',
];

// ───────────────────────────────────────────────────────────────
// ROUND 1 — BLIND GUESS
// ───────────────────────────────────────────────────────────────
function RoundBlind({onNext, store, setStore}){
  const [guess, setGuess] = React.useState(store.guess1 ?? 25);
  const [submitted, setSubmitted] = React.useState(store.guess1 != null);
  const real = 38;           // "ground truth" for the round
  const diff = Math.abs(guess - real);
  const score = Math.max(0, Math.round(100 - diff*3));

  return (
    <div style={{maxWidth:1080, margin:'0 auto', padding:'56px 40px'}}>
      <ScreenHead
        kicker="Ronda 1 · adivina a ciegas"
        title="¿Qué tan contaminado estará el aire mañana?"
        sub="Hoy es viernes en Medellín. Mañana sábado. Sin mirar nada — ni sensores, ni satélites, ni meteorología — arrastra el deslizador hasta el valor que crees que tendrá el PM2.5 al mediodía."
      />

      <Card style={{maxWidth:880, margin:'0 auto'}}>
        {/* Big number readout */}
        <div style={{textAlign:'center'}}>
          <div style={{
            fontFamily:'var(--mono)', fontSize:13, color:'var(--gray)',
            letterSpacing:'0.24em', textTransform:'uppercase',
          }}>Tu predicción · PM2.5 μg/m³</div>
          <div style={{
            fontSize:180, fontWeight:800, lineHeight:1,
            color: pmColor(guess), marginTop:14,
            textShadow:'0 8px 40px ' + pmColor(guess) + '55',
            fontVariantNumeric:'tabular-nums',
            letterSpacing:'-0.04em',
          }}>
            <AnimNum value={guess} duration={120} />
          </div>
          <div style={{
            fontSize:22, color:'var(--gray)', marginTop:14,
            display:'flex', alignItems:'center', justifyContent:'center', gap:12,
          }}>
            <span style={{fontSize:36}}>{pmEmoji(guess)}</span>
            <span>Aire <strong style={{color:pmColor(guess), fontWeight:700}}>{pmLabel(guess)}</strong></span>
          </div>
        </div>

        {/* Slider */}
        <div style={{marginTop:40}}>
          <input type="range" className="pm-slider"
            min={2} max={80} step={1} value={guess}
            disabled={submitted}
            onChange={e=> setGuess(Number(e.target.value))} />
          <div style={{marginTop:18}}>
            <PMScale value={guess} />
          </div>
        </div>

        {/* CTA / Reveal */}
        {!submitted ? (
          <div style={{marginTop:40, textAlign:'center'}}>
            <PrimaryBtn onClick={()=>{
              setStore({...store, guess1:guess});
              setSubmitted(true);
            }}>Confirmar mi predicción →</PrimaryBtn>
            <div style={{
              marginTop:18, fontSize:13, color:'var(--dim)',
              fontFamily:'var(--mono)', letterSpacing:'0.16em', textTransform:'uppercase',
            }}>Una vez confirmes, te muestro lo que pasó realmente</div>
          </div>
        ) : (
          <Reveal guess={guess} real={real} score={score} onNext={onNext} />
        )}
      </Card>
    </div>
  );
}

function Reveal({guess, real, score, onNext}){
  return (
    <div className="fade-up" style={{
      marginTop:36, paddingTop:30,
      borderTop:'1px dashed rgba(255,255,255,0.16)',
    }}>
      <div style={{
        display:'grid', gridTemplateColumns:'1fr 1fr', gap:24,
      }}>
        <MiniReadout label="Tu predicción" value={guess} muted />
        <MiniReadout label="Aire real medido" value={real} highlight />
      </div>

      <div className="fade-up delay-2" style={{
        marginTop:28,
        padding:'24px 28px',
        background:'rgba(13,204,192,0.08)',
        border:'1px solid rgba(13,204,192,0.3)',
        borderRadius:10,
      }}>
        <div style={{
          fontFamily:'var(--mono)', fontSize:12, color:'var(--cyan)',
          letterSpacing:'0.24em', textTransform:'uppercase', marginBottom:12,
        }}>Tu margen de error</div>
        <div style={{display:'flex', alignItems:'baseline', gap:24, flexWrap:'wrap'}}>
          <div style={{
            fontSize:54, fontWeight:700, color:'#fff', lineHeight:1,
            fontVariantNumeric:'tabular-nums',
          }}>± {Math.abs(guess-real).toFixed(0)} <span style={{fontSize:22, color:'var(--gray)'}}>μg/m³</span></div>
          <div style={{fontSize:17, color:'var(--gray)', lineHeight:1.55, flex:1, minWidth:300}}>
            Adivinar el aire es difícil: la diferencia entre <strong style={{color:'#00E676'}}>respirar aire limpio</strong> y <strong style={{color:'#FF8A3D'}}>respirar aire contaminado</strong> son apenas 15 μg. Por eso los pronósticos no se hacen a ojo.
          </div>
        </div>
      </div>

      <div style={{marginTop:36, textAlign:'center'}}>
        <PrimaryBtn onClick={onNext}>Veamos cómo lo hace la ciencia →</PrimaryBtn>
      </div>
    </div>
  );
}

function MiniReadout({label, value, muted, highlight}){
  return (
    <div style={{
      padding:'22px 24px',
      background: highlight ? 'rgba(255,179,0,0.08)' : 'rgba(255,255,255,0.03)',
      border: '1px solid ' + (highlight ? 'rgba(255,179,0,0.35)' : 'rgba(255,255,255,0.08)'),
      borderRadius:10,
    }}>
      <div style={{
        fontFamily:'var(--mono)', fontSize:12,
        color: highlight ? '#FFB300' : 'var(--gray)',
        letterSpacing:'0.24em', textTransform:'uppercase', marginBottom:12,
      }}>{label}</div>
      <div style={{display:'flex', alignItems:'baseline', gap:12}}>
        <div style={{
          fontSize:58, fontWeight:700, lineHeight:1,
          color: pmColor(value), fontVariantNumeric:'tabular-nums',
        }}>{value}</div>
        <div style={{fontSize:15, color:'var(--gray)'}}>μg/m³</div>
        <div style={{marginLeft:'auto', fontSize:13, color:pmColor(value), fontWeight:600}}>
          {pmLabel(value)}
        </div>
      </div>
    </div>
  );
}

// ───────────────────────────────────────────────────────────────
// ROUND 2 — INGREDIENTS (toggle data sources, watch uncertainty shrink)
// ───────────────────────────────────────────────────────────────
const INGREDIENTS = [
  {
    id:'sat', icon:'🛰️',
    name:'Satélites globales',
    sys:'CAMS · Copernicus',
    desc:'Cada 12 h, satélites europeos miden polvo, humo y gases sobre todo el planeta. Nos dicen, por ejemplo, si llega humo del Amazonas o polvo del Sahara.',
    reduces: 18, // μg/m³ uncertainty removed
    color:'#A78BFA',
  },
  {
    id:'wrf', icon:'🌬️',
    name:'Modelo meteorológico local',
    sys:'WRF · 1 km Valle de Aburrá',
    desc:'Una simulación meteorológica del valle: viento, lluvia, inversión térmica. Nos dice si el material particulado se va a quedar atrapado entre las montañas o se va a dispersar.',
    reduces: 14,
    color:'#0DCCC0',
  },
  {
    id:'sens', icon:'🌡️',
    name:'Sensores en tierra',
    sys:'20 estaciones SIATA',
    desc:'Mediciones reales, minuto a minuto, en estaciones del Valle. Corrigen al modelo cuando se equivoca: lo aterrizan al aire que de verdad estamos respirando.',
    reduces: 8,
    color:'#84BD45',
  },
];

function RoundIngredients({onNext, store, setStore}){
  const [active, setActive] = React.useState(store.active || {});
  const baseUncertainty = 42;
  const reduced = INGREDIENTS.reduce((s,i)=> active[i.id] ? s + i.reduces : s, 0);
  const uncertainty = Math.max(2, baseUncertainty - reduced);
  const prediction = 38;
  const accuracy = Math.round( ((baseUncertainty - uncertainty) / baseUncertainty) * 100 );
  const allOn = INGREDIENTS.every(i => active[i.id]);

  const toggle = (id)=>{
    const next = {...active, [id]: !active[id]};
    setActive(next);
    setStore({...store, active: next});
  };

  return (
    <div style={{maxWidth:1500, margin:'0 auto', padding:'56px 40px'}}>
      <ScreenHead
        kicker="Ronda 2 · suma ingredientes"
        title="Activa los datos. Mira cómo el margen de error se encoge."
        sub="El SIATA no adivina: combina información de tres fuentes muy distintas. Toca cada tarjeta para encenderla y observa qué tan cierto se vuelve el pronóstico."
      />

      <div style={{
        display:'grid', gridTemplateColumns:'1.1fr 1fr', gap:32,
        alignItems:'start',
      }}>
        {/* Left: ingredient toggles */}
        <div style={{display:'flex', flexDirection:'column', gap:18}}>
          {INGREDIENTS.map((ing, i)=>(
            <IngredientCard key={ing.id} ing={ing}
              active={!!active[ing.id]}
              onToggle={()=>toggle(ing.id)}
              delay={i} />
          ))}
        </div>

        {/* Right: forecast band */}
        <ForecastBand
          prediction={prediction}
          uncertainty={uncertainty}
          accuracy={accuracy}
          ingredients={INGREDIENTS}
          active={active} />
      </div>

      <div style={{marginTop:36, textAlign:'center'}}>
        <PrimaryBtn onClick={onNext} disabled={!allOn}>
          {allOn ? 'Usar este pronóstico para decidir →' : 'Activa los 3 ingredientes para continuar'}
        </PrimaryBtn>
      </div>
    </div>
  );
}

function IngredientCard({ing, active, onToggle, delay}){
  return (
    <div className={'fade-up delay-' + ((delay+1)%5)}
      onClick={onToggle}
      style={{
        cursor:'pointer',
        padding:'26px 28px',
        borderRadius:12,
        background: active
          ? 'linear-gradient(135deg, ' + ing.color + '22, ' + ing.color + '08)'
          : 'rgba(255,255,255,0.025)',
        border: '1px solid ' + (active ? ing.color : 'rgba(255,255,255,0.1)'),
        display:'flex', gap:22, alignItems:'flex-start',
        transition:'all 0.3s cubic-bezier(.2,.7,.2,1)',
        boxShadow: active ? '0 8px 28px ' + ing.color + '30' : 'none',
      }}>
      <div style={{
        width:96, height:96, borderRadius:16, flexShrink:0,
        background: active ? ing.color : 'rgba(255,255,255,0.06)',
        display:'flex', alignItems:'center', justifyContent:'center',
        fontSize:52, transition:'all 0.3s ease',
        filter: active ? 'none' : 'grayscale(1)',
      }}>{ing.icon}</div>
      <div style={{flex:1, minWidth:0}}>
        <div style={{display:'flex', alignItems:'baseline', gap:14, flexWrap:'wrap'}}>
          <div style={{fontSize:28, fontWeight:600, lineHeight:1.2}}>{ing.name}</div>
          <div style={{
            fontFamily:'var(--mono)', fontSize:14, color: active ? ing.color : 'var(--dim)',
            letterSpacing:'0.16em', textTransform:'uppercase',
          }}>{ing.sys}</div>
        </div>
        <div style={{
          fontSize:19, color: active ? 'var(--gray)' : 'var(--dim)',
          lineHeight:1.55, marginTop:14, textWrap:'pretty',
        }}>{ing.desc}</div>
      </div>
      <div style={{
        flexShrink:0,
        width:52, height:28, borderRadius:16, position:'relative',
        background: active ? ing.color : 'rgba(255,255,255,0.12)',
        transition:'all 0.3s ease',
      }}>
        <div style={{
          position:'absolute', top:2,
          left: active ? 26 : 2,
          width:24, height:24, borderRadius:'50%',
          background:'#fff',
          transition:'all 0.3s cubic-bezier(.2,.7,.2,1)',
        }} />
      </div>
    </div>
  );
}

function ForecastBand({prediction, uncertainty, accuracy, ingredients, active}){
  const min = Math.max(0, prediction - uncertainty);
  const max = prediction + uncertainty;
  const scale = 80; // 0..80 μg/m³
  const pct = (v) => Math.min(100, (v/scale)*100) + '%';

  return (
    <Card accent={'linear-gradient(90deg, #A78BFA, #0DCCC0, #84BD45)'}>
      <div style={{
        fontFamily:'var(--mono)', fontSize:12, color:'var(--cyan)',
        letterSpacing:'0.24em', textTransform:'uppercase',
      }}>Tu pronóstico para mañana</div>
      <div style={{
        fontSize:108, fontWeight:800, lineHeight:1, marginTop:14,
        color: pmColor(prediction), fontVariantNumeric:'tabular-nums',
        letterSpacing:'-0.03em',
      }}>
        {prediction} <span style={{fontSize:28, color:'var(--gray)'}}>μg/m³</span>
      </div>
      <div style={{fontSize:18, color:'var(--gray)', marginTop:10}}>
        ± <AnimNum value={uncertainty} /> μg/m³ de incertidumbre
      </div>

      {/* Bar */}
      <div style={{marginTop:28, position:'relative', height:64}}>
        {/* Color background */}
        <div style={{
          position:'absolute', top:22, left:0, right:0, height:18, borderRadius:10,
          background:'linear-gradient(90deg, #00E676 0%, #FFEB3B 18%, #FFB300 36%, #FF8A3D 56%, #E8735A 80%, #B0306E 100%)',
          opacity:0.25,
        }} />
        {/* Uncertainty band */}
        <div style={{
          position:'absolute', top:22,
          left: pct(min), width: 'calc(' + pct(max) + ' - ' + pct(min) + ')',
          height:18, borderRadius:10,
          background:'rgba(255,255,255,0.35)',
          border:'1px solid rgba(255,255,255,0.5)',
          transition:'all 0.5s cubic-bezier(.2,.7,.2,1)',
        }} />
        {/* Prediction marker */}
        <div style={{
          position:'absolute', top:14, left: pct(prediction),
          transform:'translateX(-50%)',
          width:5, height:36,
          background:'#fff',
          borderRadius:3,
          boxShadow:'0 0 0 2px ' + pmColor(prediction) + ', 0 4px 16px rgba(0,0,0,0.5)',
        }} />
        {/* Labels */}
        <div style={{position:'absolute', bottom:0, left:0, fontSize:12, fontFamily:'var(--mono)', color:'var(--dim)'}}>0</div>
        <div style={{position:'absolute', bottom:0, right:0, fontSize:12, fontFamily:'var(--mono)', color:'var(--dim)'}}>80 μg</div>
      </div>

      {/* Accuracy bar */}
      <div style={{marginTop:30}}>
        <div style={{
          display:'flex', justifyContent:'space-between',
          fontFamily:'var(--mono)', fontSize:12,
          letterSpacing:'0.2em', textTransform:'uppercase',
          color:'var(--gray)', marginBottom:10,
        }}>
          <span>Certeza</span>
          <span style={{color:'var(--cyan)', fontSize:14, fontWeight:600}}><AnimNum value={accuracy} />%</span>
        </div>
        <div style={{height:10, background:'rgba(255,255,255,0.06)', borderRadius:5, overflow:'hidden'}}>
          <div style={{
            width: accuracy + '%', height:'100%',
            background:'linear-gradient(90deg, #A78BFA, #0DCCC0, #84BD45)',
            transition:'width 0.5s cubic-bezier(.2,.7,.2,1)',
            boxShadow:'0 0 12px rgba(13,204,192,0.6)',
          }} />
        </div>
      </div>

      {/* Active sources */}
      <div style={{
        marginTop:24, paddingTop:24,
        borderTop:'1px dashed rgba(255,255,255,0.1)',
        fontSize:14, color:'var(--gray)', lineHeight:1.6,
      }}>
        {ingredients.filter(i=>active[i.id]).length === 0
          ? <span style={{color:'var(--dim)'}}>↑ Activa fuentes de datos para reducir la incertidumbre</span>
          : (
            <div style={{display:'flex', flexWrap:'wrap', gap:8}}>
              {ingredients.filter(i=>active[i.id]).map(i=>(
                <span key={i.id} style={{
                  padding:'6px 14px', borderRadius:6,
                  background: i.color + '20',
                  color:'#fff', fontSize:13,
                  border:'1px solid ' + i.color + '60',
                  fontFamily:'var(--mono)', letterSpacing:'0.08em',
                }}>{i.icon} {i.sys}</span>
              ))}
            </div>
          )
        }
      </div>
    </Card>
  );
}

// ───────────────────────────────────────────────────────────────
// ROUND 3 — DECISIONS (apply the 72h forecast to 3 people)
// ───────────────────────────────────────────────────────────────
const HOURS = Array.from({length:24}, (_,i) => i);
// 3-day fake forecast, but plausible: bad morning, ok afternoon, peak Sunday
const FORECAST = [
  // Day 1 — Saturday
  {label:'Sábado', values: [22,28,34,38,42,46,48,44,38,32,28,24,22,20,18,17,18,22,28,34,38,42,40,36]},
  // Day 2 — Sunday (asado peak evening)
  {label:'Domingo', values: [30,32,36,40,44,48,52,50,44,36,30,26,24,22,22,24,28,36,46,56,62,58,50,42]},
  // Day 3 — Monday
  {label:'Lunes', values: [34,30,26,24,22,20,22,28,32,30,26,22,20,18,16,16,18,22,26,30,32,30,28,26]},
];

const PEOPLE = [
  {
    id:'sofia', emoji:'🏃‍♀️', name:'Sofía, 12 años',
    plan:'Quiere correr en el parque mañana sábado a las 7 a.m.',
    when:{day:0, hour:7},
    options:[
      {id:'go', label:'Sí, que corra'},
      {id:'late', label:'Esperar a la tarde'},
      {id:'no', label:'Mejor que descanse'},
    ],
    best:'late',
    feedback:{
      go:{ok:false, text:'A las 7 a.m. el aire está en su peor momento (~48 μg/m³). Sofía termina con tos y dolor de cabeza.'},
      late:{ok:true, text:'¡Perfecto! Hacia las 3 p.m. el viento baja el PM2.5 a ~17 μg/m³ — aire aceptable para correr.'},
      no:{ok:false, text:'No hace falta cancelar. El pronóstico muestra una ventana limpia por la tarde — solo había que esperar.'},
    },
  },
  {
    id:'carlos', emoji:'🔥', name:'Don Carlos, 58 años',
    plan:'Quiere hacer un asado con leña el domingo a las 7 p.m.',
    when:{day:1, hour:19},
    options:[
      {id:'go', label:'Encender la leña'},
      {id:'gas', label:'Cambiar a parrilla a gas'},
      {id:'move', label:'Aplazar al lunes'},
    ],
    best:'move',
    feedback:{
      go:{ok:false, text:'Domingo a las 7 p.m. el valle está en ~56 μg/m³ y atrapando humo bajo inversión térmica. Sumar leña empeora todo el barrio.'},
      gas:{ok:false, text:'Mejor, pero el aire afuera ya está dañino — los invitados respirarán mal igual.'},
      move:{ok:true, text:'Lunes 7 p.m. el pronóstico baja a ~30 μg/m³. Asado feliz, vecinos felices.'},
    },
  },
  {
    id:'rosa', emoji:'🚶‍♀️', name:'Doña Rosa, 71 años, asmática',
    plan:'Acostumbra caminar 30 minutos cada mañana. ¿Y el lunes?',
    when:{day:2, hour:8},
    options:[
      {id:'go', label:'Caminar como siempre'},
      {id:'mask', label:'Caminar con tapabocas'},
      {id:'in', label:'Caminar adentro'},
    ],
    best:'go',
    feedback:{
      go:{ok:true, text:'Lunes 8 a.m. el aire estará en ~28 μg/m³ — aceptable para caminar. ¡Que disfrute!'},
      mask:{ok:false, text:'No es necesario. El pronóstico muestra aire aceptable — el tapabocas es para los días dañinos.'},
      in:{ok:false, text:'Encerrarla cuando no hace falta le quita salud. El pronóstico es para usarlo, no para tenerle miedo.'},
    },
  },
];

function RoundDecide({onNext, store, setStore}){
  const [choices, setChoices] = React.useState(store.choices || {});
  const allDone = PEOPLE.every(p => choices[p.id]);

  const pickFor = (pid, oid) => {
    const next = {...choices, [pid]:oid};
    setChoices(next);
    setStore({...store, choices: next});
  };

  return (
    <div style={{maxWidth:1500, margin:'0 auto', padding:'56px 40px'}}>
      <ScreenHead
        kicker="Ronda 3 · usa el pronóstico"
        title="Tres personas necesitan decidir. ¿Qué les recomiendas?"
        sub="Aquí está tu pronóstico de 72 horas. Cada barra horaria es un valor de PM2.5. Lee la gráfica y escoge la mejor opción para cada persona — el aire cambia mucho según la hora."
      />

      <ForecastChart forecast={FORECAST} highlights={PEOPLE} choices={choices} />

      <div style={{
        display:'grid', gridTemplateColumns:'repeat(3, 1fr)', gap:22,
        marginTop:36,
      }}>
        {PEOPLE.map(p => (
          <PersonCard key={p.id} person={p}
            chosen={choices[p.id]} onPick={(o)=>pickFor(p.id, o)} />
        ))}
      </div>

      <div style={{marginTop:36, textAlign:'center'}}>
        <PrimaryBtn onClick={onNext} disabled={!allDone}
          variant={allDone ? 'green' : 'cyan'}>
          {allDone ? 'Ver mi resultado →' : 'Decide por las 3 personas para continuar'}
        </PrimaryBtn>
      </div>
    </div>
  );
}

function ForecastChart({forecast, highlights, choices}){
  // 72 bars total
  const max = 70;
  return (
    <Card>
      <div style={{
        display:'flex', alignItems:'baseline', justifyContent:'space-between',
        marginBottom:24, flexWrap:'wrap', gap:10,
      }}>
        <div>
          <div style={{
            fontFamily:'var(--mono)', fontSize:12, color:'var(--cyan)',
            letterSpacing:'0.24em', textTransform:'uppercase',
          }}>Pronóstico 72 h · PM2.5 μg/m³</div>
          <div style={{fontSize:26, fontWeight:600, marginTop:6}}>
            Valle de Aburrá · próximos 3 días
          </div>
        </div>
        <PMScaleMini />
      </div>

      <div style={{
        display:'grid', gridTemplateColumns:'repeat(72, 1fr)',
        alignItems:'stretch', height:300, gap:2, position:'relative',
      }}>
        {forecast.flatMap((day, di) => day.values.map((v, hi) => {
          const idx = di*24 + hi;
          const hl = highlights.find(p => p.when.day===di && p.when.hour===hi);
          const chosen = hl && choices[hl.id];
          const isBest = hl && chosen === hl.best;
          return (
            <div key={idx} style={{
              position:'relative', height:'100%',
              display:'flex', flexDirection:'column', justifyContent:'flex-end',
            }}>
              <div style={{
                height: (v/max)*100 + '%',
                background: pmColor(v),
                borderRadius: '3px 3px 0 0',
                opacity: hl ? 1 : 0.85,
                outline: hl ? '2px solid #fff' : 'none',
                outlineOffset: 1,
                boxShadow: hl ? '0 0 16px ' + pmColor(v) : 'none',
                transition:'all 0.3s ease',
              }} />
              {hl && (
                <div style={{
                  position:'absolute', bottom:'100%', left:'50%',
                  transform:'translateX(-50%) translateY(-8px)',
                  fontSize:34, whiteSpace:'nowrap',
                  filter:'drop-shadow(0 2px 4px rgba(0,0,0,0.5))',
                }}>{hl.emoji}</div>
              )}
            </div>
          );
        }))}

        {/* Day separators */}
        {[24, 48].map(d => (
          <div key={d} style={{
            position:'absolute',
            left: (d/72)*100 + '%', top:0, bottom:0,
            width:1, background:'rgba(255,255,255,0.18)',
          }} />
        ))}
      </div>

      {/* Day labels */}
      <div style={{
        display:'grid', gridTemplateColumns:'repeat(3, 1fr)',
        marginTop:14,
        fontFamily:'var(--mono)', fontSize:13,
        letterSpacing:'0.2em', textTransform:'uppercase',
        color:'var(--gray)', textAlign:'center',
      }}>
        {forecast.map(d => <div key={d.label}>{d.label}</div>)}
      </div>
    </Card>
  );
}

function PMScaleMini(){
  const items = [
    {c:'#00E676', l:'0–12'},
    {c:'#FFEB3B', l:'12–25'},
    {c:'#FFB300', l:'25–37'},
    {c:'#FF8A3D', l:'37–55'},
    {c:'#E8735A', l:'55+'},
  ];
  return (
    <div style={{display:'flex', gap:14, alignItems:'center'}}>
      {items.map((i,k)=>(
        <div key={k} style={{display:'flex', alignItems:'center', gap:7}}>
          <div style={{width:14, height:14, background:i.c, borderRadius:3}} />
          <span style={{fontSize:12, fontFamily:'var(--mono)', color:'var(--gray)', letterSpacing:'0.08em'}}>{i.l}</span>
        </div>
      ))}
    </div>
  );
}

function PersonCard({person, chosen, onPick}){
  const fb = chosen ? person.feedback[chosen] : null;
  return (
    <div style={{
      borderRadius:12, padding:'26px 24px',
      background: chosen
        ? (fb.ok ? 'rgba(132,189,69,0.08)' : 'rgba(232,115,90,0.08)')
        : 'rgba(255,255,255,0.025)',
      border: '1px solid ' + (chosen
        ? (fb.ok ? 'rgba(132,189,69,0.5)' : 'rgba(232,115,90,0.5)')
        : 'rgba(255,255,255,0.1)'),
      transition:'all 0.3s ease',
    }}>
      <div style={{display:'flex', gap:18, alignItems:'flex-start'}}>
        <div style={{fontSize:64, lineHeight:1}}>{person.emoji}</div>
        <div style={{flex:1, minWidth:0}}>
          <div style={{fontSize:21, fontWeight:600}}>{person.name}</div>
          <div style={{fontSize:16, color:'var(--gray)', marginTop:8, lineHeight:1.55}}>
            {person.plan}
          </div>
        </div>
      </div>

      <div style={{
        display:'flex', flexDirection:'column', gap:10, marginTop:22,
      }}>
        {person.options.map(o => {
          const sel = chosen === o.id;
          const showResult = !!chosen;
          const isBest = o.id === person.best;
          return (
            <button key={o.id}
              onClick={()=> !chosen && onPick(o.id)}
              disabled={!!chosen}
              style={{
                textAlign:'left', cursor: chosen?'default':'pointer',
                padding:'18px 22px', borderRadius:10,
                background: sel
                  ? (fb.ok ? 'rgba(132,189,69,0.2)' : 'rgba(232,115,90,0.2)')
                  : (showResult && isBest ? 'rgba(132,189,69,0.12)' : 'rgba(255,255,255,0.03)'),
                border: '1px solid ' + (sel
                  ? (fb.ok ? '#84BD45' : '#E8735A')
                  : (showResult && isBest ? 'rgba(132,189,69,0.5)' : 'rgba(255,255,255,0.1)')),
                color:'#fff', fontSize:17,
                display:'flex', alignItems:'center', gap:12,
              }}>
              <span style={{fontSize:20}}>
                {showResult ? (sel ? (fb.ok ? '✓' : '✗') : (isBest ? '★' : ' ')) : '○'}
              </span>
              {o.label}
            </button>
          );
        })}
      </div>

      {chosen && (
        <div className="fade-up" style={{
          marginTop:20, padding:'18px 22px', borderRadius:10,
          background: fb.ok ? 'rgba(132,189,69,0.12)' : 'rgba(255,255,255,0.04)',
          fontSize:16, lineHeight:1.6, color: fb.ok ? '#a8e072' : 'var(--gray)',
          textWrap:'pretty',
        }}>
          <strong style={{color: fb.ok ? '#84BD45' : '#E8735A'}}>
            {fb.ok ? '¡Buena decisión!' : 'Hmm...'}
          </strong> {fb.text}
        </div>
      )}
    </div>
  );
}

// ───────────────────────────────────────────────────────────────
// ROUND 4 — WHY IT MATTERS (recap + impact)
// ───────────────────────────────────────────────────────────────
function RoundOutro({onRestart, store}){
  const correct = PEOPLE.filter(p => store.choices?.[p.id] === p.best).length;
  const verdict = correct === 3
    ? {title:'¡Pronosticador del SIATA!', sub:'Las 3 decisiones acertadas. Sabes leer el aire del valle.'}
    : correct === 2
    ? {title:'Vas por buen camino', sub:'2 de 3. Mira la gráfica de nuevo — el aire cambia mucho según la hora.'}
    : correct === 1
    ? {title:'Aprendizaje en curso', sub:'1 de 3. El pronóstico solo sirve si lo lees con calma — la peor hora no siempre es la noche.'}
    : {title:'Vuelve a intentarlo', sub:'Las decisiones rápidas no son aliadas del aire. Reinicia y observa las horas pico.'};

  return (
    <div style={{maxWidth:1200, margin:'0 auto', padding:'56px 40px 0'}}>
      <ScreenHead
        kicker="Cierre"
        title={verdict.title}
        sub={verdict.sub} />

      <div style={{
        display:'grid', gridTemplateColumns:'repeat(3, 1fr)', gap:22,
        marginTop:20,
      }}>
        <ImpactStat
          num="2.1M"
          label="Personas respiran el aire del Valle de Aburrá"
          tone="cyan" />
        <ImpactStat
          num={correct + '/3'}
          label="Decisiones que acertaste con el pronóstico"
          tone="green" />
        <ImpactStat
          num="1×"
          label="Vez al día que el SIATA recalcula el pronóstico del valle"
          tone="amber" />
      </div>

      <div style={{
        marginTop:40,
        padding:'36px 40px',
        borderRadius:14,
        background:'linear-gradient(135deg, rgba(13,204,192,0.08), rgba(132,189,69,0.04))',
        border:'1px solid rgba(13,204,192,0.25)',
      }}>
        <div style={{
          fontFamily:'var(--mono)', fontSize:13, color:'var(--cyan)',
          letterSpacing:'0.24em', textTransform:'uppercase', marginBottom:20,
        }}>Lo que aprendiste · resumen</div>
        <div style={{display:'grid', gridTemplateColumns:'repeat(3, 1fr)', gap:32}}>
          <LessonRow num="01" title="Adivinar no sirve"
            text="A ojo, el error es de decenas de μg/m³. La diferencia entre aire buena y dañina son apenas 15." />
          <LessonRow num="02" title="Tres ingredientes"
            text="Satélites (CAMS) ven lejos, modelos de clima (WRF) ven cerca, sensores miden la verdad. Solos fallan; juntos aciertan." />
          <LessonRow num="03" title="La hora importa"
            text="El aire del valle cambia 30 μg en pocas horas. El pronóstico te dice cuándo correr, cuándo no quemar leña, cuándo salir." />
        </div>
      </div>

      <div style={{
        marginTop:36, padding:'32px 36px', borderRadius:12,
        border:'1px solid rgba(255,255,255,0.1)',
        display:'flex', gap:32, alignItems:'center',
        background:'rgba(255,255,255,0.02)',
      }}>
        <div style={{fontSize:68, lineHeight:1}}>🫁</div>
        <div style={{flex:1}}>
          <div style={{fontSize:22, fontWeight:600, marginBottom:10}}>
            Por eso pronosticamos
          </div>
          <div style={{fontSize:17, color:'var(--gray)', lineHeight:1.6}}>
            El pronóstico no es un juego. Le dice a colegios cuándo cancelar deporte al aire libre, a hospitales cuándo preparar más broncodilatadores, a alcaldías cuándo declarar pico-y-placa ambiental. Tu cuerpo lo agradece sin enterarse.
          </div>
        </div>
      </div>

      <div style={{marginTop:44, marginBottom:30, display:'flex', justifyContent:'center', gap:18, flexWrap:'wrap'}}>
        <PrimaryBtn onClick={onRestart} variant="cyan">↺ Jugar de nuevo</PrimaryBtn>
        <a href="animacion_V01.html" target="_blank" rel="noopener noreferrer" style={{textDecoration:'none'}}>
          <PrimaryBtn variant="ghost">Ver el video del SIATA →</PrimaryBtn>
        </a>
        <a href="infografia_V01.html" target="_blank" rel="noopener noreferrer" style={{textDecoration:'none'}}>
          <PrimaryBtn variant="ghost">Ver la infografía →</PrimaryBtn>
        </a>
      </div>
    </div>
  );
}

function ImpactStat({num, label, tone}){
  const toneC = {cyan:'#0DCCC0', green:'#84BD45', amber:'#FFB300'}[tone] || '#0DCCC0';
  return (
    <div style={{
      padding:'30px 32px', borderRadius:12,
      background:'rgba(255,255,255,0.02)',
      border:'1px solid rgba(255,255,255,0.08)',
      borderLeft:'4px solid ' + toneC,
    }}>
      <div style={{
        fontSize:60, fontWeight:800, color:toneC, lineHeight:1,
        fontVariantNumeric:'tabular-nums', letterSpacing:'-0.02em',
      }}>{num}</div>
      <div style={{fontSize:16, color:'var(--gray)', marginTop:14, lineHeight:1.5}}>
        {label}
      </div>
    </div>
  );
}

function LessonRow({num, title, text}){
  return (
    <div>
      <div style={{
        fontFamily:'var(--mono)', fontSize:13, color:'var(--cyan)',
        letterSpacing:'0.2em', fontWeight:600,
      }}>{num}</div>
      <div style={{fontSize:19, fontWeight:600, marginTop:10}}>{title}</div>
      <div style={{fontSize:16, color:'var(--gray)', marginTop:10, lineHeight:1.6, textWrap:'pretty'}}>
        {text}
      </div>
    </div>
  );
}

// ───────────────────────────────────────────────────────────────
// WELCOME — cinematic hero
// ───────────────────────────────────────────────────────────────
function Welcome({onStart}){
  return (
    <div style={{
      minHeight:'100vh', position:'relative',
      display:'flex', flexDirection:'column', justifyContent:'center',
      padding:'80px 40px 40px',
      overflow:'hidden',
    }}>
      <div style={{
        position:'absolute', top:'-10%', right:'-5%', width:600, height:600,
        borderRadius:'50%', background:'radial-gradient(circle, rgba(13,204,192,0.18), transparent 70%)',
        pointerEvents:'none',
      }} />
      <div style={{
        position:'absolute', bottom:'-15%', left:'-10%', width:700, height:700,
        borderRadius:'50%', background:'radial-gradient(circle, rgba(132,189,69,0.12), transparent 70%)',
        pointerEvents:'none',
      }} />

      <div style={{maxWidth:1600, margin:'0 auto', width:'100%', position:'relative'}}>
        <div className="fade-up" style={{
          display:'inline-flex', alignItems:'center', gap:14,
          padding:'12px 24px', borderRadius:40,
          background:'rgba(13,204,192,0.08)',
          border:'1px solid rgba(13,204,192,0.35)',
          fontFamily:'var(--mono)', fontSize:15, color:'var(--cyan)',
          letterSpacing:'0.28em', textTransform:'uppercase',
        }}>
          <span style={{
            width:8, height:8, borderRadius:'50%', background:'var(--cyan)',
            animation:'pulse-cyan 2s infinite',
          }} />
          SIATA · Valle de Aburrá
        </div>

        <h1 className="fade-up delay-1" style={{
          fontSize:'clamp(54px, 8.5vw, 130px)', fontWeight:900,
          lineHeight:0.95, marginTop:36,
          letterSpacing:'-0.035em', textWrap:'balance',
        }}>
          ¿Puedes <span style={{
            background:'linear-gradient(135deg, #0DCCC0 0%, #84BD45 100%)',
            WebkitBackgroundClip:'text', WebkitTextFillColor:'transparent',
          }}>predecir el aire</span><br/>del Valle de Aburrá?
        </h1>

        <p className="fade-up delay-2" style={{
          fontSize:'clamp(20px, 2.2vw, 30px)', color:'var(--gray)',
          marginTop:40, lineHeight:1.45, maxWidth:980, textWrap:'pretty',
          fontWeight:300,
        }}>
          Conviértete en pronosticador del SIATA. <strong style={{color:'#fff', fontWeight:600}}>5 niveles</strong> para entender, paso a paso, cómo predecir el aire del valle — desde las fuentes que usamos hasta las decisiones que cambian vidas.
        </p>

        <div className="fade-up delay-3" style={{
          marginTop:60,
          display:'grid', gridTemplateColumns:'repeat(5, 1fr)', gap:18,
        }}>
          {[
            {n:'01', t:'Las fuentes',     d:'Conoce a CAMS, WRF y los sensores',     c:'#A78BFA'},
            {n:'02', t:'Significados',    d:'Qué ve y qué no ve cada uno',           c:'#0DCCC0'},
            {n:'03', t:'Matemáticas',    d:'Las 3 ecuaciones que mueven todo',      c:'#FFB300'},
            {n:'04', t:'Comprensión',    d:'Test de 5 preguntas',                   c:'#FF8A3D'},
            {n:'05', t:'A pronosticar',   d:'4 rondas de decisiones reales',         c:'#84BD45'},
          ].map((s, i) => (
            <div key={s.n} style={{
              padding:'38px 32px', borderRadius:16,
              background:'rgba(255,255,255,0.03)',
              border:'1px solid ' + s.c + '40',
              borderTop:'4px solid ' + s.c,
              position:'relative', overflow:'hidden',
            }}>
              <div style={{
                position:'absolute', top:-30, right:-30, width:120, height:120,
                borderRadius:'50%', background: s.c + '15',
              }} />
              <div style={{
                fontFamily:'var(--mono)', fontSize:19, color: s.c,
                letterSpacing:'0.22em', fontWeight:600, position:'relative',
              }}>Nivel {s.n}</div>
              <div style={{fontSize:38, fontWeight:700, marginTop:18, position:'relative', lineHeight:1.1, textWrap:'balance', letterSpacing:'-0.01em'}}>{s.t}</div>
              <div style={{fontSize:24, color:'var(--gray)', marginTop:22, lineHeight:1.4, position:'relative', textWrap:'pretty'}}>{s.d}</div>
            </div>
          ))}
        </div>

        <div className="fade-up delay-4" style={{
          marginTop:70, display:'flex', justifyContent:'center', alignItems:'center',
          gap:24, flexWrap:'wrap',
        }}>
          <PrimaryBtn onClick={onStart} variant="cyan">
            Empezar Nivel 1 →
          </PrimaryBtn>
          <div style={{
            fontFamily:'var(--mono)', fontSize:13, color:'var(--dim)',
            letterSpacing:'0.22em', textTransform:'uppercase',
          }}>
            ∼ 10 minutos · niños desde 10 años · curiosos de toda edad
          </div>
        </div>
      </div>
    </div>
  );
}

// ───────────────────────────────────────────────────────────────
// APP
// ───────────────────────────────────────────────────────────────
function App(){
  const [step, setStep] = React.useState(0);
  const [store, setStore] = React.useState({});
  const [levelKey, setLevelKey] = React.useState(0);

  const next = ()=> setStep(s => Math.min(STEPS.length-1, s+1));
  const restart = ()=> { setStep(0); setStore({}); setLevelKey(k=>k+1); window.scrollTo({top:0, behavior:'smooth'}); };
  const retryLevel = ()=> {
    const s = {...store};
    if (step === 4) delete s.quiz;
    if (step === 5) delete s.guess1;
    if (step === 6) delete s.active;
    if (step === 7) delete s.choices;
    setStore(s);
    setLevelKey(k => k + 1);
    window.scrollTo({top:0, behavior:'smooth'});
  };

  React.useEffect(()=>{ window.scrollTo({top:0, behavior:'smooth'}); }, [step]);

  return (
    <div>
      {step > 0 && <TopBar step={step} total={STEPS.length} onRestart={restart} onRetryLevel={retryLevel} label={STEPS[step]} />}
      {step === 0 && <Welcome onStart={next} />}
      {step === 1 && <Level1Sources key={'l1-'+levelKey} onNext={next} />}
      {step === 2 && <Level2Meaning key={'l2-'+levelKey} onNext={next} />}
      {step === 3 && <Level3Math key={'l3-'+levelKey} onNext={next} />}
      {step === 4 && <Level4Quiz key={'l4-'+levelKey} onNext={next} store={store} setStore={setStore} />}
      {step === 5 && <RoundBlind key={'l5a-'+levelKey} onNext={next} store={store} setStore={setStore} />}
      {step === 6 && <RoundIngredients key={'l5b-'+levelKey} onNext={next} store={store} setStore={setStore} />}
      {step === 7 && <RoundDecide key={'l5c-'+levelKey} onNext={next} store={store} setStore={setStore} />}
      {step === 8 && <RoundOutro onRestart={restart} store={store} />}
      <BottomBar />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
