/* The 7 wizard step components.
   Exports: StepClade, StepSpecies, StepClass, StepBackground, StepStats, StepSkills, StepReview
   All read/write through the shared `state` object passed via props. */

const { useState, useMemo, useEffect } = React;

// ============ STEP 1: CLADE ============
const StepClade = ({ state, set, tweaks }) => {
  const { clades } = state.data;
  const groupBy = tweaks.predatorPrey;

  const groups = groupBy
    ? [
        { label: "Predators", items: clades.filter(c => c.kind === "predator") },
        { label: "Prey", items: clades.filter(c => c.kind === "prey") },
      ]
    : [{ label: null, items: clades }];

  const renderCard = (c) => {
    const sel = state.cladeId === c.id;
    return (
      <div
        key={c.id}
        className={"card scented" + (sel ? " selected" : "")}
        onClick={() => set({ cladeId: c.id, speciesId: state.data.species.find(s => s.clade_id === c.id)?.id })}
      >
        <span className="scent-aura" />
        <div style={{display: "flex", alignItems: "flex-start", gap: 14}}>
          <div className="sigil"><Sigil id={c.id} /></div>
          <div style={{flex: 1}}>
            <div className="name">{c.name}</div>
            <div className="meta">{c.kind}</div>
          </div>
        </div>
        <div className="mods">
          {Object.entries(c.ability_mods).map(([k,v]) => (
            <span key={k} className={"mod " + (v >= 0 ? "pos" : "neg")}>{k} {signed(v)}</span>
          ))}
        </div>
        <div className="trait-chips-label">Languages</div>
        <div className="trait-chips lang-chips">
          {c.languages.map(l => (
            <LanguageChip key={l} id={l} />
          ))}
        </div>
        <div className="trait-chips-label">Traits</div>
        <div className="trait-chips">
          {c.traits.map(t => (
            <TraitName key={t.id} trait={t} suffix="" />
          ))}
          {tweaks.showDetriments && c.detriments.map(t => (
            <TraitName key={t.id} trait={t} detriment suffix="" />
          ))}
        </div>
      </div>
    );
  };

  return (
    <>
      <div className="page-intro">
        <div>
          <div className="eyebrow">Folio I — Of Bloodlines</div>
          <h2>Choose your Clade</h2>
          <p>The seven great families of Theriapolis. Your clade is the body you were born to — the broad shape of your gait, the fall of your shadow, the words your scent carries before you speak.</p>
        </div>
      </div>
      {groups.map(g => (
        <div key={g.label || "all"}>
          {g.label && <div className="clade-group-label">{g.label}</div>}
          <div className="card-grid">{g.items.map(renderCard)}</div>
        </div>
      ))}
    </>
  );
};

// ============ STEP 2: SPECIES ============
const StepSpecies = ({ state, set, tweaks }) => {
  const clade = state.data.clades.find(c => c.id === state.cladeId);
  const filtered = state.data.species.filter(s => s.clade_id === state.cladeId);
  if (!clade) return <p>Pick a clade first.</p>;

  return (
    <>
      <div className="page-intro">
        <div>
          <div className="eyebrow">Folio II — Of Lineage within {clade.name}</div>
          <h2>Choose your Species</h2>
          <p>Within every clade are kindreds — different statures, ranges, and inheritances. The species refines what the clade began.</p>
        </div>
      </div>
      <div className="card-grid">
        {filtered.map(s => {
          const sel = state.speciesId === s.id;
          return (
            <div
              key={s.id}
              className={"card" + (sel ? " selected" : "")}
              onClick={() => set({ speciesId: s.id })}
            >
              <div className="name">{s.name}</div>
              <div className="meta">{SIZE_LABEL[s.size] || s.size} · {s.base_speed_ft} ft.</div>
              <div className="mods">
                {Object.entries(s.ability_mods).map(([k,v]) => (
                  <span key={k} className={"mod " + (v >= 0 ? "pos" : "neg")}>{k} {signed(v)}</span>
                ))}
              </div>
              <div className="trait-chips" style={{marginTop: 12}}>
                {s.traits.map(t => (
                  <TraitName key={t.id} trait={t} suffix="" />
                ))}
                {tweaks.showDetriments && s.detriments.map(t => (
                  <TraitName key={t.id} trait={t} detriment suffix="" />
                ))}
              </div>
            </div>
          );
        })}
      </div>
    </>
  );
};

