/* iBD Coliseum — Competition: executives post seasonal missions; users enter (card-style) & discuss */

function MissionBrief({ mission }) {
  return (
    <div className="mbrief" style={{ "--cat": mission.color || "var(--accent)" }}>
      <div className="mbrief-head">
        <span className="mbrief-eyebrow"><Icon name="target" className="ic" />The brief</span>
        <span className="mbrief-tags">
          {mission.tags.map((t) => <span className="mtag" key={t}>{t}</span>)}
        </span>
      </div>
      <p className="mbrief-lede">{mission.brief}</p>
      <p className="mbrief-detail">{mission.detail}</p>
      <div className="mbrief-prompts">
        <div className="mp-label">What a strong entry answers</div>
        {mission.prompts.map((p, i) =>
        <div className="mp-row" key={i}>
            <span className="mp-num">{i + 1}</span>
            <span className="mp-text">{p}</span>
          </div>
        )}
      </div>
    </div>);

}

/* card-style entry — mirrors the gallery use-case card vocabulary */
function EntryCard({ entry, voted, onVote, openCard, openDetail, canManage, onEdit, onDelete, isWinner, canPickWinner, onChooseWinner, rewardPoints, canHof, inHof, onHallOfFame, onArchive, userId, displayName }) {
  const { avatarColor, initials, CATEGORIES, TOOLS, isOwnEntry } = window.COLISEUM_DATA;
  const cat = CATEGORIES.find((c) => c.id === entry.cat);
  const catColor = cat ? cat.color : "var(--accent)";
  const open = () => {if (entry.cardId) openCard(entry.cardId);else openDetail(entry);};
  const isOwn = isOwnEntry(entry, userId, displayName);
  return (
    <div className={"entry-card card" + (isWinner ? " is-winner" : "")} style={{ "--cat": catColor }}>
      <div className="ctop">
        <span className="cat"><span className="sq"></span>{cat ? cat.label : "Entry"}</span>
        {isWinner
          ? <span className="winner-pill"><Icon name="trophy" className="ic" />Winner{rewardPoints > 0 ? ` · +${rewardPoints} pts` : ""}</span>
          : <span className="when">{entry.when} ago</span>}
      </div>
      <h3 className="card-title" onClick={open} title="See skill & output">{entry.title}</h3>
      <p className="desc">{entry.desc}</p>
      {entry.tools && entry.tools.length > 0 &&
      <div className="tools">
          {entry.tools.map((t) =>
        <span className="tool" key={t}><span className="blob" style={{ background: TOOLS[t] || "#999" }}></span>{t}</span>
        )}
        </div>}
      <div className="clinks">
        <button className="clink dm-link" onClick={open} style={{ background: "none", border: "none", padding: 0, cursor: "pointer" }}>
          <Icon name="sparkle" className="ic" />Skill &amp; output
        </button>
        {entry.cardId &&
        <button className="clink dm-link" onClick={() => openCard(entry.cardId)} style={{ background: "none", border: "none", padding: 0, cursor: "pointer" }}>
            <Icon name="external" className="ic" />View card
          </button>}
      </div>
      <div className="cfoot">
        <div className="author">
          <span className="av" style={{ background: avatarColor(entry.author) }}>{initials(entry.author)}</span>
          <div className="author-meta">
            <div className="nm">{entry.author}</div>
            <div className="tm">{entry.team}</div>
          </div>
        </div>
        {isOwn
          ? <span className="vote own" title="You can't upvote your own entry"><Icon name="up" className="ic" />{entry.votes}</span>
          : <button className={"vote" + (voted ? " " : "")} aria-pressed={voted} onClick={() => onVote(entry.id)} title={voted ? "Remove upvote" : "Upvote"}>
              <Icon name="up" className="ic" />{entry.votes}
            </button>}
      </div>
      {canManage &&
        <div className="manage-row">
          <button className="manage-btn" onClick={() => onEdit(entry)}><Icon name="pencil" className="ic" />Edit</button>
          <button className="manage-btn danger" onClick={() => onDelete(entry.id)}><Icon name="trash" className="ic" />Delete</button>
        </div>}
      {canPickWinner &&
        <div className="manage-row">
          <button className={"manage-btn" + (isWinner ? " on" : "")} onClick={() => onChooseWinner(isWinner ? null : entry.id)}>
            <Icon name="trophy" className="ic" />{isWinner ? "Remove winner" : (rewardPoints > 0 ? `Choose winner (+${rewardPoints} pts)` : "Choose winner")}
          </button>
        </div>}
      {canHof &&
        <div className="manage-row">
          <button className={"manage-btn hof" + (inHof ? " on" : "")} onClick={() => onHallOfFame && onHallOfFame(entry, !inHof)}>
            <Icon name="trophy" className="ic" />{inHof ? "Remove from Hall of Fame" : "Hall of Fame"}
          </button>
          <button className="manage-btn archive" onClick={() => onArchive && onArchive(entry)} title="Hide this entry everywhere; the submitter keeps their points">
            <Icon name="archive" className="ic" />Archive
          </button>
        </div>}
    </div>);

}

