// flow.jsx — Episode flow scenes S1, S2, S3 Q-MAP, S4

const { useState: useStateF, useRef: useRefF, useEffect: useEffectF } = React;

/* ─── S1 · Story Panel ───────────────────────────────────── */
function S1Story() {
  return (
    <div className="screen">
      <Topbar crumbs={["M01", "E01", "S1 · Story"]} mastery={0} />
      <ReglaFinaz step={1} />

      <div style={{ flex: 1, display: 'grid', gridTemplateColumns: '1fr 280px', minHeight: 0 }}>
        <div className="scroll-y" style={{ padding: '32px 56px 24px' }}>
          <div className="kicker" style={{ marginBottom: 14 }}>Escena 1 · Hook · 5 min</div>
          <h1 className="editorial-display" style={{ fontSize: 34, marginBottom: 28, maxWidth: 620 }}>
            «Dos empresas ganan 100 M€. ¿Cuál merece múltiplo mayor?»
          </h1>

          {/* Photographic placeholder + narrative split */}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 22, alignItems: 'start', marginBottom: 28 }}>
            <Placeholder label="Imagen editorial · escena de oficina con dos analistas comparando informes" aspect="4 / 3" />
            <div style={{ paddingTop: 4 }}>
              <p style={{ fontSize: 14.5, lineHeight: 1.6, color: 'var(--ink)', marginBottom: 14 }}>
                El <strong>EPS</strong> es la foto que el mercado mira primero. Pero el analista avanzado pregunta
                quién puso la luz, qué quedó fuera del encuadre y si la foto se repite mañana.
              </p>
              <p style={{ fontSize: 13.5, lineHeight: 1.6, color: 'var(--ink-muted)' }}>
                Mi primera tentación sería mirar el ratio y decidir rápido. Pero en análisis avanzado eso no basta.
                Necesito saber qué parte del dato es <span className="hl">observable</span>, qué parte es interpretación
                y qué evidencia falta.
              </p>
            </div>
          </div>

          {/* Optional capture */}
          <div className="card" style={{ background: 'var(--bg-elev-1)', borderStyle: 'dashed' }}>
            <div className="kicker" style={{ marginBottom: 8 }}>Antes de calcular nada</div>
            <p style={{ fontSize: 13, color: 'var(--ink-muted)', marginBottom: 10 }}>
              Escribe en una línea qué esperas encontrar al evaluar la <strong>calidad</strong> del beneficio. No te juzgamos.
            </p>
            <textarea
              placeholder="Espero encontrar… porque…"
              style={{
                width: '100%', minHeight: 60, padding: 12, font: 'inherit', fontSize: 13,
                background: 'var(--bg)', color: 'var(--ink)',
                border: '0.5px solid var(--rule-strong)', borderRadius: 'var(--radius-sm)',
                outline: 'none', resize: 'vertical',
              }}
            />
          </div>

          <div style={{ display: 'flex', gap: 10, marginTop: 24, alignItems: 'center' }}>
            <button className="btn">Repetir narración</button>
            <button className="btn btn-primary">Pasar a S2 · Concepto <Icon.arrowR /></button>
            <span style={{ marginLeft: 'auto', fontSize: 11, color: 'var(--ink-quiet)' }}>
              <span className="mono">132 wpm</span> · pace objetivo
            </span>
          </div>
        </div>
        <TutorPanel
          actions={["explain_formula", "show_hint", "ask_socratic_question"]}
          message="Tómate el tiempo del hook. No hace falta clicar. Cuando termine la narración, el panel se moverá solo al S2."
        />
      </div>

      <VoicePlayer
        caption={{
          voice: 's', name: 'Locutora Sofía',
          text: '«El EPS es la foto que el mercado mira primero. Pero el analista avanzado pregunta quién puso la luz…»',
          cue: 'música breve',
        }}
        progress={0.34} time="01:24 / 04:08" speed="1×"
      />
      <Disclaimer />
    </div>
  );
}