// ============ STEP 3: CLASS ============
const StepClass = ({ state, set, tweaks }) => {
  const recommendedClasses = useMemo(() => {
    const recs = [];
    Object.entries(CLASS_CLADE_REC).forEach(([cls, clades]) => {
      if (clades.includes(state.cladeId)) recs.push(cls);
    });
    return new Set(recs);
  }, [state.cladeId]);

  return (
    <>
      <div className="page-intro">
        <div>
          <div className="eyebrow">Folio III — Of Vocations</div>
          <h2>Choose your Calling</h2>
          <p>Eight callings exist within the Covenant. Each shapes how you fight, treat, parley, or unmake the world.</p>
        </div>
      </div>
      <div className="card-grid">
        {state.data.classes.map(c => {
          const sel = state.classId === c.id;
          const rec = recommendedClasses.has(c.id);
          return (
            <div
              key={c.id}
              className={"card" + (sel ? " selected" : "")}
              onClick={() => set({ classId: c.id })}
            >
              <div className="name">
                {c.name}
                {rec && <span className="badge-rec" title="Suits your clade">★ Suits Clade</span>}
              </div>
              <div className="meta">d{c.hit_die} · primary {c.primary_ability.join("/")} · saves {c.saves.join("/")}</div>
              <div className="trait-chips" style={{marginTop: 12}}>
                {(c.level_table?.find(l => l.level === 1)?.features || [])
                  .filter(k => !["asi","subclass_select","subclass_feature"].includes(k))
                  .map(k => {
                    const f = c.feature_definitions[k];
                    if (!f) return null;
                    return <TraitName key={k} trait={{ id: c.id+"_"+k, name: f.name, description: f.description, tag: f.kind }} suffix="" />;
                  })}
              </div>
              <div style={{marginTop: 10, fontFamily: "var(--mono)", fontSize: 10, letterSpacing: "0.16em", color: "var(--ink-mute)", textTransform: "uppercase"}}>
                Picks {c.skills_choose} skill{c.skills_choose > 1 ? "s" : ""} · armor: {c.armor_proficiencies.join(", ")}
              </div>
            </div>
          );
        })}
      </div>
    </>
  );
};

// ============ STEP 4: BACKGROUND ============
const StepBackground = ({ state, set, tweaks }) => {
  return (
    <>
      <div className="page-intro">
        <div>
          <div className="eyebrow">Folio IV — Of Histories</div>
          <h2>Choose your Background</h2>
          <p>Where the clade gives you body and the calling gives you craft, the background gives you a past — debts, contacts, scars, the way you sleep.</p>
        </div>
      </div>
      <div className="card-grid">
        {state.data.backgrounds.map(b => {
          const sel = state.backgroundId === b.id;
          return (
            <div
              key={b.id}
              className={"card bg-card" + (sel ? " selected" : "")}
              onClick={() => set({ backgroundId: b.id })}
            >
              <div className="name">{b.name}</div>
              {tweaks.showFlavor && <div className="flavor">{b.flavor}</div>}
              <div className="trait-chips-label" style={{marginTop: 10}}>Feature</div>
              <div className="trait-chips bg-feat-row">
                <TraitName trait={{ id: b.id+"_feat", name: b.feature_name, description: b.feature_description, tag: "feature" }} suffix="" />
              </div>
              <div className="trait-chips-label" style={{marginTop: 10}}>Skills</div>
              <div className="trait-chips">
                {b.skill_proficiencies.map(s => <SkillChip key={s} id={s} />)}
              </div>
            </div>
          );
        })}
      </div>
    </>
  );
};

