const { Icon } = window.PryzeDesignSystem_b2bad9;
const { USER, REWARDS, COMPANIES, PTS_PER_DOLLAR, NOTIFICATIONS, TODAY_GOALS, ALL_GOALS, ACTIVITY_LOG, ACTION_PLAN } = window.PryzeData;

function NotificationsScreen({ items, onBack, onReadAll, onRead }) {
  const groups = [...new Set(items.map(n => n.group || 'Earlier'))].map(g => [g, items.filter(n => (n.group || 'Earlier') === g)]);
  const unread = items.filter(n => n.unread).length;
  return (
    <div className="nc-screen">
      <div className="gl-head">
        <button className="hm-icon-btn" onClick={onBack}><Icon name="arrow-left" size={18} color="var(--fg-primary)" /></button>
        <div className="gl-head-text">
          <p className="gl-title">Notifications</p>
          <p className="hm-list-sub">{unread > 0 ? unread + ' new' : 'all caught up'}</p>
        </div>
        {unread > 0 && <button className="nc-mark" onClick={onReadAll}>Mark all read</button>}
      </div>
      <div className="nc-body">
        {groups.map(([label, list]) => list.length > 0 && (
          <div className="nc-group" key={label}>
            <p className="gl-group-label">{label}</p>
            <div className="nc-list">
              {list.map(n => (
                <button key={n.id} className={`nc-item ${n.unread ? 'nc-item-unread' : ''}`} onClick={() => onRead(n.id)}>
                  <span className="nc-rail" />
                  <span className="nc-item-body">
                    <span className="nc-item-title">{n.title}</span>
                    <span className="nc-item-sub">{n.body}</span>
                    <span className="nc-meta">
                      <span className={`nc-kind nc-kind-${n.tone}`}><Icon name={n.icon} size={12} weight="fill" color="currentColor" />{n.kind}</span>
                      <span className="nc-time">{n.time}</span>
                    </span>
                  </span>
                </button>
              ))}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

const BOOST_WINDOW = 3 * 3600;
function BoostStrip() {
  const [left, setLeft] = React.useState(2 * 3600 + 14 * 60 + 8);
  React.useEffect(() => { const t = setInterval(() => setLeft(v => (v > 0 ? v - 1 : 0)), 1000); return () => clearInterval(t); }, []);
  const p = n => String(n).padStart(2, '0');
  const pct = Math.max(0, Math.min(1, left / BOOST_WINDOW));
  return (
    <div className="hm-boost">
      <div className="hm-boost-top">
        <span className="hm-boost-x">2<em>×</em></span>
        <div className="hm-boost-mid">
          <p className="hm-boost-say">Everything pays double</p>
          <p className="hm-boost-sub">a 300 pt goal banks <b>600</b> right now</p>
        </div>
      </div>
      <div className="hm-boost-pips">
        {Array.from({ length: 12 }).map((_, i) => (
          <i key={i} className={i < Math.ceil(pct * 12) ? 'is-on' : ''} style={{ '--i': i }} />
        ))}
      </div>
      <div className="hm-boost-foot">
        <span className="hm-boost-timer">{p(Math.floor(left / 3600))}:{p(Math.floor((left % 3600) / 60))}:{p(left % 60)}<em>on the clock</em></span>
        <span className="hm-boost-goals">{Math.ceil(pct * 12)}<em>/12 blocks left</em></span>
      </div>
    </div>
  );
}

function PinnedGoal({ reward, points, onOpen }) {
  const cost = 25 * PTS_PER_DOLLAR;
  const pct = Math.min(1, points / cost);
  const left = Math.max(0, cost - points);
  const [w, setW] = React.useState(0);
  const [plan, setPlan] = React.useState(false);
  React.useEffect(() => { const t = setTimeout(() => setW(pct), 180); return () => clearTimeout(t); }, [pct]);
  return (
    <div className="hm-goal">
      <div className="hm-goal-noise" />
      <span className="hm-goal-sticker">pinned</span>
      <div className="hm-goal-head" onClick={onOpen}>
        <div className="hm-goal-logo">{reward.logo ? <img src={reward.logo} alt="" /> : <span style={{ background: reward.bg }}>{reward.initials}</span>}</div>
        <p className="hm-goal-brand">{reward.title}<span>$25 gift card</span></p>
      </div>
      <p className="hm-goal-say">almost there — <b>{left.toLocaleString()} pts</b> to go, about two shifts</p>
      <div className="hm-goal-track">
        <span className="hm-goal-fill" style={{ width: w * 100 + '%' }} />
        <span className="hm-goal-rider" style={{ left: w * 100 + '%' }}>
          <Icon name="gift" size={13} weight="fill" color="var(--lime-500)" />
          <b>{Math.round(pct * 100)}%</b>
        </span>
      </div>
      <div className="hm-goal-foot">
        <span className="hm-goal-saved">${(points / PTS_PER_DOLLAR).toFixed(2)} of $25 saved</span>
        <button className={`hm-plan-toggle ${plan ? 'hm-plan-open' : ''}`} onClick={() => setPlan(v => !v)}>
          {plan ? 'Hide plan' : 'How I get there'}<Icon name="caret-down" size={12} weight="bold" color="#0E1408" />
        </button>
      </div>
      {plan && (
        <ol className="hm-plan">
          {ACTION_PLAN.map((s, i) => (
            <li className="hm-plan-row" key={i}>
              <span className="hm-plan-mark"><Icon name="circle-dashed" size={15} color="rgba(14,20,8,.5)" /></span>
              <span className="hm-plan-body">
                <span className="hm-plan-step">{s.step}</span>
                <span className="hm-plan-pts">{s.pts}</span>
              </span>
            </li>
          ))}
        </ol>
      )}
    </div>
  );
}

function GoalRow({ g, i, onClick, picked, selectable }) {
  return (
    <button className={`hm-row ${picked ? 'hm-row-picked' : ''}`} onClick={onClick}>
      {selectable
        ? <span className="hm-row-check">{picked && <Icon name="check" size={13} weight="bold" color="#0E1408" />}</span>
        : <span className="hm-row-emoji">{g.emoji || '🎯'}</span>}
      <span className="hm-row-main">
        <span className="hm-row-title">{g.title}</span>
        <span className="hm-row-meta">
          <span className={`hm-src hm-src-${g.src.toLowerCase()}`}>{g.src}</span>
          {g.scope && <span className="hm-scope"><Icon name={g.scope.startsWith('Store') ? 'storefront' : 'buildings'} size={9} color="currentColor" />{g.scope}</span>}
          <span className="hm-row-cad">{g.mins ? g.mins + ' min' : 'instant'}</span>
          {g.cap && <span className="hm-row-cap"><Icon name="repeat" size={10} color="var(--fg-muted)" />{g.cap}</span>}
          {g.hot && <span className="hm-row-hot">🔥 hot</span>}
        </span>
      </span>
      <span className="hm-row-pts">+{g.pts}<em>pts</em></span>
    </button>
  );
}

const SOURCE_INFO = [
  { src: 'Manager', body: 'Set by your store lead, for your store only. These change through the day and often repeat.' },
  { src: 'Company', body: 'Paris Baguette Corp programs. Same goal at every store, usually weekly.' },
  { src: 'Pryze', body: 'Always on, any store, any shift. Small and quick to bank.' },
];

function SourceInfo() {
  const [open, setOpen] = React.useState(false);
  return (
    <React.Fragment>
      <button className="hm-info" onClick={() => setOpen(true)} aria-label="Where goals come from">
        <Icon name="info" size={14} weight="fill" color="var(--fg-muted)" />
      </button>
      {open && (
        <div className="sheet-backdrop sheet-open" onClick={() => setOpen(false)}>
          <div className="sheet-panel hm-src-sheet" onClick={e => e.stopPropagation()}>
            <div className="sheet-handle" />
            <p className="sheet-title">Where goals come from</p>
            <div className="hm-src-list">
              {SOURCE_INFO.map(x => (
                <div className="hm-src-item" key={x.src}>
                  <span className={`hm-src hm-src-${x.src.toLowerCase()}`}>{x.src}</span>
                  <p className="hm-src-body">{x.body}</p>
                </div>
              ))}
            </div>
            <button className="hm-src-close" onClick={() => setOpen(false)}>Got it</button>
          </div>
        </div>
      )}
    </React.Fragment>
  );
}

function GoalList({ goals, onSeeAll }) {
  return (
    <div className="hm-list">
      <p className="hm-list-title">Ways to earn today<SourceInfo /></p>
      <div className="hm-list-rows">
        {goals.map((g, i) => <GoalRow key={g.id} g={g} i={i} onClick={onSeeAll} />)}
      </div>
      <button className="hm-list-all" onClick={onSeeAll}><Icon name="list-checks" size={16} color="var(--color-primary)" />Open the goal list</button>
    </div>
  );
}

function GoldListScreen({ onBack }) {
  const groups = [...new Set(ALL_GOALS.map(g => g.group))];
  const total = ALL_GOALS.reduce((s, g) => s + g.pts, 0);
  return (
    <div className="gl-screen">
      <div className="gl-head">
        <button className="hm-icon-btn" onClick={onBack}><Icon name="arrow-left" size={18} color="var(--fg-primary)" /></button>
        <div className="gl-head-text">
          <p className="gl-title">Goal list</p>
          <p className="hm-list-sub">Manager, company and Pryze</p>
        </div>
        <span className="gl-total">{total.toLocaleString()}<em>pts live</em></span>
      </div>
      <div className="gl-body">
        {groups.map(gr => (
          <div className="gl-group" key={gr}>
            <p className="gl-group-label">{gr}</p>
            <div className="hm-list-rows">
              {ALL_GOALS.filter(g => g.group === gr).map((g, i) => <GoalRow key={g.id} g={g} i={i} />)}
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

/* Picker — "on your mark". Three beats: the payoff, the six, the GO.
   Airy on purpose: one thing per band, nothing competing. */
const bestSix = () => [...ALL_GOALS].sort((a, b) => (b.pts / Math.max(1, b.mins)) - (a.pts / Math.max(1, a.mins))).slice(0, 3).map(g => g.id);

function useCountUp(target) {
  const [n, setN] = React.useState(target);
  const ref = React.useRef(target);
  React.useEffect(() => {
    const from = ref.current, delta = target - from, t0 = performance.now();
    if (!delta) return;
    let raf;
    const tick = t => {
      const p = Math.min(1, (t - t0) / 420);
      setN(Math.round(from + delta * (1 - Math.pow(1 - p, 3))));
      if (p < 1) raf = requestAnimationFrame(tick); else ref.current = target;
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [target]);
  return n;
}

/* Launch: the six you just committed to settle into place, one after another.
   Calm, no spinner, no countdown — it reads as the list becoming real. */
function Boot({ goals, onDone }) {
  const [out, setOut] = React.useState(false);
  React.useEffect(() => {
    const a = setTimeout(() => setOut(true), 300 + goals.length * 250 + 1100);
    const b = setTimeout(onDone, 300 + goals.length * 250 + 1100 + 1450);
    return () => { clearTimeout(a); clearTimeout(b); };
  }, []);
  return (
    <div className={`boot ${out ? 'boot-out' : ''}`}>
      <span className="boot-paint boot-paint-c" />
      <span className="boot-paint boot-paint-b" />
      <span className="boot-paint boot-paint-a">
        {Array.from({ length: 7 }).map((_, i) => <i key={i} style={{ left: 6 + i * 14 + '%', '--d': i }} />)}
      </span>
      <p className="boot-cap" style={{ animationDelay: '80ms' }}>Today's goals</p>
      <div className="boot-list">
        {goals.map((g, i) => (
          <div className="boot-beat" key={g.id} style={{ animationDelay: 300 + i * 250 + 'ms' }}>
            <span className="boot-mark"><Icon name="check" size={11} weight="bold" color="#fff" /></span>
            <span className="boot-emoji">{g.emoji}</span>
            <span className="boot-text">{g.short || g.title}</span>
            <span className="boot-pts">+{g.pts}</span>
          </div>
        ))}
      </div>
      <p className="boot-end" style={{ animationDelay: 420 + goals.length * 250 + 'ms' }}>Shift started</p>
    </div>
  );
}
function GoalPickerScreen({ onBack, onStart }) {
  const MAX = 3;
  const [six, setSix] = React.useState(bestSix);
  const [mode, setMode] = React.useState('suggested');
  const [going, setGoing] = React.useState(false);
  const chosen = six.map(id => ALL_GOALS.find(g => g.id === id)).filter(Boolean);
  const pts = chosen.reduce((s, g) => s + g.pts, 0);
  const mins = chosen.reduce((s, g) => s + g.mins, 0);
  const shown = useCountUp(pts);
  const shuffle = () => setSix([...ALL_GOALS].sort(() => Math.random() - 0.5).slice(0, MAX).map(g => g.id));
  const toggle = id => setSix(s => s.includes(id) ? s.filter(x => x !== id) : (s.length >= MAX ? s : [...s, id]));
  if (going) return <Boot goals={chosen} onDone={() => onStart(chosen)} />;
  return (
    <div className="gp-screen gp-arrive">
      <div className="gp-top">
        <button className="hm-icon-btn" onClick={onBack}><Icon name="arrow-left" size={18} color="var(--fg-primary)" /></button>
        {mode === 'suggested'
          ? <button className="gp-forme" onClick={shuffle}><Icon name="shuffle" size={13} weight="bold" color="var(--color-primary)" />Shuffle</button>
          : <span style={{ width: 38 }} />}
      </div>
      <div className="gp-intro">
        <p className="gp-over">Today</p>
        <p className="gp-say">Your {chosen.length} goals<span> — shuffle for a new set</span></p>
      </div>
      <div className="gp-hero">
        <p className="gp-hero-num">{shown.toLocaleString()}</p>
        <p className="gp-hero-side"><b>points</b><em>·</em><em>{mins} min of work</em></p>
      </div>
      <div className="gp-modes">
        <button className={mode === 'suggested' ? 'gp-mode gp-mode-on' : 'gp-mode'} onClick={() => setMode('suggested')}>Picked for you</button>
        <button className={mode === 'all' ? 'gp-mode gp-mode-on' : 'gp-mode'} onClick={() => setMode('all')}>Choose your own</button>
      </div>
      {mode === 'suggested' ? (
        <div className="gp-six">
          {chosen.map(g => (
            <div className="gp-pick" key={g.id}>
              <span className="gp-pick-emoji">{g.emoji}</span>
              <span className="gp-pick-main">
                <span className="gp-pick-title">{g.short || g.title}</span>
                <span className="gp-pick-meta"><span className={`hm-src hm-src-${g.src.toLowerCase()}`}>{g.src}</span>{g.scope && <span className="hm-scope">{g.scope}</span>}{g.mins ? g.mins + ' min' : 'instant'}</span>
              </span>
              <span className="gp-pick-pts"><span>{'+' + g.pts}</span><em>pts</em></span>
            </div>
          ))}
        </div>
      ) : (
        <div className="gp-six">
          {ALL_GOALS.map(g => {
            const on = six.includes(g.id);
            return (
              <button className={`gp-pick gp-pick-btn ${on ? 'gp-pick-on' : ''} ${!on && six.length >= MAX ? 'gp-pick-full' : ''}`} key={g.id} disabled={!on && six.length >= MAX} onClick={() => toggle(g.id)}>
                <span className="gp-pick-emoji">{g.emoji}</span>
                <span className="gp-pick-main">
                  <span className="gp-pick-title">{g.short || g.title}</span>
                  <span className="gp-pick-meta"><span className={`hm-src hm-src-${g.src.toLowerCase()}`}>{g.src}</span>{g.scope && <span className="hm-scope">{g.scope}</span>}{g.mins ? g.mins + ' min' : 'instant'}</span>
                </span>
                <span className="gp-pick-pts"><span>{'+' + g.pts}</span><em>pts</em></span>
                <span className="gp-pick-check">{on && <Icon name="check" size={12} weight="bold" color="#fff" />}</span>
              </button>
            );
          })}
        </div>
      )}
      <div className="gp-go-wrap">
        <button className="gp-go" disabled={!chosen.length} onClick={() => setGoing(true)}>
          <span className="gp-go-ring" />
          <span className="gp-go-shoulder" />
          <span className="gp-go-cap"><em>GO</em></span>
        </button>
        <p className="gp-go-note">Start shift</p>
      </div>
    </div>
  );
}

const DAY_FACE = (d, best) => {
  if (!d.worked) return '';
  if (d.pts >= best * 0.72) return '🔥';
  if (d.redeemed) return '🎁';
  if (d.kudosGot >= 3) return '💜';
  if (d.pts >= best * 0.4) return '⚡';
  return '';
};
const MONTHS_LONG = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

function DayCard({ day, isRecord, hot }) {
  return (
    <div className="cal-day">
      <div className="cal-detail-head">
        <p className="cal-detail-date">{MONTHS_LONG[day.month].slice(0, 3)} {day.day}
          {isRecord ? <span className="cal-record">your record</span> : hot ? <span className="cal-record cal-record-fire">you cooked</span> : null}</p>
        <span className="cal-detail-pts">{day.pts ? '+' + day.pts.toLocaleString() : '0'}<em>pts</em></span>
      </div>
      {day.worked ? (
        <div className="cal-facts">
          <span className="cal-fact"><em>shift</em><span>{day.start + ' – ' + day.end}</span></span>
          <span className="cal-fact"><em>hours</em><span>{day.hours + 'h'}</span></span>
          <span className="cal-fact"><em>kudos out</em><span>{day.kudosGiven}</span></span>
          <span className="cal-fact"><em>kudos in</em><span>{day.kudosGot}</span></span>
          <span className="cal-fact"><em>goals done</em><span>{day.goalsDone}</span></span>
          <span className="cal-fact"><em>redeemed</em><span>{day.redeemed ? day.redeemed.toLocaleString() + ' pts' : '—'}</span></span>
        </div>
      ) : null}
      {day.items.length ? day.items.map((it, i) => (
        <div className="cal-line" key={i}>
          <span className="cal-line-dot" />
          <span className="cal-line-label">{it.label}</span>
          <span className="cal-line-n">×{it.count}</span>
          <span className="cal-line-pts">+{it.pts}</span>
        </div>
      )) : <p className="cal-empty">day off — you earned it</p>}
      {day.trivia && <p className="cal-trivia"><Icon name="sparkle" size={12} weight="fill" color="var(--lime-500)" />{day.trivia}</p>}
    </div>
  );
}

function CalendarScreen({ onBack }) {
  const [view, setView] = React.useState('month');
  const [sel, setSel] = React.useState(null);
  const [openDay, setOpenDay] = React.useState(null);
  const [mIdx, setMIdx] = React.useState(() => {
    const last = ACTIVITY_LOG[ACTIVITY_LOG.length - 1];
    return [...new Set(ACTIVITY_LOG.map(d => d.year + '-' + d.month))].indexOf(last.year + '-' + last.month);
  });
  const today = ACTIVITY_LOG[ACTIVITY_LOG.length - 1].date;
  const months = [];
  ACTIVITY_LOG.forEach(d => {
    const key = d.year + '-' + d.month;
    let m = months.find(x => x.key === key);
    if (!m) { m = { key, month: d.month, year: d.year, days: [] }; months.push(m); }
    m.days.push(d);
  });
  const best = Math.max(...ACTIVITY_LOG.map(d => d.pts)) || 1;
  const record = ACTIVITY_LOG.find(d => d.pts === best);
  const tier = d => (!d.worked || !d.pts ? 0 : d.pts >= best * 0.72 ? 3 : d.pts >= best * 0.4 ? 2 : 1);
  const workedPts = ACTIVITY_LOG.filter(d => d.worked && d.pts).map(d => d.pts).sort((a, b) => a - b);
  const logTier = d => {
    if (!d.worked || !d.pts) return 0;
    const rank = workedPts.filter(p => p <= d.pts).length / workedPts.length;
    return rank >= 0.72 ? 3 : rank >= 0.38 ? 2 : 1;
  };
  const shifts = ACTIVITY_LOG.filter(d => d.worked).length;
  const total = ACTIVITY_LOG.reduce((s, d) => s + d.pts, 0);
  const fires = ACTIVITY_LOG.filter(d => tier(d) === 3).length;
  const selDay = sel && ACTIVITY_LOG.find(d => d.date === sel);
  const logMonth = months[Math.min(mIdx, months.length - 1)];
  const logDays = [...logMonth.days].reverse();
  const yday = ACTIVITY_LOG[ACTIVITY_LOG.length - 2];
  const isLoop = d => d.worked && d.hours >= 6;
  const isAlive = d => isLoop(d) || d.goalsDone > 0;
  const STATE_LABEL = { power: 'Power', steady: 'Steady', forget: 'Forgetful', dormant: 'Dormant' };
  const stateByDate = {};
  ACTIVITY_LOG.forEach((d, i) => {
    const w = ACTIVITY_LOG.slice(Math.max(0, i - 6), i + 1);
    const loops = w.filter(isLoop).length;
    const goals = w.reduce((s, x) => s + x.goalsDone, 0);
    stateByDate[d.date] = (loops >= 3 && goals >= 3) ? 'power' : (loops >= 1 && goals >= 1) ? 'steady' : (loops >= 1 || goals >= 1) ? 'forget' : 'dormant';
  });
  const runByDate = {};
  const habitDays = new Set();
  let hrun = 0, bestRun = 0;
  ACTIVITY_LOG.forEach(d => {
    hrun = isAlive(d) ? hrun + 1 : 0;
    runByDate[d.date] = hrun;
    bestRun = Math.max(bestRun, hrun);
    if (hrun === 21) habitDays.add(d.date);
  });
  const curRun = runByDate[today] || 0;
  const formed = bestRun >= 21;
  const dayLabel = d => d.date === today ? 'Today' : (yday && d.date === yday.date ? 'Yesterday' : MONTHS_LONG[d.month].slice(0, 3) + ' ' + d.day + ', ' + d.year);
  return (
    <div className="cal-screen">
      <div className="gl-head">
        <button className="hm-icon-btn" onClick={onBack}><Icon name="arrow-left" size={18} color="var(--fg-primary)" /></button>
        <div className="gl-head-text">
          <p className="gl-title">Your run</p>
          <p className="hm-list-sub">{shifts} shifts · {(total / 1000).toFixed(1)}k pts · {fires} 🔥 days</p>
        </div>
      </div>
      <div className="gp-modes cal-tabs">
        <button className={view === 'month' ? 'gp-mode gp-mode-on' : 'gp-mode'} onClick={() => setView('month')}>Month</button>
        <button className={view === 'day' ? 'gp-mode gp-mode-on' : 'gp-mode'} onClick={() => setView('day')}>Activity log</button>
      </div>
      {view === 'month' ? (
        <div className="cal-body">
          <div className={'cal-habit' + (formed ? ' is-formed' : '')}>
            <div className="cal-habit-top">
              <p className="cal-habit-h">{formed ? '21 days — you did it' : `Day ${curRun} of 21`}</p>
              <span className="cal-habit-n">{formed ? 21 : curRun}<em>/21</em></span>
            </div>
            <div className="cal-habit-track">
              {Array.from({ length: 21 }).map((_, i) => <span key={i} className={'cal-habit-pip' + (i < (formed ? 21 : curRun) ? ' is-on' : '')} />)}
            </div>
            <p className="cal-habit-sub">{formed ? 'It takes 21 days to form a habit. You cleared it — from here it gets easier, not harder.' : 'It takes 21 days to form a habit. Show up — a focus loop or a goal banked — and the pips fill.'}</p>
          </div>
          <div className="cal-legend">
            {[['power', 3], ['steady', 2], ['forget', 1], ['dormant', 0]].map(([k, t]) => (
              <span className="cal-legend-item" key={k}><i className={'cal-swatch cal-lt' + t} />{STATE_LABEL[k]}</span>
            ))}
          </div>
          {months.map(m => (
            <div className="cal-month" key={m.key}>
              <div className="cal-month-head">
                <p className="cal-month-label">{MONTHS_LONG[m.month]}</p>
                <p className="cal-month-line">{m.days.filter(x => x.worked).length} shifts · {m.days.reduce((s, x) => s + x.pts, 0).toLocaleString()} pts</p>
              </div>
              <div className="cal-grid">
                {['s', 'm', 't', 'w', 't', 'f', 's'].map((d, i) => <span className="cal-dow" key={i}>{d}</span>)}
                {Array.from({ length: m.days[0].dow }).map((_, i) => <span key={'p' + i} />)}
                {m.days.map(d => {
                  const isRecord = record && d.date === record.date;
                  const st = stateByDate[d.date];
                  const t = st === 'power' ? 3 : st === 'steady' ? 2 : st === 'forget' ? 1 : 0;
                  const pct = [0, .34, .66, 1][t];
                  return (
                    <button key={d.date}
                      className={`cal-cell cal-t${t} ${d.date === today ? 'cal-cell-today' : ''} ${t === 0 ? 'cal-cell-off' : ''} ${habitDays.has(d.date) ? 'cal-cell-h21' : ''}`}
                      onClick={() => setSel(d.date)}>
                      {t > 0 && <span className="cal-bar" style={{ height: (pct * 100) + '%' }} />}
                      {habitDays.has(d.date) && <span className="cal-h21">21</span>}
                      {isRecord && <span className="cal-star"><Icon name="star" size={9} weight="fill" color="#0E1408" /></span>}
                      <span className="cal-num">{d.day}</span>
                    </button>
                  );
                })}
              </div>
            </div>
          ))}
        </div>
      ) : (
        <div className="cal-log">
          <div className="cal-mbar">
            <span className="cal-mbar-main">
              <b>{MONTHS_LONG[logMonth.month]} {logMonth.year}</b>
              <em><span>{logMonth.days.filter(d => d.worked).length} shifts</span><span>{(logMonth.days.reduce((n, d) => n + d.hours, 0)).toFixed(0)}h</span><span>{logMonth.days.reduce((n, d) => n + d.pts, 0).toLocaleString()} pts</span></em>
            </span>
            <button className="cal-mnav" disabled={mIdx === 0} onClick={() => setMIdx(v => Math.max(0, v - 1))} aria-label="Previous month"><Icon name="caret-left" size={14} weight="bold" color="var(--fg-secondary)" /></button>
            <button className="cal-mnav" disabled={mIdx >= months.length - 1} onClick={() => setMIdx(v => Math.min(months.length - 1, v + 1))} aria-label="Next month"><Icon name="caret-right" size={14} weight="bold" color="var(--fg-secondary)" /></button>
          </div>
          <div className="cal-log-body">
            {logDays.map(d => (
              <div className="cal-log-day" key={d.date}>
                <p className="cal-log-label">{dayLabel(d)}</p>
                <button className={`cal-log-card ${openDay === d.date ? 'cal-log-card-open' : ''}`} onClick={() => setOpenDay(v => v === d.date ? null : d.date)}>
                  {record && d.date === record.date
                    ? <span className="cal-log-face">⭐</span>
                    : <span className={`cal-log-dot cal-log-dot-t${logTier(d)}`} />}
                  <span className="cal-log-mid">
                    <span className="cal-log-head">{d.worked ? `${d.goalsDone} ${d.goalsDone === 1 ? 'goal' : 'goals'} banked` : 'Day off'}</span>
                    <span className="cal-log-sub">{d.worked ? `${d.start} – ${d.end} · ${d.hours}h` : 'nothing logged'}</span>
                  </span>
                  <span className="cal-log-big">{d.pts ? '+' + d.pts.toLocaleString() : '—'}</span>
                  <span className="cal-log-caret"><Icon name="caret-down" size={12} weight="bold" color="var(--fg-muted)" /></span>
                </button>
                <div className={`cal-log-more ${openDay === d.date ? 'cal-log-more-open' : ''}`}>
                  <div className="cal-log-more-in">
                    {d.worked && (
                      <div className="cal-log-stats">
                        <span><em>hours</em>{d.hours}h</span>
                        <span><em>goals</em>{d.goalsDone}</span>
                        <span><em>kudos in</em>{d.kudosGot}</span>
                        <span><em>kudos out</em>{d.kudosGiven}</span>
                      </div>
                    )}
                    {d.items.map((it, i) => (
                      <div className="cal-log-item" key={i}>
                        <span className="cal-log-item-dot" />
                        <span className="cal-log-item-name">{it.label}</span>
                        <span className="cal-log-item-n">×{it.count}</span>
                        <span className="cal-log-item-pts">+{it.pts}</span>
                      </div>
                    ))}
                    {d.trivia && <p className="cal-log-trivia"><Icon name="sparkle" size={11} weight="fill" color="var(--color-accent-secondary)" />{d.trivia}</p>}
                    {!d.worked && <p className="cal-log-trivia">day off — you earned it</p>}
                  </div>
                </div>
              </div>
            ))}
          </div>
        </div>
      )}
      {selDay && (
        <div className="sheet-backdrop sheet-open" onClick={() => setSel(null)}>
          <div className="sheet-panel cal-sheet" onClick={e => e.stopPropagation()}>
            <div className="sheet-handle" />
            <DayCard day={selDay} isRecord={record && selDay.date === record.date} hot={tier(selDay) === 3} />
          </div>
        </div>
      )}
    </div>
  );
}

/* Launch sequence, following real liftoff order: thrust ramp against hold-down,
   clamp release, slow climb, then acceleration. */
const IGNITE_MS = 620, CLIMB_MS = 900;
const HINT_WORDS = ['Show up','Lock in','Go time','Let’s get it','Make it count','Be present','Zero in','Be great','Show out','Ryze up','Prove it','Go win','Work','Earn it','Own it','Do it','Game on','Let’s go'];
const HYPE = [
  { t: 'LET’S GOOO', e: '🚀', kind: 'chip' },
  { t: 'no notes', e: '', kind: 'bubble' },
  { t: 'clocked in', e: '⭐', kind: 'chip' },
  { t: 'you ate', e: '🔥', kind: 'bubble' },
  { t: 'main character energy', e: '', kind: 'chip' },
  { t: 'points incoming', e: '💸', kind: 'bubble' },
  { t: 'lock in', e: '🔒', kind: 'chip' },
  { t: 'crew watching', e: '👀', kind: 'bubble' },
  { t: 'that’s the one', e: '✅', kind: 'chip' },
  { t: 'go win', e: '🏆', kind: 'bubble' },
  { t: 'certified', e: '💯', kind: 'chip' },
  { t: 'they’re gonna notice', e: '', kind: 'bubble' },
  { t: 'bag secured', e: '💰', kind: 'chip' },
  { t: 'shift mode', e: '⚡', kind: 'bubble' },
  { t: 'first place feels good', e: '', kind: 'chip' },
  { t: 'unbothered', e: '😤', kind: 'bubble' },
  { t: 'streak alive', e: '🔥', kind: 'chip' },
  { t: 'built different', e: '', kind: 'bubble' },
  { t: 'cash out soon', e: '🎁', kind: 'chip' },
  { t: 'eyes up', e: '👁', kind: 'bubble' },
  { t: 'no days off', e: '', kind: 'chip' },
  { t: 'green all day', e: '🟢', kind: 'bubble' },
  { t: 'run it up', e: '📈', kind: 'chip' },
  { t: 'that’s a W', e: '', kind: 'bubble' },
  { t: 'top of the board', e: '👑', kind: 'chip' },
  { t: 'easy work', e: '🤝', kind: 'bubble' },
  { t: 'manager’s favorite', e: '', kind: 'chip' },
  { t: 'points printer', e: '🖨', kind: 'bubble' },
  { t: 'showtime', e: '🎬', kind: 'chip' },
  { t: 'zero excuses', e: '', kind: 'bubble' },
  { t: 'first in', e: '🥇', kind: 'chip' },
  { t: 'they need you', e: '', kind: 'bubble' },
  { t: 'locked in', e: '🔒', kind: 'chip' },
  { t: 'main character', e: '', kind: 'bubble' },
  { t: 'points loading', e: '💸', kind: 'chip' },
  { t: 'not today', e: '', kind: 'bubble' },
  { t: 'built for this', e: '🛠️', kind: 'chip' },
  { t: 'eyes up', e: '', kind: 'bubble' },
  { t: 'run it', e: '🏃', kind: 'chip' },
  { t: 'aura +100', e: '', kind: 'bubble' },
  { t: 'clock is yours', e: '⏱️', kind: 'chip' },
  { t: 'no half shifts', e: '', kind: 'bubble' },
  { t: 'boss mode', e: '😤', kind: 'chip' },
  { t: 'watch this', e: '', kind: 'bubble' },
  { t: 'streak safe', e: '🔥', kind: 'chip' },
  { t: 'floor is yours', e: '', kind: 'bubble' },
  { t: 'send it', e: '📡', kind: 'chip' },
  { t: 'we outside', e: '', kind: 'bubble' },
  { t: 'cash mode', e: '🤑', kind: 'chip' },
  { t: 'lowkey elite', e: '', kind: 'bubble' },
];
function pickHype() {
  const pool = [...HYPE], out = [];
  while (out.length < 12 && pool.length) out.push(pool.splice(Math.floor(Math.random() * pool.length), 1)[0]);
  return out;
}

function StartDial({ onLaunch, floodRef, forcedIdle }) {
  const [dragging, setDragging] = React.useState(false);
  const [phase, setPhase] = React.useState('idle');
  const dialRef = React.useRef(null);
  const st = React.useRef({ y: 0, active: false });
  const GRAB = 30;

  // The dome is a full-height sheet scaled from its base, so every pointer sample
  // lands as a transform (no layout constraint can freeze it).
  const paint = d => {
    if (dialRef.current) dialRef.current.style.transform = `translateY(${-d}px)`;
    const f = floodRef.current;
    if (f) {
      f.classList.remove('hm-flood-go');
      f.style.visibility = 'visible';
      f.style.transform = `scaleY(${0.02 + (d / GRAB) * 0.2})`;
    }
  };
  const reset = () => {
    if (dialRef.current) dialRef.current.style.transform = '';
    const f = floodRef.current;
    if (f) { f.classList.remove('hm-flood-go'); f.getAnimations().forEach(a => a.cancel()); f.style.transform = 'scaleY(0)'; f.style.visibility = 'hidden'; }
  };

  const fire = () => {
    st.current.active = false;
    setDragging(false);
    setPhase('ignite');
    if (dialRef.current) dialRef.current.style.transform = '';
    setTimeout(() => {
      setPhase('climb');
      const f = floodRef.current;
      if (f) { f.getAnimations().forEach(a => a.cancel()); f.classList.add('hm-flood-go'); }
    }, IGNITE_MS);
    setTimeout(() => { onLaunch(); setPhase('idle'); reset(); }, IGNITE_MS + CLIMB_MS + 120);
  };

  const down = e => { if (phase !== 'idle') return; st.current = { y: e.clientY, active: true }; setDragging(true); e.currentTarget.setPointerCapture(e.pointerId); paint(0); };
  const move = e => {
    if (!st.current.active || phase !== 'idle') return;
    const d = Math.min(GRAB, Math.max(0, st.current.y - e.clientY));
    paint(d);
    if (d >= GRAB) fire();
  };
  const up = () => { if (st.current.active) { st.current.active = false; setDragging(false); reset(); } };

  const [word, setWord] = React.useState(0);
  const [hype, setHype] = React.useState(pickHype);
  const [idleState, setIdleState] = React.useState('active');
  React.useEffect(() => {
    if (forcedIdle && forcedIdle !== 'auto') { setIdleState(forcedIdle); return; }
    if (phase !== 'idle') { setIdleState('active'); return; }
    const nudgeT = setTimeout(() => setIdleState('nudge'), 30000);
    return () => { clearTimeout(nudgeT); };
  }, [phase, forcedIdle]);
  React.useEffect(() => {
    if (phase !== 'idle') return;
    const t = setInterval(() => setWord(w => (w + 1) % HINT_WORDS.length), 2200);
    return () => clearInterval(t);
  }, [phase]);
  React.useEffect(() => { if (phase === 'ignite') setHype(pickHype()); }, [phase]);
  const busy = phase !== 'idle';
  return (
    <div className={`hm-dial-wrap ${dragging ? 'hm-dial-drag' : ''} hm-ph-${phase} ${idleState === 'nudge' ? 'hm-nudge' : ''}`}>
      {idleState === 'nudge' && <span className="hm-nudge-wisp" />}
      {!busy && !dragging && <span className="hm-swipe-cue" aria-hidden="true"><i /><i /></span>}
      {(dragging || busy) && (
        <div className="hm-fog">
          {Array.from({ length: 10 }).map((_, i) => <i key={i} style={{ '--i': i, animationDelay: i * 290 + 'ms' }} />)}
        </div>
      )}
      {busy && (
        <div className="hm-clouds">
          {Array.from({ length: 9 }).map((_, i) => (
            <span key={i} className="hm-cloud" style={{ '--i': i, left: 50 + (i % 2 ? 1 : -1) * (4 + i * 5) + '%', animationDelay: i * 70 + 'ms' }}>
              <i /><i /><i />
            </span>
          ))}
        </div>
      )}
      {busy && (
        <div className="hm-smoke">
          {Array.from({ length: 14 }).map((_, i) => (
            <span key={i} className="hm-puff" style={{ '--i': i, left: 50 + (i % 2 ? 1 : -1) * (6 + i * 3) + '%', animationDelay: i * 45 + 'ms' }} />
          ))}
        </div>
      )}
      <button className="hm-dial" ref={dialRef}
        onPointerDown={down} onPointerMove={move} onPointerUp={up} onPointerCancel={up}>
        <span className="hm-dial-ring" />
        <span className="hm-dial-ring2" />
        <span className="hm-dial-core"><span className="hm-rocket" aria-hidden="true"><b /><b /></span></span>
        <span className="hm-flame"><i /><i /></span>
      </button>
      <span className="hm-dial-hint">{phase === 'ignite' ? 'ignition' : phase === 'climb' ? 'we have liftoff' : dragging ? (
        <span className="hm-word-slot"><span className="hm-word hm-word-armed" key="armed">ready to launch — keep going up</span></span>
      ) : (
        <span className="hm-word-slot"><span className="hm-word" key={word}>{HINT_WORDS[word]}</span></span>
      )}</span>
      {busy && (
        <div className="hm-stickers">
          {hype.map((x, i) => (
            <span key={x.t} className={`hm-sticker hm-sticker-${x.kind} hm-sticker-p${i}`}>
              {x.t}{x.e && <b>{x.e}</b>}
            </span>
          ))}
        </div>
      )}
    </div>
  );
}

function BalancePill({ earned = 0, onShown }) {
  const base = USER.points;
  const [n, setN] = React.useState(base);
  const [hot, setHot] = React.useState(false);
  React.useEffect(() => {
    if (!earned) return;
    setHot(true);
    let raf, t0;
    const tick = t => {
      if (!t0) t0 = t;
      const p = Math.min(1, (t - t0) / 1400);
      setN(Math.round(base + earned * (1 - Math.pow(1 - p, 3))));
      if (p < 1) raf = requestAnimationFrame(tick);
      else { setTimeout(() => setHot(false), 700); onShown && onShown(); }
    };
    const start = setTimeout(() => { raf = requestAnimationFrame(tick); }, 420);
    return () => { clearTimeout(start); cancelAnimationFrame(raf); };
  }, [earned]);
  return (
    <div className={'balance-pill' + (hot ? ' is-hot' : '')}>
      <span className="coin"><Icon name="sparkle" size={13} weight="fill" color="var(--neutral-950)" /></span>
      {n.toLocaleString()}
      {hot && <span className="balance-bump">+{earned}</span>}
    </div>
  );
}

function BoostOfferPop({ offer, onAccept, onDecline }) {
  return (
    <div className="bo-back" onClick={onDecline}>
      <div className="bo-pop" onClick={e => e.stopPropagation()}>
        <span className="bo-streaks">{Array.from({ length: 7 }).map((_, i) => <i key={i} style={{ '--i': i }} />)}</span>
        <p className="bo-kick"><i />POWER-UP INCOMING</p>
        <div className="bo-x">2<em>×</em></div>
        <p className="bo-head">3 hours to<br />double your rate</p>
        <div className="bo-meter"><span className="bo-meter-fill" /><em>energy full</em></div>
        <div className="bo-stats">
          <span><b>600</b><em>pts on a 300 goal</em></span>
          <span><b>3h</b><em>on the clock</em></span>
          <span><b>{offer.goal.split(' ')[0]}</b><em>boosted goal</em></span>
        </div>
        <p className="bo-line">{offer.from} put this on you. Every rep counts twice while it burns — go beat your own number.</p>
        <button className="bo-ok" onClick={onAccept}>TAKE THE 2×</button>
        <button className="bo-no" onClick={onDecline}>Not now</button>
      </div>
    </div>
  );
}

function HomeScreen({ onLaunch, onOpenReward, onOpenCalendar, onOpenList, onOpenNotes, onOpenManager, unread = 0, boostLive, boostOffer, onAcceptBoost, onDeclineBoost, pinnedReward, rocketPreview, earned = 0, onEarnedShown }) {
  const pinned = pinnedReward || REWARDS.find(r => r.id === 'starbucks');
  const company = COMPANIES[USER.company];
  const floodRef = React.useRef(null);
  return (
    <div className="hm-screen">
      <div className="hm-body">
        <div className="hm-top">
          <button className="hm-icon-btn" onClick={onOpenCalendar} aria-label="Activity"><Icon name="calendar-blank" size={18} color="var(--fg-primary)" /></button>
          <div className="hm-actions">
            <button className="hm-mgr" onClick={onOpenManager}><Icon name="crown-simple" size={14} weight="fill" color="var(--lime-500)" />Manager</button>
            <button className="hm-icon-btn" onClick={onOpenNotes} aria-label="Notifications">
              <Icon name="bell" size={18} weight="fill" color="var(--fg-primary)" />
              {unread > 0 && <span className="hm-bell-dot">{unread}</span>}
            </button>
          </div>
        </div>
        <div className="hm-ident">
          <div className="hm-ident-row">
            <img className="hm-avatar" src={USER.photo} alt="" />
            <p className="hm-name">hey {USER.name.split(' ')[0]}</p>
            <BalancePill earned={earned} onShown={onEarnedShown} />
          </div>
          <div className="hm-meta">
            <span className="hm-crew">{company.logo ? <img src={company.logo} alt="" /> : null}{USER.store}<b>#9</b></span>
            <span className="hm-streak">{USER.streak} day streak</span>
          </div>
        </div>
        {boostLive && <BoostStrip />}
        <PinnedGoal reward={pinned} points={USER.points} onOpen={() => onOpenReward && onOpenReward(pinned)} />
        <GoalList goals={TODAY_GOALS} onSeeAll={onOpenList} />
      </div>
      <div className="hm-dock"><StartDial onLaunch={onLaunch} floodRef={floodRef} forcedIdle={rocketPreview} /></div>
      <div className="hm-flood" ref={floodRef} style={{ transform: 'scaleY(0)', visibility: 'hidden' }}>
        <span className="hm-arc" />
      </div>
      {boostOffer && <BoostOfferPop offer={boostOffer} onAccept={onAcceptBoost} onDecline={onDeclineBoost} />}
    </div>
  );
}

window.PryzeHome = { HomeScreen, GoldListScreen, GoalPickerScreen, CalendarScreen, NotificationsScreen };