/* Inline placeholder with monospace explainer */
function Placeholder({ label, aspect = "16 / 9" }) {
  return (
    <div style={{
      aspectRatio: aspect, background: `repeating-linear-gradient(135deg,
        var(--bg-elev-1) 0, var(--bg-elev-1) 12px,
        var(--bg-elev-2) 12px, var(--bg-elev-2) 22px)`,
      border: '0.5px solid var(--rule-strong)', borderRadius: 'var(--radius-md)',
      display: 'grid', placeItems: 'center', padding: 16, position: 'relative',
    }}>
      <div className="mono" style={{ fontSize: 10.5, color: 'var(--ink-muted)', textAlign: 'center', textTransform: 'uppercase', letterSpacing: '0.08em', background: 'var(--bg)', padding: '4px 10px', borderRadius: 3 }}>
        {label}
      </div>
    </div>
  );
}

/* ─── S2 · Annotated statement / formula ──────────────────── */
function S2Annotated() {
  const [consulted, setConsulted] = useStateF({});
  const mark = (id) => setConsulted(c => ({ ...c, [id]: true }));
  const total = 6;
  const seen = Object.keys(consulted).length;

  return (
    <div className="screen">
      <Topbar crumbs={["M01", "E01", "S2 · Concepto"]} mastery={0}
        right={<span className="chip chip-mono">consultados {seen}/{total}</span>} />
      <ReglaFinaz step={2} />

      <div style={{ flex: 1, display: 'grid', gridTemplateColumns: '1fr 280px', minHeight: 0 }}>
        <div className="scroll-y" style={{ padding: '32px 56px 24px' }}>
          <div className="kicker" style={{ marginBottom: 12 }}>Escena 2 · Fórmula anotada · 6 min</div>
          <h2 className="editorial-display" style={{ fontSize: 24, marginBottom: 12, maxWidth: 640 }}>
            Cuatro pruebas antes de creer el EPS
          </h2>
          <p style={{ fontSize: 13.5, color: 'var(--ink-muted)', maxWidth: 580, marginBottom: 22 }}>
            Toca el icono <i className="info-i" style={{ display: 'inline-grid' }}>i</i> sobre cada término antes de pasar al lab.
            Una fórmula sin significado no cuenta como análisis.
          </p>

          {/* Four pillars as annotated chips */}
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 14, marginBottom: 28 }}>
            <Pillar n="01" title="Conversión a caja"
              terms={[["accruals", "Accruals"], ["sloan", "Sloan ratio"], ["cfo", "CFO"]]}
              onMark={mark}
              gloss="Si el beneficio devengado no llega a CFO durante varios periodos, la calidad cae." />
            <Pillar n="02" title="Recurrencia"
              terms={[["oneoffs", "One-offs"], ["recurrence", "Recurrencia"]]}
              onMark={mark}
              gloss="Lo que no se repite vale menos. Restructuring que aparece cuatro años seguidos deja de ser one-off." />
            <Pillar n="03" title="Intensidad de estimaciones"
              terms={[["earnpwr", "Earning power"], ["policychange", "Cambio de política"]]}
              onMark={mark}
              gloss="A más juicio contable, más subjetividad. Mira vida útil, provisiones, capitalizaciones." />
            <Pillar n="04" title="Trazabilidad en notas"
              terms={[["segments", "Segmentos"], ["kam", "KAM"]]}
              onMark={mark}
              gloss="Lo que el P&L afirma debe poder rastrearse en notas. Si no, hipótesis pendiente." />
          </div>

          {/* Formula */}
          <div className="card">
            <div className="kicker" style={{ marginBottom: 12 }}>Marco operativo · 4 ratios en orden</div>
            <div className="mono" style={{ fontSize: 13.5, lineHeight: 2, color: 'var(--ink)', background: 'var(--bg-elev-1)', padding: '14px 18px', borderRadius: 'var(--radius-sm)', whiteSpace: 'pre-wrap' }}>
              {`1.  `}<InfoI termId="cashconv">cash_conversion</InfoI>{` = `}<InfoI termId="cfo">CFO</InfoI>{` / EBITDA            ≥ 0,80\n`}
              {`2.  `}<InfoI termId="sloan">Sloan</InfoI>{` = (NI − CFO − CFI) / Activos     < 0,10\n`}
              {`3.  `}<InfoI termId="accruals">Accruals</InfoI>{`  = NI − CFO                      relación 1 : 1 con ΔWC\n`}
              {`4.  `}<InfoI termId="ownerearnings">owner_earnings</InfoI>{` = NI + D&A − maintenance_capex ± ΔWC`}
            </div>
            <div style={{ marginTop: 12, fontSize: 11.5, color: 'var(--ink-quiet)' }}>
              <em>«Score sobre el umbral no prueba manipulación; prioriza una investigación más profunda.»</em>
            </div>
          </div>

          {/* Nudge */}
          {seen < 4 && (
            <div className="tutor-msg" style={{ marginTop: 18 }}>
              <span className="tutor-msg-name">Tutor Finaz</span>
              No abriste el icono <span className="mono">i</span> de <strong>Sloan ratio</strong>. ¿Quieres revisarlo antes de
              entrar al lab?
            </div>
          )}

          <div style={{ display: 'flex', gap: 10, marginTop: 24, alignItems: 'center' }}>
            <button className="btn">Volver a S1</button>
            <button className="btn btn-primary">Entrar al lab · S3 · Q-MAP <Icon.arrowR /></button>
          </div>
        </div>

        <TutorPanel
          actions={["explain_formula", "show_hint", "map_item_to_statement", "open_inline_glossary"]}
          message="Antes de usar Sloan, confirma su misconception: un Sloan alto no es prueba. Es un priorizador."
        />
      </div>

      <VoicePlayer
        caption={{
          voice: 't', name: 'Tutor Finaz',
          text: 'Toca los iconos «i» antes de usar una métrica. Una fórmula sin significado no cuenta como análisis.',
          cue: 'sonido de panel interactivo',
        }}
        progress={0.58} time="03:32 / 06:04" speed="1×"
      />
      <Disclaimer />
    </div>
  );
}