// ============ STEP 5: STATS ============
const StepStats = ({ state, set, tweaks }) => {
  const clade = state.data.clades.find(c => c.id === state.cladeId);
  const species = state.data.species.find(s => s.id === state.speciesId);
  const cls = state.data.classes.find(c => c.id === state.classId);

  const method = state.statMethod; // "array" | "roll"

  // Drag/drop handlers cover three cases:
  //   pool   -> slot     (assign; if slot has a value, return that to pool)
  //   slot   -> slot     (move; if dest has a value, swap the two)
  //   slot   -> pool     (return value to pool)
  const handleDrop = (destAbility, payload) => {
    const newPool = [...state.statPool];
    const newAssign = { ...state.statAssign };
    if (payload.from === "pool") {
      // If dest already has a value, return it to the pool first.
      if (newAssign[destAbility] != null) {
        newPool.push({ value: newAssign[destAbility] });
      }
      newPool.splice(payload.idx, 1);
      newAssign[destAbility] = payload.value;
    } else if (payload.from === "slot") {
      const srcAbility = payload.ability;
      if (srcAbility === destAbility) return;
      const srcVal = newAssign[srcAbility];
      const destVal = newAssign[destAbility];
      // swap (or move if dest empty)
      newAssign[destAbility] = srcVal;
      if (destVal != null) newAssign[srcAbility] = destVal;
      else delete newAssign[srcAbility];
    }
    set({ statPool: newPool, statAssign: newAssign });
  };

  // Drop a slot value back into the pool.
  const dropToPool = (payload) => {
    if (payload.from !== "slot") return;
    const newAssign = { ...state.statAssign };
    const v = newAssign[payload.ability];
    if (v == null) return;
    delete newAssign[payload.ability];
    set({
      statPool: [...state.statPool, { value: v }],
      statAssign: newAssign,
    });
  };

  const clearAbility = (ab) => {
    const newPool = [...state.statPool];
    const newAssign = { ...state.statAssign };
    if (newAssign[ab] != null) {
      newPool.push({ value: newAssign[ab], used: false });
      delete newAssign[ab];
    }
    set({ statPool: newPool, statAssign: newAssign });
  };

  const reroll = () => {
    const r = () => {
      const dice = Array.from({length: 4}, () => 1 + Math.floor(Math.random() * 6));
      dice.sort((a,b) => a-b);
      return dice[1] + dice[2] + dice[3];
    };
    const vals = Array.from({length: 6}, r);
    set({
      statPool: vals.map(v => ({ value: v })),
      statAssign: {},
      statHistory: [...(state.statHistory || []), { vals, ts: Date.now() }],
    });
  };

  const useArray = () => {
    set({
      statMethod: "array",
      statPool: STANDARD_ARRAY.map(v => ({ value: v })),
      statAssign: {},
    });
  };
  const useRoll = () => {
    set({ statMethod: "roll" });
    reroll();
  };

  const autoAssign = () => {
    if (!cls) return;
    // Honor abilities the user already pinned. Only fill remaining ones from
    // values still in the pool, and only into ability slots still empty.
    const newAssign = { ...state.statAssign };
    const assignedAbilities = new Set(Object.keys(newAssign));

    // Order of preference: class primary first (any not yet pinned), then
    // a sensible default fallback for the rest.
    const order = [...cls.primary_ability];
    ["CON","DEX","STR","WIS","INT","CHA"].forEach(a => { if (!order.includes(a)) order.push(a); });
    const remainingAbilities = order.filter(a => !assignedAbilities.has(a));

    // Sort the still-in-pool values descending and place onto remaining
    // abilities in preference order.
    const remainingValues = [...state.statPool.map(p => p.value)].sort((a,b) => b-a);

    const newPool = [];
    remainingAbilities.forEach((a, i) => {
      if (i < remainingValues.length) {
        newAssign[a] = remainingValues[i];
      }
    });
    // If pool had more values than empty slots (shouldn't happen, but be
    // defensive), keep the leftovers in the pool.
    if (remainingValues.length > remainingAbilities.length) {
      remainingValues.slice(remainingAbilities.length).forEach(v => {
        newPool.push({ value: v });
      });
    }

    set({ statPool: newPool, statAssign: newAssign });
  };

  return (
    <>
      <div className="page-intro">
        <div>
          <div className="eyebrow">Folio V — Of Aptitudes</div>
          <h2>Set your Abilities</h2>
          <p>Six numbers describe what your body and mind can do. Drag values from the pool onto the abilities — your primary calling preference is suggested.</p>
        </div>
      </div>

      <div className="stat-tabs">
        <div className={"stat-tab" + (method === "array" ? " active" : "")} onClick={useArray}>Standard Array</div>
        <div className={"stat-tab" + (method === "roll" ? " active" : "")} onClick={useRoll}>Roll 4d6 — drop lowest</div>
      </div>

      <div
        className="pool"
        onDragOver={(e) => { e.preventDefault(); e.currentTarget.classList.add("drag-over"); }}
        onDragLeave={(e) => e.currentTarget.classList.remove("drag-over")}
        onDrop={(e) => {
          e.preventDefault();
          e.currentTarget.classList.remove("drag-over");
          try {
            const payload = JSON.parse(e.dataTransfer.getData("text/plain"));
            dropToPool(payload);
          } catch {}
        }}
      >
        {state.statPool.length === 0 && <div style={{fontFamily: "var(--mono)", fontSize: 11, letterSpacing: "0.18em", color: "var(--ink-mute)", textTransform: "uppercase"}}>All values assigned. Drag from a slot to return.</div>}
        {state.statPool.map((p, i) => (
          <div
            key={i+"-"+p.value}
            className="die"
            draggable
            onDragStart={(e) => {
              e.dataTransfer.setData("text/plain", JSON.stringify({ from: "pool", value: p.value, idx: i }));
              e.dataTransfer.effectAllowed = "move";
            }}
          >{p.value}</div>
        ))}
        <div style={{marginLeft: "auto", display: "flex", gap: 8, alignItems: "center"}}>
          {method === "roll" && <button className="btn small ghost" onClick={reroll}>Reroll</button>}
          <button className="btn small ghost" onClick={autoAssign} disabled={state.statPool.length === 0}>Auto-assign</button>
          <button className="btn small ghost" onClick={() => { const ks = Object.keys(state.statAssign); const vals = ks.map(k => state.statAssign[k]); set({ statPool: [...state.statPool, ...vals.map(v => ({value: v}))], statAssign: {}}); }}>Clear</button>
        </div>
      </div>

      {/* Roll history */}
      {method === "roll" && (state.statHistory || []).length > 1 && (
        <div style={{marginBottom: 18, fontFamily: "var(--mono)", fontSize: 11, color: "var(--ink-mute)"}}>
          <strong style={{fontFamily: "var(--serif-display)", fontStyle: "italic", fontSize: 13, color: "var(--ink-soft)", textTransform: "none", letterSpacing: 0}}>Previous rolls:</strong>{" "}
          {state.statHistory.slice(0, -1).slice(-3).map((h, i) => (
            <span key={i} style={{marginRight: 12}}>[{h.vals.join(", ")}]</span>
          ))}
        </div>
      )}

      <div>
        {ABILITIES.map(ab => {
          const v = state.statAssign[ab];
          const cladeMod = clade?.ability_mods[ab] || 0;
          const speciesMod = species?.ability_mods[ab] || 0;
          const totalBonus = cladeMod + speciesMod;
          const bonusSources = [];
          if (cladeMod) bonusSources.push({ source: clade?.name || "Clade", value: cladeMod });
          if (speciesMod) bonusSources.push({ source: species?.name || "Species", value: speciesMod });
          const final = (v ?? 0) + cladeMod + speciesMod;
          const finalMod = abilityMod(final);
          const isPrimary = cls?.primary_ability.includes(ab);
          return (
            <div className="ability-row" key={ab}>
              <div className="ab-name">
                <span style={{display: "inline-flex", alignItems: "center", gap: 6}}>
                  {ab}
                  {totalBonus !== 0 && (
                    <BonusPill total={totalBonus} sources={bonusSources} ability={ab} />
                  )}
                </span>
                <small>{ABILITY_LABELS[ab]}{isPrimary && " · primary"}</small>
              </div>
              <div
                className={"slot" + (v != null ? " filled" : "")}
                draggable={v != null}
                onDragStart={(e) => {
                  if (v == null) { e.preventDefault(); return; }
                  e.dataTransfer.setData("text/plain", JSON.stringify({ from: "slot", value: v, ability: ab }));
                  e.dataTransfer.effectAllowed = "move";
                }}
                onDragOver={(e) => { e.preventDefault(); e.currentTarget.classList.add("drag-over"); }}
                onDragLeave={(e) => e.currentTarget.classList.remove("drag-over")}
                onDrop={(e) => {
                  e.preventDefault();
                  e.currentTarget.classList.remove("drag-over");
                  try {
                    const payload = JSON.parse(e.dataTransfer.getData("text/plain"));
                    handleDrop(ab, payload);
                  } catch {}
                }}
                onClick={() => v != null && clearAbility(ab)}
                title={v != null ? "Drag to swap, or click to return to pool" : "Drop a value here"}
              >
                {v ?? "—"}
              </div>
              <div className="formula">
                {v != null && (cladeMod || speciesMod) ? `base ${v}` : (v != null ? "" : "")}
              </div>
              <div style={{display: "flex", flexDirection: "column"}}>
                <div className="ab-name" style={{fontSize: 22}}>
                  {v != null ? final : "—"}
                  <small style={{color: finalMod >= 0 ? "var(--seal)" : "var(--ink-mute)", letterSpacing: "0.1em"}}>{v != null ? signed(finalMod) : ""}</small>
                </div>
              </div>
              <div className="bar">
                <div className="bar-fill" style={{width: Math.max(0, Math.min(100, (final/20)*100)) + "%"}} />
              </div>
            </div>
          );
        })}
      </div>
    </>
  );
};