/* executive composes / edits a mission (modal) — picks which executive is posting */
function MissionComposerModal({ onClose, onLaunch, initial }) {
  const execs = window.COLISEUM_DATA.COMPETITION.executives;
  const { avatarColor, initials } = window.COLISEUM_DATA;
  const isEdit = !!initial;
  const init = initial || {};
  const [who, setWho] = useState(init.postedBy || execs[0].name);
  const [title, setTitle] = useState(init.title || "");
  const [brief, setBrief] = useState(init.brief || "");
  const [detail, setDetail] = useState(init.detail || "");
  const [closes, setCloses] = useState(init.closesAtISO || "");
  const [rewardPoints, setRewardPoints] = useState(init.rewardPoints || 0);
  const [tags, setTags] = useState(init.tags ? init.tags.join(", ") : "");
  const POINT_OPTIONS = [0, 50, 100, 150, 250, 500];
  const [fileName, setFileName] = useState(init.file || "");
  const fileRef = React.useRef(null);
  const canLaunch = title.trim() && brief.trim();
  const exec = execs.find((e) => e.name === who) || execs[0];

  const launch = () => {
    if (!canLaunch) return;
    onLaunch({
      title: title.trim(), brief: brief.trim(),
      detail: detail.trim() || "Freshly posted by leadership — be among the first to enter.",
      closesAt: closes || null,
      closes: closes ? new Date(closes + "T00:00:00").toLocaleDateString("en-US", { month: "short", day: "numeric" }) : "TBD",
      reward: "",
      rewardPoints,
      tags: tags.trim() ? tags.split(",").map((t) => t.trim()).filter(Boolean).slice(0, 3) : ["New mission"],
      postedBy: exec.name, postedRole: exec.role, color: exec.color, file: fileName || null
    });
  };

  const onFilePick = (e) => {
    const f = e.target.files && e.target.files[0];
    if (f) setFileName(f.name);
  };

  return (
    <div className="overlay" onClick={(e) => {if (e.target === e.currentTarget) onClose();}}>
      <div className="modal" role="dialog" aria-modal="true" style={{ "--accent": exec.color }}>
        <div className="mhead">
          <div>
            <div className="eyebrow">{isEdit ? "Executive · edit tournament" : "Executive · new mission"}</div>
            <h2>{isEdit ? "Edit this tournament" : "Post a mission to the org"}</h2>
            <p>{isEdit ? "Update the brief, dates, or winner points. Entries stay attached." : "Runs alongside other live missions. Everyone sees it on their Competition tab."}</p>
          </div>
          <button className="x" onClick={onClose} aria-label="Close"><Icon name="x" className="ic" style={{ width: 16, height: 16 }} /></button>
        </div>
        <div className="mbody">
          <div className="field">
            <label>Posting as <span className="req">*</span></label>
            <div className="tagpick exec-pick">
              {execs.map((e) =>
              <button key={e.name} aria-pressed={who === e.name} onClick={() => setWho(e.name)}>
                  <span className="ep-av" style={{ background: avatarColor(e.name) }}>{initials(e.name)}</span>
                  <span className="ep-meta"><b>{e.name}</b><span>{e.role}</span></span>
                </button>
              )}
            </div>
          </div>
          <div className="field">
            <label>Mission title <span className="req">*</span></label>
            <input type="text" maxLength={40} value={title} placeholder="e.g. Reclaim an Hour" onChange={(e) => setTitle(e.target.value)} />
          </div>
          <div className="field">
            <label>The brief <span className="req">*</span></label>
            <textarea maxLength={180} value={brief} placeholder="One or two sentences on what you're asking the org to try…" onChange={(e) => setBrief(e.target.value)}></textarea>
          </div>
          <div className="field">
            <label>More detail <span className="hint">— what a great entry looks like</span></label>
            <textarea maxLength={320} value={detail} placeholder="Set expectations: the kind of wins you want, what to include…" style={{ minHeight: 60 }} onChange={(e) => setDetail(e.target.value)}></textarea>
          </div>
          <div className="mc-row">
            <div className="field">
              <label>Due date <span className="hint">— winner can be chosen on/after this day</span></label>
              <input type="date" value={closes} onChange={(e) => setCloses(e.target.value)} />
            </div>
            <div className="field">
              <label>Tags <span className="hint">— comma-separated</span></label>
              <input type="text" maxLength={48} value={tags} placeholder="Time-saving, Any team" onChange={(e) => setTags(e.target.value)} />
            </div>
          </div>
          <div className="field">
            <label>Winner points <span className="hint">— awarded to the entry you pick as winner</span></label>
            <div className="tagpick points-pick">
              {POINT_OPTIONS.map((p) =>
              <button key={p} type="button" aria-pressed={rewardPoints === p} onClick={() => setRewardPoints(p)}>
                  {p === 0 ? "No points" : `+${p} pts`}
                </button>
              )}
            </div>
          </div>
          <div className="field">
            <label>Attach a file <span className="hint">— optional: a brief, template, or example</span></label>
            <input ref={fileRef} type="file" style={{ display: "none" }} onChange={onFilePick} />
            {fileName ?
            <div className="file-chip">
                  <Icon name="clip" className="ic" />
                  <span className="fc-name">{fileName}</span>
                  <button className="fc-x" onClick={() => {setFileName("");if (fileRef.current) fileRef.current.value = "";}} aria-label="Remove file"><Icon name="x" className="ic" /></button>
                </div> :
            <button type="button" className="file-drop" onClick={() => fileRef.current && fileRef.current.click()}>
                  <Icon name="clip" className="ic" />
                  <span>Choose a file to attach <span className="fd-hint">PDF, doc, image, or sheet</span></span>
                </button>}
          </div>
        </div>
        <div className="mfoot">
          <span className="left"><Icon name="users" className="ic" style={{ width: 14, height: 14, color: "var(--accent)" }} />Goes live for all 47 in the pilot</span>
          <button className="btn btn-primary" disabled={!canLaunch} style={!canLaunch ? { opacity: 0.45, cursor: "not-allowed" } : {}} onClick={launch}>
            {isEdit ? "Save changes" : "Launch mission"}<Icon name="arrow" className="ic" />
          </button>
        </div>
      </div>
    </div>);

}

