// UNIFIED FULL-BODY TRACKER — equipment tabs, muscle map, imbalance, head-to-head

// Maps a muscle id → broad training zone (color + label)
const ZONE_MAP = {
  chest: "push", front_delt: "push", side_delt: "push", triceps: "push",
  upper_back: "pull", lats: "pull", rear_delt: "pull", traps: "pull", biceps: "pull", forearms: "pull",
  quads: "legs", glutes: "legs", hamstrings: "legs", calves: "legs", adductors: "legs",
  abs: "core", obliques: "core", lower_back: "core",
};
const ZONE_INFO = {
  push: { label: "PUSH", color: "#ff5b3a" },
  pull: { label: "PULL", color: "#3aa8ff" },
  legs: { label: "LEGS", color: "#ffb730" },
  core: { label: "CORE", color: "#9d6bff" },
};
const muscleZones = (ex) => {
  const zones = new Set();
  (ex.primary || []).forEach(m => { if (ZONE_MAP[m]) zones.add(ZONE_MAP[m]); });
  return [...zones].map(id => ({ id, ...ZONE_INFO[id] }));
};

// Muscle chips: every primary muscle as its own chip, color-coded by zone.
// e.g. BB Squat → [{ label: "QUADS", color: "#ffb730" }, { label: "GLUTES", color: "#ffb730" }]
const muscleChips = (ex, max = 3) => {
  const D = window.FITNESS_DATA;
  const primary = (ex.primary || []).slice(0, max);
  return primary.map(m => {
    const zone = ZONE_MAP[m];
    return {
      id: m,
      label: (D.muscles[m]?.label || m).toUpperCase(),
      color: zone ? ZONE_INFO[zone].color : "#888",
      zone
    };
  });
};
const secondaryChips = (ex, max = 2) => {
  const D = window.FITNESS_DATA;
  const sec = (ex.secondary || []).slice(0, max);
  return sec.map(m => {
    const zone = ZONE_MAP[m];
    return {
      id: m,
      label: (D.muscles[m]?.label || m).toUpperCase(),
      color: zone ? ZONE_INFO[zone].color : "#888",
      zone
    };
  });
};

// === PROFILE EDITOR ===
const BW_MIN = 20;
const BW_MAX = 300;
const clampBW = (v) => {
  const n = typeof v === "number" ? v : parseFloat(v);
  if (!Number.isFinite(n)) return 70;
  return Math.max(BW_MIN, Math.min(BW_MAX, Math.round(n * 10) / 10));
};

const ProfileEditor = ({ athlete, onSave, onClose, onCancel }) => {
  const [name, setName] = React.useState(athlete.placeholder ? "" : athlete.name);
  const [short, setShort] = React.useState(athlete.placeholder ? "" : athlete.short);
  const [color, setColor] = React.useState(athlete.color);
  // Always store bodyweight as a number internally so steppers + saves stay safe.
  const [bodyweight, setBodyweight] = React.useState(clampBW(athlete.bodyweight));
  // Separate mirror string for the input so users can mid-type ("", "7", "70.")
  const [bwInput, setBwInput] = React.useState(String(clampBW(athlete.bodyweight)));

  const palette = ["#D4FF3F", "#FF2D6F", "#3AA8FF", "#FFB800", "#9D6BFF", "#00E5C7", "#FF5B3A", "#FFFFFF"];

  const stepBW = (delta) => {
    const next = clampBW(bodyweight + delta);
    setBodyweight(next);
    setBwInput(String(next));
  };

  const onBWInput = (e) => {
    const raw = e.target.value;
    setBwInput(raw);
    const n = parseFloat(raw);
    if (Number.isFinite(n)) setBodyweight(clampBW(n));
  };

  const onBWBlur = () => {
    // On blur, snap input back to canonical clamped value
    setBwInput(String(bodyweight));
  };

  const cleanName = name.trim();
  const cleanShort = short.trim().toUpperCase().slice(0, 4);
  const isValid = cleanName.length >= 2 && cleanShort.length >= 2;

  const handleSave = () => {
    if (!isValid) return;
    onSave({
      name: cleanName,
      short: cleanShort,
      avatar: cleanShort.slice(0, 3),
      color,
      bodyweight: clampBW(bodyweight)
    });
  };

  return (
    <div className="pe-card" onClick={e => e.stopPropagation()} style={{ "--c": color }}>
      <div className="pe-head">
        <div>
          <div className="pe-tag">{athlete.placeholder ? "ADD ATHLETE" : "EDIT PROFILE"}</div>
          <div className="pe-title">{athlete.placeholder ? "NEW SQUAD MEMBER" : athlete.name.toUpperCase()}</div>
        </div>
        <button className="pe-x" onClick={onClose} aria-label="Close">×</button>
      </div>

      <div className="pe-preview">
        <div className="pe-av-big" style={{ background: color }}>
          {(cleanShort || "??").slice(0, 3) || "??"}
        </div>
        <div className="pe-prev-info">
          <div className="pe-prev-name">{cleanName || "Your name here"}</div>
          <div className="pe-prev-bw">{bodyweight} KG BODYWEIGHT</div>
        </div>
      </div>

      <div className="pe-field">
        <label className="pe-lbl">FULL NAME</label>
        <input className="pe-input" value={name} onChange={e => setName(e.target.value)} placeholder="e.g. Alex Chen" maxLength="32" autoFocus={athlete.placeholder} />
      </div>

      <div className="pe-field">
        <label className="pe-lbl">SHORT TAG (2–4 LETTERS)</label>
        <input className="pe-input pe-input--short" value={short} onChange={e => setShort(e.target.value.toUpperCase().slice(0, 4))} placeholder="ALEX" maxLength="4" />
      </div>

      <div className="pe-field">
        <label className="pe-lbl">ACCENT COLOR</label>
        <div className="pe-colors">
          {palette.map(p => (
            <button key={p}
              type="button"
              aria-label={`Pick color ${p}`}
              aria-pressed={color === p}
              className={`pe-color ${color === p ? "pe-color--on" : ""}`}
              style={{ background: p }}
              onClick={() => setColor(p)}>
              {color === p && <span className="pe-color-check">✓</span>}
            </button>
          ))}
        </div>
      </div>

      <div className="pe-field">
        <label className="pe-lbl">BODYWEIGHT (KG) · USED FOR BW VOLUME CALC</label>
        <div className="pe-bw-row">
          <button type="button" className="pe-bw-step" onClick={() => stepBW(-1)} aria-label="Decrease bodyweight">−</button>
          <input className="pe-input pe-input--bw"
            type="number" inputMode="decimal" min={BW_MIN} max={BW_MAX} step="0.5"
            value={bwInput} onChange={onBWInput} onBlur={onBWBlur} />
          <button type="button" className="pe-bw-step" onClick={() => stepBW(1)} aria-label="Increase bodyweight">+</button>
        </div>
        <div className="pe-hint">Range: {BW_MIN}–{BW_MAX} kg</div>
      </div>

      <div className="pe-actions">
        <button type="button" className="pe-cancel" onClick={onCancel}>CANCEL</button>
        <button type="button" className="pe-save" style={{ background: color }} onClick={handleSave} disabled={!isValid}>
          ▸ {athlete.placeholder ? "ADD TO SQUAD" : "SAVE CHANGES"}
        </button>
      </div>
    </div>
  );
};