// ============ STEP 6: SKILLS ============
const StepSkills = ({ state, set, tweaks }) => {
  const cls = state.data.classes.find(c => c.id === state.classId);
  const bg = state.data.backgrounds.find(b => b.id === state.backgroundId);
  if (!cls) return <p>Pick a class first.</p>;

  const lockedFromBg = new Set((bg?.skill_proficiencies || []));
  const classOptions = new Set(cls.skill_options);
  const required = cls.skills_choose;
  const chosen = state.chosenSkills;

  const toggle = (skillId) => {
    if (lockedFromBg.has(skillId)) return;
    const has = chosen.includes(skillId);
    if (has) set({ chosenSkills: chosen.filter(s => s !== skillId) });
    else if (chosen.length < required) set({ chosenSkills: [...chosen, skillId] });
  };

  // Group all 18 skills by ability
  const grouped = {};
  ABILITIES.forEach(a => grouped[a] = []);
  Object.entries(SKILL_LABEL).forEach(([id]) => {
    grouped[SKILL_ABILITY[id]].push(id);
  });

  return (
    <>
      <div className="page-intro">
        <div>
          <div className="eyebrow">Folio VI — Of Trained Hands</div>
          <h2>Choose your Skills</h2>
          <p>Your background grants two skills automatically (sealed). From your calling's offered list, choose {required} more.</p>
        </div>
      </div>

      <div className="skills-meta">
        <div>
          <div className="count"><em>{chosen.length}</em> / {required} chosen</div>
          <div style={{fontFamily: "var(--mono)", fontSize: 10, letterSpacing: "0.2em", color: "var(--ink-mute)", textTransform: "uppercase", marginTop: 2}}>
            + {lockedFromBg.size} sealed by background
          </div>
        </div>
        <div style={{fontFamily: "var(--mono)", fontSize: 10, letterSpacing: "0.18em", color: "var(--ink-mute)", textTransform: "uppercase"}}>
          Class: {cls.name} · Background: {bg?.name || "—"}
        </div>
      </div>

      <div className="skill-grid-by-ability">
        {ABILITIES.map(ab => (
          <div className="skill-group" key={ab}>
            <h5>
              {ABILITY_LABELS[ab]}
              <small>{ab}</small>
            </h5>
            {grouped[ab].map(skillId => {
              const fromBg = lockedFromBg.has(skillId);
              const fromClass = classOptions.has(skillId);
              const checked = chosen.includes(skillId);
              const klass = fromBg ? "locked" : (!fromClass ? "unavailable" : (checked ? "checked" : ""));
              return (
                <div
                  key={skillId}
                  className={"skill-row " + klass}
                  onClick={() => fromClass && toggle(skillId)}
                >
                  <div className="label">
                    <div className="check">{(checked || fromBg) ? "✓" : ""}</div>
                    <SkillChip id={skillId} />
                  </div>
                  <div className="source-tag">
                    {fromBg ? "Background" : (fromClass ? "Class" : "—")}
                  </div>
                </div>
              );
            })}
          </div>
        ))}
      </div>
    </>
  );
};