function Competition({ empty, openCard, openDetail, tone, dbOn, userId, displayName, isExecOrAdmin, voted: sharedVoted, onVote: sharedOnVote, onGalleryRefresh, canHof, hofIds, onHallOfFame, onArchive }) {
  const { COMPETITION, avatarColor, initials } = window.COLISEUM_DATA;
  const seedMissions = COMPETITION.missions;

  const makeState = (isEmpty) => isEmpty ? [] : seedMissions.map((m) => ({
    ...m,
    entries: m.entries.map((e) => ({ ...e })),
    discussion: m.discussion.map((c) => ({ ...c }))
  }));

  const [role, setRole] = useState(() => (dbOn && isExecOrAdmin ? "exec" : "user"));
  const [missions, setMissions] = useState(() => (dbOn ? [] : makeState(empty)));
  const [activeId, setActiveId] = useState(() => (dbOn ? null : (empty ? null : seedMissions[0].id)));
  const [localVoted, setLocalVoted] = useState(() => new Set());
  const voted = dbOn && sharedVoted ? sharedVoted : localVoted;
  const [dbLoading, setDbLoading] = useState(!!dbOn);
  const [dbError, setDbError] = useState("");
  const [entryOpen, setEntryOpen] = useState(false);
  const [editingEntry, setEditingEntry] = useState(null);
  const [missionComposerOpen, setMissionComposerOpen] = useState(false);
  const [editingMission, setEditingMission] = useState(null);
  const [entered, setEntered] = useState(false);

  const refreshMissions = React.useCallback(async () => {
    if (!dbOn || !userId) return;
    setDbLoading(true);
    try {
      const loaded = await window.COLISEUM_DB.loadMissions(userId);
      setMissions(loaded);
      setActiveId((prev) => {
        if (prev && loaded.some((m) => m.id === prev)) return prev;
        return loaded[0]?.id || null;
      });
      setDbError("");
    } catch (err) {
      console.error(err);
      setDbError(err.message || "Could not load tournaments from Supabase.");
    } finally {
      setDbLoading(false);
    }
  }, [dbOn, userId]);

  React.useEffect(() => {
    if (!dbOn) return;
    refreshMissions();
  }, [dbOn, refreshMissions]);

  // reset when empty/seeded flips (demo mode only)
  const lastEmpty = React.useRef(empty);
  React.useEffect(() => {
    if (dbOn) return;
    if (lastEmpty.current !== empty) {
      lastEmpty.current = empty;
      setMissions(makeState(empty));
      setLocalVoted(new Set());
    }
  }, [empty, dbOn]);

  const active = missions.find((m) => m.id === activeId) || missions[0];
  const isMissionOwner = !!(dbOn && userId && active?.postedById === userId);
  const isExec = isExecOrAdmin || isMissionOwner || (!dbOn && role === "exec");
  const canManageMission = isExecOrAdmin || isMissionOwner;
  // A winner can only be chosen on/after the due date. Missions without a due
  // date (or demo mode) stay pickable so nothing is ever locked out.
  const dueReached = !dbOn || !active?.closesAtISO || (active?.daysLeft || 0) <= 0;
  const canPickWinner = canManageMission && dueReached;

  const onVote = async (id) => {
    const entry = active?.entries?.find((e) => e.id === id);
    if (entry && window.COLISEUM_DATA.isOwnEntry(entry, userId, displayName)) return;
    if (dbOn && sharedOnVote) {
      await sharedOnVote(id);
      await refreshMissions();
      return;
    }
    setLocalVoted((prev) => {
      const next = new Set(prev);
      const was = next.has(id);
      was ? next.delete(id) : next.add(id);
      setMissions((ms) => ms.map((m) => m.id !== active.id ? m : {
        ...m, entries: m.entries.map((e) => e.id === id ? { ...e, votes: e.votes + (was ? -1 : 1) } : e)
      }));
      return next;
    });
  };

  const addEntry = async (data) => {
    if (dbOn && userId && active) {
      try {
        if (editingEntry) {
          await window.COLISEUM_DB.updateEntry(userId, editingEntry.id, data);
        } else {
          await window.COLISEUM_DB.createMissionEntry(userId, active.id, data);
        }
        await refreshMissions();
        if (onGalleryRefresh) onGalleryRefresh();
      } catch (err) {
        console.error(err);
        setDbError(err.message || "Could not save your tournament entry.");
      }
      return;
    }
    if (editingEntry) {
      setMissions((ms) => ms.map((m) => m.id !== active.id ? m : {
        ...m, entries: m.entries.map((e) => e.id === editingEntry.id
          ? { ...e, title: data.title, desc: data.desc, cat: data.cat, tools: data.tools, hasLink: !!data.skill, skill: data.skill || "" } : e),
      }));
      return;
    }
    const newEntry = { id: "ne-" + Date.now(), author: "You", team: "iBD · Pilot", when: "now", votes: 0,
      title: data.title, desc: data.desc, cat: data.cat, tools: data.tools, hasRepro: true, hasLink: !!data.skill, skill: data.skill || "" };
    setMissions((ms) => ms.map((m) => m.id !== active.id ? m : { ...m, entries: [newEntry, ...m.entries] }));
  };

  const deleteEntry = async (id) => {
    if (dbOn && userId) {
      try {
        await window.COLISEUM_DB.deleteEntry(id);
        await refreshMissions();
        if (onGalleryRefresh) onGalleryRefresh();
      } catch (err) {
        console.error(err);
        setDbError(err.message || "Could not delete this entry.");
      }
      return;
    }
    setMissions((ms) => ms.map((m) => m.id !== active.id ? m : { ...m, entries: m.entries.filter((e) => e.id !== id) }));
    setLocalVoted((prev) => { const n = new Set(prev); n.delete(id); return n; });
  };

  const chooseWinner = async (entryId) => {
    if (dbOn && userId && canManageMission && active) {
      try {
        await window.COLISEUM_DB.setMissionWinner(active.id, entryId);
        await refreshMissions();
        if (onGalleryRefresh) onGalleryRefresh();
      } catch (err) {
        console.error(err);
        setDbError(err.message || "Could not set the winner.");
      }
      return;
    }
    setMissions((ms) => ms.map((m) => m.id !== active.id ? m : { ...m, winnerEntryId: entryId }));
  };

  // Tag the entry with its mission so the Hall of Fame can group it under
  // "Competition submissions" even in demo mode (DB mode reads mission_id).
  const handleHof = (entry, value) =>
    onHallOfFame && onHallOfFame({ ...entry, missionId: entry.missionId || active.id }, value);

  // Only the person who submitted the entry can edit or delete it.
  const canManageEntry = (e) =>
    (dbOn && userId && e.authorId === userId) ||
    (!dbOn && (e.author === "You" || (displayName && e.author === displayName)));
  const closeEntryModal = () => { setEntryOpen(false); setEditingEntry(null); };

  const addComment = async (text) => {
    if (dbOn && userId && active) {
      try {
        const added = await window.COLISEUM_DB.addMissionDiscussion(userId, active.id, text);
        setMissions((ms) => ms.map((m) => m.id !== active.id ? m : { ...m, discussion: [...m.discussion, added] }));
      } catch (err) {
        console.error(err);
        setDbError(err.message || "Could not post your comment.");
      }
      return;
    }
    const mine = role === "exec" ?
    { author: "Luke Park", team: "iBD · Executive", when: "now", text, exec: true, mine: true } :
    { author: "You", team: "iBD · Pilot", when: "now", text, mine: true };
    setMissions((ms) => ms.map((m) => m.id !== active.id ? m : { ...m, discussion: [...m.discussion, mine] }));
  };

  const launchMission = async (m) => {
    if (dbOn && userId && (isExecOrAdmin || (editingMission && editingMission.postedById === userId))) {
      try {
        if (editingMission) {
          await window.COLISEUM_DB.updateMission(editingMission.id, m);
        } else {
          await window.COLISEUM_DB.createMission(userId, {
            ...m,
            missionCount: missions.length,
            prompts: seedMissions[0]?.prompts || [],
            tagline: "New mission",
          });
        }
        await refreshMissions();
        setMissionComposerOpen(false);
        setEditingMission(null);
      } catch (err) {
        console.error(err);
        setDbError(err.message || "Could not save this tournament.");
      }
      return;
    }
    const demoDaysLeft = m.closesAt
      ? Math.max(0, Math.ceil((new Date(m.closesAt + "T00:00:00").getTime() - Date.now()) / 86400000))
      : 28;
    if (editingMission) {
      setMissions((ms) => ms.map((x) => x.id !== editingMission.id ? x : {
        ...x, title: m.title, brief: m.brief, detail: m.detail, tags: m.tags,
        closes: m.closes, closesAtISO: m.closesAt || "", daysLeft: demoDaysLeft,
        reward: m.reward, rewardPoints: m.rewardPoints || 0, file: m.file || null,
        postedBy: m.postedBy, postedRole: m.postedRole, color: m.color,
      }));
      setMissionComposerOpen(false);
      setEditingMission(null);
      return;
    }
    const id = "nm-" + Date.now();
    const newMission = {
      id, no: String(40 + missions.length), title: m.title, tagline: "New mission", color: m.color,
      brief: m.brief, detail: m.detail, prompts: seedMissions[0].prompts, tags: m.tags,
      postedBy: m.postedBy, postedRole: m.postedRole, opened: "Today", closes: m.closes,
      closesAtISO: m.closesAt || "", daysLeft: demoDaysLeft,
      reward: m.reward, rewardPoints: m.rewardPoints || 0, winnerEntryId: null, file: m.file || null, entries: [], discussion: []
    };
    setMissions((ms) => [newMission, ...ms]);
    setActiveId(id);
    setMissionComposerOpen(false);
    setRole("user");
  };

  const deleteMission = async (id) => {
    const target = missions.find((m) => m.id === id);
    const allowed = isExecOrAdmin || (dbOn && userId && target?.postedById === userId);
    if (dbOn && userId && allowed) {
      try {
        await window.COLISEUM_DB.deleteMission(id);
        await refreshMissions();
      } catch (err) {
        console.error(err);
        setDbError(err.message || "Could not delete this tournament.");
      }
      return;
    }
    setMissions((ms) => {
      const remaining = ms.filter((m) => m.id !== id);
      if (id === activeId) setActiveId(remaining.length ? remaining[0].id : null);
      return remaining;
    });
  };

  const openEditMission = () => { setEditingMission(active); setMissionComposerOpen(true); };
  const closeMissionModal = () => { setMissionComposerOpen(false); setEditingMission(null); };

  // Entries inducted into the Hall of Fame graduate out of the competition list.
  const sorted = active
    ? [...active.entries].filter((e) => !(hofIds && hofIds.has(e.id))).sort((a, b) => b.votes - a.votes)
    : [];

  const downloadTemplate = () => {
    const { CATEGORIES, TOOLS } = window.COLISEUM_DATA;
    const tpl = [
      "iBD COLISEUM — TOURNAMENT SUBMISSION TEMPLATE",
      "=============================================",
      "",
      "Tournament / topic: ____________________________",
      "Your name: ____________________   Department: ____________________",
      "",
      "1) Headline — the win in one line",
      "   ",
      "2) How you did it — before → after, what changed",
      "   ",
      "3) Category (pick one):",
      "   " + CATEGORIES.map((c) => c.label).join("  /  "),
      "   ",
      "4) Tools used:",
      "   " + Object.keys(TOOLS).join(", "),
      "   ",
      "5) How to reproduce it — the prompt or steps a colleague can follow",
      "   ",
      "6) Link to your Claude skill (optional):",
      "   ",
      "",
      "Submit at: Coliseum › Competition › Submit your entry",
    ].join("\n");
    const blob = new Blob([tpl], { type: "text/plain;charset=utf-8" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url; a.download = "coliseum-submission-template.txt";
    document.body.appendChild(a); a.click(); a.remove();
    setTimeout(() => URL.revokeObjectURL(url), 1000);
  };

  const roleSwitch = (
    <div className="role-switch" role="group" aria-label="Viewing as">
      <span className="rs-label">Viewing as</span>
      <button aria-pressed={role === "user"} onClick={() => setRole("user")}><Icon name="users" className="ic" />Employee</button>
      <button aria-pressed={role === "exec"} onClick={() => setRole("exec")}><Icon name="shield" className="ic" />Executive</button>
    </div>
  );

  if (dbOn && dbLoading && missions.length === 0) {
    return (
      <div className="competition">
        <div className="auth-gate"><div className="auth-card"><p>Loading tournaments…</p></div></div>
      </div>
    );
  }

  if (!active) {
    return (
      <div className="competition">
        <section className="ghero arena">
          <div className="wrap">
            {dbError && <div className="db-banner" role="alert">{dbError}</div>}
            <div className="comp-hero-top">
              <div className="eyebrow">iBD Coliseum · Tournaments</div>
              {!dbOn && roleSwitch}
            </div>
            <h1>Tournament <em>Submissions</em></h1>
            <p className="sub">Showcase submission to a topic given by leaders.</p>
          </div>
        </section>
        <section className="comp-body">
          <div className="wrap" style={{ display: "block" }}>
            <div className="cards-empty">
              <EmptyState icon="target"
                title={isExec ? "No tournaments yet" : "No tournaments running"}
                message={isExec
                  ? "Post the first tournament topic for the org to respond to — or share the blank template so people can draft offline."
                  : "Leadership hasn't posted a tournament yet. Grab the blank template to get a head start, then check back."}
                cta={isExec ? "Post a tournament" : "Download blank template"}
                onCta={isExec ? () => setMissionComposerOpen(true) : downloadTemplate} />
            </div>
          </div>
        </section>
        {missionComposerOpen &&
          <MissionComposerModal initial={editingMission} onClose={closeMissionModal} onLaunch={launchMission} />}
      </div>
    );
  }

  if (!entered) {
    return (
      <div className="competition">
        <section className="ghero arena">
          <div className="wrap">
            {dbError && <div className="db-banner" role="alert">{dbError}</div>}
            <div className="comp-hero-top">
              <div className="eyebrow">iBD Coliseum · Live competitions</div>
              {!dbOn && roleSwitch}
            </div>
            <h1>Live <em>competitions</em></h1>
            <p className="sub">Jump into a live tournament posted by leadership.</p>
          </div>
        </section>
        <section className="comp-body">
          <div className="wrap" style={{ display: "block" }}>
            <div className="section-head">
              <h2>Live now <span className="muted">· {missions.length}</span></h2>
              {isExec &&
                <button className="btn btn-primary" onClick={() => setMissionComposerOpen(true)}>
                  <Icon name="plus" className="ic" />New competition
                </button>}
            </div>
            <div className="comp-landing-grid">
              {missions.map((m) => (
                <button key={m.id} className="comp-landing-card card" style={{ "--cat": m.color || "var(--accent)" }}
                  onClick={() => { setActiveId(m.id); setEntered(true); }}>
                  <div className="clc-top">
                    <span className="clc-no">Mission {m.no}</span>
                    <span className="clc-live"><span className="live-dot"></span>Live</span>
                  </div>
                  <h3 className="clc-title">{m.title}</h3>
                  <p className="clc-brief">{m.brief}</p>
                  <div className="clc-tags">{(m.tags || []).map((t) => <span className="mtag" key={t}>{t}</span>)}</div>
                  <div className="clc-foot">
                    <span className="clc-poster"><span className="av" style={{ background: avatarColor(m.postedBy) }}>{initials(m.postedBy)}</span>{m.postedBy}</span>
                    <span className="clc-meta">{m.entries.length} {m.entries.length === 1 ? "entry" : "entries"} · {m.daysLeft}d left</span>
                  </div>
                  {m.rewardPoints > 0 && <div className="clc-reward"><Icon name="gift" className="ic" />+{m.rewardPoints} pts to the winner</div>}
                </button>
              ))}
            </div>
          </div>
        </section>
        {missionComposerOpen &&
          <MissionComposerModal initial={editingMission} onClose={closeMissionModal} onLaunch={launchMission} />}
      </div>
    );
  }

  return (
    <div className="competition">
      {dbError && <div className="db-banner" role="alert">{dbError}</div>}
      <section className="ghero arena" style={{ "--cat": active.color || "var(--accent)" }}>
        <div className="wrap">
          <button className="comp-back" onClick={() => setEntered(false)}><Icon name="arrow" className="ic" style={{ transform: "rotate(180deg)" }} />All competitions</button>
          <div className="comp-hero-top">
            <div className="eyebrow">iBD Coliseum · Mission {active.no} · {active.tagline}</div>
            {!dbOn &&
            <div className="role-switch" role="group" aria-label="Viewing as">
              <span className="rs-label">Viewing as</span>
              <button aria-pressed={role === "user"} onClick={() => setRole("user")}><Icon name="users" className="ic" />Employee</button>
              <button aria-pressed={role === "exec"} onClick={() => setRole("exec")}><Icon name="shield" className="ic" />Executive</button>
            </div>}
          </div>
          <h1>Tournament <em>Submissions</em></h1>
          <p className="sub">Showcase submission to a topic given by leaders.</p>
          <div className="season-meta">
            <span className="count-pill"><span className="post-av" style={{ background: avatarColor(active.postedBy) }}>{initials(active.postedBy)}</span>Posted by {active.postedBy}</span>
            <span className="count-pill"><Icon name="clock" className="ic" />Closes {active.closes} · <b>{active.daysLeft}d left</b></span>
            <span className="count-pill"><Icon name="flag" className="ic" />{active.entries.length} {active.entries.length === 1 ? "entry" : "entries"}</span>
          </div>
          <div className="comp-reward"><Icon name="gift" className="ic" /><span><b>Reward</b> · {active.rewardPoints > 0 ? `+${active.rewardPoints} pts to the winner` : "Recognition at the town hall"}</span></div>
        </div>
      </section>

      {/* mission switcher — several executives' missions run at once */}
      <div className="mission-strip">
        <div className="wrap">
          <span className="ms-label"><Icon name="target" className="ic" />Live missions</span>
          <div className="ms-rail">
            {missions.map((m) =>
            <button key={m.id} className={"ms-chip" + (m.id === active.id ? " on" : "")} style={{ "--cat": m.color || "var(--accent)" }} onClick={() => setActiveId(m.id)}>
                <span className="ms-av" style={{ background: avatarColor(m.postedBy) }}>{initials(m.postedBy)}</span>
                <span className="ms-meta">
                  <span className="ms-title">{m.title}</span>
                  <span className="ms-sub">{m.postedBy.split(" ")[0]} · {m.entries.length} {m.entries.length === 1 ? "entry" : "entries"} · {m.daysLeft}d</span>
                </span>
                <span className="ms-dot"></span>
              </button>
            )}
            {isExec &&
            <button className="ms-new" onClick={() => setMissionComposerOpen(true)}>
                <Icon name="plus" className="ic" />New mission
              </button>}
          </div>
        </div>
      </div>

      <section className="comp-body">
        <div className="wrap">
          <div className="comp-main">
            <MissionBrief mission={active} />

            <div className="comp-entries">
              <div className="section-head">
                <h2>Entries</h2>
                <div className="head-actions">
                  <button className="btn btn-ghost" onClick={downloadTemplate}>
                    <Icon name="download" className="ic" />Download blank template
                  </button>
                  {role === "user" &&
                  <button className="btn btn-primary" onClick={() => setEntryOpen(true)}>
                    <Icon name="plus" className="ic" />Submit your entry
                  </button>}
                </div>
              </div>

              {sorted.length === 0 ?
              <div className="cards-empty">
                  <EmptyState icon="flag"
                title={isExec ? "No entries yet" : "Be the first to enter"}
                message={isExec ?
                "Your tournament is live. Entries from the org will appear here as people respond — each one is a full card with a skill link and output. Share the blank template so people can draft offline." :
                "Nobody's entered yet — grab the blank template to draft yours, then post it. Entries work just like a gallery card: category, tools, skill link, and output."}
                cta={role === "user" ? "Submit your entry" : undefined}
                onCta={() => setEntryOpen(true)} />
                </div> :
              <div className="entry-grid">
                  {sorted.map((e) =>
                <EntryCard key={e.id} entry={e} voted={voted.has(e.id)} onVote={onVote} openCard={openCard} openDetail={openDetail}
                  canManage={canManageEntry(e)} onEdit={(en) => { setEditingEntry(en); setEntryOpen(true); }} onDelete={deleteEntry}
                  isWinner={active.winnerEntryId === e.id} canPickWinner={canPickWinner} onChooseWinner={chooseWinner} rewardPoints={active.rewardPoints || 0}
                  canHof={canHof} inHof={hofIds && hofIds.has(e.id)} onHallOfFame={handleHof} onArchive={onArchive}
                  userId={userId} displayName={displayName} />
                )}
                </div>}
              {canManageMission && !dueReached && sorted.length > 0 &&
                <div className="winner-lock"><Icon name="clock" className="ic" />You can choose a winner on <b>{active.closes}</b> ({active.daysLeft}d left){active.rewardPoints > 0 ? ` — the winner gets +${active.rewardPoints} pts` : ""}.</div>}
            </div>

            <div className="comp-discussion">
              <div className="section-head">
                <h2><Icon name="chat" className="ic disc-ic" />Mission discussion</h2>
                <span className="muted">Ask questions, share tips, tag a teammate</span>
              </div>
              {isExec &&
              <div className="exec-banner"><Icon name="shield" className="ic" />You're replying as <b>leadership</b> — your comments are badged for the org.</div>}
              <CommentThread comments={active.discussion} onAdd={addComment} catColor={active.color || "var(--accent)"} />
            </div>
          </div>

          <aside className="comp-aside">
            <div className="panel from-leadership" style={{ "--cat": active.color || "var(--accent)" }}>
              <div className="ph"><h3><Icon name="target" className="ic" />From leadership</h3>{isExec && <span className="tag exec">Executive</span>}</div>
              <div className="fl-body">
                <div className="fl-poster">
                  <span className="av" style={{ background: avatarColor(active.postedBy) }}>{initials(active.postedBy)}</span>
                  <div>
                    <div className="nm">{active.postedBy}</div>
                    <div className="tm">{active.postedRole}</div>
                  </div>
                </div>
                <div className="fl-rows">
                  <div className="fl-row"><span className="k"><Icon name="cal" className="ic" />Opened</span><span className="v">{active.opened}</span></div>
                  <div className="fl-row"><span className="k"><Icon name="clock" className="ic" />Closes</span><span className="v">{active.closes} · {active.daysLeft}d</span></div>
                  <div className="fl-row"><span className="k"><Icon name="gift" className="ic" />Reward</span><span className="v">{active.rewardPoints > 0 ? `+${active.rewardPoints} pts to the winner` : "Recognition at the town hall"}</span></div>
                </div>
                {active.file &&
                <a className="fl-file" href="#" onClick={(e) => e.preventDefault()} title="Download attachment">
                    <Icon name="clip" className="ic" />
                    <span className="ff-name">{active.file}</span>
                    <Icon name="download" className="ic ff-dl" />
                  </a>}
                {canManageMission ?
                <div className="exec-mission-actions">
                      {isExecOrAdmin &&
                      <button className="btn btn-primary btn-block" onClick={() => setMissionComposerOpen(true)}><Icon name="plus" className="ic" />Post another tournament</button>}
                      <div className="ema-row">
                        <button className="manage-btn" onClick={openEditMission}><Icon name="pencil" className="ic" />Edit tournament</button>
                        <button className="manage-btn danger" onClick={() => deleteMission(active.id)}><Icon name="trash" className="ic" />Delete tournament</button>
                      </div>
                    </div> :
                <div className="fl-how">
                      <b>How to enter</b>
                      <ol>
                        <li>Answer the three brief questions.</li>
                        <li>Submit a card-style entry — category, tools, skill link.</li>
                        <li>Colleagues upvote; top 3 reach the town hall.</li>
                      </ol>
                    </div>}
              </div>
            </div>

            <div className="panel past-missions">
              <div className="ph"><h3><Icon name="repeat" className="ic" />Past Tournaments</h3></div>
              {empty ?
              <div className="pm-empty">No past tournaments yet — they'll appear here as seasons wrap up.</div> :
              COMPETITION.past.map((m) =>
              <div className="pm-item" key={m.id}>
                  <span className="pm-no">{m.no}</span>
                  <div className="pm-main">
                    <div className="pm-title">{m.title}</div>
                    <div className="pm-win"><Icon name="trophy" className="ic" />{m.winner}</div>
                    <div className="pm-meta">{m.author} · {m.team} · {m.entries} entries · {m.quarter}</div>
                  </div>
                </div>
              )}
            </div>
          </aside>
        </div>
      </section>

      {entryOpen &&
      <SubmitModal context="mission" missionTitle={active.title} accent={active.color} initial={editingEntry}
      tone={tone} onSubmit={addEntry} onClose={closeEntryModal} />}
      {missionComposerOpen &&
      <MissionComposerModal initial={editingMission} onClose={closeMissionModal} onLaunch={launchMission} />}
    </div>);

}

window.Competition = Competition;