// === TRASH TALK SENDER ===
const TrashTalkSender = ({ from, to, onSend, onClose }) => {
  const [msg, setMsg] = React.useState("");
  const presets = [
    "Catch up. The bar's getting lonely.",
    "Skipped leg day again? Tragic.",
    `${from.short} just out-volumed you. By a lot.`,
    "Streak's still going. Yours?",
    "Bench press is calling. It says you're ghosting it.",
    "Imagine training arms harder than your back. Couldn't be me."
  ];
  return (
    <div className="tt-card" onClick={e => e.stopPropagation()} style={{ "--c": from.color, "--c2": to.color }}>
      <div className="tt-head">
        <div className="tt-route">
          <span className="tt-from" style={{ background: from.color }}>{from.short}</span>
          <span className="tt-arrow">→</span>
          <span className="tt-to" style={{ background: to.color }}>{to.short}</span>
        </div>
        <button className="tt-x" onClick={onClose}>×</button>
      </div>
      <div className="tt-title">SEND A JAB</div>

      <div className="tt-presets">
        {presets.map((p, i) => (
          <button key={i} className="tt-preset" onClick={() => setMsg(p)}>{p}</button>
        ))}
      </div>

      <textarea className="tt-input" value={msg} onChange={e => setMsg(e.target.value)}
        placeholder="Write your own (or pick one above)..." rows="3" maxLength="120" />

      <div className="tt-actions">
        <div className="tt-count">{msg.length}/120</div>
        <button className="tt-send" style={{ background: from.color }} disabled={!msg.trim()} onClick={() => onSend(msg.trim())}>
          ▸ SEND IT
        </button>
      </div>
    </div>
  );
};

// Compute personal records by scanning the full set log.
// Returns { athleteId: { exerciseId: bestWeight } }.
const computePRs = (sets) => {
  const map = {};
  for (const s of sets) {
    if (!s.weight || s.weight <= 0) continue; // ignore bodyweight rows for "PR weight"
    map[s.athlete] = map[s.athlete] || {};
    if (!map[s.athlete][s.exercise] || s.weight > map[s.athlete][s.exercise]) {
      map[s.athlete][s.exercise] = s.weight;
    }
  }
  return map;
};

// Persistence helpers — wrap fetch with safe defaults
const api = {
  state: () => fetch("/api/state").then(r => r.json()),
  upsertAthlete: (athlete) => fetch("/api/athletes", {
    method: "PUT",
    headers: { "content-type": "application/json" },
    body: JSON.stringify(athlete),
  }).then(r => r.json()),
  appendSet: (set) => fetch("/api/sets", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify(set),
  }).then(r => r.json()),
  appendCheer: (cheer) => fetch("/api/cheers", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify(cheer),
  }).then(r => r.json()),
  appendTrash: (msg) => fetch("/api/trash", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify(msg),
  }).then(r => r.json()),
};