// ============ STEP 7: NAME + REVIEW ============
const StepReview = ({ state, set, tweaks, goTo }) => {
  const clade = state.data.clades.find(c => c.id === state.cladeId);
  const species = state.data.species.find(s => s.id === state.speciesId);
  const cls = state.data.classes.find(c => c.id === state.classId);
  const bg = state.data.backgrounds.find(b => b.id === state.backgroundId);

  return (
    <>
      <div className="page-intro">
        <div>
          <div className="eyebrow">Folio VII — Of Names & Witness</div>
          <h2>Sign the Codex</h2>
          <p>Review your character. The name you sign here is the one the world will speak.</p>
        </div>
      </div>

      <div style={{marginBottom: 22}}>
        <h4 style={{marginBottom: 4}}>Name</h4>
        <input
          type="text"
          value={state.name}
          onChange={(e) => set({ name: e.target.value })}
          placeholder="Wanderer"
          style={{maxWidth: 480}}
        />
      </div>

      <div className="review-grid">
        <div className="review-block">
          <div className="head">
            <h3 style={{fontStyle: "italic"}}>{clade?.name}</h3>
            <button className="edit-link" onClick={() => goTo(0)}>Edit ›</button>
          </div>
          <div style={{fontFamily: "var(--serif-display)", fontSize: 18}}>{species?.name} <span style={{color: "var(--ink-mute)", fontSize: 13, fontFamily: "var(--mono)", letterSpacing: "0.16em", textTransform: "uppercase", marginLeft: 8}}>{SIZE_LABEL[species?.size]}</span></div>
        </div>
        <div className="review-block">
          <div className="head">
            <h3 style={{fontStyle: "italic"}}>{cls?.name}</h3>
            <button className="edit-link" onClick={() => goTo(2)}>Edit ›</button>
          </div>
          <div style={{fontFamily: "var(--mono)", fontSize: 11, letterSpacing: "0.18em", color: "var(--ink-mute)", textTransform: "uppercase"}}>
            d{cls?.hit_die} · {cls?.primary_ability.join("/")}
          </div>
          <div style={{fontFamily: "var(--serif-display)", fontStyle: "italic", color: "var(--ink-soft)", marginTop: 6, fontSize: 14}}>
            {bg?.name}
          </div>
        </div>
      </div>

      <div className="review-block" style={{marginTop: 18}}>
        <div className="head">
          <h3 style={{fontStyle: "italic"}}>Final Abilities</h3>
          <button className="edit-link" onClick={() => goTo(4)}>Edit ›</button>
        </div>
        <div className="stat-strip" style={{marginTop: 6}}>
          {ABILITIES.map(ab => {
            const base = state.statAssign[ab] || 0;
            const cm = clade?.ability_mods[ab] || 0;
            const sm = species?.ability_mods[ab] || 0;
            const f = base + cm + sm;
            const m = abilityMod(f);
            return (
              <div className="cell" key={ab}>
                <div className="ab">{ab}</div>
                <div className="sc">{f}</div>
                <div className={"md" + (m < 0 ? " neg" : "")}>{signed(m)}</div>
              </div>
            );
          })}
        </div>
      </div>

      <div className="review-block" style={{marginTop: 18}}>
        <div className="head">
          <h3 style={{fontStyle: "italic"}}>Skills</h3>
          <button className="edit-link" onClick={() => goTo(5)}>Edit ›</button>
        </div>
        <div className="mods" style={{marginTop: 4}}>
          {(bg?.skill_proficiencies || []).map(s => (
            <span key={s} className="mod" style={{borderColor: "var(--gild)", color: "var(--gild)"}}>{SKILL_LABEL[s]} · BG</span>
          ))}
          {state.chosenSkills.map(s => (
            <span key={s} className="mod pos">{SKILL_LABEL[s]}</span>
          ))}
        </div>
      </div>

      <div className="review-block" style={{marginTop: 18}}>
        <div className="head">
          <h3 style={{fontStyle: "italic"}}>Starting Kit</h3>
          <button className="edit-link" onClick={() => goTo(2)}>Edit ›</button>
        </div>
        <div className="kit-grid" style={{marginTop: 6}}>
          {(cls?.starting_kit || []).map((it, i) => (
            <div className={"kit-item" + (it.auto_equip ? " equipped" : "")} key={i}>
              <div>{ITEM_NAME[it.item_id] || it.item_id}</div>
              <div className="qty">×{it.qty}</div>
              {it.auto_equip && <div className="equipped-tag">{it.equip_slot}</div>}
            </div>
          ))}
        </div>
      </div>
    </>
  );
};

window.Steps = { StepClade, StepSpecies, StepClass, StepBackground, StepStats, StepSkills, StepReview };