function Pillar({ n, title, terms, gloss, onMark }) {
  return (
    <div className="card" style={{ padding: 16 }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between' }}>
        <div className="kicker">{n} · prueba</div>
      </div>
      <div style={{ fontSize: 15, fontWeight: 600, margin: '6px 0 10px', letterSpacing: '-0.01em' }}>{title}</div>
      <div style={{ fontSize: 12.5, color: 'var(--ink-muted)', lineHeight: 1.5, marginBottom: 12 }}>{gloss}</div>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
        {terms.map(([id, lbl]) => (
          <span key={id} onClick={() => onMark && onMark(id)} style={{ display: 'inline-block' }}>
            <InfoI termId={id}>{lbl}</InfoI>
          </span>
        ))}
      </div>
    </div>
  );
}

/* ─── S3 · Q-MAP (drag & drop) ────────────────────────────── */
function S3Qmap() {
  const { qmapChips, quadrants } = window.FinazData;
  const [placed, setPlaced] = useStateF({}); // chipId -> quadrantIndex
  const [dragging, setDragging] = useStateF(null);
  const [feedback, setFeedback] = useStateF(null);

  const unplaced = qmapChips.filter(c => placed[c.id] == null);
  const correct = qmapChips.filter(c => placed[c.id] === c.correct).length;
  const incorrect = qmapChips.filter(c => placed[c.id] != null && placed[c.id] !== c.correct).length;
  const progress = Math.round((qmapChips.length - unplaced.length) / qmapChips.length * 100);

  const handleDrop = (qid) => (e) => {
    e.preventDefault();
    if (!dragging) return;
    setPlaced(p => ({ ...p, [dragging]: qid }));
    const chip = qmapChips.find(c => c.id === dragging);
    setFeedback({
      chipLabel: chip.label,
      correct: chip.correct === qid,
      why: chip.why,
      correctIdx: chip.correct,
    });
    setDragging(null);
  };

  return (
    <div className="screen">
      <Topbar
        crumbs={["M01", "E01", "S3 · Q-MAP"]}
        mastery={Math.round(progress * 0.5)}
        right={
          <>
            <span className="chip"><span className="status-dot done"/> {correct} acertados</span>
            <span className="chip"><span className="status-dot lock"/> {qmapChips.length - correct - incorrect} pendientes</span>
            {incorrect > 0 && <span className="chip chip-amber">{incorrect} a revisar</span>}
          </>
        }
      />
      <ReglaFinaz step={3} />

      <div style={{ flex: 1, display: 'grid', gridTemplateColumns: '300px 1fr 280px', minHeight: 0 }}>
        {/* Chips well */}
        <div style={{ borderRight: '0.5px solid var(--rule)', padding: '20px 18px', background: 'var(--bg-elev-1)', display: 'flex', flexDirection: 'column', minHeight: 0 }}>
          <div className="kicker" style={{ marginBottom: 6 }}>Señales a clasificar</div>
          <div style={{ fontSize: 11.5, color: 'var(--ink-muted)', marginBottom: 14 }}>
            Arrastra cada señal al cuadrante donde pertenece. Tu objetivo no es acertar por intuición, sino dejar una traza
            de razonamiento que otra persona pueda auditar.
          </div>
          <div className="scroll-y" style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 6 }}>
            {unplaced.map(c => (
              <div key={c.id}
                draggable
                onDragStart={() => setDragging(c.id)}
                onDragEnd={() => setDragging(null)}
                style={{
                  padding: '10px 12px', background: 'var(--bg)',
                  border: '0.5px solid var(--rule-strong)', borderRadius: 'var(--radius-sm)',
                  fontSize: 12, cursor: 'grab', boxShadow: dragging === c.id ? 'var(--shadow-pop)' : 'none',
                  opacity: dragging === c.id ? 0.5 : 1,
                }}>
                {c.label}
              </div>
            ))}
            {unplaced.length === 0 && (
              <div style={{ textAlign: 'center', padding: 24, color: 'var(--ink-quiet)', fontSize: 12 }}>
                Todas las señales clasificadas. Mira los aciertos y errores para escribir el memo.
              </div>
            )}
          </div>
        </div>

        {/* Quadrants */}
        <div style={{ padding: 20, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 12 }}>
            <h2 style={{ fontSize: 16, fontWeight: 550 }}>Las 4 pruebas de calidad del beneficio</h2>
            <div style={{ fontSize: 11.5, color: 'var(--ink-muted)' }}>
              progreso <span className="mono strong">{progress}%</span>
            </div>
          </div>
          <div style={{ flex: 1, display: 'grid', gridTemplateColumns: '1fr 1fr', gridTemplateRows: '1fr 1fr', gap: 12, minHeight: 0 }}>
            {quadrants.map((q, qi) => {
              const items = qmapChips.filter(c => placed[c.id] === q.id);
              return (
                <div key={q.id}
                  onDragOver={(e) => e.preventDefault()}
                  onDrop={handleDrop(q.id)}
                  style={{
                    border: '0.5px dashed var(--rule-strong)', borderRadius: 'var(--radius-md)',
                    background: dragging ? 'var(--accent-soft)' : 'var(--bg-card)',
                    padding: 14, display: 'flex', flexDirection: 'column', gap: 8,
                    transition: 'background 120ms ease-out',
                    minHeight: 0,
                  }}>
                  <div>
                    <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between' }}>
                      <div className="kicker">Cuadrante {qi + 1}</div>
                      <span className="mono" style={{ fontSize: 10.5, color: 'var(--ink-quiet)' }}>{items.length} clasificadas</span>
                    </div>
                    <div style={{ fontSize: 14, fontWeight: 600, marginTop: 2 }}>{q.label}</div>
                    <div style={{ fontSize: 11, color: 'var(--ink-muted)', marginTop: 2 }}>{q.hint}</div>
                  </div>
                  <div className="scroll-y" style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 4 }}>
                    {items.map(c => {
                      const ok = c.correct === q.id;
                      return (
                        <div key={c.id} style={{
                          padding: '6px 8px', borderRadius: 'var(--radius-sm)',
                          background: ok ? 'var(--green-soft)' : 'var(--amber-soft)',
                          color: ok ? 'var(--green)' : 'var(--amber)',
                          fontSize: 11.5, display: 'flex', alignItems: 'center', gap: 6,
                          borderLeft: `2px solid ${ok ? 'var(--green)' : 'var(--amber)'}`,
                        }}>
                          {ok ? <Icon.check /> : <span style={{ width: 12, textAlign: 'center' }}>↺</span>}
                          <span style={{ color: 'var(--ink)' }}>{c.label}</span>
                        </div>
                      );
                    })}
                  </div>
                </div>
              );
            })}
          </div>

          {feedback && (
            <div className="tutor-msg" style={{ marginTop: 12, borderLeftColor: feedback.correct ? 'var(--green)' : 'var(--amber)', background: feedback.correct ? 'var(--green-soft)' : 'var(--amber-soft)' }}>
              <span className="tutor-msg-name" style={{ color: feedback.correct ? 'var(--green)' : 'var(--amber)' }}>
                {feedback.correct ? "Acierto" : "Reasigna"} · {feedback.chipLabel}
              </span>
              {feedback.why}
              {!feedback.correct && (
                <> {' '}Pertenece a <strong>{quadrants[feedback.correctIdx].label}</strong>.</>
              )}
            </div>
          )}
        </div>

        <TutorPanel
          actions={["ask_socratic_question", "show_hint", "suggest_remediation"]}
          message={`Si dudas, vuelve a S2 y revisa la definición de cada prueba. La asignación tiene que defenderse con una frase, no con un click.`}
        />
      </div>

      <div style={{ padding: '12px 24px', borderTop: '0.5px solid var(--rule)', display: 'flex', alignItems: 'center', gap: 12, background: 'var(--bg-elev-1)', flexShrink: 0 }}>
        <button className="btn">Reasignar todas</button>
        <button className="btn">Pista (resta puntos)</button>
        <span className="spacer"/>
        <span style={{ fontSize: 12, color: 'var(--ink-muted)' }}>
          {unplaced.length === 0 ? 'Listo · pasa al memo para fijar el aprendizaje' : `${unplaced.length} señales pendientes`}
        </span>
        <button className="btn btn-primary" disabled={unplaced.length > 0} style={{ opacity: unplaced.length > 0 ? 0.5 : 1 }}>
          Pasar a S4 · Memo <Icon.arrowR />
        </button>
      </div>
      <Disclaimer />
    </div>
  );
}

