// mograndom — all six screens. Each accepts ({ ctx }) where ctx contains
// theme, currentMu, opponentMu, hype, phase. Screens are designed to fill
// their parent (artboard) at any size; sizing happens via the artboard.

// ─────────────────────────────────────────────────────────────────────────
// 1. LANDING / SIGNUP — age + category lock
// ─────────────────────────────────────────────────────────────────────────
function ScreenLanding({ ctx }) {
  const [stage, setStage] = React.useState('hero'); // hero | verify | category
  const [cat, setCat] = React.useState('f_25_34');
  const [name, setName] = React.useState('');

  return (
    <div className="mg mg-screen" style={{ display: 'flex', flexDirection: 'column' }}>
      <TopBar tab="landing" />
      <div style={{ flex: 1, display: 'grid', gridTemplateColumns: '1.05fr 0.95fr', minHeight: 0 }}>
        {/* LEFT — pitch */}
        <div style={{ padding: '64px 56px 56px', display: 'flex', flexDirection: 'column', justifyContent: 'space-between', borderRight: '1px solid var(--mg-line)' }}>
          <div>
            <div className="mg-label" style={{ marginBottom: 22 }}>SEASON 1 · ORIGIN — ENDS IN 23D 14H</div>
            <h1 className="mg-display" style={{ fontSize: 76, margin: 0, textWrap: 'balance' }}>
              Two cameras.<br/>
              One verdict.<br/>
              <span style={{ color: 'var(--mg-text-3)' }}>Decided by the people in the room.</span>
            </h1>
            <p style={{ marginTop: 24, maxWidth: 520, color: 'var(--mg-text-2)', fontSize: 16, lineHeight: 1.5 }}>
              mograndom pairs you 1‑on‑1 with a stranger in your bracket. You both call the winner. Glicko‑2 does the math. No algorithmic scoring of faces — every result comes from a human on the other end.
            </p>
            <div style={{ marginTop: 32, display: 'flex', gap: 12 }}>
              <button className="mg-btn mg-btn-primary" onClick={() => setStage('verify')}>Enter the queue</button>
              <button className="mg-btn mg-btn-ghost">How rating works</button>
            </div>
            <div style={{ marginTop: 28, display: 'flex', gap: 28, color: 'var(--mg-text-3)', fontSize: 12 }}>
              <Stat n="184k" label="matches this season" />
              <Stat n="12" label="categories" />
              <Stat n="0" label="algorithmic face scoring" />
            </div>
          </div>
          <div style={{ display: 'flex', gap: 18, alignItems: 'center', color: 'var(--mg-text-3)', fontSize: 11.5 }} className="mg-mono">
            <span>18+ · ID-VERIFIED</span>
            <span style={{ width: 4, height: 4, borderRadius: 999, background: 'currentColor' }} />
            <span>COMMIT-REVEAL FAIRNESS</span>
            <span style={{ width: 4, height: 4, borderRadius: 999, background: 'currentColor' }} />
            <span>NO RECORDING</span>
          </div>
        </div>

        {/* RIGHT — staged signup */}
        <div style={{ padding: '64px 56px', display: 'flex', flexDirection: 'column', gap: 24, background: 'var(--mg-bg-2)' }}>
          <SignupSteps stage={stage} />
          {stage === 'hero' && (
            <SignupCard title="Pick a handle" sub="Display only. Your real identity stays with the verifier.">
              <input className="mg-input" placeholder="e.g. lacquer.bird" value={name} onChange={(e) => setName(e.target.value)} />
              <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
                <button className="mg-btn mg-btn-primary" disabled={name.length < 2} onClick={() => setStage('verify')}>Continue</button>
                <button className="mg-btn mg-btn-ghost" onClick={() => setName('lacquer.bird')}>Suggest one</button>
              </div>
            </SignupCard>
          )}
          {stage === 'verify' && (
            <SignupCard title="Age & identity check" sub="Handled by Persona. We store a token, never your document.">
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
                <VerifyTile vendor="Persona" sub="Government ID + selfie" active />
                <VerifyTile vendor="Stripe Identity" sub="If you already have an account" />
              </div>
              <div style={{ marginTop: 14, padding: 12, border: '1px dashed var(--mg-line-2)', borderRadius: 6, fontSize: 12, color: 'var(--mg-text-3)' }} className="mg-mono">
                age_verification_provider = "persona"<br/>
                age_verification_ref = "evf_4QnL…ax9k"<br/>
                category_lock = derived from gov_id; user cannot edit
              </div>
              <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
                <button className="mg-btn mg-btn-primary" onClick={() => setStage('category')}>Verify (mock)</button>
              </div>
            </SignupCard>
          )}
          {stage === 'category' && (
            <SignupCard title="Your bracket" sub="Locked at signup against your verified DOB so nobody can sandbag.">
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 6 }}>
                {CATEGORIES.map(c => (
                  <button key={c.id} onClick={() => setCat(c.id)}
                    style={{
                      padding: '10px 12px', textAlign: 'left',
                      border: `1px solid ${c.id === cat ? 'var(--mg-text)' : 'var(--mg-line)'}`,
                      background: c.id === cat ? 'color-mix(in oklab, var(--mg-text) 6%, transparent)' : 'var(--mg-surface)',
                      borderRadius: 6, color: 'var(--mg-text)', cursor: 'pointer',
                      font: 'inherit', fontSize: 13,
                    }}>
                    <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                      <span>{c.display}</span>
                      <span className="mg-mono" style={{ color: 'var(--mg-text-3)', fontSize: 10 }}>{c.id}</span>
                    </div>
                  </button>
                ))}
              </div>
              <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
                <button className="mg-btn mg-btn-primary">Lock & enter lobby</button>
              </div>
            </SignupCard>
          )}
        </div>
      </div>
    </div>
  );
}
function Stat({ n, label }) {
  return (
    <div>
      <div className="mg-mono" style={{ color: 'var(--mg-text)', fontSize: 22, fontWeight: 600 }}>{n}</div>
      <div className="mg-label" style={{ marginTop: 4 }}>{label}</div>
    </div>
  );
}
function SignupSteps({ stage }) {
  const steps = [['hero', 'Handle'], ['verify', 'Verify'], ['category', 'Bracket']];
  const i = steps.findIndex(s => s[0] === stage);
  return (
    <div style={{ display: 'flex', gap: 0, alignItems: 'center', fontFamily: 'JetBrains Mono, monospace', fontSize: 11, letterSpacing: '0.1em', textTransform: 'uppercase' }}>
      {steps.map(([key, label], idx) => (
        <React.Fragment key={key}>
          <span style={{ color: idx <= i ? 'var(--mg-text)' : 'var(--mg-text-3)' }}>
            {String(idx + 1).padStart(2, '0')} · {label}
          </span>
          {idx < steps.length - 1 && <span style={{ width: 36, height: 1, background: 'var(--mg-line-2)', margin: '0 14px' }} />}
        </React.Fragment>
      ))}
    </div>
  );
}
function SignupCard({ title, sub, children }) {
  return (
    <div className="mg-card" style={{ padding: 28, animation: 'mg-fade-up 220ms ease-out' }}>
      <div style={{ fontSize: 20, fontWeight: 600, letterSpacing: '-0.02em' }}>{title}</div>
      {sub && <div style={{ color: 'var(--mg-text-3)', fontSize: 13, marginTop: 4, marginBottom: 18 }}>{sub}</div>}
      {children}
    </div>
  );
}
function VerifyTile({ vendor, sub, active }) {
  return (
    <div style={{
      padding: 14, borderRadius: 6,
      border: `1px solid ${active ? 'var(--mg-text)' : 'var(--mg-line)'}`,
      background: 'var(--mg-surface)',
    }}>
      <div style={{ fontWeight: 600 }}>{vendor}</div>
      <div style={{ color: 'var(--mg-text-3)', fontSize: 12, marginTop: 2 }}>{sub}</div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// 2. LOBBY — matchmaking queue
// ─────────────────────────────────────────────────────────────────────────
function ScreenLobby({ ctx }) {
  const [queued, setQueued] = React.useState(true);
  const [t, setT] = React.useState(7);
  useInterval(() => setT(x => x + 1), queued ? 1000 : null);

  const myTier = tierFor(ctx.currentMu, ctx.theme);
  const oppTier = tierFor(ctx.opponentMu, ctx.theme);
  const inMyBand = OPPONENTS.filter(o => Math.abs(o.mu - ctx.currentMu) < 600).slice(0, 6);

  return (
    <div className="mg mg-screen" style={{ display: 'flex', flexDirection: 'column' }}>
      <TopBar tab="play" myTier={myTier} myMu={ctx.currentMu} />
      <div style={{ flex: 1, display: 'grid', gridTemplateColumns: '1fr 380px', minHeight: 0 }}>
        {/* center — finder */}
        <div style={{ padding: '56px 56px', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', position: 'relative' }}>
          <RadarFinder color={myTier.color} />
          <div className="mg-label" style={{ marginTop: -16 }}>SEARCHING · {ctx.category || 'WOMEN, 25–34'}</div>
          <div className="mg-display" style={{ fontSize: 56, marginTop: 14 }}>
            <span className="mg-mono">{String(Math.floor(t / 60)).padStart(2, '0')}:{String(t % 60).padStart(2, '0')}</span>
          </div>
          <div style={{ color: 'var(--mg-text-3)', fontSize: 13, marginTop: 6 }}>
            avg time at this tier · 14s
          </div>
          <div style={{ marginTop: 36, display: 'flex', gap: 8 }}>
            <button className="mg-btn" onClick={() => setQueued(false)}>Cancel queue</button>
            <button className="mg-btn mg-btn-ghost">Widen tier band ±400 μ</button>
          </div>
          <div style={{ position: 'absolute', bottom: 24, left: 56, right: 56, display: 'flex', justifyContent: 'space-between', color: 'var(--mg-text-3)', fontSize: 11 }} className="mg-mono">
            <span>FAIR PAIRING · LAST OPP DECAY 12H</span>
            <span>RTT 38ms · LIVEKIT EU-WEST</span>
          </div>
        </div>
        {/* right — context */}
        <div style={{ padding: '24px 24px', display: 'flex', flexDirection: 'column', gap: 14, borderLeft: '1px solid var(--mg-line)', background: 'var(--mg-bg-2)', overflowY: 'auto' }}>
          <SidePanel title="Your tier">
            <TierProgress mu={ctx.currentMu} theme={ctx.theme} />
          </SidePanel>
          <SidePanel title="Likely opponents">
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              {inMyBand.map(o => (
                <div key={o.id} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 10px', border: '1px solid var(--mg-line)', borderRadius: 6, background: 'var(--mg-surface)' }}>
                  <Avatar seed={o.id} size={28} />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 13, fontWeight: 500 }}>{o.name}</div>
                    <div className="mg-mono" style={{ color: 'var(--mg-text-3)', fontSize: 10 }}>{flagOf(o.country)} · {o.w}–{o.l}</div>
                  </div>
                  <TierChip tier={tierFor(o.mu, ctx.theme)} size="sm" />
                </div>
              ))}
            </div>
          </SidePanel>
          <SidePanel title="Match rules">
            <ul style={{ margin: 0, padding: 0, listStyle: 'none', display: 'flex', flexDirection: 'column', gap: 8, color: 'var(--mg-text-2)', fontSize: 12.5 }}>
              <li>· 30s call · then 20s commit · then 10s reveal</li>
              <li>· Both contestants must vote a winner</li>
              <li>· Disconnect = forfeit (rating loss capped)</li>
              <li>· Recordings disabled — peer streams ephemeral</li>
            </ul>
          </SidePanel>
        </div>
      </div>
    </div>
  );
}

function RadarFinder({ color }) {
  return (
    <div style={{ width: 320, height: 320, position: 'relative' }}>
      {[0, 1, 2].map(i => (
        <div key={i} style={{
          position: 'absolute', inset: 0,
          border: `1px solid ${color}`, borderRadius: '50%', opacity: 0.18,
          animation: `mg-radar 2.4s ${i * 0.8}s ease-out infinite`,
        }} />
      ))}
      <div style={{ position: 'absolute', inset: 100, borderRadius: '50%', border: `1px solid ${color}`, opacity: 0.4 }} />
      <div style={{
        position: 'absolute', left: '50%', top: '50%', width: 12, height: 12, marginLeft: -6, marginTop: -6,
        borderRadius: '50%', background: color, boxShadow: `0 0 24px ${color}`,
      }} />
      <style>{`@keyframes mg-radar { 0% { transform: scale(0.6); opacity: 0.6; } 100% { transform: scale(1.2); opacity: 0; } }`}</style>
    </div>
  );
}

function SidePanel({ title, children }) {
  return (
    <div className="mg-card" style={{ padding: 14 }}>
      <div className="mg-label" style={{ marginBottom: 10 }}>{title}</div>
      {children}
    </div>
  );
}

function TierProgress({ mu, theme, compact }) {
  const p = progressToNextTier(mu, theme);
  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
        <TierChip tier={p.current} size="md" />
        {p.next && <TierChip tier={p.next} size="sm" muted />}
      </div>
      <div style={{ height: 6, background: 'var(--mg-bg-2)', borderRadius: 999, overflow: 'hidden', border: '1px solid var(--mg-line)' }}>
        <div style={{
          width: `${p.percent * 100}%`, height: '100%',
          background: `linear-gradient(90deg, ${p.current.color}, ${p.current.glow})`,
        }} />
      </div>
      <div className="mg-mono" style={{ display: 'flex', justifyContent: 'space-between', marginTop: 8, fontSize: 11, color: 'var(--mg-text-3)' }}>
        <span>μ {fmtMu(mu)}</span>
        {!compact && <span>{p.next ? `+${p.eloToNext} to ${p.next.name}` : 'apex'}</span>}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// 3. LIVE BATTLE — Variation A (Broadcast) and Variation B (Arena)
// ─────────────────────────────────────────────────────────────────────────
function ScreenLive({ ctx, variant = 'broadcast' }) {
  // phase comes from ctx.phase ('countdown' | 'live' | 'wrap')
  const phase = ctx.livePhase || 'live';
  const [countdown, setCountdown] = React.useState(3);
  React.useEffect(() => {
    if (phase !== 'countdown') return;
    setCountdown(3);
    const id = setInterval(() => setCountdown(c => Math.max(0, c - 1)), 800);
    return () => clearInterval(id);
  }, [phase]);

  const [t, setT] = React.useState(0);
  useInterval(() => setT(x => x + 1), phase === 'live' ? 1000 : null);
  const total = 30;
  const remaining = Math.max(0, total - t);

  const myTier = tierFor(ctx.currentMu, ctx.theme);
  const oppTier = tierFor(ctx.opponentMu, ctx.theme);

  if (variant === 'arena') return <LiveArena ctx={ctx} myTier={myTier} oppTier={oppTier} remaining={remaining} total={total} phase={phase} countdown={countdown} />;
  return <LiveBroadcast ctx={ctx} myTier={myTier} oppTier={oppTier} remaining={remaining} total={total} phase={phase} countdown={countdown} />;
}

function LiveBroadcast({ ctx, myTier, oppTier, remaining, total, phase, countdown }) {
  const { videoRef, state, request } = useWebcam();
  const canvasRef = React.useRef(null);
  const myPresence = usePresenceEngine({ videoRef, canvasRef, active: state === 'live', accentColor: myTier.color });
  const oppPresence = useSimulatedPresence({ targetMu: ctx.opponentMu, hot: phase === 'live' });
  return (
    <div className="mg mg-screen" style={{ display: 'flex', flexDirection: 'column', background: '#000' }}>
      {/* compact broadcast bar */}
      <div style={{ height: 56, padding: '0 22px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', background: 'var(--mg-bg)', borderBottom: '1px solid var(--mg-line)' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
          <LiveDot />
          <span className="mg-mono" style={{ fontSize: 11, letterSpacing: '0.14em', color: 'var(--mg-text-2)' }}>MATCH 0xA47C · {ctx.category?.toUpperCase() || 'WOMEN, 25–34'}</span>
        </div>
        <Timer remaining={remaining} total={total} hype={ctx.hype} />
        <div className="mg-mono" style={{ fontSize: 11, color: 'var(--mg-text-3)' }}>RTT 36 · LIVEKIT</div>
      </div>

      {/* split panels */}
      <div style={{ flex: 1, display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 1, background: 'var(--mg-line)', position: 'relative' }}>
        <CamPanel
          side="left" name="you" tier={myTier} mu={ctx.currentMu}
          videoRef={videoRef} canvasRef={canvasRef} camState={state} onRequest={request}
          presence={myPresence} presenceColor={myTier.color}
          isYou
        />
        <CamPanel
          side="right" name={ctx.opponentName} tier={oppTier} mu={ctx.opponentMu}
          presence={oppPresence} presenceColor={oppTier.color}
          isYou={false} seed={42} hue={oppTier.color === '#fbbf24' ? 70 : 300}
        />
        <VsBadge phase={phase} countdown={countdown} hype={ctx.hype} />
        <MogCallout delta={myPresence.score - oppPresence.score} />
      </div>

      {/* bottom action bar */}
      <div style={{ height: 64, padding: '0 22px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', background: 'var(--mg-bg)', borderTop: '1px solid var(--mg-line)' }}>
        <div style={{ display: 'flex', gap: 8 }}>
          <button className="mg-btn mg-btn-ghost"><Icon name="mic" /> Mute</button>
          <button className="mg-btn mg-btn-ghost"><Icon name="cam" /> Camera</button>
          <button className="mg-btn mg-btn-ghost" style={{ color: 'var(--mg-danger)', borderColor: 'color-mix(in oklab, var(--mg-danger) 40%, transparent)' }}>Forfeit</button>
        </div>
        <div className="mg-mono" style={{ fontSize: 11, color: 'var(--mg-text-3)' }}>
          stream is peer-to-peer · not recorded
        </div>
        <div>
          <button className="mg-btn mg-btn-primary" disabled={remaining > 0}>
            {remaining > 0 ? `Vote opens in ${remaining}s` : 'Vote winner →'}
          </button>
        </div>
      </div>
    </div>
  );
}

function LiveArena({ ctx, myTier, oppTier, remaining, total, phase, countdown }) {
  const { videoRef, state, request } = useWebcam();
  const canvasRef = React.useRef(null);
  const myPresence = usePresenceEngine({ videoRef, canvasRef, active: state === 'live', accentColor: myTier.color });
  const oppPresence = useSimulatedPresence({ targetMu: ctx.opponentMu, hot: phase === 'live' });
  return (
    <div className="mg mg-screen" style={{ background: 'radial-gradient(80% 60% at 50% 0%, color-mix(in oklab, ' + myTier.color + ' 16%, var(--mg-bg)), var(--mg-bg))' }}>
      {/* arena chrome — vertical rim, scoreboard center top */}
      <div style={{ position: 'absolute', top: 22, left: 22, right: 22, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div className="mg-mono" style={{ fontSize: 11, color: 'var(--mg-text-3)', letterSpacing: '0.14em' }}>MOGRANDOM · S1 · ROUND 0142</div>
        <Timer remaining={remaining} total={total} hype={ctx.hype} arena />
        <div className="mg-mono" style={{ fontSize: 11, color: 'var(--mg-text-3)' }}>{ctx.category?.toUpperCase() || 'WOMEN, 25–34'}</div>
      </div>

      <div style={{ position: 'absolute', inset: '64px 22px 80px', display: 'grid', gridTemplateColumns: '1fr auto 1fr', gap: 22, alignItems: 'center' }}>
        <ArenaPanel side="left" tier={myTier} mu={ctx.currentMu} name="you" videoRef={videoRef} canvasRef={canvasRef} camState={state} onRequest={request} presence={myPresence} isYou />
        <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 14 }}>
          <CountdownGlyph phase={phase} countdown={countdown} hype={ctx.hype} />
          <div style={{ width: 1, height: 80, background: 'var(--mg-line-2)' }} />
          <div className="mg-mono" style={{ fontSize: 11, color: 'var(--mg-text-3)', letterSpacing: '0.14em' }}>VS</div>
        </div>
        <ArenaPanel side="right" tier={oppTier} mu={ctx.opponentMu} name={ctx.opponentName} seed={42} isYou={false} presence={oppPresence} />
      </div>

      <div style={{ position: 'absolute', bottom: 22, left: 22, right: 22, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div style={{ display: 'flex', gap: 8 }}>
          <button className="mg-btn mg-btn-ghost"><Icon name="mic" /></button>
          <button className="mg-btn mg-btn-ghost"><Icon name="cam" /></button>
        </div>
        <div className="mg-mono" style={{ fontSize: 11, color: 'var(--mg-text-3)' }}>stream peer-to-peer · not recorded</div>
        <button className="mg-btn mg-btn-primary" disabled={remaining > 0}>
          {remaining > 0 ? `Vote in ${remaining}s` : 'Vote winner'}
        </button>
      </div>
    </div>
  );
}

function CamPanel({ side, name, tier, mu, videoRef, canvasRef, camState, onRequest, presence, presenceColor, isYou, seed, hue }) {
  return (
    <div style={{ position: 'relative', overflow: 'hidden', background: '#0a0a0a' }}>
      {isYou ? (
        <>
          {camState === 'live' && (
            <>
              <video ref={videoRef} autoPlay muted playsInline
                style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', transform: 'scaleX(-1)' }} />
              <canvas ref={canvasRef} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', pointerEvents: 'none' }} />
            </>
          )}
          {camState !== 'live' && (
            <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', flexDirection: 'column', gap: 14, color: 'var(--mg-text-2)' }}>
              <div style={{ width: 56, height: 56, borderRadius: 999, border: '1px solid var(--mg-line-2)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <Icon name="cam" size={22} />
              </div>
              <div className="mg-mono" style={{ fontSize: 11, color: 'var(--mg-text-3)', letterSpacing: '0.14em' }}>
                {camState === 'requesting' ? 'REQUESTING CAMERA…' : camState === 'denied' ? 'CAMERA BLOCKED' : camState === 'unsupported' ? 'CAMERA UNSUPPORTED' : 'CAMERA OFF'}
              </div>
              {(camState === 'idle' || camState === 'denied') && (
                <button className="mg-btn mg-btn-primary" onClick={onRequest}>
                  <Icon name="cam" /> Request camera
                </button>
              )}
              <div className="mg-mono" style={{ fontSize: 10, color: 'var(--mg-text-3)', maxWidth: 280, textAlign: 'center', lineHeight: 1.5 }}>
                Local face-landmark inference. Video never leaves your device.
              </div>
            </div>
          )}
        </>
      ) : (
        <SimPortrait seed={seed} hue={hue} label={name} />
      )}
      {presence && ((isYou && camState === 'live' && presence.hasFace) || (!isYou && presence.hasFace)) && (
        <PresenceMeter score={presence.score} breakdown={presence.breakdown} color={presenceColor} label={isYou ? 'YOU' : 'OPP'} side={side} />
      )}
      {isYou && camState === 'live' && presence && !presence.hasFace && (
        <div style={{
          position: 'absolute', top: 16, left: side === 'right' ? 'auto' : 16, right: side === 'right' ? 16 : 'auto',
          padding: '10px 14px', background: 'rgba(0,0,0,0.55)', backdropFilter: 'blur(8px)',
          border: '1px solid rgba(255,255,255,0.14)', borderRadius: 8,
          fontFamily: 'JetBrains Mono, monospace', fontSize: 11, letterSpacing: '0.14em',
          color: 'var(--mg-text-3)', textTransform: 'uppercase',
        }}>NO FACE · CENTER YOURSELF</div>
      )}
      {/* gradient edge */}
      <div style={{
        position: 'absolute', inset: 0, pointerEvents: 'none',
        background: side === 'left'
          ? 'linear-gradient(90deg, transparent 60%, rgba(0,0,0,0.6))'
          : 'linear-gradient(270deg, transparent 60%, rgba(0,0,0,0.6))',
      }} />
      {/* Lower-third name plate */}
      <div style={{ position: 'absolute', left: side === 'left' ? 18 : 'auto', right: side === 'right' ? 18 : 'auto', bottom: 18, display: 'flex', flexDirection: 'column', gap: 6, alignItems: side === 'left' ? 'flex-start' : 'flex-end' }}>
        <TierChip tier={tier} size="md" />
        <div style={{ fontSize: 22, fontWeight: 600, letterSpacing: '-0.02em' }}>{name}</div>
        <div className="mg-mono" style={{ fontSize: 11, color: 'var(--mg-text-3)' }}>μ {fmtMu(mu)} · φ {tier.short === 'STC' ? 312 : 88}</div>
      </div>
      {/* corner stamp */}
      <div style={{ position: 'absolute', top: 14, left: side === 'left' ? 14 : 'auto', right: side === 'right' ? 14 : 'auto', display: 'flex', gap: 6 }}>
        <span className="mg-mono" style={{ fontSize: 10, padding: '3px 7px', background: 'rgba(0,0,0,0.4)', border: '1px solid rgba(255,255,255,0.12)', borderRadius: 3, letterSpacing: '0.14em' }}>
          {side === 'left' ? 'PLAYER A' : 'PLAYER B'}
        </span>
      </div>
    </div>
  );
}

function ArenaPanel({ side, tier, mu, name, videoRef, canvasRef, camState, onRequest, presence, isYou, seed }) {
  return (
    <div style={{ position: 'relative', height: '100%', borderRadius: 12, overflow: 'hidden', border: `1px solid color-mix(in oklab, ${tier.color} 50%, transparent)`, boxShadow: `0 0 0 1px var(--mg-bg), 0 0 60px color-mix(in oklab, ${tier.color} 30%, transparent)` }}>
      {isYou ? (
        camState === 'live'
          ? <>
              <video ref={videoRef} autoPlay muted playsInline style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', transform: 'scaleX(-1)' }} />
              <canvas ref={canvasRef} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', pointerEvents: 'none' }} />
            </>
          : <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#0a0a0a', color: 'var(--mg-text-3)' }}>
              <div style={{ textAlign: 'center', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 12 }}>
                <Icon name="cam" size={28} />
                <div className="mg-mono" style={{ fontSize: 11, letterSpacing: '0.14em' }}>{camState === 'requesting' ? 'REQUESTING…' : 'CAMERA OFF'}</div>
                {(camState === 'idle' || camState === 'denied') && (
                  <button className="mg-btn mg-btn-primary" onClick={onRequest}>
                    <Icon name="cam" /> Request camera
                  </button>
                )}
              </div>
            </div>
      ) : (
        <SimPortrait seed={seed} hue={300} label={name} />
      )}
      {presence && ((isYou && camState === 'live' && presence.hasFace) || (!isYou && presence.hasFace)) && (
        <PresenceMeter score={presence.score} breakdown={presence.breakdown} color={tier.color} label={isYou ? 'YOU' : 'OPP'} side={side} />
      )}
      <div style={{ position: 'absolute', top: 14, left: 14, display: 'flex', gap: 6 }}>
        <span className="mg-mono" style={{ fontSize: 10, padding: '3px 7px', background: 'rgba(0,0,0,0.5)', borderRadius: 3, letterSpacing: '0.14em' }}>
          {side === 'left' ? 'A' : 'B'}
        </span>
      </div>
      <div style={{ position: 'absolute', left: 14, right: 14, bottom: 14, display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
        <div>
          <div style={{ fontSize: 22, fontWeight: 600 }}>{name}</div>
          <div className="mg-mono" style={{ fontSize: 11, color: 'var(--mg-text-3)' }}>μ {fmtMu(mu)}</div>
        </div>
        <TierChip tier={tier} size="md" />
      </div>
    </div>
  );
}

function VsBadge({ phase, countdown, hype }) {
  return (
    <div style={{ position: 'absolute', left: '50%', top: '50%', transform: 'translate(-50%, -50%)', zIndex: 2 }}>
      {phase === 'countdown' ? (
        <div style={{ width: 130, height: 130, borderRadius: 999, background: 'rgba(0,0,0,0.7)', border: '1px solid rgba(255,255,255,0.18)', display: 'flex', alignItems: 'center', justifyContent: 'center', backdropFilter: 'blur(12px)' }}>
          <div className="mg-display" style={{ fontSize: 78, animation: 'mg-tick 800ms ease-out' }} key={countdown}>{countdown || 'GO'}</div>
        </div>
      ) : (
        <div style={{ width: 64, height: 64, borderRadius: 999, background: 'rgba(0,0,0,0.7)', border: '1px solid rgba(255,255,255,0.16)', display: 'flex', alignItems: 'center', justifyContent: 'center', backdropFilter: 'blur(8px)' }}>
          <span className="mg-mono" style={{ fontSize: 14, fontWeight: 700, letterSpacing: '0.14em' }}>VS</span>
        </div>
      )}
    </div>
  );
}

function CountdownGlyph({ phase, countdown, hype }) {
  if (phase === 'countdown') {
    return (
      <div className="mg-display" style={{ fontSize: 110, lineHeight: 1, animation: 'mg-tick 700ms ease-out' }} key={countdown}>
        {countdown || 'GO'}
      </div>
    );
  }
  return (
    <div style={{ width: 64, height: 64, border: '1px solid var(--mg-line-2)', borderRadius: 999, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <span className="mg-mono" style={{ fontSize: 14, fontWeight: 700, letterSpacing: '0.16em' }}>VS</span>
    </div>
  );
}

function Timer({ remaining, total, hype, arena }) {
  const pct = remaining / total;
  const danger = remaining <= 5 && hype !== 'minimal';
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
      <svg width="24" height="24" viewBox="0 0 24 24" style={{ flex: 'none' }}>
        <circle cx="12" cy="12" r="10" fill="none" stroke="var(--mg-line-2)" strokeWidth="2" />
        <circle cx="12" cy="12" r="10" fill="none"
          stroke={danger ? 'var(--mg-danger)' : 'var(--mg-text)'}
          strokeWidth="2" strokeLinecap="round"
          strokeDasharray={62.83}
          strokeDashoffset={62.83 * (1 - pct)}
          transform="rotate(-90 12 12)"
          style={{ transition: 'stroke-dashoffset 1s linear' }}
        />
      </svg>
      <span className="mg-mono" style={{ fontSize: arena ? 18 : 16, fontWeight: 600, color: danger ? 'var(--mg-danger)' : 'var(--mg-text)', animation: danger ? 'mg-blink 1s steps(2) infinite' : 'none' }}>
        00:{String(remaining).padStart(2, '0')}
      </span>
    </div>
  );
}

function LiveDot() {
  return (
    <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
      <span style={{ width: 8, height: 8, borderRadius: 999, background: 'var(--mg-danger)', boxShadow: '0 0 12px var(--mg-danger)', animation: 'mg-pulse 1.4s ease-in-out infinite' }} />
      <span className="mg-mono" style={{ fontSize: 11, fontWeight: 700, letterSpacing: '0.18em' }}>LIVE</span>
    </span>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// 4. POST-MATCH RATING — commit → reveal
// ─────────────────────────────────────────────────────────────────────────
function ScreenRating({ ctx }) {
  // phase: pick | committed | revealing
  const [phase, setPhase] = React.useState(ctx.ratingPhase || 'pick');
  const [pick, setPick] = React.useState(null); // 'me' | 'opp'
  const [conf, setConf] = React.useState(0);
  React.useEffect(() => { setPhase(ctx.ratingPhase || 'pick'); }, [ctx.ratingPhase]);

  const myTier = tierFor(ctx.currentMu, ctx.theme);
  const oppTier = tierFor(ctx.opponentMu, ctx.theme);

  const commitHash = pick && conf ? hashShort(`${pick}:${conf}:nonce-7Qv`) : null;

  return (
    <div className="mg mg-screen" style={{ display: 'flex', flexDirection: 'column' }}>
      <TopBar tab="play" />
      <div style={{ flex: 1, display: 'grid', gridTemplateColumns: '1fr 420px', minHeight: 0 }}>
        <div style={{ padding: '40px 56px 40px', display: 'flex', flexDirection: 'column', gap: 28, justifyContent: 'center' }}>
          <div>
            <div className="mg-label" style={{ marginBottom: 10 }}>POST-MATCH · CALL THE PERFORMANCE</div>
            <h2 className="mg-display" style={{ fontSize: 44, margin: 0 }}>Who brought it?</h2>
            <p style={{ color: 'var(--mg-text-2)', fontSize: 14, marginTop: 8, maxWidth: 560 }}>
              Judge presence, not faces — energy, expression, command of the moment. Your pick is sealed before either of you sees the other's; hash committed first, plaintext revealed once both commits exist.
            </p>
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14 }}>
            <PickCard
              tier={myTier} name="you" mu={ctx.currentMu}
              selected={pick === 'me'} onClick={() => phase === 'pick' && setPick('me')}
              disabled={phase !== 'pick'} side="left"
            />
            <PickCard
              tier={oppTier} name={ctx.opponentName} mu={ctx.opponentMu}
              selected={pick === 'opp'} onClick={() => phase === 'pick' && setPick('opp')}
              disabled={phase !== 'pick'} side="right"
            />
          </div>

          <div>
            <div className="mg-label" style={{ marginBottom: 10 }}>HOW SURE? · 1 = TOSS-UP · 5 = NO QUESTION</div>
            <div style={{ display: 'flex', gap: 6, alignItems: 'flex-end' }}>
              {[1, 2, 3, 4, 5].map(i => (
                <button key={i} onClick={() => phase === 'pick' && setConf(i)}
                  className={'mg-conf-bar' + (conf >= i ? ' on' : '')}
                  style={{
                    height: 18 + i * 8,
                    flex: 1,
                    ['--mg-tier']: pick === 'me' ? myTier.color : pick === 'opp' ? oppTier.color : 'var(--mg-text)',
                  }} />
              ))}
              <span className="mg-mono" style={{ marginLeft: 14, fontSize: 28, fontWeight: 700, color: conf ? 'var(--mg-text)' : 'var(--mg-text-3)', minWidth: 36 }}>
                {conf || '–'}
              </span>
            </div>
          </div>

          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <div className="mg-mono" style={{ fontSize: 11, color: 'var(--mg-text-3)' }}>
              REVEAL WINDOW · 00:23 LEFT
            </div>
            <button
              className="mg-btn mg-btn-primary"
              disabled={!pick || !conf || phase !== 'pick'}
              onClick={() => setPhase('committed')}
            >
              {phase === 'pick' ? 'Seal pick' : phase === 'committed' ? 'Sealed · waiting on opponent' : 'Reveal in progress…'}
            </button>
          </div>
        </div>

        {/* RIGHT — commit-reveal panel */}
        <div style={{ padding: '40px 28px 28px', borderLeft: '1px solid var(--mg-line)', background: 'var(--mg-bg-2)', display: 'flex', flexDirection: 'column', gap: 14 }}>
          <SidePanel title="Commit-reveal">
            <CommitTimeline phase={phase} commitHash={commitHash} />
          </SidePanel>
          <SidePanel title="What this affects">
            <ul style={{ margin: 0, padding: 0, listStyle: 'none', display: 'flex', flexDirection: 'column', gap: 8, color: 'var(--mg-text-2)', fontSize: 12.5 }}>
              <li>· Both agree → strong rating swing</li>
              <li>· One vote only → weight 0.4</li>
              <li>· Disagree → resolved by confidence delta, weight 0.3</li>
              <li>· No votes → no rating change, match abandoned</li>
            </ul>
          </SidePanel>
          <SidePanel title="Cap on rating loss">
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <span style={{ color: 'var(--mg-text-2)', fontSize: 13 }}>You can't lose more than</span>
              <span className="mg-mono" style={{ fontSize: 16, fontWeight: 600 }}>−42 μ</span>
            </div>
          </SidePanel>
        </div>
      </div>
    </div>
  );
}

function PickCard({ tier, name, mu, selected, onClick, disabled, side }) {
  return (
    <button onClick={onClick} disabled={disabled} style={{
      position: 'relative', overflow: 'hidden', textAlign: 'left',
      padding: 0, height: 220, borderRadius: 10, cursor: disabled ? 'default' : 'pointer',
      border: `1px solid ${selected ? tier.color : 'var(--mg-line-2)'}`,
      background: selected ? `color-mix(in oklab, ${tier.color} 8%, var(--mg-surface))` : 'var(--mg-surface)',
      boxShadow: selected ? `0 0 0 3px color-mix(in oklab, ${tier.color} 30%, transparent)` : 'none',
      transition: 'all 160ms', font: 'inherit', color: 'var(--mg-text)',
    }}>
      <div style={{ position: 'absolute', inset: 0 }}>
        {side === 'left' ? null : null}
        <div style={{ position: 'absolute', left: 0, right: 0, top: 0, height: 130, overflow: 'hidden', borderTopLeftRadius: 10, borderTopRightRadius: 10 }}>
          <SimPortrait seed={side === 'left' ? 11 : 73} hue={side === 'left' ? 200 : 320} label={name} />
        </div>
      </div>
      <div style={{ position: 'absolute', inset: '130px 16px 14px', display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
        <div>
          <div style={{ fontSize: 17, fontWeight: 600 }}>{name}</div>
          <div className="mg-mono" style={{ fontSize: 11, color: 'var(--mg-text-3)' }}>μ {fmtMu(mu)}</div>
        </div>
        <TierChip tier={tier} size="sm" />
      </div>
      {selected && (
        <div style={{ position: 'absolute', top: 12, right: 12, padding: '4px 8px', borderRadius: 4, background: tier.color, color: '#000', fontSize: 10, fontFamily: 'JetBrains Mono, monospace', fontWeight: 700, letterSpacing: '0.14em' }}>
          WINNER
        </div>
      )}
    </button>
  );
}

function CommitTimeline({ phase, commitHash }) {
  const steps = [
    { id: 'pick', label: 'You compose', sub: 'pick + confidence + nonce' },
    { id: 'committed', label: 'Hash committed', sub: 'sha256(pick:conf:nonce)' },
    { id: 'revealing', label: 'Both reveal', sub: 'cleartext + nonce verified' },
    { id: 'resolved', label: 'Glicko-2 step', sub: 'μ updated atomically' },
  ];
  const order = ['pick', 'committed', 'revealing', 'resolved'];
  const idx = order.indexOf(phase);
  return (
    <div style={{ display: 'flex', flexDirection: 'column' }}>
      {steps.map((s, i) => {
        const done = i < idx; const current = i === idx;
        return (
          <div key={s.id} style={{ display: 'grid', gridTemplateColumns: '20px 1fr', gap: 12, padding: '10px 0', borderTop: i === 0 ? 0 : '1px solid var(--mg-line)' }}>
            <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'center', paddingTop: 2 }}>
              <span style={{
                width: 12, height: 12, borderRadius: 999,
                border: `1px solid ${done || current ? 'var(--mg-text)' : 'var(--mg-text-3)'}`,
                background: done ? 'var(--mg-text)' : current ? 'transparent' : 'transparent',
                animation: current ? 'mg-pulse 1.4s ease-in-out infinite' : 'none',
              }} />
            </div>
            <div>
              <div style={{ fontSize: 13, fontWeight: 500, color: done || current ? 'var(--mg-text)' : 'var(--mg-text-3)' }}>{s.label}</div>
              <div className="mg-mono" style={{ fontSize: 10.5, color: 'var(--mg-text-3)', marginTop: 2 }}>{s.sub}</div>
              {s.id === 'committed' && phase !== 'pick' && commitHash && (
                <div className="mg-seal" style={{ marginTop: 8 }}>
                  <Icon name="lock" size={11} /> 0x{commitHash.slice(0, 24)}…
                </div>
              )}
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// 5. RESULT — winner reveal + Glicko delta
// ─────────────────────────────────────────────────────────────────────────
function ScreenResult({ ctx }) {
  const youWon = ctx.iWon !== false;
  const myTier = tierFor(ctx.currentMu, ctx.theme);
  const oppTier = tierFor(ctx.opponentMu, ctx.theme);
  const muDelta = youWon ? +28 : -22;
  const phiDelta = -8;
  const newMu = ctx.currentMu + muDelta;
  const newTier = tierFor(newMu, ctx.theme);
  const tierChanged = newTier.id !== myTier.id;

  return (
    <div className="mg mg-screen" style={{ display: 'flex', flexDirection: 'column' }}>
      <TopBar tab="play" />
      <div style={{ flex: 1, display: 'grid', gridTemplateColumns: '1.15fr 0.85fr', minHeight: 0 }}>
        {/* LEFT — verdict */}
        <div style={{ padding: '48px 56px', display: 'flex', flexDirection: 'column', justifyContent: 'space-between', position: 'relative', overflow: 'hidden' }}>
          <div style={{ position: 'absolute', top: -120, left: -120, width: 480, height: 480, borderRadius: 999,
            background: `radial-gradient(circle, color-mix(in oklab, ${(youWon ? myTier : oppTier).color} 40%, transparent), transparent 70%)`, filter: 'blur(40px)', pointerEvents: 'none' }} />
          <div style={{ position: 'relative' }}>
            <div className="mg-label" style={{ marginBottom: 12 }}>VERDICT · BOTH AGREED</div>
            <h1 className="mg-display" style={{ fontSize: 96, margin: 0, animation: 'mg-fade-up 320ms ease-out' }}>
              {youWon ? 'You won.' : 'You lost.'}
            </h1>
            <div style={{ marginTop: 24, display: 'flex', gap: 28, alignItems: 'center' }}>
              <ResultPlayer tier={myTier} name="you" mu={ctx.currentMu} delta={muDelta} winner={youWon} side="me" />
              <span className="mg-display" style={{ fontSize: 34, color: 'var(--mg-text-3)' }}>vs</span>
              <ResultPlayer tier={oppTier} name={ctx.opponentName} mu={ctx.opponentMu} delta={-muDelta} winner={!youWon} side="opp" />
            </div>
          </div>

          <div style={{ position: 'relative', marginTop: 36 }}>
            <div className="mg-label" style={{ marginBottom: 10 }}>RATING STEP</div>
            <RatingDelta from={ctx.currentMu} delta={muDelta} theme={ctx.theme} tierChanged={tierChanged} newTier={newTier} />
          </div>

          <div style={{ position: 'relative', marginTop: 36, display: 'flex', gap: 10 }}>
            <button className="mg-btn mg-btn-primary">Queue again</button>
            <button className="mg-btn mg-btn-ghost">Back to lobby</button>
            <button className="mg-btn mg-btn-ghost">Report opponent</button>
          </div>
        </div>

        {/* RIGHT — math + history */}
        <div style={{ padding: '40px 28px', borderLeft: '1px solid var(--mg-line)', background: 'var(--mg-bg-2)', display: 'flex', flexDirection: 'column', gap: 14, overflowY: 'auto' }}>
          <SidePanel title="Glicko-2 step">
            <div style={{ display: 'grid', gridTemplateColumns: '1fr auto 1fr', gap: 8, alignItems: 'center', fontFamily: 'JetBrains Mono, monospace', fontSize: 12 }}>
              <Field label="μ" before={fmtMu(ctx.currentMu)} after={fmtMu(newMu)} delta={muDelta} />
              <Field label="φ" before="96" after={String(96 + phiDelta)} delta={phiDelta} />
              <Field label="σ" before="0.06013" after="0.05984" delta={-0.00029} />
              <Field label="W·L" before="41 · 18" after={youWon ? '42 · 18' : '41 · 19'} />
              <Field label="weight" before="" after="0.84" />
              <Field label="outcome" before="" after={youWon ? '1.000' : '0.000'} />
            </div>
            <div style={{ marginTop: 10, padding: 10, background: 'var(--mg-bg)', border: '1px solid var(--mg-line)', borderRadius: 6, fontFamily: 'JetBrains Mono, monospace', fontSize: 10.5, color: 'var(--mg-text-3)', lineHeight: 1.5 }}>
              both players' votes agreed →<br/>
              s_a = {youWon ? '1.0' : '0.0'}, weight = (c_a + c_b) / 10 = 0.84<br/>
              applied via glicko2_update under snapshot ratings
            </div>
          </SidePanel>
          <SidePanel title="Tier progress">
            <TierProgress mu={newMu} theme={ctx.theme} />
          </SidePanel>
          <SidePanel title="Streak">
            <div style={{ display: 'flex', gap: 4 }}>
              {['W','W','L','W','W','W',youWon?'W':'L'].map((r, i) => (
                <div key={i} style={{ flex: 1, height: 24, borderRadius: 3, background: r === 'W' ? 'color-mix(in oklab, var(--mg-ok) 30%, transparent)' : 'color-mix(in oklab, var(--mg-danger) 30%, transparent)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontFamily: 'JetBrains Mono, monospace', fontSize: 10, fontWeight: 700 }}>{r}</div>
              ))}
            </div>
          </SidePanel>
        </div>
      </div>
    </div>
  );
}

function ResultPlayer({ tier, name, mu, delta, winner, side }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 12, opacity: winner ? 1 : 0.55 }}>
      <div style={{ width: 64, height: 64, borderRadius: 8, overflow: 'hidden', position: 'relative', border: `1px solid ${winner ? tier.color : 'var(--mg-line-2)'}`, boxShadow: winner ? `0 0 30px color-mix(in oklab, ${tier.color} 50%, transparent)` : 'none' }}>
        <SimPortrait seed={side === 'me' ? 11 : 73} hue={side === 'me' ? 200 : 320} label={name} />
      </div>
      <div>
        <TierChip tier={tier} size="sm" />
        <div style={{ fontSize: 18, fontWeight: 600, marginTop: 6 }}>{name}</div>
        <div className="mg-mono" style={{ fontSize: 11, color: delta > 0 ? 'var(--mg-ok)' : 'var(--mg-danger)' }}>
          {delta > 0 ? '+' : ''}{delta} μ
        </div>
      </div>
    </div>
  );
}

function RatingDelta({ from, delta, theme, tierChanged, newTier }) {
  const to = from + delta;
  const minBar = Math.min(from, to) - 100;
  const maxBar = Math.max(from, to) + 100;
  const x = (v) => ((v - minBar) / (maxBar - minBar)) * 100;
  return (
    <div style={{ position: 'relative', height: 56, padding: '12px 0', border: '1px solid var(--mg-line)', borderRadius: 6, background: 'var(--mg-bg-2)' }}>
      <div style={{ position: 'absolute', left: 14, right: 14, top: '50%', height: 2, background: 'var(--mg-line-2)' }} />
      <div style={{ position: 'absolute', left: `calc(14px + ${Math.min(x(from), x(to))}% * (1 - 28px / 100%))`, top: '50%', width: `${Math.abs(x(to) - x(from))}%`, height: 2, background: delta > 0 ? 'var(--mg-ok)' : 'var(--mg-danger)' }} />
      <Pin x={x(from)} label={`from · ${fmtMu(from)}`} dim />
      <Pin x={x(to)} label={`to · ${fmtMu(to)}${tierChanged ? ' · ' + newTier.name + ' ↑' : ''}`} bold color={delta > 0 ? 'var(--mg-ok)' : 'var(--mg-danger)'} />
    </div>
  );
}
function Pin({ x, label, color, dim, bold }) {
  return (
    <div style={{ position: 'absolute', left: `calc(14px + ${x}% - 6px)`, top: '50%', transform: 'translateY(-50%)' }}>
      <div style={{ width: 12, height: 12, borderRadius: 999, background: color || 'var(--mg-text)', border: '2px solid var(--mg-bg)', opacity: dim ? 0.6 : 1 }} />
      <div className="mg-mono" style={{ position: 'absolute', top: 16, left: '50%', transform: 'translateX(-50%)', fontSize: 11, color: dim ? 'var(--mg-text-3)' : 'var(--mg-text)', fontWeight: bold ? 600 : 400, whiteSpace: 'nowrap' }}>
        {label}
      </div>
    </div>
  );
}
function Field({ label, before, after, delta }) {
  return (
    <>
      <div style={{ color: 'var(--mg-text-3)' }}>{label}</div>
      <div style={{ color: 'var(--mg-text-3)' }}>{before}{before && after ? ' →' : ''}</div>
      <div style={{ display: 'flex', justifyContent: 'space-between' }}>
        <span>{after}</span>
        {delta !== undefined && delta !== 0 && (
          <span style={{ color: delta > 0 ? 'var(--mg-ok)' : 'var(--mg-danger)' }}>
            {delta > 0 ? '+' : ''}{typeof delta === 'number' && Math.abs(delta) < 0.01 ? delta.toFixed(5) : delta}
          </span>
        )}
      </div>
    </>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// 6. PROFILE
// ─────────────────────────────────────────────────────────────────────────
function ScreenProfile({ ctx }) {
  const myTier = tierFor(ctx.currentMu, ctx.theme);
  const peakMu = ctx.currentMu + 180;
  const peakTier = tierFor(peakMu, ctx.theme);
  const games = [
    { id: 'g7', opp: 'mireille', oppMu: 3760, result: 'W', delta: +24 },
    { id: 'g6', opp: 'umbra__', oppMu: 1860, result: 'W', delta: +18 },
    { id: 'g5', opp: 'kestrel', oppMu: 5240, result: 'L', delta: -41 },
    { id: 'g4', opp: 'thrushwing', oppMu: 3110, result: 'W', delta: +22 },
    { id: 'g3', opp: 'opaline', oppMu: 3320, result: 'L', delta: -19 },
    { id: 'g2', opp: 'cinderlake', oppMu: 3940, result: 'W', delta: +29 },
    { id: 'g1', opp: 'sable_quartz', oppMu: 2980, result: 'W', delta: +21 },
  ];

  return (
    <div className="mg mg-screen" style={{ display: 'flex', flexDirection: 'column', overflowY: 'auto' }}>
      <TopBar tab="profile" />
      <div style={{ padding: '40px 56px 56px', display: 'flex', flexDirection: 'column', gap: 28 }}>
        {/* Hero */}
        <div style={{ display: 'grid', gridTemplateColumns: '160px 1fr auto', gap: 28, alignItems: 'center' }}>
          <div style={{ width: 160, height: 160, borderRadius: 12, overflow: 'hidden', position: 'relative', border: `1px solid color-mix(in oklab, ${myTier.color} 50%, transparent)`, boxShadow: `0 0 60px color-mix(in oklab, ${myTier.color} 30%, transparent)` }}>
            <SimPortrait seed={11} hue={200} label="me" />
          </div>
          <div>
            <TierChip tier={myTier} size="lg" />
            <h1 className="mg-display" style={{ fontSize: 56, margin: '12px 0 4px' }}>lacquer.bird</h1>
            <div style={{ display: 'flex', gap: 18, color: 'var(--mg-text-3)', fontSize: 13 }} className="mg-mono">
              <span>{ctx.category || 'WOMEN, 25–34'}</span>
              <span>·</span>
              <span>SEASON 1</span>
              <span>·</span>
              <span>JOINED MAR 2026</span>
            </div>
          </div>
          <div style={{ display: 'flex', gap: 14 }}>
            <Big label="μ rating" value={fmtMu(ctx.currentMu)} mono />
            <Big label="W · L" value="41 · 18" mono />
            <Big label="streak" value="W4" mono accent />
          </div>
        </div>

        {/* Tier ladder */}
        <div className="mg-card" style={{ padding: 22 }}>
          <div className="mg-label" style={{ marginBottom: 14 }}>TIER LADDER · {ctx.theme?.toUpperCase() || 'VOLTAGE'}</div>
          <TierLadder mu={ctx.currentMu} peakMu={peakMu} theme={ctx.theme} />
        </div>

        {/* split: μ chart + recent games */}
        <div style={{ display: 'grid', gridTemplateColumns: '1.1fr 0.9fr', gap: 18 }}>
          <div className="mg-card" style={{ padding: 22 }}>
            <div className="mg-label" style={{ marginBottom: 14 }}>μ THIS SEASON · PEAK {fmtMu(peakMu)} <span style={{ color: peakTier.color }}>· {peakTier.name}</span></div>
            <MuChart current={ctx.currentMu} peak={peakMu} theme={ctx.theme} />
          </div>
          <div className="mg-card" style={{ padding: 22 }}>
            <div className="mg-label" style={{ marginBottom: 14 }}>RECENT MATCHES</div>
            <table className="mg-table">
              <thead><tr><th>opp</th><th>tier</th><th>res</th><th style={{ textAlign: 'right' }}>Δμ</th></tr></thead>
              <tbody>
                {games.map(g => {
                  const t = tierFor(g.oppMu, ctx.theme);
                  return (
                    <tr key={g.id}>
                      <td>{g.opp}</td>
                      <td><TierChip tier={t} size="sm" /></td>
                      <td><span className="mg-mono" style={{ fontWeight: 700, color: g.result === 'W' ? 'var(--mg-ok)' : 'var(--mg-danger)' }}>{g.result}</span></td>
                      <td className="mg-mono" style={{ textAlign: 'right', color: g.delta > 0 ? 'var(--mg-ok)' : 'var(--mg-danger)' }}>{g.delta > 0 ? '+' : ''}{g.delta}</td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        </div>
      </div>
    </div>
  );
}

function Big({ label, value, mono, accent }) {
  return (
    <div style={{ minWidth: 100 }}>
      <div className="mg-label">{label}</div>
      <div className={mono ? 'mg-mono' : ''} style={{ fontSize: 30, fontWeight: 600, color: accent ? 'var(--mg-ok)' : 'var(--mg-text)' }}>{value}</div>
    </div>
  );
}

function TierLadder({ mu, peakMu, theme }) {
  const tiers = getTiers(theme);
  return (
    <div style={{ display: 'flex', gap: 6 }}>
      {tiers.map(t => {
        const reached = mu >= t.min;
        const peakReached = peakMu >= t.min;
        const inThis = mu >= t.min && mu < t.max;
        return (
          <div key={t.id} style={{ flex: 1, position: 'relative', padding: '12px 10px', borderRadius: 6,
            border: `1px solid ${inThis ? t.color : reached ? 'var(--mg-line-2)' : 'var(--mg-line)'}`,
            background: inThis ? `color-mix(in oklab, ${t.color} 14%, transparent)` : reached ? 'var(--mg-surface-2)' : 'var(--mg-surface)',
            opacity: reached ? 1 : 0.55, minWidth: 0,
          }}>
            <div className="mg-mono" style={{ fontSize: 9.5, letterSpacing: '0.1em', color: t.color, fontWeight: 700 }}>{t.short}</div>
            <div style={{ fontSize: 12, fontWeight: 500, marginTop: 2, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{t.name}</div>
            <div className="mg-mono" style={{ fontSize: 9.5, color: 'var(--mg-text-3)', marginTop: 4 }}>μ {t.min}{t.max === Infinity ? '+' : `–${t.max}`}</div>
            {peakReached && !inThis && <div style={{ position: 'absolute', top: 8, right: 8, width: 6, height: 6, borderRadius: 999, background: t.color }} />}
            {inThis && <div style={{ position: 'absolute', bottom: -1, left: 0, right: 0, height: 2, background: t.color }} />}
          </div>
        );
      })}
    </div>
  );
}

function MuChart({ current, peak, theme }) {
  const tiers = getTiers(theme);
  // simulated 30-day series ending at `current`, peaking at `peak` mid-way
  const points = React.useMemo(() => {
    const start = current - 360;
    const out = [];
    let v = start;
    for (let i = 0; i < 30; i++) {
      const step = (Math.sin(i / 3 + 1.2) * 30) + (Math.cos(i / 4) * 18) + (i < 15 ? 12 : -2);
      v += step + (Math.random() - 0.5) * 4;
      // pin peak around day 18
      if (i === 18) v = peak;
      out.push(v);
    }
    out[out.length - 1] = current;
    return out;
  }, [current, peak]);
  const W = 480, H = 180;
  const min = Math.min(...points) - 40;
  const max = Math.max(...points) + 40;
  const sx = (i) => (i / (points.length - 1)) * W;
  const sy = (v) => H - ((v - min) / (max - min)) * H;
  const d = points.map((v, i) => `${i === 0 ? 'M' : 'L'} ${sx(i).toFixed(1)} ${sy(v).toFixed(1)}`).join(' ');
  const fill = `${d} L ${W} ${H} L 0 ${H} Z`;

  return (
    <div style={{ position: 'relative' }}>
      <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={H} preserveAspectRatio="none">
        <defs>
          <linearGradient id="mu-fill" x1="0" x2="0" y1="0" y2="1">
            <stop offset="0%" stopColor={tierFor(current, theme).color} stopOpacity="0.35" />
            <stop offset="100%" stopColor={tierFor(current, theme).color} stopOpacity="0" />
          </linearGradient>
        </defs>
        {/* tier boundary lines */}
        {tiers.filter(t => t.min > min && t.min < max).map(t => (
          <g key={t.id}>
            <line x1={0} x2={W} y1={sy(t.min)} y2={sy(t.min)} stroke={t.color} strokeOpacity="0.18" strokeDasharray="3 4" />
            <text x={6} y={sy(t.min) - 4} fill={t.color} fillOpacity="0.7" fontSize="9" fontFamily="JetBrains Mono, monospace" letterSpacing="0.1em">{t.short}</text>
          </g>
        ))}
        <path d={fill} fill="url(#mu-fill)" />
        <path d={d} fill="none" stroke={tierFor(current, theme).color} strokeWidth="1.6" />
        <circle cx={sx(points.length - 1)} cy={sy(current)} r="4" fill={tierFor(current, theme).color} />
      </svg>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// 7. LEADERBOARD
// ─────────────────────────────────────────────────────────────────────────
function ScreenLeaderboard({ ctx }) {
  const sorted = [...OPPONENTS].sort((a, b) => b.mu - a.mu);
  // inject "you" at a realistic rank
  const me = { id: 'me', name: 'lacquer.bird', mu: ctx.currentMu, phi: 96, w: 41, l: 18, country: 'US', isMe: true };
  const all = [...sorted, me].sort((a, b) => b.mu - a.mu).map((u, i) => ({ ...u, rank: i + 1 }));

  return (
    <div className="mg mg-screen" style={{ display: 'flex', flexDirection: 'column' }}>
      <TopBar tab="leaderboard" />
      <div style={{ padding: '28px 56px 14px', display: 'flex', flexDirection: 'column', gap: 16 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end' }}>
          <div>
            <div className="mg-label" style={{ marginBottom: 8 }}>SEASON 1: ORIGIN · ENDS IN 23D 14H</div>
            <h1 className="mg-display" style={{ fontSize: 44, margin: 0 }}>{ctx.category || 'Women, 25–34'}</h1>
          </div>
          <div style={{ display: 'flex', gap: 8 }}>
            <FilterChip active>μ rating</FilterChip>
            <FilterChip>peak μ</FilterChip>
            <FilterChip>win rate</FilterChip>
            <FilterChip>volume</FilterChip>
          </div>
        </div>
        <div className="mg-scroll-x" style={{ display: 'flex', gap: 6 }}>
          {CATEGORIES.map(c => (
            <button key={c.id} style={{
              padding: '7px 12px', borderRadius: 4, border: '1px solid var(--mg-line)',
              background: c.id === 'f_25_34' ? 'var(--mg-surface-2)' : 'transparent',
              color: c.id === 'f_25_34' ? 'var(--mg-text)' : 'var(--mg-text-3)',
              font: 'inherit', fontSize: 12, cursor: 'pointer', whiteSpace: 'nowrap',
            }}>{c.display}</button>
          ))}
        </div>
      </div>
      <div style={{ padding: '0 56px 40px', flex: 1, overflowY: 'auto' }}>
        <table className="mg-table">
          <thead>
            <tr>
              <th style={{ width: 60 }}>rank</th>
              <th>player</th>
              <th>tier</th>
              <th style={{ textAlign: 'right' }}>μ</th>
              <th style={{ textAlign: 'right' }}>w · l</th>
              <th style={{ textAlign: 'right' }}>win %</th>
              <th style={{ textAlign: 'right' }}>last seen</th>
            </tr>
          </thead>
          <tbody>
            {all.map(u => {
              const t = tierFor(u.mu, ctx.theme);
              const wp = Math.round((u.w / (u.w + u.l)) * 100);
              return (
                <tr key={u.id} className={u.isMe ? 'me' : ''}>
                  <td className="mg-mono" style={{ color: u.rank <= 3 ? t.color : 'var(--mg-text-3)', fontWeight: u.rank <= 3 ? 700 : 400 }}>
                    #{String(u.rank).padStart(2, '0')}
                  </td>
                  <td>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                      <Avatar seed={u.id} size={26} />
                      <div>
                        <div style={{ fontWeight: 500 }}>{u.name}{u.isMe && <span className="mg-mono" style={{ marginLeft: 8, fontSize: 10, color: 'var(--mg-text-3)' }}>YOU</span>}</div>
                        <div className="mg-mono" style={{ fontSize: 10, color: 'var(--mg-text-3)' }}>{flagOf(u.country)}</div>
                      </div>
                    </div>
                  </td>
                  <td><TierChip tier={t} size="sm" /></td>
                  <td className="mg-mono" style={{ textAlign: 'right', fontWeight: 600 }}>{fmtMu(u.mu)}</td>
                  <td className="mg-mono" style={{ textAlign: 'right', color: 'var(--mg-text-2)' }}>{u.w} · {u.l}</td>
                  <td className="mg-mono" style={{ textAlign: 'right', color: 'var(--mg-text-2)' }}>{wp}%</td>
                  <td className="mg-mono" style={{ textAlign: 'right', color: 'var(--mg-text-3)' }}>{u.isMe ? 'now' : `${1 + (u.id.charCodeAt(2) % 9)}h ago`}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function FilterChip({ active, children }) {
  return (
    <button style={{
      padding: '6px 12px', borderRadius: 4, border: `1px solid ${active ? 'var(--mg-text)' : 'var(--mg-line-2)'}`,
      background: active ? 'var(--mg-text)' : 'transparent',
      color: active ? 'var(--mg-bg)' : 'var(--mg-text-2)',
      font: 'inherit', fontSize: 12, fontWeight: 500, cursor: 'pointer',
    }}>{children}</button>
  );
}

// ─────────────────────────────────────────────────────────────────────────
// SHARED — TopBar / Avatar / Icon
// ─────────────────────────────────────────────────────────────────────────
function TopBar({ tab, myTier, myMu }) {
  const tabs = [['play', 'Play'], ['leaderboard', 'Leaderboard'], ['profile', 'Profile']];
  return (
    <div style={{ height: 56, padding: '0 22px', display: 'flex', alignItems: 'center', justifyContent: 'space-between', borderBottom: '1px solid var(--mg-line)', background: 'var(--mg-bg)' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 28 }}>
        <Logo />
        <nav style={{ display: 'flex', gap: 6 }}>
          {tabs.map(([k, l]) => (
            <button key={k} style={{
              padding: '6px 12px', borderRadius: 4, border: 'none', cursor: 'pointer',
              background: tab === k ? 'var(--mg-surface-2)' : 'transparent',
              color: tab === k ? 'var(--mg-text)' : 'var(--mg-text-3)',
              font: 'inherit', fontSize: 13, fontWeight: 500,
            }}>{l}</button>
          ))}
        </nav>
      </div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
        {myTier && (
          <div className="mg-mono" style={{ fontSize: 11, color: 'var(--mg-text-3)', display: 'flex', alignItems: 'center', gap: 8 }}>
            μ <span style={{ color: 'var(--mg-text)' }}>{fmtMu(myMu)}</span>
          </div>
        )}
        {myTier && <TierChip tier={myTier} size="sm" />}
        <div style={{ width: 1, height: 22, background: 'var(--mg-line)' }} />
        <Avatar seed="me" size={28} />
      </div>
    </div>
  );
}

function Logo() {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
      <svg width="22" height="22" viewBox="0 0 22 22">
        <path d="M3 18 L8 4 L11 14 L14 4 L19 18" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinejoin="miter" />
      </svg>
      <span style={{ fontWeight: 700, letterSpacing: '-0.01em', fontSize: 15 }}>mograndom</span>
    </div>
  );
}

function Avatar({ seed, size = 32 }) {
  // deterministic abstract — never a face
  const h = (typeof seed === 'string' ? seed.charCodeAt(0) : seed) * 31 % 360;
  return (
    <div style={{
      width: size, height: size, borderRadius: 999, flex: 'none',
      background: `radial-gradient(circle at 30% 30%, oklch(0.65 0.12 ${h}), oklch(0.3 0.08 ${(h + 60) % 360}))`,
      border: '1px solid var(--mg-line-2)',
    }} />
  );
}

function Icon({ name, size = 14 }) {
  const s = size;
  if (name === 'mic') return <svg width={s} height={s} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><rect x="6" y="2" width="4" height="8" rx="2" /><path d="M3 8 a5 5 0 0 0 10 0 M8 13 v2" /></svg>;
  if (name === 'cam') return <svg width={s} height={s} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><rect x="2" y="4" width="9" height="8" rx="1.5" /><path d="M11 7 l3 -2 v6 l-3 -2z" /></svg>;
  if (name === 'lock') return <svg width={s} height={s} viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5"><rect x="3" y="7" width="10" height="7" rx="1.5" /><path d="M5 7 V5 a3 3 0 0 1 6 0 V7" /></svg>;
  return null;
}

// ─────────────────────────────────────────────────────────────────
// 0. WARMUP — coaching cam preview before queuing
// ─────────────────────────────────────────────────────────────────
function ScreenWarmup({ ctx }) {
  const { videoRef, state, request } = useWebcam();
  const canvasRef = React.useRef(null);
  const myTier = tierFor(ctx.currentMu, ctx.theme);
  const presence = usePresenceEngine({ videoRef, canvasRef, active: state === 'live', accentColor: myTier.color });

  const tip = pickTip(presence?.breakdown, presence?.hasFace);

  return (
    <div className="mg mg-screen" style={{ background: '#000', display: 'grid', gridTemplateColumns: '1fr 380px' }}>
      {/* big mirror */}
      <div style={{ position: 'relative', overflow: 'hidden', background: '#0a0a0a' }}>
        {state === 'live' ? (
          <>
            <video ref={videoRef} autoPlay muted playsInline
              style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', objectFit: 'cover', transform: 'scaleX(-1)' }} />
            <canvas ref={canvasRef} style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', pointerEvents: 'none' }} />
            {/* corner stamps */}
            <div style={{ position: 'absolute', top: 18, left: 18, display: 'flex', gap: 8, alignItems: 'center' }}>
              <div className="mg-mono" style={{ fontSize: 11, padding: '4px 8px', background: 'rgba(0,0,0,0.55)', border: '1px solid rgba(255,255,255,0.14)', borderRadius: 3, letterSpacing: '0.14em' }}>WARM-UP · MIRROR</div>
              <div className="mg-mono" style={{ fontSize: 11, padding: '4px 8px', background: 'rgba(0,0,0,0.55)', border: `1px solid ${myTier.color}55`, borderRadius: 3, letterSpacing: '0.14em', color: myTier.color }}>{myTier.short} · {myTier.name.toUpperCase()}</div>
            </div>
            {presence.hasFace && (
              <PresenceMeter score={presence.score} breakdown={presence.breakdown} color={myTier.color} label="YOU" side="left" />
            )}
            {!presence.hasFace && (
              <div style={{ position: 'absolute', top: 18, right: 18, padding: '10px 14px', background: 'rgba(0,0,0,0.55)', backdropFilter: 'blur(8px)', border: '1px solid rgba(255,255,255,0.14)', borderRadius: 8, fontFamily: 'JetBrains Mono, monospace', fontSize: 11, letterSpacing: '0.14em', color: 'var(--mg-text-3)', textTransform: 'uppercase' }}>NO FACE · CENTER YOURSELF</div>
            )}
            {/* live coaching tip — bottom */}
            <div style={{ position: 'absolute', left: 18, bottom: 22, right: 18, display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', gap: 24 }}>
              <div style={{ maxWidth: 520 }}>
                <div className="mg-mono" style={{ fontSize: 11, color: '#fff7', letterSpacing: '0.14em' }}>COACHING</div>
                <div style={{ fontSize: 28, fontWeight: 600, letterSpacing: '-0.02em', color: '#fff', marginTop: 6, textShadow: '0 2px 18px rgba(0,0,0,0.6)' }}>
                  {tip.headline}
                </div>
                <div style={{ fontSize: 14, color: '#fffb', marginTop: 4, textShadow: '0 1px 8px rgba(0,0,0,0.6)' }}>{tip.body}</div>
              </div>
            </div>
          </>
        ) : (
          <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 18, color: 'var(--mg-text-2)' }}>
            <div style={{ width: 64, height: 64, borderRadius: 999, border: '1px solid var(--mg-line-2)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              <Icon name="cam" size={26} />
            </div>
            <div style={{ fontSize: 24, fontWeight: 600, letterSpacing: '-0.02em', color: '#fff' }}>Warm up before you queue</div>
            <div style={{ maxWidth: 460, textAlign: 'center', fontSize: 14, color: 'var(--mg-text-3)' }}>
              We'll mirror what your opponent will see and rate your camera game in real time. Local inference — your video never leaves this device.
            </div>
            <button className="mg-btn mg-btn-primary" onClick={request}><Icon name="cam" /> Request camera</button>
          </div>
        )}
      </div>

      {/* coaching side panel */}
      <div style={{ borderLeft: '1px solid var(--mg-line)', padding: 28, display: 'flex', flexDirection: 'column', gap: 18, background: 'var(--mg-bg)' }}>
        <div>
          <div className="mg-label" style={{ marginBottom: 8 }}>WARM-UP</div>
          <h2 className="mg-display" style={{ fontSize: 32, margin: 0, lineHeight: 1.05 }}>Tune in.</h2>
          <p style={{ fontSize: 13.5, color: 'var(--mg-text-2)', marginTop: 10, lineHeight: 1.55 }}>
            Camera Game is a coaching score — not a verdict. <strong style={{ color: 'var(--mg-text)' }}>Peers decide the match.</strong> Use this minute to land your light, frame, and energy before the queue.
          </p>
        </div>

        <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          <Checkpoint label="Centered & framed" hit={presence.breakdown?.composure > 0.55} />
          <Checkpoint label="Looking at camera" hit={presence.breakdown?.engagement > 0.55} />
          <Checkpoint label="Bringing expression" hit={presence.breakdown?.expression > 0.35} />
          <Checkpoint label="Relaxed motion" hit={presence.breakdown?.motion > 0.15 && presence.breakdown?.motion < 0.7} />
        </div>

        <div className="mg-card" style={{ padding: 14 }}>
          <div className="mg-label" style={{ marginBottom: 8 }}>WHAT THIS DOES</div>
          <ul style={{ margin: 0, padding: 0, listStyle: 'none', display: 'flex', flexDirection: 'column', gap: 7, fontSize: 12.5, color: 'var(--mg-text-2)' }}>
            <li>· Local face-landmark inference (MediaPipe)</li>
            <li>· No video leaves your device, ever</li>
            <li>· Score is private — only you see it</li>
            <li>· Match outcome is 100% peer-decided</li>
          </ul>
        </div>

        <div style={{ marginTop: 'auto', display: 'flex', gap: 8 }}>
          <button className="mg-btn mg-btn-ghost" style={{ flex: 1 }}>Skip</button>
          <button className="mg-btn mg-btn-primary" style={{ flex: 2 }} disabled={state !== 'live' || !presence.hasFace}>
            Enter the queue →
          </button>
        </div>
      </div>
    </div>
  );
}

function Checkpoint({ label, hit }) {
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
      <div style={{ width: 16, height: 16, borderRadius: 999, border: `1px solid ${hit ? 'var(--mg-text)' : 'var(--mg-line-2)'}`, background: hit ? 'var(--mg-text)' : 'transparent', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, transition: 'all 200ms' }}>
        {hit && <svg width="9" height="9" viewBox="0 0 10 10"><path d="M2 5 l2 2 l4 -4" stroke="var(--mg-bg)" strokeWidth="1.6" fill="none" /></svg>}
      </div>
      <span style={{ fontSize: 13, color: hit ? 'var(--mg-text)' : 'var(--mg-text-3)', transition: 'color 200ms' }}>{label}</span>
    </div>
  );
}

function pickTip(b, hasFace) {
  if (!hasFace) return { headline: 'Step into frame', body: "Center your face — we can't see you yet." };
  if (!b) return { headline: 'Warming up…', body: 'Loading the tracker.' };
  if (b.composure < 0.4) return { headline: 'Frame yourself up', body: 'Move closer or center yourself in the panel.' };
  if (b.engagement < 0.4) return { headline: 'Look at the camera', body: 'Eye contact reads as confidence to your judges.' };
  if (b.expression < 0.2) return { headline: 'Bring something', body: 'Smile, raise a brow — give the camera a read.' };
  if (b.motion > 0.85) return { headline: 'Settle a touch', body: 'Too much motion reads as nervous. Slow your shoulders.' };
  return { headline: 'You\'re dialed in', body: "This is what they'll see. Hit the queue." };
}