const FullBodyTracker = () => {
  const D = window.FITNESS_DATA;
  // Hydration state — true once we've loaded from /api/state
  const [hydrated, setHydrated] = React.useState(false);
  const [hydrationError, setHydrationError] = React.useState(null);

  const [athletes, setAthletes] = React.useState(D.athletes);
  const [whoami, setWhoami] = React.useState("myat");
  const [equipFilter, setEquipFilter] = React.useState("all");
  const [view, setView] = React.useState("track"); // track | body | leaderboard | feed
  const [picker, setPicker] = React.useState(null);
  const [weight, setWeight] = React.useState(0);
  const [reps, setReps] = React.useState(5);
  const [sets, setSets] = React.useState([]);
  const [flash, setFlash] = React.useState(null);
  const [trashIdx, setTrashIdx] = React.useState(0);
  const [windowDays, setWindowDays] = React.useState(7);
  const [howTo, setHowTo] = React.useState(null);
  const [editProfile, setEditProfile] = React.useState(null);
  const [bodyCompare, setBodyCompare] = React.useState({ mode: "solo", second: null });
  const [cheers, setCheers] = React.useState([]);
  const [trashTalk, setTrashTalk] = React.useState([]);
  const [trashOpen, setTrashOpen] = React.useState(false);
  const [trashTarget, setTrashTarget] = React.useState(null);
  const [sundayRecapOpen, setSundayRecapOpen] = React.useState(false);

  // Auto-open weekly recap on Sat/Sun, once per device per day
  React.useEffect(() => {
    const t = new Date(today);
    const day = t.getDay();
    if (day !== 0 && day !== 6) return; // Sun=0, Sat=6
    try {
      const dismissed = localStorage.getItem(`recap-dismissed-${today}`);
      if (!dismissed) setSundayRecapOpen(true);
    } catch {}
  }, [today]);

  // Hydrate from D1-backed API on mount
  React.useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const data = await api.state();
        if (cancelled) return;
        if (data && data.athletes) setAthletes(data.athletes);
        if (data && Array.isArray(data.sets)) setSets(data.sets);
        if (data && Array.isArray(data.cheers)) setCheers(data.cheers);
        if (data && Array.isArray(data.trashTalk)) setTrashTalk(data.trashTalk);
        setHydrated(true);
      } catch (err) {
        console.error("Failed to load state from /api/state:", err);
        if (!cancelled) {
          setHydrationError(err.message || "Failed to load");
          setHydrated(true); // fail-open so the UI still shows seeded reference data
        }
      }
    })();
    return () => { cancelled = true; };
  }, []);

  const activeAthletes = Object.values(athletes).filter(a => !a.placeholder);
  // Derived: PRs from sets (no separate table)
  const prs = React.useMemo(() => computePRs(sets), [sets]);
  const myPRs = prs[whoami] || {};

  const me = athletes[whoami];
  const them = activeAthletes.find(a => a.id !== whoami) || me;
  const compareTarget = bodyCompare.second ? athletes[bodyCompare.second] : them;

  // Today filtered
  const today = "2026-04-27";
  const todaySets = sets.filter(s => s.date === today);
  const myToday = todaySets.filter(s => s.athlete === whoami).reduce((t, s) => t + (s.weight || 0) * s.reps, 0);
  const themToday = todaySets.filter(s => s.athlete !== whoami).reduce((t, s) => t + (s.weight || 0) * s.reps, 0);

  // Muscle volumes for window
  const myVolumes = window.computeMuscleVolume(sets, whoami, windowDays);
  const themVolumes = window.computeMuscleVolume(sets, them.id, windowDays);

  // === LEADERBOARD STATS (computed across all active athletes) ===
  const computeAthleteStats = (aid) => {
    const week = sets.filter(s => {
      if (s.athlete !== aid) return null;
      const d = new Date(s.date);
      const ref = new Date(today);
      const diff = (ref - d) / 86400000;
      return diff >= 0 && diff < 7;
    });
    const month = sets.filter(s => {
      if (s.athlete !== aid) return false;
      const d = new Date(s.date);
      const ref = new Date(today);
      const diff = (ref - d) / 86400000;
      return diff >= 0 && diff < 30;
    });
    const a = athletes[aid];
    const weeklyVolume = week.reduce((t, s) => t + ((s.weight || a.bodyweight || 70) * s.reps), 0);
    const monthlyWorkouts = new Set(month.map(s => s.date)).size;
    const weeklyPRs = week.filter(s => s.isPR).length;
    return {
      id: aid, weeklyVolume, monthlyWorkouts, weeklyPRs,
      streak: a.streak, totalVolume: a.totalVolume, sessions: a.sessions,
      bodyweight: a.bodyweight, color: a.color, short: a.short, name: a.name, avatar: a.avatar
    };
  };
  const leaderStats = activeAthletes.map(a => computeAthleteStats(a.id));
  const groupWeeklyTotal = leaderStats.reduce((t, s) => t + s.weeklyVolume, 0);
  const challengePct = Math.min(100, (groupWeeklyTotal / D.groupChallenge.goal) * 100);

  // Imbalance detection — find under/over trained
  const sortedMuscles = Object.entries(myVolumes).sort((a, b) => b[1] - a[1]);
  const top3 = sortedMuscles.slice(0, 3);
  const bottom3 = sortedMuscles.filter(([k, v]) => v < (top3[0][1] * 0.2)).slice(0, 5);
  const maxVol = top3[0][1] || 1;

  const filteredExercises = equipFilter === "all"
    ? D.exercises
    : D.exercises.filter(e => e.equip === equipFilter);

  const openPicker = (ex) => {
    if (me.placeholder) return;
    setPicker(ex);
    const isBW = ex.equip === "bw" || ex.equip === "pullup";
    setWeight(myPRs[ex.id] || (isBW ? 0 : 20));
    setReps(5);
  };

  const openPickerPrescribed = (ex, weight, reps) => {
    if (me.placeholder) return;
    setPicker(ex);
    setWeight(weight ?? 0);
    setReps(reps ?? 5);
  };

  const commitSet = async () => {
    const isPR = picker.equip !== "bw" && weight > (myPRs[picker.id] || 0);
    const newSet = {
      athlete: whoami,
      exercise: picker.id,
      weight, reps,
      set: sets.filter(s => s.athlete === whoami && s.exercise === picker.id && s.date === today).length + 1,
      date: today,
      time: new Date().toLocaleTimeString("en-GB").slice(0, 5),
      isPR
    };
    // Optimistic update
    setSets(prev => [...prev, { ...newSet, id: `tmp-${Date.now()}` }]);
    setFlash(isPR ? `★ NEW PR · ${weight}kg ★` : `+ SET LOGGED`);
    setTimeout(() => setFlash(null), 1400);
    setPicker(null);
    // Persist
    try {
      const saved = await api.appendSet(newSet);
      // Replace tmp row with the canonical one (so we have the real id)
      setSets(prev => prev.map(s => s.id && String(s.id).startsWith("tmp-") ? saved : s));
    } catch (err) {
      console.error("Failed to persist set:", err);
      setFlash("⚠ NETWORK ERROR — set NOT saved");
      setTimeout(() => setFlash(null), 2400);
    }
  };

  // Save profile changes back into athletes state + persist via API
  const saveProfile = async (id, updates) => {
    const next = { ...athletes[id], ...updates, placeholder: false, id };
    // Optimistic update
    setAthletes(a => ({ ...a, [id]: next }));
    setEditProfile(null);
    try {
      const saved = await api.upsertAthlete(next);
      setAthletes(a => ({ ...a, [id]: { ...a[id], ...saved } }));
    } catch (err) {
      console.error("Failed to persist profile:", err);
      setFlash("⚠ NETWORK ERROR — profile NOT saved");
      setTimeout(() => setFlash(null), 2400);
    }
  };

  // Send a cheer/high-five emoji on a specific set
  const sendCheer = async (setIdx, emoji) => {
    const targetSet = todaySets[todaySets.length - 1 - setIdx];
    if (!targetSet) return;
    const cheer = { from: whoami, to: targetSet.athlete, on: targetSet.exercise, msg: emoji, date: today };
    setCheers(prev => [...prev, cheer]);
    setFlash(`${emoji} CHEER SENT`);
    setTimeout(() => setFlash(null), 1000);
    try {
      await api.appendCheer(cheer);
    } catch (err) {
      console.error("Failed to persist cheer:", err);
    }
  };

  return (
    <div className="ft-root">
      <div className="ft-halftone" />

      {/* HEADER */}
      <div className="ft-header">
        <div className="ft-brand">
          <div className="ft-brand-mark">▮▮▮</div>
          <div className="ft-brand-name">FAMILY FITNESS / SQUAD</div>
          <div className="ft-brand-date">SUN · APR 27 · WK 17</div>
        </div>

        <div className="ft-who ft-who--squad">
          {Object.values(athletes).map(a => {
            const isActive = whoami === a.id;
            const isPlace = a.placeholder;
            return (
              <button key={a.id}
                className={`ft-pill ${isActive ? "ft-pill--on" : ""} ${isPlace ? "ft-pill--ghost" : ""}`}
                style={{ "--c": a.color }}
                onClick={() => {
                  if (isPlace) setEditProfile(a.id);
                  else setWhoami(a.id);
                }}
                onContextMenu={(e) => { e.preventDefault(); setEditProfile(a.id); }}>
                <span className="ft-pill-av" style={{ background: a.color }}>{a.avatar}</span>
                <span className="ft-pill-info">
                  <span className="ft-pill-name">{a.short}</span>
                  <span className="ft-pill-sub">{isPlace ? "TAP TO ADD" : `🔥${a.streak} · ${(a.totalVolume/1000).toFixed(0)}T`}</span>
                </span>
                {!isPlace && <span className="ft-pill-edit" onClick={(e) => { e.stopPropagation(); setEditProfile(a.id); }}>✎</span>}
              </button>
            );
          })}
        </div>
      </div>

      {/* GROUP CHALLENGE BANNER */}
      <div className="ft-challenge">
        <div className="ft-challenge-l">
          <div className="ft-challenge-tag">★ {D.groupChallenge.title}</div>
          <div className="ft-challenge-sub">{D.groupChallenge.period} · {activeAthletes.length} ATHLETES</div>
        </div>
        <div className="ft-challenge-bar">
          <div className="ft-challenge-fill" style={{ width: `${challengePct}%`,
            background: `linear-gradient(90deg, ${activeAthletes.map(a => a.color).join(", ")})` }} />
          <div className="ft-challenge-bar-text">
            <span className="ft-challenge-now">{(groupWeeklyTotal/1000).toFixed(1)}T</span>
            <span className="ft-challenge-goal">/ {(D.groupChallenge.goal/1000).toFixed(0)}T GOAL</span>
          </div>
        </div>
        <div className="ft-challenge-r">
          <div className="ft-challenge-pct">{Math.round(challengePct)}%</div>
        </div>
      </div>

      {/* TABS */}
      <div className="ft-tabs">
        {[
          { id: "track", label: "LOG A SET" },
          { id: "plan", label: "PROGRAMS" },
          { id: "leaderboard", label: "LEADERBOARD" },
          { id: "body", label: "MUSCLE MAP" },
          { id: "feed", label: "ACTIVITY FEED" },
          { id: "journey", label: "MY JOURNEY" }
        ].map(t => (
          <button key={t.id}
            className={`ft-tab ${view === t.id ? "ft-tab--on" : ""}`}
            onClick={() => setView(t.id)}>
            {t.label}
          </button>
        ))}
      </div>

      {/* TRACK VIEW */}
      {view === "track" && (() => {
        const insights = window.coach.computeInsights({
          sets, whoami, athletes, today, exercises: D.exercises
        });
        const handleCoachAction = (action) => {
          if (action.type === "exercise") {
            const ex = D.exercises.find(e => e.id === action.exerciseId);
            if (!ex) return;
            if (action.weight != null) openPickerPrescribed(ex, action.weight, action.reps || 5);
            else openPicker(ex);
          }
        };
        const replayLift = (ex, w, r) => openPickerPrescribed(ex, w, r);
        const prReadySet = window.coach.computePRReady(sets.filter(s => s.athlete === whoami), whoami, D.exercises);
        const prReadyId = prReadySet?.exerciseId;
        const SOC = window.social;

        return (
        <div className="ft-pane">
          <div className="ft-pane-head">
            <div className="ft-pane-title" style={{ color: me.color }}>{me.short}'S RACK</div>
            <div className="ft-pane-sub">PICK EQUIPMENT, TAP A LIFT, LOG IN 2 SECONDS</div>
          </div>

          {/* Live family ticker — only shows if someone in family logged in last 8h */}
          {SOC && <SOC.FamilyTicker sets={sets} athletes={athletes} today={today} whoami={whoami} />}

          {/* Monthly squad challenge */}
          {SOC && <SOC.MonthlyChallenge sets={sets} athletes={athletes} today={today} />}

          {/* Coach insights */}
          <CoachCard insights={insights} onAction={handleCoachAction} />

          {/* Workout of the day */}
          {SOC && <SOC.WorkoutOfDayCard
            sets={sets} whoami={whoami} athletes={athletes} today={today}
            exercises={D.exercises} accent={me.color}
            onStart={(ex, w, r) => openPickerPrescribed(ex, w ?? 0, r ?? 5)} />}

          {/* Recent workouts replay strip */}
          <RecentWorkouts
            sets={sets}
            athleteId={whoami}
            today={today}
            exercises={D.exercises}
            athletes={athletes}
            onReplaySet={replayLift} />

          {/* Equipment filter */}
          <div className="ft-equip">
            <button className={`ft-equip-btn ${equipFilter === "all" ? "ft-equip-btn--on" : ""}`}
              onClick={() => setEquipFilter("all")} style={{ "--c": me.color }}>
              <span className="ft-equip-icon">≡</span><span>ALL · {D.exercises.length}</span>
            </button>
            {D.equipment.map(eq => {
              const count = D.exercises.filter(e => e.equip === eq.id).length;
              return (
                <button key={eq.id}
                  className={`ft-equip-btn ${equipFilter === eq.id ? "ft-equip-btn--on" : ""}`}
                  onClick={() => setEquipFilter(eq.id)} style={{ "--c": me.color }}>
                  <span className="ft-equip-icon">{eq.icon}</span>
                  <span>{eq.label.toUpperCase()} · {count}</span>
                </button>
              );
            })}
          </div>

          {/* Exercise grid */}
          <div className="ft-lifts">
            {filteredExercises.map(ex => {
              const setsForEx = todaySets.filter(s => s.athlete === whoami && s.exercise === ex.id);
              const pr = myPRs[ex.id];
              return (
                <button key={ex.id} className="ft-lift" onClick={() => openPicker(ex)} style={{ "--c": me.color }}>
                  <div className="ft-lift-howto" onClick={(e) => { e.stopPropagation(); setHowTo(ex); }}>?</div>
                  <div className="ft-lift-glyph"><ExerciseGlyph id={ex.id} /></div>
                  <div className="ft-lift-name">{ex.name}</div>
                  <div className="ft-lift-chips">
                    {muscleChips(ex, 3).map(c => (
                      <span key={c.id} className="ft-mus-chip" style={{ "--mc": c.color }}>
                        {c.label}
                      </span>
                    ))}
                  </div>
                  <div className="ft-lift-foot-new">
                    <span className="ft-lift-equip-pill">{D.equipment.find(e => e.id === ex.equip)?.label.toUpperCase()}</span>
                    <span className="ft-lift-pr-new">{pr ? `${pr}KG` : "BW"}</span>
                  </div>
                  {setsForEx.length > 0 && <div className="ft-lift-dot-new">{setsForEx.length}</div>}
                  {prReadyId === ex.id && <div className="ft-lift-pr-ready" title="PR ready — last 2+ sessions show progression">🎯</div>}
                  <div className="ft-lift-muscles" style={{ display: "none" }}>
                    {ex.primary.slice(0, 3).map(m => (
                      <span key={m} className="ft-tag-primary">{D.muscles[m].label}</span>
                    ))}
                    {ex.secondary.slice(0, 2).map(m => (
                      <span key={m} className="ft-tag-secondary">{D.muscles[m].label}</span>
                    ))}
                  </div>
                  <div className="ft-lift-foot" style={{ display: "none" }}>
                    <span className="ft-lift-pr">PR · {pr ? `${pr}kg` : "BW"}</span>
                  </div>
                </button>
              );
            })}
          </div>

          {/* Templates */}
          <div className="ft-templates">
            <div className="ft-templates-lbl">QUICK TEMPLATES ▸</div>
            {D.templates.map(t => (
              <button key={t.id} className="ft-template" style={{ "--c": me.color }}>{t.name.toUpperCase()}</button>
            ))}
          </div>
        </div>
        );
      })()}

      {/* BODY MAP */}
      {view === "body" && (
        <div className="ft-pane">
          <div className="ft-pane-head">
            <div className="ft-pane-title" style={{ color: me.color }}>MUSCLE HEATMAP</div>
            <div className="ft-pane-sub">VOLUME PER GROUP · LAST {windowDays} DAYS</div>
            <div className="ft-window">
              {[7, 14, 30].map(d => (
                <button key={d}
                  className={`ft-window-btn ${windowDays === d ? "ft-window-btn--on" : ""}`}
                  onClick={() => setWindowDays(d)}>
                  {d}D
                </button>
              ))}
            </div>
          </div>

          {/* Compare mode toggle */}
          <div className="ft-compare-mode">
            {[
              { id: "solo", label: "SOLO" },
              { id: "h2h", label: "HEAD-TO-HEAD" },
              { id: "group", label: `GROUP (${activeAthletes.length})` }
            ].map(m => (
              <button key={m.id}
                className={`ft-cmp-btn ${bodyCompare.mode === m.id ? "ft-cmp-btn--on" : ""}`}
                onClick={() => setBodyCompare({ ...bodyCompare, mode: m.id })}
                style={{ "--c": me.color }}>
                {m.label}
              </button>
            ))}
          </div>

          {bodyCompare.mode === "h2h" && (
            <div className="ft-h2h-pick">
              <div className="ft-h2h-lbl">COMPARE WITH ▸</div>
              {activeAthletes.filter(a => a.id !== whoami).map(a => (
                <button key={a.id}
                  className={`ft-h2h-target ${bodyCompare.second === a.id ? "ft-h2h-target--on" : ""}`}
                  style={{ "--c": a.color }}
                  onClick={() => setBodyCompare({ mode: "h2h", second: a.id })}>
                  {a.short}
                </button>
              ))}
            </div>
          )}

          <div className={`ft-bodymap ft-bodymap--${bodyCompare.mode}`}>
            {bodyCompare.mode === "solo" && (
              <div className="ft-bodymap-col">
                <div className="ft-bodymap-name" style={{ color: me.color }}>{me.short}</div>
                <MuscleMap volumes={myVolumes} color={me.color} />
              </div>
            )}
            {bodyCompare.mode === "h2h" && (
              <>
                <div className="ft-bodymap-col">
                  <div className="ft-bodymap-name" style={{ color: me.color }}>{me.short}</div>
                  <MuscleMap volumes={myVolumes} color={me.color} />
                </div>
                <div className="ft-bodymap-col">
                  <div className="ft-bodymap-name" style={{ color: compareTarget.color }}>{compareTarget.short}</div>
                  <MuscleMap volumes={window.computeMuscleVolume(sets, compareTarget.id, windowDays)} color={compareTarget.color} />
                </div>
              </>
            )}
            {bodyCompare.mode === "group" && activeAthletes.map(a => (
              <div key={a.id} className="ft-bodymap-col ft-bodymap-col--small">
                <div className="ft-bodymap-name" style={{ color: a.color }}>{a.short}</div>
                <MuscleMap volumes={window.computeMuscleVolume(sets, a.id, windowDays)} color={a.color} />
              </div>
            ))}
          </div>

          {/* Insights */}
          <div className="ft-insights">
            <div className="ft-insight ft-insight--top">
              <div className="ft-insight-head">⚠ MOST TRAINED ({me.short})</div>
              <div className="ft-insight-list">
                {top3.map(([m, v]) => (
                  <div key={m} className="ft-insight-row">
                    <span className="ft-insight-name">{D.muscles[m].label}</span>
                    <div className="ft-insight-bar"><div className="ft-insight-fill" style={{ width: `${(v / maxVol) * 100}%`, background: me.color }} /></div>
                    <span className="ft-insight-v">{Math.round(v).toLocaleString()}kg</span>
                  </div>
                ))}
              </div>
            </div>

            <div className="ft-insight ft-insight--bottom">
              <div className="ft-insight-head">↗ NEEDS ATTENTION</div>
              {bottom3.length === 0 ? (
                <div className="ft-insight-empty">Balanced ✓ Keep going.</div>
              ) : (
                <div className="ft-insight-list">
                  {bottom3.map(([m, v]) => (
                    <div key={m} className="ft-insight-row">
                      <span className="ft-insight-name">{D.muscles[m].label}</span>
                      <div className="ft-insight-bar"><div className="ft-insight-fill" style={{ width: `${(v / maxVol) * 100}%`, background: "#666" }} /></div>
                      <span className="ft-insight-v">{Math.round(v).toLocaleString()}kg</span>
                    </div>
                  ))}
                </div>
              )}
              <div className="ft-insight-cta">
                {bottom3.length > 0 && <>Try: {D.exercises.filter(ex => ex.primary.some(m => bottom3.find(([id]) => id === m))).slice(0, 3).map(e => e.name).join(" · ")}</>}
              </div>
            </div>
          </div>
        </div>
      )}

      {/* ACTIVITY FEED */}
      {view === "feed" && (
        <div className="ft-pane">
          <div className="ft-pane-head">
            <div className="ft-pane-title">ACTIVITY FEED</div>
            <div className="ft-pane-sub">{todaySets.length} SETS LOGGED TODAY · {activeAthletes.length} ATHLETES · CHEER ANY PR</div>
          </div>

          <div className="ft-feed">
            {todaySets.slice().reverse().map((s, i) => {
              const ath = athletes[s.athlete];
              const ex = D.exercises.find(e => e.id === s.exercise);
              const setCheers = cheers.filter(c => c.to === s.athlete && c.on === s.exercise && c.date === today);
              return (
                <div key={i} className="ft-feed-row">
                  <div className="ft-feed-time">{s.time}</div>
                  <div className="ft-feed-tag" style={{ background: ath.color, color: "#0A0A0A" }}>{ath.short}</div>
                  <div className="ft-feed-info">
                    <div className="ft-feed-ex">{ex.name}</div>
                    <div className="ft-feed-musc">
                      {ex.primary.slice(0, 3).map(m => D.muscles[m].label).join(" · ")}
                    </div>
                  </div>
                  <div className="ft-feed-set">SET {s.set}</div>
                  <div className="ft-feed-load">{s.weight || "BW"}{s.weight ? "kg" : ""} × {s.reps}</div>
                  <div className="ft-feed-vol">{((s.weight || 0) * s.reps).toLocaleString()}kg</div>
                  <div className={s.isPR ? "ft-feed-pr" : "ft-feed-pr ft-feed-pr--placeholder"}>{s.isPR ? "PR" : ""}</div>
                  <div className="ft-feed-social">
                    {setCheers.length > 0 && (
                      <div className="ft-feed-cheers" title={setCheers.map(c => `${athletes[c.from]?.short || c.from} ${c.msg}`).join(" · ")}>
                        {setCheers.map((c, ci) => <span key={ci}>{c.msg}</span>)}
                      </div>
                    )}
                    {s.athlete !== whoami && (
                      <div className="ft-feed-react">
                        <button className="ft-react-btn" onClick={() => sendCheer(i, "🔥")} title="Fire">🔥</button>
                        <button className="ft-react-btn" onClick={() => sendCheer(i, "💪")} title="Strong">💪</button>
                        <button className="ft-react-btn" onClick={() => sendCheer(i, "👏")} title="Clap">👏</button>
                      </div>
                    )}
                  </div>
                </div>
              );
            })}
          </div>

          {/* Trash talk launcher */}
          <div className="ft-trash-launcher">
            <div className="ft-trash-prompt">PLAYFUL JABS · SEND A TRASH TALK TO ANYONE</div>
            <div className="ft-trash-targets">
              {activeAthletes.filter(a => a.id !== whoami).map(a => (
                <button key={a.id}
                  className="ft-trash-target"
                  style={{ "--c": a.color }}
                  onClick={() => { setTrashTarget(a.id); setTrashOpen(true); }}>
                  → {a.short}
                </button>
              ))}
            </div>
          </div>

          {trashTalk.length > 0 && (
            <div className="ft-trash" onClick={() => setTrashIdx((trashIdx + 1) % trashTalk.length)}>
              <div className="ft-trash-tag" style={{ background: athletes[trashTalk[trashIdx].from]?.color || "#666", color: "#0A0A0A" }}>
                {athletes[trashTalk[trashIdx].from]?.short || "—"} → {athletes[trashTalk[trashIdx].to]?.short || "—"}
              </div>
              <div className="ft-trash-msg">"{trashTalk[trashIdx].msg}"</div>
              <div className="ft-trash-next">TAP ▸</div>
            </div>
          )}
        </div>
      )}

      {/* LEADERBOARD DASHBOARD */}
      {view === "leaderboard" && (() => {
        const ranked = (key, descending = true) =>
          [...leaderStats].sort((a, b) => descending ? b[key] - a[key] : a[key] - b[key]);
        const podium = (list, formatter) => list.map((s, i) => ({ ...s, rank: i + 1, value: formatter(s) }));
        const weeklyVol = podium(ranked("weeklyVolume"), s => `${(s.weeklyVolume/1000).toFixed(1)}T`);
        const streaks = podium(ranked("streak"), s => `${s.streak} DAYS`);
        const monthly = podium(ranked("monthlyWorkouts"), s => `${s.monthlyWorkouts} WORKOUTS`);
        const allTime = podium(ranked("totalVolume"), s => `${(s.totalVolume/1000).toFixed(1)}T`);

        // Per-exercise leaderboard for big lifts
        const bigLifts = ["bb_squat", "bb_deadlift", "bb_bench", "bb_ohp", "pu_pullup"];
        const liftBoard = bigLifts.map(eid => {
          const ex = D.exercises.find(e => e.id === eid);
          const rows = activeAthletes.map(a => ({
            id: a.id, color: a.color, short: a.short, avatar: a.avatar,
            value: prs[a.id]?.[eid] || 0,
            rel: (prs[a.id]?.[eid] || 0) / (a.bodyweight || 70)
          })).sort((a, b) => b.value - a.value);
          return { ex, rows };
        });

        const Card = ({ title, sub, rows, accent, valueLabel = "" }) => (
          <div className="lb-card">
            <div className="lb-card-head">
              <div className="lb-card-title">{title}</div>
              <div className="lb-card-sub">{sub}</div>
            </div>
            <div className="lb-rank">
              {rows.map(r => (
                <div key={r.id} className={`lb-row lb-row--${r.rank}`}>
                  <div className="lb-medal">
                    {r.rank === 1 ? "🥇" : r.rank === 2 ? "🥈" : r.rank === 3 ? "🥉" : `#${r.rank}`}
                  </div>
                  <div className="lb-av" style={{ background: r.color }}>{r.avatar}</div>
                  <div className="lb-name">{r.short}</div>
                  <div className="lb-val" style={{ color: r.rank === 1 ? r.color : undefined }}>{r.value}</div>
                </div>
              ))}
            </div>
          </div>
        );

        return (
          <div className="ft-pane">
            <div className="ft-pane-head">
              <div>
                <div className="ft-pane-title">SQUAD LEADERBOARD</div>
                <div className="ft-pane-sub">{activeAthletes.length} ACTIVE ATHLETES · LIVE RANKINGS</div>
              </div>
              <button className="lb-recap-btn" onClick={() => setSundayRecapOpen(true)}>
                👑 WEEKLY RECAP
              </button>
            </div>

            {/* Top: Hero podium for weekly volume */}
            <div className="lb-hero">
              <div className="lb-hero-tag">★ THIS WEEK'S TOP LIFTER</div>
              <div className="lb-podium">
                {[weeklyVol[1], weeklyVol[0], weeklyVol[2]].filter(Boolean).map((s, i) => {
                  const pos = i === 0 ? "left" : i === 1 ? "center" : "right";
                  const heights = { left: 100, center: 140, right: 80 };
                  return (
                    <div key={s.id} className={`lb-stand lb-stand--${pos}`}>
                      <div className="lb-stand-av" style={{ background: s.color }}>{s.avatar}</div>
                      <div className="lb-stand-name">{s.short}</div>
                      <div className="lb-stand-vol" style={{ color: s.color }}>{s.value}</div>
                      <div className="lb-stand-block" style={{ height: heights[pos], background: s.color }}>
                        <div className="lb-stand-rank">#{s.rank}</div>
                      </div>
                    </div>
                  );
                })}
              </div>
            </div>

            {/* Dashboard grid */}
            <div className="lb-grid">
              <Card title="WEEKLY VOLUME" sub="KG LIFTED · LAST 7 DAYS" rows={weeklyVol} />
              <Card title="STREAK" sub="DAYS IN A ROW" rows={streaks} />
              <Card title="THIS MONTH" sub="WORKOUT DAYS" rows={monthly} />
              <Card title="ALL-TIME VOLUME" sub="LIFETIME KG" rows={allTime} />
            </div>

            {/* Per-exercise leaderboard */}
            <div className="lb-lifts">
              <div className="lb-lifts-head">
                <div className="lb-lifts-title">PER-LIFT KING/QUEEN</div>
                <div className="lb-lifts-sub">PR FACE-OFF · MAJOR COMPOUNDS</div>
              </div>
              <div className="lb-lifts-grid">
                {liftBoard.map(({ ex, rows }) => (
                  <div key={ex.id} className="lb-lift">
                    <div className="lb-lift-head">
                      <div className="lb-lift-glyph"><ExerciseGlyph id={ex.id} /></div>
                      <div className="lb-lift-name">{ex.name}</div>
                    </div>
                    <div className="lb-lift-rows">
                      {rows.map((r, ri) => {
                        const max = rows[0].value || 1;
                        return (
                          <div key={r.id} className="lb-lift-row">
                            <div className="lb-lift-rank">{ri === 0 ? "👑" : `#${ri+1}`}</div>
                            <div className="lb-lift-tag" style={{ background: r.color }}>{r.short}</div>
                            <div className="lb-lift-bar">
                              <div className="lb-lift-fill" style={{ width: `${(r.value/max)*100}%`, background: r.color }} />
                              <span className="lb-lift-v">{r.value > 0 ? `${r.value}${ex.equip === "bw" || ex.equip === "pullup" ? "" : "kg"}` : "—"}</span>
                            </div>
                            <div className="lb-lift-rel">{r.value > 0 ? `${r.rel.toFixed(2)}×BW` : ""}</div>
                          </div>
                        );
                      })}
                    </div>
                  </div>
                ))}
              </div>
            </div>

            {/* Solo summary for active user */}
            <div className="lb-solo">
              <div className="lb-solo-head" style={{ color: me.color }}>
                YOUR SCORECARD · {me.short}
              </div>
              <div className="lb-solo-grid">
                {(() => {
                  const myStats = leaderStats.find(s => s.id === whoami) || {};
                  const myRank = (key) => leaderStats.sort((a,b) => b[key]-a[key]).findIndex(s => s.id === whoami) + 1;
                  return [
                    { l: "WEEKLY VOLUME", v: `${(myStats.weeklyVolume/1000).toFixed(1)}T`, r: myRank("weeklyVolume") },
                    { l: "STREAK", v: `${myStats.streak} DAYS`, r: myRank("streak") },
                    { l: "MONTHLY WORKOUTS", v: `${myStats.monthlyWorkouts}`, r: myRank("monthlyWorkouts") },
                    { l: "ALL-TIME", v: `${(myStats.totalVolume/1000).toFixed(1)}T`, r: myRank("totalVolume") }
                  ].map((s, i) => (
                    <div key={i} className="lb-solo-stat" style={{ "--c": me.color }}>
                      <div className="lb-solo-l">{s.l}</div>
                      <div className="lb-solo-v">{s.v}</div>
                      <div className="lb-solo-r">RANK #{s.r}/{activeAthletes.length}</div>
                    </div>
                  ));
                })()}
              </div>
            </div>
          </div>
        );
      })()}

      {/* PICKER MODAL — energetic set logger */}
      {picker && (() => {
        const isBW = picker.equip === "bw";
        const isPullup = picker.equip === "pullup";
        const currentPR = myPRs[picker.id] || 0;
        const lastSet = [...sets].reverse().find(s => s.athlete === whoami && s.exercise === picker.id);
        const willBePR = !isBW && weight > currentPR && weight > 0;
        const volume = weight * reps;
        const weightLabel = isBW ? (weight > 0 ? "+ ADDED LOAD" : "BODYWEIGHT") :
                           isPullup ? (weight > 0 ? "+ WEIGHTED" : "BODYWEIGHT") : "WEIGHT";
        const equipLabel = D.equipment.find(e => e.id === picker.equip)?.label.toUpperCase();

        // Suggestions based on last set + PR
        const suggestions = [];
        if (lastSet) suggestions.push({ label: "REPEAT LAST", w: lastSet.weight, r: lastSet.reps, hint: `${lastSet.weight}×${lastSet.reps}` });
        if (lastSet && !isBW) suggestions.push({ label: "ADD 2.5KG", w: lastSet.weight + 2.5, r: lastSet.reps, hint: `${lastSet.weight + 2.5}×${lastSet.reps}` });
        if (currentPR > 0 && !isBW) suggestions.push({ label: "MATCH PR", w: currentPR, r: 5, hint: `${currentPR}×5` });
        if (!lastSet) suggestions.push({ label: "WARM-UP", w: isBW ? 0 : 20, r: 8, hint: isBW ? "BW×8" : "20×8" });

        return (
          <div className="ft-modal" onClick={() => setPicker(null)}>
            <div className="lg-card" onClick={e => e.stopPropagation()} style={{ "--c": me.color }}>

              {/* Top bar: athlete tag + close */}
              <div className="lg-top">
                <div className="lg-top-l">
                  <div className="lg-tag" style={{ background: me.color }}>{me.short}</div>
                  <div className="lg-meta">
                    <div className="lg-meta-equip">{equipLabel}</div>
                    <div className="lg-meta-name">{picker.name.toUpperCase()}</div>
                  </div>
                </div>
                <div className="lg-top-r">
                  <button className="lg-howto" onClick={() => { setHowTo(picker); setPicker(null); }}>
                    <span className="lg-howto-q">?</span>
                    <span>HOW TO</span>
                  </button>
                  <button className="lg-x" onClick={() => setPicker(null)}>×</button>
                </div>
              </div>

              {/* Muscles hit by this lift */}
              <div className="lg-muscles">
                <span className="lg-muscles-l">HITS</span>
                <div className="lg-muscles-list">
                  {muscleChips(picker, 4).map(c => (
                    <span key={c.id} className="ft-mus-chip ft-mus-chip--solid" style={{ "--mc": c.color }}>
                      {c.label}
                    </span>
                  ))}
                  {secondaryChips(picker, 3).map(c => (
                    <span key={`s-${c.id}`} className="ft-mus-chip ft-mus-chip--ghost" style={{ "--mc": c.color }}>
                      {c.label}
                    </span>
                  ))}
                </div>
              </div>

              {/* Stats strip */}
              <div className="lg-stats">
                <div className="lg-stat">
                  <span className="lg-stat-l">YOUR PR</span>
                  <span className="lg-stat-v">{currentPR > 0 ? `${currentPR}KG` : "—"}</span>
                </div>
                <div className="lg-stat">
                  <span className="lg-stat-l">LAST SET</span>
                  <span className="lg-stat-v">{lastSet ? `${lastSet.weight}×${lastSet.reps}` : "—"}</span>
                </div>
                <div className="lg-stat">
                  <span className="lg-stat-l">VOLUME</span>
                  <span className="lg-stat-v" style={{ color: me.color }}>{volume.toLocaleString()}KG</span>
                </div>
              </div>

              {/* MAIN: weight stacker visual */}
              <div className="lg-stage">
                <div className="lg-stage-bg" />
                {willBePR && <div className="lg-pr-banner">★ NEW PR INCOMING ★</div>}

                {/* Visual: barbell with plates OR dumbbell OR bodyweight icon */}
                <div className="lg-viz">
                  {(picker.equip === "barbell" || picker.equip === "dumbbell") && (
                    <BarbellViz weight={weight} kind={picker.equip === "barbell" ? "bb" : "db"} color={me.color} />
                  )}
                  {(isBW || isPullup) && (
                    <BodyweightViz added={weight} pullup={isPullup} color={me.color} />
                  )}
                </div>

                {/* Big weight number */}
                <div className="lg-w-display">
                  <div className="lg-w-lbl">{weightLabel}</div>
                  <div className="lg-w-num" style={{ color: me.color }}>
                    {isBW && weight === 0 ? "BW" : weight}
                    {!(isBW && weight === 0) && <span className="lg-w-unit">KG</span>}
                  </div>
                </div>
              </div>

              {/* Weight controls: stepper + plate chips */}
              <div className="lg-w-controls">
                <button className="lg-step lg-step--minus" onClick={() => setWeight(Math.max(0, +(weight - 2.5).toFixed(2)))}>−</button>
                <div className="lg-plates">
                  {[1.25, 2.5, 5, 10, 20].map(p => (
                    <button key={p} className="lg-plate" onClick={() => setWeight(+(weight + p).toFixed(2))}>
                      <span className="lg-plate-sign">+</span>
                      <span className="lg-plate-v">{p}</span>
                    </button>
                  ))}
                </div>
                <button className="lg-step lg-step--plus" onClick={() => setWeight(+(weight + 2.5).toFixed(2))}>+</button>
              </div>

              {/* Reps grid — tap-to-set */}
              <div className="lg-reps-block">
                <div className="lg-reps-head">
                  <span className="lg-reps-lbl">REPS</span>
                  <span className="lg-reps-num" style={{ color: me.color }}>×{reps}</span>
                </div>
                <div className="lg-reps-grid">
                  {[1,2,3,4,5,6,7,8,9,10,11,12,15,20].map(n => (
                    <button key={n}
                      className={`lg-rep ${reps === n ? "lg-rep--on" : ""}`}
                      onClick={() => setReps(n)}>{n}</button>
                  ))}
                  <button className="lg-rep lg-rep--more" onClick={() => setReps(reps + 1)}>+1</button>
                </div>
              </div>

              {/* Smart suggestions */}
              {suggestions.length > 0 && (
                <div className="lg-suggest">
                  <div className="lg-suggest-lbl">QUICK PICK</div>
                  <div className="lg-suggest-row">
                    {suggestions.map((s, i) => (
                      <button key={i} className="lg-sug" onClick={() => { setWeight(s.w); setReps(s.r); }}>
                        <span className="lg-sug-l">{s.label}</span>
                        <span className="lg-sug-h">{s.hint}</span>
                      </button>
                    ))}
                  </div>
                </div>
              )}

              {/* COMMIT */}
              <button className="lg-commit" onClick={commitSet} style={{ background: me.color }}>
                <span className="lg-commit-arrow">▸</span>
                <span className="lg-commit-text">LOG THIS SET</span>
                <span className="lg-commit-vol">{volume.toLocaleString()}KG</span>
              </button>
            </div>
          </div>
        );
      })()}

      {/* PROGRAMS — browse-only library */}
      {view === "plan" && <PlansExplorer accent={me.color} />}

      {/* MY JOURNEY — personal analytics + achievements */}
      {view === "journey" && (
        <>
          <JourneyView
            athleteId={whoami}
            allSets={sets}
            athletes={athletes}
            today={today}
          />
          {window.social && (
            <div className="ft-pane" style={{ paddingTop: 0 }}>
              <window.social.AchievementsRail
                athleteId={whoami}
                sets={sets}
                athletes={athletes}
                cheers={cheers}
                today={today}
                accent={me.color}
              />
            </div>
          )}
        </>
      )}

      {/* Sunday recap — pop on Sunday only, dismissible */}
      {sundayRecapOpen && window.social && (
        <window.social.SundayRecap
          sets={sets} athletes={athletes} today={today} whoami={whoami}
          onClose={() => setSundayRecapOpen(false)}
        />
      )}

      {flash && <div className="ft-flash">{flash}</div>}
      {howTo && <HowToView exercise={howTo} color={me.color} onClose={() => setHowTo(null)} />}

      {/* PROFILE EDITOR */}
      {editProfile && (() => {
        const a = athletes[editProfile];
        return (
          <div className="ft-modal" onClick={() => setEditProfile(null)}>
            <ProfileEditor athlete={a} onSave={(updates) => saveProfile(editProfile, updates)} onClose={() => setEditProfile(null)} onCancel={() => setEditProfile(null)} />
          </div>
        );
      })()}

      {/* TRASH TALK MODAL */}
      {trashOpen && trashTarget && (
        <div className="ft-modal" onClick={() => setTrashOpen(false)}>
          <TrashTalkSender from={me} to={athletes[trashTarget]}
            onSend={async (msg) => {
              const entry = { from: whoami, to: trashTarget, msg };
              setTrashTalk(prev => [entry, ...prev]);
              setTrashIdx(0);
              setTrashOpen(false);
              setFlash("💀 TRASH SENT");
              setTimeout(() => setFlash(null), 1200);
              try { await api.appendTrash(entry); }
              catch (err) { console.error("Failed to persist trash talk:", err); }
            }}
            onClose={() => setTrashOpen(false)} />
        </div>
      )}
    </div>
  );
};

window.FullBodyTracker = FullBodyTracker;