/* ─── S4 · Mini-memo writer ────────────────────────────── */
function S4Memo() {
  const PROHIBITED = ["compra", "vende", "venda", "fraude", "garantía", "garantia"];
  const REVIEW = ["manipula", "engaña", "miente", "estafa"];

  const [text, setText] = useStateF(
    `Dato observable: Cygnus reporta EPS idéntico a Asteria (100 M€) pero su CFO/NI es 0,45 frente a 1,55 de Asteria, con receivables creciendo +34% y ventas +12%.
Hipótesis: el beneficio reportado de Cygnus podría estar adelantándose a la caja vía working capital y políticas de reconocimiento.
Evidencia pendiente: envejecimiento de cuentas a cobrar, política de revenue recognition, segmento de canal nuevo.
Transferencia: aplicar las cuatro pruebas a la siguiente empresa con CFO/NI < 0,7 sostenido durante 2-3 trimestres.`
  );

  const words = text.trim().split(/\s+/).filter(Boolean).length;
  const tgt = 90;
  const lower = text.toLowerCase();
  const banned = PROHIBITED.filter(p => lower.includes(p));
  const review = REVIEW.filter(p => lower.includes(p));

  const rubric = [
    { lbl: "precision técnica",       max: 30, score: 24 },
    { lbl: "uso de evidencia",        max: 25, score: 19 },
    { lbl: "interpretación prudente", max: 25, score: 18 },
    { lbl: "transferencia",           max: 10, score:  8 },
    { lbl: "claridad",                max: 10, score:  7 },
  ];
  const totalScore = rubric.reduce((s, r) => s + r.score, 0);
  const totalMax = rubric.reduce((s, r) => s + r.max, 0);

  // simple highlight pass — render text with banned/review words wrapped
  const renderHighlighted = () => {
    const words = text.split(/(\s+)/);
    return words.map((w, i) => {
      const wl = w.toLowerCase().replace(/[.,;:]/g, '');
      if (PROHIBITED.includes(wl)) return <mark key={i} style={{ background: 'var(--red-soft)', color: 'var(--red)', borderBottom: '2px solid var(--red)', padding: 0 }}>{w}</mark>;
      if (REVIEW.includes(wl)) return <mark key={i} style={{ background: 'var(--amber-soft)', color: 'var(--amber)', borderBottom: '2px dashed var(--amber)', padding: 0 }}>{w}</mark>;
      return <React.Fragment key={i}>{w}</React.Fragment>;
    });
  };

  return (
    <div className="screen">
      <Topbar crumbs={["M01", "E01", "S4 · Memo"]} mastery={42}
        right={
          <>
            <span className="chip"><span className="mono">{words}</span> / {tgt} palabras</span>
            {banned.length === 0 && review.length === 0
              ? <span className="chip chip-green"><Icon.check /> lenguaje OK</span>
              : <span className="chip chip-amber">{banned.length + review.length} alertas</span>}
          </>
        }
      />
      <ReglaFinaz step={4} />

      <div style={{ flex: 1, display: 'grid', gridTemplateColumns: '1fr 320px 240px', minHeight: 0 }}>
        <div className="scroll-y" style={{ padding: '24px 32px' }}>
          <div className="kicker" style={{ marginBottom: 8 }}>Escena 4 · Mini-memo · objetivo {tgt} palabras</div>
          <h2 style={{ fontSize: 16, fontWeight: 550, marginBottom: 16 }}>
            Cierra el episodio fijando lo aprendido en una nota que otra persona pueda auditar.
          </h2>

          {/* Template preview */}
          <div className="card" style={{ padding: 0, background: 'var(--bg-card)' }}>
            <div style={{ padding: '10px 14px', borderBottom: '0.5px solid var(--rule)', display: 'flex', justifyContent: 'space-between', alignItems: 'center', background: 'var(--bg-elev-1)' }}>
              <div style={{ display: 'flex', gap: 14, fontSize: 11.5, color: 'var(--ink-muted)' }}>
                <span><strong style={{ color: 'var(--ink)' }}>Plantilla</strong> · 4 bloques</span>
                <span>Pace lectura ≈ 26 s</span>
              </div>
              <div style={{ display: 'flex', gap: 6 }}>
                <button className="btn btn-quiet btn-sm">Reset</button>
                <button className="btn btn-quiet btn-sm">Plantilla pre-llenada</button>
              </div>
            </div>
            <div style={{ position: 'relative' }}>
              <div aria-hidden style={{
                position: 'absolute', inset: 0, padding: '16px 18px',
                font: 'inherit', fontSize: 13.5, lineHeight: 1.6, color: 'transparent',
                whiteSpace: 'pre-wrap', wordWrap: 'break-word', pointerEvents: 'none',
                fontFamily: 'inherit',
              }}>
                {renderHighlighted()}
              </div>
              <textarea
                value={text}
                onChange={e => setText(e.target.value)}
                spellCheck={false}
                style={{
                  width: '100%', minHeight: 280, padding: '16px 18px',
                  font: 'inherit', fontSize: 13.5, lineHeight: 1.6,
                  background: 'transparent', color: 'var(--ink)',
                  border: 'none', outline: 'none', resize: 'vertical',
                  position: 'relative', caretColor: 'var(--accent)',
                }}
              />
            </div>
            <div style={{ padding: '10px 14px', borderTop: '0.5px solid var(--rule)', display: 'flex', alignItems: 'center', gap: 10 }}>
              <button className="btn btn-quiet btn-sm">Sugerir mejora</button>
              <button className="btn btn-quiet btn-sm">Pedir pista</button>
              <span className="spacer"/>
              <span style={{ fontSize: 11, color: 'var(--ink-quiet)' }}>autoguardado · hace 6 s</span>
              <button className="btn btn-primary btn-sm">Finalizar episodio <Icon.check /></button>
            </div>
          </div>

          {(banned.length > 0 || review.length > 0) && (
            <div className="tutor-msg" style={{ marginTop: 14, borderLeftColor: banned.length ? 'var(--red)' : 'var(--amber)', background: banned.length ? 'var(--red-soft)' : 'var(--amber-soft)' }}>
              <span className="tutor-msg-name" style={{ color: banned.length ? 'var(--red)' : 'var(--amber)' }}>
                Linter de lenguaje
              </span>
              {banned.length > 0 && (
                <div style={{ marginBottom: 4 }}>
                  <strong>Bloqueado: </strong>
                  {banned.map(b => <span key={b} className="mono" style={{ marginRight: 6 }}>{b}</span>)}
                  · reformula sin acusar. Estás en territorio de hipótesis.
                </div>
              )}
              {review.length > 0 && (
                <div>
                  <strong>A revisar: </strong>
                  {review.map(b => <span key={b} className="mono" style={{ marginRight: 6 }}>{b}</span>)}
                  · sugerencia: «<em>presenta diferencias materiales con la práctica habitual, según [fuente]</em>».
                </div>
              )}
            </div>
          )}

          <div style={{ display: 'flex', gap: 14, marginTop: 16, fontSize: 11.5, color: 'var(--ink-quiet)' }}>
            <span>Palabras prohibidas: <span className="mono">compra · vende · fraude · garantía</span></span>
            <span>· Revisión: <span className="mono">manipula · engaña</span></span>
          </div>
        </div>

        {/* Rubric */}
        <div style={{ borderLeft: '0.5px solid var(--rule)', padding: 22, background: 'var(--bg-elev-1)', display: 'flex', flexDirection: 'column', gap: 14 }}>
          <div>
            <div className="kicker" style={{ marginBottom: 6 }}>Rúbrica · {totalMax} pts</div>
            <div className="bignum" style={{ fontSize: 36, marginTop: 4 }}>{totalScore}<span style={{ fontSize: 14, color: 'var(--ink-muted)' }}> / {totalMax}</span></div>
            <div className="progress-bar" style={{ marginTop: 6 }}>
              <div className="progress-bar-fill" style={{ width: `${(totalScore/totalMax)*100}%`, background: totalScore >= 75 ? 'var(--green)' : 'var(--accent)' }}/>
              <div className="progress-bar-mark" style={{ left: '75%' }}/>
            </div>
            <div className="quiet" style={{ fontSize: 10.5, marginTop: 4 }}>Mastery ≥ 75 desbloquea siguiente episodio.</div>
          </div>
          <hr className="rule"/>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
            {rubric.map(r => (
              <div key={r.lbl}>
                <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 4 }}>
                  <span>{r.lbl}</span>
                  <span className="mono"><strong>{r.score}</strong><span className="quiet"> / {r.max}</span></span>
                </div>
                <div className="progress-bar" style={{ height: 2 }}>
                  <div className="progress-bar-fill" style={{ width: `${(r.score/r.max)*100}%` }}/>
                </div>
              </div>
            ))}
          </div>
        </div>

        <TutorPanel
          actions={["show_hint", "suggest_remediation", "ask_socratic_question"]}
          message="Lo que tienes ya es defendible. Si lo refinas, añade el tamaño de la diferencia (cuántos pp de CFO/NI). Eso convierte hipótesis en algo medible."
        />
      </div>

      <Disclaimer />
    </div>
  );
}

Object.assign(window, { S1Story, S2Annotated, S3Qmap, S4Memo });
