// PROVE web app — all pages.
// Design system: dark bg, coral accent, JetBrains Mono numbers, surface cards.

const { useState: useStateW, useEffect: useEffectW, useMemo: useMemoW } = React;

// ────────────────────────────────────────────────────────────────────────
// ICONS
// ────────────────────────────────────────────────────────────────────────
const Icon = {
  feed:    (p) => <svg {...iconBase(p)}><rect x="3" y="4" width="18" height="8" rx="2"/><rect x="3" y="14" width="18" height="6" rx="2"/></svg>,
  compass: (p) => <svg {...iconBase(p)}><circle cx="12" cy="12" r="9"/><path d="M15.5 8.5L12 12l-3.5 3.5L12 12z" fill={p.fill || 'currentColor'}/></svg>,
  trophy:  (p) => <svg {...iconBase(p)}><path d="M7 4h10v5a5 5 0 01-10 0V4z"/><path d="M4 5H2v2.5A3 3 0 005 10.5M20 5h2v2.5A3 3 0 0119 10.5"/><path d="M12 14v3M8 20h8"/></svg>,
  bell:    (p) => <svg {...iconBase(p)}><path d="M6 9a6 6 0 0112 0c0 4 2 6 2 6H4s2-2 2-6zM10 19a2 2 0 004 0"/></svg>,
  user:    (p) => <svg {...iconBase(p)}><circle cx="12" cy="8" r="3.5"/><path d="M5 20c0-3.5 3.1-6 7-6s7 2.5 7 6"/></svg>,
  bolt:    (p) => <svg {...iconBase(p)}><path d="M13 2L4 14h7l-1 8 9-12h-7l1-8z" fill={p.fill || 'none'}/></svg>,
  coin:    (p) => <svg {...iconBase(p)}><circle cx="12" cy="12" r="9"/><path d="M9 9.5c0-1.4 1.3-2.5 3-2.5s3 1.1 3 2.5-1 2-3 2.5-3 1.1-3 2.5 1.3 2.5 3 2.5 3-1.1 3-2.5"/><path d="M12 6v12"/></svg>,
  shield:  (p) => <svg {...iconBase(p)}><path d="M12 2l8 3v7c0 5-4 9.5-8 10-4-.5-8-5-8-10V5z"/></svg>,
  flame:   (p) => <svg {...iconBase(p)}><path d="M12 2c0 4-5 6-5 11a5 5 0 0010 0c0-3-3-3-3-7-1 1.5-2 2.5-2 2.5"/></svg>,
  gear:    (p) => <svg {...iconBase(p)}><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 00.4 1.9l.1.1a2 2 0 11-2.8 2.8l-.1-.1a1.7 1.7 0 00-1.9-.4 1.7 1.7 0 00-1 1.5V21a2 2 0 11-4 0v-.1a1.7 1.7 0 00-1-1.5 1.7 1.7 0 00-1.9.4l-.1.1a2 2 0 11-2.8-2.8l.1-.1a1.7 1.7 0 00.4-1.9 1.7 1.7 0 00-1.5-1H3a2 2 0 110-4h.1a1.7 1.7 0 001.5-1 1.7 1.7 0 00-.4-1.9l-.1-.1a2 2 0 112.8-2.8l.1.1a1.7 1.7 0 001.9.4h.1a1.7 1.7 0 001-1.5V3a2 2 0 114 0v.1a1.7 1.7 0 001 1.5 1.7 1.7 0 001.9-.4l.1-.1a2 2 0 112.8 2.8l-.1.1a1.7 1.7 0 00-.4 1.9V9a1.7 1.7 0 001.5 1H21a2 2 0 110 4h-.1a1.7 1.7 0 00-1.5 1z"/></svg>,
  search:  (p) => <svg {...iconBase(p)}><circle cx="11" cy="11" r="7"/><path d="M21 21l-4.5-4.5" strokeLinecap="round"/></svg>,
  rooms:   (p) => <svg {...iconBase(p)}><path d="M3 12 L12 4 L21 12 V20 H3 Z"/><circle cx="9" cy="15" r="1.5" fill="currentColor"/><circle cx="15" cy="15" r="1.5" fill="currentColor"/></svg>,
  plus:    (p) => <svg {...iconBase(p)}><path d="M12 5v14M5 12h14" strokeLinecap="round"/></svg>,
  chevronR:(p) => <svg {...iconBase(p)}><path d="M9 6l6 6-6 6" strokeLinecap="round" strokeLinejoin="round"/></svg>,
  chevronL:(p) => <svg {...iconBase(p)}><path d="M15 6l-6 6 6 6" strokeLinecap="round" strokeLinejoin="round"/></svg>,
  x:       (p) => <svg {...iconBase(p)}><path d="M6 6l12 12M18 6l-12 12" strokeLinecap="round"/></svg>,
  check:   (p) => <svg {...iconBase(p)}><path d="M5 12l5 5L20 6" strokeLinecap="round" strokeLinejoin="round"/></svg>,
  share:   (p) => <svg {...iconBase(p)}><circle cx="6" cy="12" r="2.5"/><circle cx="18" cy="6" r="2.5"/><circle cx="18" cy="18" r="2.5"/><path d="M8.2 11l7.6-4M8.2 13l7.6 4"/></svg>,
  chat:    (p) => <svg {...iconBase(p)}><path d="M21 12a8.5 8.5 0 01-13.5 7L3 21l1.4-4.5A8.5 8.5 0 1121 12z"/></svg>,
  lock:    (p) => <svg {...iconBase(p)}><rect x="5" y="11" width="14" height="10" rx="2"/><path d="M8 11V7a4 4 0 018 0v4"/></svg>,
  apple:   (p) => <svg {...iconBase(p)} fill="currentColor" stroke="none"><path d="M17 12.5c0-2.4 2-3.6 2.1-3.7-1.1-1.6-2.9-1.8-3.5-1.9-1.5-.1-2.9.9-3.6.9-.8 0-1.9-.9-3.1-.8-1.6 0-3.1 1-3.9 2.4-1.7 2.9-.4 7.2 1.2 9.5.8 1.2 1.8 2.5 3 2.4 1.2 0 1.7-.8 3.1-.8s1.9.8 3.1.8c1.3 0 2.2-1.2 3-2.3.9-1.3 1.2-2.6 1.2-2.7-.1 0-2.5-1-2.6-3.8zM14.7 4.4c.7-.8 1.1-1.9 1-3-1 .1-2.1.7-2.7 1.4-.6.7-1.2 1.8-1 2.9 1.1.1 2.1-.5 2.7-1.3z"/></svg>,
  camera:  (p) => <svg {...iconBase(p)}><rect x="3" y="7" width="18" height="13" rx="2"/><circle cx="12" cy="13.5" r="4"/><path d="M9 7l2-3h2l2 3"/></svg>,
  cameraBig:(p) => <svg {...iconBase(p)}><rect x="6" y="14" width="36" height="26" rx="3" strokeWidth="2"/><circle cx="24" cy="27" r="8" strokeWidth="2"/><path d="M18 14l3-6h6l3 6" strokeWidth="2"/></svg>,
  envelope:(p) => <svg {...iconBase(p)}><rect x="3" y="6" width="18" height="13" rx="1.5"/><path d="M3 7l9 7 9-7"/></svg>,
  wifiOff: (p) => <svg {...iconBase(p)}><path d="M2 8 a14 14 0 0120 0M5 12 a10 10 0 0114 0M8 15.5 a6 6 0 018 0" strokeLinecap="round"/><circle cx="12" cy="19" r="1.4" fill="currentColor"/><line x1="3" y1="3" x2="21" y2="21" strokeLinecap="round" strokeWidth="2"/></svg>,
  vault:   (p) => <svg {...iconBase(p)}><rect x="3" y="4" width="18" height="16" rx="2"/><circle cx="13" cy="12" r="4"/><path d="M13 8v8M9 12h8" strokeWidth="1"/><circle cx="13" cy="12" r="1.4" fill="currentColor" stroke="none"/></svg>,
  star:    (p) => <svg {...iconBase(p)}><path d="M12 3l2.5 6 6.5.5-5 4.5 1.5 6.5L12 17l-5.5 3.5L8 14 3 9.5 9.5 9z"/></svg>,
  upload:  (p) => <svg {...iconBase(p)}><path d="M12 16V4M7 9l5-5 5 5" strokeLinecap="round" strokeLinejoin="round"/><path d="M4 17v2a2 2 0 002 2h12a2 2 0 002-2v-2"/></svg>,
};
function iconBase({ size = 18, stroke = 'currentColor', fill = 'none', strokeWidth = 1.6 }) {
  return { width: size, height: size, viewBox: '0 0 24 24', fill, stroke, strokeWidth, strokeLinecap: 'round', strokeLinejoin: 'round' };
}

// ────────────────────────────────────────────────────────────────────────
// SIDEBAR — 240px, premium spacing
// ────────────────────────────────────────────────────────────────────────
function Sidebar({ active = 'feed', windowState = 'open' }) {
  const items = [
    { id: 'feed',          label: 'Feed',          icon: 'feed',     hash: '/feed' },
    { id: 'explore',       label: 'Explore',       icon: 'compass',  hash: '/explore' },
    { id: 'leaderboard',   label: 'Leaderboard',   icon: 'trophy',   hash: '/leaderboard' },
    { id: 'notifications', label: 'Notifications', icon: 'bell',     hash: '/notifications', dot: true },
    { id: 'activity',      label: 'Activity',      icon: 'bolt',     hash: '/activity' },
    { id: 'rooms',         label: 'Rooms',         icon: 'rooms',    hash: '/rooms' },
    { id: 'profile',       label: 'Profile',       icon: 'user',     hash: '/profile' },
  ];
  return (
    <aside style={{
      width: 240, flexShrink: 0,
      background: 'var(--sidebar-bg)',
      borderRight: '1px solid rgba(255,255,255,0.06)',
      padding: '24px 20px 20px',
      display: 'flex', flexDirection: 'column',
      height: '100%',
      overflow: 'hidden',
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 20 }}>
        <ProveLogo size={22} color="#fff" />
        <Day1MiniPill />
      </div>

      <div style={{ marginBottom: 24 }}>
        <PROVEWindowTimer
          as="compact"
          forceState={windowState}
          initialSeconds={windowState === 'closing' ? 5400 : windowState === 'closed' ? 0 : 14535}
        />
      </div>

      <nav style={{ display: 'flex', flexDirection: 'column', gap: 2, flex: 1 }}>
        {items.map((item) => <SideItem key={item.id} item={item} active={active === item.id} />)}
      </nav>

      <div style={{
        display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8,
        marginTop: 20, marginBottom: 12,
      }}>
        <StatTile icon="coin"   label="Coins" value="2,840" color="var(--coral)" />
        <StatTile icon="shield" label="REP"   value="6.4K"  color="#fff" />
      </div>

      <button
        onClick={() => (window.location.hash = '/post')}
        style={{
        width: '100%', height: 44, padding: '0 16px',
        background: 'var(--coral)', color: '#0D0D0D',
        border: 'none', borderRadius: 999,
        fontSize: 13, fontWeight: 700,
        letterSpacing: 0.06 + 'em', textTransform: 'uppercase',
        cursor: 'pointer', fontFamily: 'inherit',
        display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
        transition: 'transform 0.12s, filter 0.12s',
      }}
      onMouseEnter={(e) => { e.currentTarget.style.transform = 'translateY(-1px)'; e.currentTarget.style.filter = 'brightness(1.08)'; }}
      onMouseLeave={(e) => { e.currentTarget.style.transform = ''; e.currentTarget.style.filter = ''; }}
      >
        {Icon.camera({ size: 14, stroke: '#0D0D0D' })}
        Post Proof
      </button>
    </aside>
  );
}

function SideItem({ item, active }) {
  return (
    <button
      onClick={() => { if (item.hash) window.location.hash = item.hash; }}
      style={{
      display: 'flex', alignItems: 'center', gap: 14,
      height: 44, padding: '0 16px',
      background: active ? 'rgba(255,97,85,0.08)' : 'transparent',
      boxShadow: active ? 'inset 0 0 20px rgba(255,97,85,0.05)' : 'none',
      color: active ? '#fff' : 'var(--text-2)',
      border: 'none', borderRadius: 10,
      fontSize: 15, fontWeight: 500, letterSpacing: '-0.005em',
      cursor: 'pointer', textAlign: 'left', fontFamily: 'inherit',
      transition: 'background 0.12s',
      position: 'relative',
    }}
    onMouseEnter={(e) => { if (!active) e.currentTarget.style.background = 'rgba(255,255,255,0.04)'; }}
    onMouseLeave={(e) => { if (!active) e.currentTarget.style.background = 'transparent'; }}
    >
      {active && (
        <span style={{
          position: 'absolute', left: -20, top: 10, bottom: 10,
          width: 3, background: 'var(--coral)', borderRadius: 2,
        }} />
      )}
      {Icon[item.icon]({ size: 18, stroke: active ? 'var(--coral)' : 'currentColor' })}
      <span style={{ flex: 1 }}>{item.label}</span>
      {item.dot && <NotificationDot size={7} />}
    </button>
  );
}

function StatTile({ icon, label, value, color }) {
  return (
    <div style={{
      background: 'linear-gradient(180deg, rgba(255,255,255,0.04), rgba(255,255,255,0.02))',
      border: '1px solid var(--border)',
      borderLeft: `2px solid ${color}`,
      borderRadius: 10,
      height: 52, padding: '0 12px',
      display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: 4,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
        {Icon[icon]({ size: 12, stroke: color })}
        <span style={{ fontSize: 9, color: 'var(--text-3)', letterSpacing: 0.14 + 'em', textTransform: 'uppercase', fontWeight: 600 }}>{label}</span>
      </div>
      <MonoNum size={18} weight={700} color={color} style={{ lineHeight: 1, letterSpacing: '-0.01em' }}>{value}</MonoNum>
    </div>
  );
}

function Day1MiniPill() {
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 5,
      padding: '3px 8px',
      background: 'rgba(255,97,85,0.12)',
      border: '1px solid rgba(255,97,85,0.4)',
      borderRadius: 999,
      fontSize: 9, fontWeight: 700,
      letterSpacing: 0.1 + 'em', textTransform: 'uppercase',
      color: 'var(--coral)',
      fontFamily: 'var(--mono)',
    }}>Day 1</span>
  );
}

// ────────────────────────────────────────────────────────────────────────
// MOBILE BOTTOM TAB BAR — 64px (+ safe-area)
// ────────────────────────────────────────────────────────────────────────
function BottomTabBar({ active = 'feed' }) {
  const items = [
    { id: 'feed',        label: 'Feed',     icon: 'feed',    hash: '/feed' },
    { id: 'explore',     label: 'Explore',  icon: 'compass', hash: '/explore' },
    { id: 'rooms',       label: 'Rooms',    icon: 'rooms',   hash: '/rooms' },
    { id: 'leaderboard', label: 'Rank',     icon: 'trophy',  hash: '/leaderboard' },
    { id: 'profile',     label: 'Profile',  icon: 'user',    hash: '/profile' },
  ];
  return (
    <div style={{
      position: 'absolute', bottom: 0, left: 0, right: 0,
      height: 64,
      background: 'rgba(10,10,10,0.92)',
      backdropFilter: 'blur(20px)',
      borderTop: '1px solid rgba(255,255,255,0.06)',
      paddingBottom: 'env(safe-area-inset-bottom, 18px)',
      display: 'flex', justifyContent: 'space-around', alignItems: 'flex-start',
      paddingTop: 8,
      zIndex: 10,
    }}>
      {items.map((item) => (
        <button key={item.id}
          onClick={() => (window.location.hash = item.hash)}
          style={{
            display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4,
            background: 'transparent', border: 'none',
            color: active === item.id ? 'var(--coral)' : 'rgba(255,255,255,0.4)',
            fontSize: 10, fontWeight: 500,
            cursor: 'pointer', fontFamily: 'inherit',
            padding: '4px 12px',
          }}>
          {Icon[item.icon]({ size: 22, stroke: active === item.id ? 'var(--coral)' : 'currentColor' })}
          {item.label}
        </button>
      ))}
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────
// PAGE SHELLS
// ────────────────────────────────────────────────────────────────────────
function PageShell({ width = 1280, height = 900, active = 'feed', windowState = 'open', children }) {
  return (
    <div style={{
      width, height, color: '#fff',
      display: 'flex', overflow: 'hidden', position: 'relative',
      fontFamily: 'var(--body)',
      background: 'radial-gradient(ellipse 80% 50% at 50% -10%, rgba(255,97,85,0.06) 0%, transparent 60%), #0D0D0D',
      borderTop: '3px solid var(--coral)',
    }}>
      <Sidebar active={active} windowState={windowState} />
      <main style={{ flex: 1, overflow: 'auto', position: 'relative' }}>{children}</main>
    </div>
  );
}

function PageShellMobile({ width = 390, height = 844, active = 'feed', hideTabBar, children }) {
  return (
    <div style={{
      width, height, color: '#fff',
      overflow: 'hidden', position: 'relative',
      fontFamily: 'var(--body)',
      background: 'radial-gradient(ellipse 80% 50% at 50% -10%, rgba(255,97,85,0.06) 0%, transparent 60%), #0D0D0D',
      borderTop: '3px solid var(--coral)',
    }}>
      <StatusBar />
      {children}
      {!hideTabBar && <BottomTabBar active={active} />}
    </div>
  );
}

function StatusBar() {
  return (
    <div style={{
      position: 'absolute', top: 0, left: 0, right: 0, height: 44,
      display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between',
      padding: '0 22px 6px', zIndex: 20,
      fontSize: 13, fontWeight: 600, color: '#fff',
      fontFamily: 'var(--mono)', letterSpacing: '-0.01em',
    }}>
      <span>9:41</span>
      <div style={{ display: 'flex', gap: 5, alignItems: 'center' }}>
        <svg width="16" height="10" viewBox="0 0 16 10" fill="currentColor"><rect x="0" y="6" width="2.5" height="4" rx="0.5"/><rect x="4" y="4" width="2.5" height="6" rx="0.5"/><rect x="8" y="2" width="2.5" height="8" rx="0.5"/><rect x="12" y="0" width="2.5" height="10" rx="0.5"/></svg>
        <svg width="14" height="10" viewBox="0 0 14 10" fill="currentColor"><path d="M7 9.2a1.2 1.2 0 100-2.4 1.2 1.2 0 000 2.4zm0-5.2c1.6 0 3 .6 4.1 1.6l1.2-1.2A7.6 7.6 0 007 2.4 7.6 7.6 0 001.7 4.4l1.2 1.2A5.6 5.6 0 017 4z"/></svg>
        <svg width="22" height="10" viewBox="0 0 22 10" fill="none"><rect x="0.5" y="0.5" width="18" height="9" rx="2" stroke="currentColor"/><rect x="2" y="2" width="14" height="6" rx="0.5" fill="currentColor"/><rect x="20" y="3" width="1.5" height="4" rx="0.5" fill="currentColor"/></svg>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────
// AUTH SHELL — true center, 440px card
// ────────────────────────────────────────────────────────────────────────
function AuthShell({ width = 1280, height = 900, children }) {
  return (
    <div style={{
      width, height, color: '#fff',
      overflow: 'hidden', position: 'relative', fontFamily: 'var(--body)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      background: 'radial-gradient(ellipse 80% 50% at 50% -10%, rgba(255,97,85,0.06) 0%, transparent 60%), #0D0D0D',
      borderTop: '3px solid var(--coral)',
    }}>
      {/* Giant watermark PROVE behind the card */}
      <div style={{
        position: 'absolute', inset: 0,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        pointerEvents: 'none', overflow: 'hidden',
      }}>
        <span style={{
          fontFamily: 'var(--display)', fontSize: '22vw',
          fontWeight: 900, letterSpacing: '-0.06em',
          color: 'rgba(255,97,85,0.04)',
          textTransform: 'uppercase', lineHeight: 0.85,
          whiteSpace: 'nowrap',
        }}>PROVE</span>
      </div>
      <div style={{ position: 'absolute', top: 32, left: 32, display: 'flex', alignItems: 'center', gap: 12, zIndex: 3 }}>
        <ProveLogo size={22} color="#fff" />
        <Day1MiniPill />
      </div>
      <div style={{ position: 'relative', zIndex: 2 }}>{children}</div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────
// FORM PRIMITIVES
// ────────────────────────────────────────────────────────────────────────
function FormField({ label, type = 'text', value, placeholder, onChange, hint, suffix, rightHint, error }) {
  const [focus, setFocus] = useStateW(false);
  return (
    <div style={{ marginBottom: 20 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 8 }}>
        <label style={{ fontSize: 12, color: 'rgba(255,255,255,0.6)', letterSpacing: 0.08 + 'em', textTransform: 'uppercase', fontWeight: 500 }}>{label}</label>
        {rightHint}
      </div>
      <div style={{ position: 'relative' }}>
        <input
          type={type}
          placeholder={placeholder}
          value={value || ''}
          onChange={(e) => onChange && onChange(e.target.value)}
          onFocus={() => setFocus(true)}
          onBlur={() => setFocus(false)}
          style={{
            width: '100%', height: 48,
            padding: '0 16px',
            paddingRight: suffix ? 44 : 16,
            background: focus ? 'rgba(255,97,85,0.05)' : 'var(--surface)',
            border: `1px solid ${focus || error ? 'var(--coral)' : 'var(--border)'}`,
            borderRadius: 16,
            color: '#fff', fontFamily: 'inherit', fontSize: 14,
            outline: 'none',
            transition: 'border-color 0.12s, background 0.12s',
            boxSizing: 'border-box',
          }}
        />
        {suffix && (
          <div style={{ position: 'absolute', right: 14, top: '50%', transform: 'translateY(-50%)' }}>
            {suffix}
          </div>
        )}
      </div>
      {hint && <div style={{ fontSize: 12, color: error ? 'var(--coral)' : 'var(--text-3)', marginTop: 6 }}>{hint}</div>}
    </div>
  );
}

function CoralButton({ children, full, onClick, size = 'md', icon }) {
  const h = size === 'lg' ? 52 : size === 'sm' ? 36 : 44;
  const fs = size === 'lg' ? 14 : 13;
  return (
    <button onClick={onClick} style={{
      width: full ? '100%' : 'auto',
      height: h, padding: '0 22px',
      background: 'var(--coral)', color: '#0D0D0D',
      border: 'none', borderRadius: 999,
      fontSize: fs, fontWeight: 700,
      letterSpacing: 0.06 + 'em', textTransform: 'uppercase',
      cursor: 'pointer', fontFamily: 'inherit',
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
      transition: 'transform 0.12s, filter 0.12s',
    }}
    onMouseEnter={(e) => { e.currentTarget.style.transform = 'translateY(-1px)'; e.currentTarget.style.filter = 'brightness(1.08)'; }}
    onMouseLeave={(e) => { e.currentTarget.style.transform = ''; e.currentTarget.style.filter = ''; }}
    >
      {icon && Icon[icon]({ size: 16, stroke: '#0D0D0D' })}
      {children}
    </button>
  );
}

function GhostButton({ children, full, onClick, size = 'md', icon, danger }) {
  const h = size === 'lg' ? 52 : size === 'sm' ? 36 : 44;
  const fs = size === 'lg' ? 14 : 13;
  return (
    <button onClick={onClick} style={{
      width: full ? '100%' : 'auto',
      height: h, padding: '0 22px',
      background: 'rgba(255,255,255,0.04)',
      color: danger ? 'var(--coral)' : '#fff',
      border: `1px solid ${danger ? 'rgba(255,97,85,0.4)' : 'var(--border)'}`,
      borderRadius: 999,
      fontSize: fs, fontWeight: 600,
      letterSpacing: 0.06 + 'em', textTransform: 'uppercase',
      cursor: 'pointer', fontFamily: 'inherit',
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
      transition: 'border-color 0.12s, background 0.12s',
    }}
    onMouseEnter={(e) => { e.currentTarget.style.borderColor = danger ? 'var(--coral)' : 'var(--border-hi)'; }}
    onMouseLeave={(e) => { e.currentTarget.style.borderColor = danger ? 'rgba(255,97,85,0.4)' : 'var(--border)'; }}
    >
      {icon && Icon[icon]({ size: 16 })}
      {children}
    </button>
  );
}

function AppleButton({ full, label = 'Continue with Apple' }) {
  return (
    <button style={{
      width: full ? '100%' : 'auto',
      height: 48, padding: '0 22px',
      background: '#fff', color: '#0D0D0D',
      border: 'none', borderRadius: 999,
      fontSize: 14, fontWeight: 600,
      cursor: 'pointer', fontFamily: 'inherit',
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 10,
    }}>
      {Icon.apple({ size: 16, stroke: '#0D0D0D' })}
      {label}
    </button>
  );
}

function OrDivider({ label = 'or' }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 12,
      margin: '20px 0', color: 'var(--text-3)',
      fontSize: 11, fontFamily: 'var(--mono)',
      letterSpacing: 0.12 + 'em', textTransform: 'uppercase',
    }}>
      <div style={{ flex: 1, height: 1, background: 'var(--border)' }} />
      <span>{label}</span>
      <div style={{ flex: 1, height: 1, background: 'var(--border)' }} />
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────
// FILTER TABS — pill style (active = coral, inactive = ghost)
// ────────────────────────────────────────────────────────────────────────
function FilterTabs({ tabs, value, onChange, size = 'md', actions }) {
  const h = size === 'sm' ? 32 : 38;
  const fs = size === 'sm' ? 12 : 13;
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: size === 'sm' ? 6 : 10,
    }}>
      {tabs.map((t) => (
        <button key={t.id} onClick={() => onChange && onChange(t.id)}
          style={{
            height: h, padding: '0 16px',
            background: value === t.id ? 'var(--coral)' : 'var(--surface)',
            color: value === t.id ? '#0D0D0D' : 'var(--text-2)',
            border: value === t.id ? '1px solid var(--coral)' : '1px solid var(--border)',
            borderRadius: 999,
            fontSize: fs, fontWeight: 600,
            letterSpacing: 0.04 + 'em', textTransform: 'uppercase',
            cursor: 'pointer', fontFamily: 'inherit',
            display: 'inline-flex', alignItems: 'center', gap: 6,
            transition: 'all 0.12s',
          }}
          onMouseEnter={(e) => { if (value !== t.id) e.currentTarget.style.borderColor = 'var(--border-hi)'; }}
          onMouseLeave={(e) => { if (value !== t.id) e.currentTarget.style.borderColor = 'var(--border)'; }}
        >
          {t.label}
          {t.count !== undefined && <MonoNum size={fs - 1} color={value === t.id ? 'rgba(13,13,13,0.6)' : 'var(--text-3)'} weight={600}>{t.count}</MonoNum>}
        </button>
      ))}
      {actions && <div style={{ marginLeft: 'auto' }}>{actions}</div>}
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────
// PROOF CARD — premium card, 16px radius, 20px padding
// 42px Back/Doubt buttons aligned identically
// ────────────────────────────────────────────────────────────────────────
function ProofCard({ proof, onBack, onDoubt, onComment, onShare, onClick, compact, hero }) {
  const D = window.PROVE_DATA;
  const u = D.byHandle[proof.user];
  const h = D.habits[proof.habit];
  const aspect = hero ? '21/9' : '16/9';
  const captionSize = hero ? 18 : 15;
  const btnHeight = hero ? 52 : 42;
  const btnFs = hero ? 14 : 13;
  const oddsHeight = hero ? 12 : 8;
  const dayHigh = proof.day >= 30;
  const defaultOpen = () => (window.location.hash = '/proof/' + proof.id);

  return (
    <div onClick={onClick || defaultOpen} style={{
      background: 'linear-gradient(180deg, #161616 0%, #0F0F0F 100%)',
      border: '1px solid rgba(255,255,255,0.06)',
      borderRadius: 'var(--radius-card)',
      overflow: 'hidden',
      cursor: 'pointer',
      transition: 'transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease',
      boxShadow: hero
        ? '0 0 0 1px rgba(255,97,85,0.3), 0 24px 80px rgba(255,97,85,0.15), 0 8px 24px rgba(0,0,0,0.4)'
        : '0 4px 16px rgba(0,0,0,0.3), 0 1px 0 rgba(255,255,255,0.04) inset',
      position: 'relative',
    }}
    onMouseEnter={(e) => {
      e.currentTarget.style.borderColor = 'rgba(255,255,255,0.14)';
      e.currentTarget.style.transform = 'translateY(-3px)';
      if (!hero) e.currentTarget.style.boxShadow = '0 12px 32px rgba(0,0,0,0.5), 0 1px 0 rgba(255,255,255,0.06) inset';
    }}
    onMouseLeave={(e) => {
      e.currentTarget.style.borderColor = 'rgba(255,255,255,0.06)';
      e.currentTarget.style.transform = '';
      if (!hero) e.currentTarget.style.boxShadow = '0 4px 16px rgba(0,0,0,0.3), 0 1px 0 rgba(255,255,255,0.04) inset';
    }}
    >
      {/* Video thumbnail */}
      <div style={{ position: 'relative' }}>
        <BlurTile hue={h.hue} seed={proof.id.charCodeAt(1) + proof.day} aspect={aspect} />
        <PlayOverlay size={hero ? 68 : 52} />
        {/* Bottom gradient overlay for readability */}
        <div style={{
          position: 'absolute', bottom: 0, left: 0, right: 0, height: hero ? 110 : 80,
          background: 'linear-gradient(transparent, rgba(0,0,0,0.7))',
          pointerEvents: 'none',
        }} />
        {/* Habit pill (or FEATURED on hero) */}
        <div style={{ position: 'absolute', top: 14, left: 14, display: 'flex', alignItems: 'center', gap: 6 }}>
          <span style={{
            display: 'inline-flex', alignItems: 'center', gap: 6,
            background: 'var(--coral)', color: '#0D0D0D',
            fontSize: 10, fontWeight: 700, padding: '6px 12px',
            letterSpacing: 0.12 + 'em', textTransform: 'uppercase',
            borderRadius: 999,
          }}>
            {hero && <span style={{ fontWeight: 800 }}>★ Featured ·</span>}
            {h.label}
          </span>
        </div>
        {/* Day pill — coral tint for day >= 30 */}
        <div style={{
          position: 'absolute', top: 14, right: 14,
          background: dayHigh ? 'rgba(255,97,85,0.25)' : 'rgba(0,0,0,0.7)',
          color: dayHigh ? 'var(--coral)' : '#fff',
          border: dayHigh ? '1px solid rgba(255,97,85,0.45)' : '1px solid transparent',
          padding: '5px 12px', borderRadius: 999,
          fontFamily: 'var(--mono)', fontSize: 11, fontWeight: 700,
          backdropFilter: 'blur(8px)',
          textTransform: 'lowercase', letterSpacing: '0.02em',
        }}>day {proof.day}</div>
        {/* User row */}
        <div style={{
          position: 'absolute', bottom: 14, left: 14,
          display: 'flex', alignItems: 'center', gap: 10,
          textShadow: '0 1px 8px rgba(0,0,0,0.8)',
        }}>
          <Avatar user={u} size={hero ? 36 : 28} />
          <span style={{
            fontSize: hero ? 15 : 13, fontWeight: 600, color: '#fff',
            textShadow: '0 1px 8px rgba(0,0,0,0.8)',
          }}>{u.handle}</span>
        </div>
      </div>

      {/* Body */}
      <div style={{ padding: hero ? 24 : 20 }}>
        <div style={{
          fontSize: captionSize, fontWeight: 600, color: '#fff', lineHeight: 1.4,
          display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical',
          overflow: 'hidden',
          marginBottom: 6,
        }}>{proof.caption}</div>
        <div style={{ fontSize: 12, color: 'var(--text-3)', fontFamily: 'var(--mono)' }}>
          posted 2h ago · inside PROVE Window
        </div>

        <div style={{ marginTop: 16 }}>
          <OddsBar back={proof.back} doubt={proof.doubt} height={oddsHeight} />
        </div>

        <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
          <ProofCardBtn variant="back"  amount={proof.back}  height={btnHeight} fs={btnFs} onClick={(e) => { e.stopPropagation(); onBack && onBack(); }} />
          <ProofCardBtn variant="doubt" amount={proof.doubt} height={btnHeight} fs={btnFs} onClick={(e) => { e.stopPropagation(); onDoubt && onDoubt(); }} />
        </div>

        <div style={{
          display: 'flex', alignItems: 'center', gap: 18,
          fontSize: 12, color: 'var(--text-2)',
          marginTop: 16,
        }}>
          <button onClick={(e) => { e.stopPropagation(); window.location.hash = '/proof/' + proof.id; }} style={metaBtnStyle}>
            <span style={{ fontSize: 14 }}>🔥</span>
            <MonoNum size={12} color="var(--text-2)" weight={600}>{proof.reactions}</MonoNum>
          </button>
          <button onClick={(e) => { e.stopPropagation(); onComment && onComment(); }} style={metaBtnStyle}>
            {Icon.chat({ size: 14, stroke: 'var(--text-2)' })}
            <MonoNum size={12} color="var(--text-2)" weight={600}>{Math.floor(proof.reactions * 0.18)}</MonoNum>
          </button>
          <button onClick={(e) => {
            e.stopPropagation();
            if (onShare) return onShare();
            const url = window.location.origin + '/#/proof/' + proof.id;
            if (navigator.share) navigator.share({ title: 'PROVE', url }).catch(() => {});
            else { navigator.clipboard?.writeText(url); alert('Link copied!'); }
          }} style={{ ...metaBtnStyle, marginLeft: 'auto' }}>
            {Icon.share({ size: 14, stroke: 'var(--text-2)' })}
          </button>
        </div>
      </div>
    </div>
  );
}

function ProofCardBtn({ variant, amount, onClick, height = 42, fs = 13 }) {
  const isBack = variant === 'back';
  return (
    <button onClick={onClick} style={{
      flex: 1, height,
      display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
      background: isBack ? 'var(--coral)' : 'rgba(255,255,255,0.04)',
      color: isBack ? '#0D0D0D' : '#fff',
      border: 'none',
      borderRadius: 999,
      fontSize: fs, fontWeight: 700,
      letterSpacing: 0.04 + 'em', textTransform: 'uppercase',
      cursor: 'pointer', fontFamily: 'inherit',
      transition: 'filter 0.12s, background 0.12s',
      boxShadow: isBack
        ? '0 6px 20px rgba(255,97,85,0.4), inset 0 1px 0 rgba(255,255,255,0.2)'
        : 'inset 0 0 0 1px rgba(255,255,255,0.12)',
    }}
    onMouseEnter={(e) => {
      if (isBack) e.currentTarget.style.filter = 'brightness(1.06)';
      else e.currentTarget.style.background = 'rgba(255,255,255,0.08)';
    }}
    onMouseLeave={(e) => {
      e.currentTarget.style.filter = '';
      if (!isBack) e.currentTarget.style.background = 'rgba(255,255,255,0.04)';
    }}
    >
      {Icon.coin({ size: fs, stroke: isBack ? '#0D0D0D' : 'currentColor' })}
      <span>{isBack ? 'Back' : 'Doubt'}</span>
      <MonoNum size={fs} weight={700} color={isBack ? '#0D0D0D' : '#fff'}>{amount.toLocaleString()}</MonoNum>
    </button>
  );
}
const metaBtnStyle = {
  display: 'inline-flex', alignItems: 'center', gap: 6,
  background: 'transparent', border: 'none', cursor: 'pointer',
  color: 'inherit', fontFamily: 'inherit', padding: 0,
};

// ────────────────────────────────────────────────────────────────────────
// EMPTY STATE — coral icon, heading, sub, CTA
// ────────────────────────────────────────────────────────────────────────
function EmptyState({ icon, title, body, primary, secondary, color = 'var(--coral)' }) {
  return (
    <div style={{
      display: 'flex', flexDirection: 'column', alignItems: 'center',
      textAlign: 'center', padding: '88px 40px 40px',
      gap: 16,
    }}>
      <div style={{
        width: 88, height: 88, borderRadius: 999,
        background: 'rgba(255,97,85,0.08)',
        border: '1px solid rgba(255,97,85,0.3)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        marginBottom: 4,
      }}>
        {Icon[icon]({ size: 48, stroke: color, strokeWidth: 1.6 })}
      </div>
      <h2 style={{
        fontFamily: 'var(--display)', fontSize: 24, fontWeight: 700,
        letterSpacing: '-0.02em', textTransform: 'uppercase', margin: 0, color: '#fff',
      }}>{title}</h2>
      <p style={{ fontSize: 14, color: 'var(--text-2)', maxWidth: 300, margin: 0, lineHeight: 1.6 }}>{body}</p>
      <div style={{ display: 'flex', gap: 10, marginTop: 8 }}>
        {primary && <CoralButton onClick={primary.onClick}>{primary.label}</CoralButton>}
        {secondary && <GhostButton onClick={secondary.onClick}>{secondary.label}</GhostButton>}
      </div>
    </div>
  );
}

const pageTitleStyle = {
  fontFamily: 'var(--display)', fontSize: 36, fontWeight: 800,
  letterSpacing: '-0.04em', margin: 0,
  textTransform: 'uppercase', color: '#fff',
  lineHeight: 0.92,
};
function PageHeader({ section, title, sub, actions, children, accent }) {
  // Split title to italicize last word (magazine headline style)
  const words = String(title).split(' ');
  const last = words.pop();
  const lead = words.join(' ');
  return (
    <div style={{
      paddingBottom: 28, marginBottom: 36,
      borderBottom: '1px solid rgba(255,255,255,0.06)',
      position: 'relative',
    }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', gap: 24 }}>
        <div style={{ minWidth: 0, flex: 1 }}>
          <div style={sectionLabelStyle}>{section}</div>
          <h1 style={{
            fontFamily: 'var(--display)', fontSize: 64, fontWeight: 800,
            letterSpacing: '-0.045em', margin: '12px 0 0',
            textTransform: 'uppercase', color: '#fff',
            lineHeight: 0.9,
          }}>
            {lead && <span>{lead} </span>}
            <span style={{
              color: 'var(--coral)',
              fontStyle: 'italic',
              fontWeight: 900,
            }}>{last}</span>
            <span style={{
              display: 'inline-block', verticalAlign: 'middle',
              width: 14, height: 14, marginLeft: 14, marginBottom: 14,
              background: 'var(--coral)',
              transform: 'rotate(45deg)',
              boxShadow: '0 0 24px rgba(255,97,85,0.6)',
            }} />
          </h1>
          {sub && <p style={{ fontSize: 15, color: 'var(--text-2)', margin: '14px 0 0', lineHeight: 1.6, maxWidth: 580 }}>{sub}</p>}
        </div>
        {actions}
      </div>
      {children}
    </div>
  );
}
const sectionLabelStyle = {
  fontSize: 11, fontWeight: 500, letterSpacing: 0.12 + 'em',
  textTransform: 'uppercase', color: 'rgba(255,255,255,0.4)',
  fontFamily: 'var(--mono)',
};

// ────────────────────────────────────────────────────────────────────────
// LEADERBOARD ROW (rank 4+)
// ────────────────────────────────────────────────────────────────────────
function LeaderRow({ row, compact = false }) {
  const D = window.PROVE_DATA;
  const u = D.byHandle[row.user];
  const h = D.habits[row.cat];
  const isCurrentUser = row.user === 'maya.k';
  const evenTint = row.rank % 2 === 0 ? 'rgba(255,255,255,0.01)' : 'transparent';
  const bg = isCurrentUser ? 'rgba(255,97,85,0.04)' : evenTint;
  const bordLeft = isCurrentUser ? '2px solid var(--coral)' : '2px solid transparent';

  if (compact) {
    return (
      <div style={{
        display: 'grid', gridTemplateColumns: '32px 1fr 70px',
        gap: 12, alignItems: 'center',
        height: 56, padding: '0 16px',
        borderBottom: '1px solid var(--border)',
        background: bg, borderLeft: bordLeft,
      }}>
        <span style={{
          fontFamily: 'var(--display)', fontSize: 14, fontWeight: 800,
          color: row.rank <= 3 ? 'var(--coral)' : 'var(--text-2)',
          letterSpacing: '-0.02em',
        }}>{String(row.rank).padStart(2, '0')}</span>
        <div style={{ display: 'flex', alignItems: 'center', gap: 10, minWidth: 0 }}>
          <Avatar user={u} size={32} />
          <div style={{ minWidth: 0 }}>
            <div style={{ fontSize: 13, color: '#fff', fontWeight: 600 }}>{u.handle}</div>
            <div style={{ fontSize: 11, color: 'var(--text-2)' }}>{h.label}</div>
          </div>
        </div>
        <MonoNum size={13} weight={600} color="#fff" style={{ textAlign: 'right' }}>{row.streak}d</MonoNum>
      </div>
    );
  }

  return (
    <div style={{
      display: 'grid',
      gridTemplateColumns: '60px 1fr 110px 130px 110px 130px',
      gap: 16, alignItems: 'center',
      height: 56, padding: '0 20px',
      borderBottom: '1px solid var(--border)',
      background: bg,
      borderLeft: bordLeft,
      transition: 'background 0.12s',
    }}
    onMouseEnter={(e) => { if (!isCurrentUser) e.currentTarget.style.background = 'rgba(255,255,255,0.03)'; }}
    onMouseLeave={(e) => { if (!isCurrentUser) e.currentTarget.style.background = evenTint; }}
    >
      <span style={{
        fontFamily: 'var(--display)', fontSize: 18, fontWeight: 800,
        color: row.rank <= 3 ? 'var(--coral)' : '#fff',
        letterSpacing: '-0.03em',
      }}>{String(row.rank).padStart(2, '0')}</span>
      <div style={{ display: 'flex', alignItems: 'center', gap: 12, minWidth: 0 }}>
        <Avatar user={u} size={36} ring={isCurrentUser} />
        <div style={{ minWidth: 0 }}>
          <div style={{ fontSize: 14, color: '#fff', fontWeight: 600, display: 'flex', alignItems: 'center', gap: 8 }}>
            {u.handle}
            {isCurrentUser && <span style={{ color: 'var(--coral)', fontSize: 10, fontFamily: 'var(--mono)', letterSpacing: 0.1 + 'em', textTransform: 'uppercase', fontWeight: 700 }}>you</span>}
          </div>
          <div style={{ fontSize: 12, color: 'var(--text-2)', display: 'flex', alignItems: 'center', gap: 6 }}>
            <span>{u.name}</span>
            <span style={{ opacity: 0.5 }}>·</span>
            <HabitPill habit={h} size="xs" />
          </div>
        </div>
      </div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 8, justifyContent: 'flex-end' }}>
        <StreakRing day={row.streak} target={Math.max(100, row.streak)} size={28} stroke={2.5} showLabel={false} animate={false} />
        <MonoNum size={15} weight={600} color="#fff">{row.streak}d</MonoNum>
      </div>
      <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
        <REPBadge score={row.rep} inline />
      </div>
      <MonoNum size={14} weight={600} color="var(--text-2)" style={{ textAlign: 'right' }}>{row.backers}</MonoNum>
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, justifyContent: 'flex-end' }}>
        {Icon.coin({ size: 13, stroke: 'var(--coral)' })}
        <MonoNum size={14} color="var(--coral)" weight={600}>{row.coins.toLocaleString()}</MonoNum>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────
// LEADERBOARD PODIUM (rank 1–3)
// ────────────────────────────────────────────────────────────────────────
function LeaderPodium({ rows }) {
  const D = window.PROVE_DATA;
  const order = [rows[1], rows[0], rows[2]];
  return (
    <div style={{
      display: 'grid', gridTemplateColumns: '1fr 1.15fr 1fr',
      gap: 20, alignItems: 'end', marginBottom: 44,
    }}>
      {order.map((row) => {
        if (!row) return null;
        const u = D.byHandle[row.user];
        const h = D.habits[row.cat];
        const isFirst = row.rank === 1;
        const isSecond = row.rank === 2;
        const borderColor = row.rank === 1 ? 'rgba(255,97,85,0.5)'
          : row.rank === 2 ? 'rgba(255,255,255,0.18)'
          : 'rgba(255,255,255,0.1)';
        const watermarkColor = row.rank === 1 ? 'rgba(255,97,85,0.18)' : 'rgba(255,255,255,0.05)';
        return (
          <div key={row.rank} style={{
            background: isFirst
              ? 'linear-gradient(180deg, rgba(255,97,85,0.06) 0%, rgba(22,22,22,0.95) 60%)'
              : 'linear-gradient(180deg, #181818 0%, #0F0F0F 100%)',
            border: `1px solid ${borderColor}`,
            borderRadius: 'var(--radius-card)',
            padding: isFirst ? '36px 26px 28px' : '26px 22px 22px',
            minHeight: isFirst ? 300 : 240,
            display: 'flex', flexDirection: 'column', alignItems: 'center',
            gap: 14, position: 'relative', overflow: 'hidden',
            boxShadow: isFirst
              ? '0 0 80px rgba(255,97,85,0.25), 0 24px 60px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,97,85,0.2)'
              : '0 8px 24px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.04)',
          }}>
            {/* Crown for #1 */}
            {isFirst && (
              <div style={{
                position: 'absolute', top: 20, left: '50%', transform: 'translateX(-50%)',
                fontSize: 11, fontFamily: 'var(--mono)', fontWeight: 700,
                letterSpacing: 0.18 + 'em', textTransform: 'uppercase',
                color: 'var(--coral)',
              }}>★ Champion</div>
            )}

            {/* Big rank watermark */}
            <span style={{
              position: 'absolute', bottom: -28, right: -8,
              fontFamily: 'var(--display)',
              fontSize: isFirst ? 200 : 160, fontWeight: 900, letterSpacing: '-0.07em',
              color: watermarkColor,
              lineHeight: 0.85, pointerEvents: 'none',
              fontStyle: 'italic',
            }}>{String(row.rank).padStart(2, '0')}</span>

            <div style={{ position: 'relative', zIndex: 2, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 16, marginTop: isFirst ? 18 : 0 }}>
              <div style={{ filter: isFirst ? 'drop-shadow(0 0 24px rgba(255,97,85,0.5))' : 'none' }}>
                <Avatar user={u} size={isFirst ? 72 : 56} ring={isFirst || isSecond} />
              </div>
              <div style={{ textAlign: 'center' }}>
                <div style={{ fontSize: isFirst ? 18 : 15, color: '#fff', fontWeight: 700, marginBottom: 6, letterSpacing: '-0.01em' }}>{u.handle}</div>
                <HabitPill habit={h} size="xs" />
              </div>
            </div>

            {/* HERO STREAK NUMBER — the visual anchor */}
            <div style={{ position: 'relative', zIndex: 2, textAlign: 'center', marginTop: isFirst ? 6 : 2 }}>
              <MonoNum
                size={isFirst ? 52 : 36}
                weight={700}
                color={isFirst ? 'var(--coral)' : '#fff'}
                style={{
                  display: 'block', lineHeight: 1,
                  letterSpacing: '-0.04em',
                  filter: isFirst ? 'drop-shadow(0 0 16px rgba(255,97,85,0.4))' : 'none',
                }}>{row.streak}<span style={{ fontSize: isFirst ? 24 : 18, opacity: 0.6 }}>d</span></MonoNum>
              <div style={{ fontSize: 10, color: 'var(--text-3)', textTransform: 'uppercase', letterSpacing: 0.16 + 'em', marginTop: 8, fontFamily: 'var(--mono)', fontWeight: 600 }}>
                day streak · {(row.rep / 1000).toFixed(1)}K rep
              </div>
            </div>
          </div>
        );
      })}
    </div>
  );
}

// FEED PAGE (desktop) — including empty + window-closed variants
// ────────────────────────────────────────────────────────────────────────
function FeedPage({ width = 1280, height = 900, windowState = 'closing', variant = 'normal' }) {
  const [tab, setTab] = useStateW(variant === 'empty' ? 'following' : 'all');
  const [modal, setModal] = useStateW(null); // {type, proof}
  const [stakes, setStakes] = useStateW({});
  const D = window.PROVE_DATA;

  const tabs = [
    { id: 'following', label: 'Following', count: variant === 'empty' ? 0 : 3 },
    { id: 'all',       label: 'All',       count: 12 },
    { id: 'trending',  label: 'Trending',  count: 8 },
  ];

  const enrich = (p) => ({
    ...p,
    back: p.back + ((stakes[p.id] || {}).back || 0),
    doubt: p.doubt + ((stakes[p.id] || {}).doubt || 0),
  });

  const list = tab === 'following' ? D.proofs.slice(0, 3)
    : tab === 'trending' ? [...D.proofs].sort((a, b) => (b.back + b.doubt) - (a.back + a.doubt)).slice(0, 8)
    : D.proofs;

  const isEmpty = variant === 'empty' && tab === 'following';

  return (
    <PageShell width={width} height={height} active="feed" windowState={windowState}>
      <div style={{ padding: 32 }}>
        <div style={{ marginBottom: 24 }}>
          <PROVEWindowTimer as="banner" forceState={windowState}
            initialSeconds={windowState === 'closing' ? 5400 : windowState === 'closed' ? 0 : 14535} />
        </div>

        <PageHeader
          section="\u00a7 01 / today"
          title="The Feed"
          sub="Active proofs in your network. Back the ones you believe in."
          actions={<FilterTabs tabs={tabs} value={tab} onChange={setTab} />}
        />

        {isEmpty ? (
          <EmptyState
            icon="cameraBig"
            title="Nothing here yet."
            body="Follow people or explore all proofs to fill your feed."
            primary={{ label: 'Explore proofs', onClick: () => setTab('all') }}
            secondary={{ label: 'Find people', onClick: () => setTab('all') }}
          />
        ) : (
          <div style={{
            display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 20,
          }}>
            {list.slice(0, 8).map((p, i) => (
              <div key={p.id} style={i === 0 ? { gridColumn: '1 / -1' } : {}}>
                <ProofCard proof={enrich(p)} hero={i === 0}
                  onBack={() => setModal({ type: 'stake', proof: enrich(p), side: 'back' })}
                  onDoubt={() => setModal({ type: 'stake', proof: enrich(p), side: 'doubt' })}
                  onComment={() => setModal({ type: 'comments', proof: enrich(p) })}
                />
              </div>
            ))}
          </div>
        )}
      </div>

      <StakeModal
        open={modal?.type === 'stake'}
        onClose={() => setModal(null)}
        proof={modal?.proof}
        initialSide={modal?.side}
        onConfirm={(side, amt) => setStakes((s) => ({ ...s, [modal.proof.id]: { ...(s[modal.proof.id] || {}), [side]: ((s[modal.proof.id] || {})[side] || 0) + amt } }))}
      />
      <CommentsModal
        open={modal?.type === 'comments'}
        onClose={() => setModal(null)}
        proof={modal?.proof}
      />
    </PageShell>
  );
}

// ────────────────────────────────────────────────────────────────────────
// FEED MOBILE
// ────────────────────────────────────────────────────────────────────────
function FeedPageMobile({ width = 390, height = 844 }) {
  const [tab, setTab] = useStateW('all');
  const [modal, setModal] = useStateW(null);
  const D = window.PROVE_DATA;
  const tabs = [
    { id: 'following', label: 'Following' },
    { id: 'all', label: 'All' },
    { id: 'trending', label: 'Trending' },
  ];

  return (
    <PageShellMobile width={width} height={height} active="feed">
      <div style={{ background: 'var(--bg)', height: '100%', paddingBottom: 80, overflow: 'auto' }}>
        <div style={{
          position: 'sticky', top: 0, background: 'rgba(13,13,13,0.92)',
          backdropFilter: 'blur(20px)', zIndex: 5,
          padding: '50px 16px 0',
        }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
            <ProveLogo size={18} color="#fff" />
            <Avatar user={D.byHandle['maya.k']} size={28} />
          </div>
          <div style={{ marginBottom: 12 }}>
            <PROVEWindowTimer as="banner" forceState="closing" initialSeconds={5400} />
          </div>
          <FilterTabs tabs={tabs} value={tab} onChange={setTab} size="sm" />
        </div>

        <div style={{ padding: '14px 16px', display: 'flex', flexDirection: 'column', gap: 14 }}>
          {(tab === 'following' ? D.proofs.slice(0, 3) : D.proofs.slice(0, 6)).map((p) => (
            <ProofCard key={p.id} proof={p}
              onBack={() => setModal({ type: 'stake', proof: p, side: 'back' })}
              onDoubt={() => setModal({ type: 'stake', proof: p, side: 'doubt' })}
              onComment={() => setModal({ type: 'comments', proof: p })}
            />
          ))}
        </div>
      </div>
      <StakeModal open={modal?.type === 'stake'} onClose={() => setModal(null)}
        proof={modal?.proof} initialSide={modal?.side} sheet />
      <CommentsModal open={modal?.type === 'comments'} onClose={() => setModal(null)}
        proof={modal?.proof} sheet />
    </PageShellMobile>
  );
}

// ────────────────────────────────────────────────────────────────────────
// EXPLORE PAGE
// ────────────────────────────────────────────────────────────────────────
function ExplorePage({ width = 1280, height = 900 }) {
  const [cat, setCat] = useStateW('all');
  const D = window.PROVE_DATA;
  const cats = [{ id: 'all', label: 'All' }, ...Object.entries(D.habits).map(([k, h]) => ({ id: k, label: h.label }))];

  const list = cat === 'all' ? D.proofs : D.proofs.filter((p) => p.habit === cat);

  return (
    <PageShell width={width} height={height} active="explore">
      <div style={{ padding: 32 }}>
        <PageHeader
          section="§ 02 / all habits"
          title="Explore"
          sub="Browse proofs across every habit. Filter to find what you’re building."
        />

        {/* Category pills */}
        <div style={{
          display: 'flex', gap: 10, overflowX: 'auto', paddingBottom: 4,
          marginBottom: 28,
        }}>
          {cats.map((c) => (
            <button key={c.id} onClick={() => setCat(c.id)}
              style={{
                padding: '0 16px', height: 38, whiteSpace: 'nowrap',
                background: cat === c.id ? 'var(--coral)' : 'var(--surface)',
                color: cat === c.id ? '#0D0D0D' : 'var(--text-2)',
                border: cat === c.id ? '1px solid var(--coral)' : '1px solid var(--border)',
                borderRadius: 999,
                fontSize: 13, fontWeight: 600,
                letterSpacing: 0.04 + 'em', textTransform: 'uppercase',
                cursor: 'pointer', fontFamily: 'inherit',
                transition: 'all 0.12s',
              }}>{c.label}</button>
          ))}
        </div>

        <div style={{
          display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 20,
        }}>
          {list.slice(0, 8).map((p) => <ProofCard key={p.id} proof={p} />)}
        </div>
      </div>
    </PageShell>
  );
}

function ExplorePageMobile({ width = 390, height = 844 }) {
  const [cat, setCat] = useStateW('all');
  const D = window.PROVE_DATA;
  const cats = [{ id: 'all', label: 'All' }, ...Object.entries(D.habits).map(([k, h]) => ({ id: k, label: h.label }))];
  const list = cat === 'all' ? D.proofs : D.proofs.filter((p) => p.habit === cat);

  return (
    <PageShellMobile width={width} height={height} active="explore">
      <div style={{ background: 'var(--bg)', height: '100%', paddingBottom: 80, overflow: 'auto' }}>
        <div style={{ padding: '52px 16px 14px', position: 'sticky', top: 0, background: 'rgba(13,13,13,0.92)', backdropFilter: 'blur(20px)', zIndex: 5 }}>
          <h1 style={{ fontFamily: 'var(--display)', fontSize: 22, fontWeight: 800, letterSpacing: '-0.03em', textTransform: 'uppercase', color: '#fff', margin: 0 }}>Explore</h1>
          <div style={{ display: 'flex', gap: 6, overflowX: 'auto', marginTop: 12, paddingBottom: 4 }}>
            {cats.map((c) => (
              <button key={c.id} onClick={() => setCat(c.id)} style={{
                padding: '6px 10px', whiteSpace: 'nowrap',
                background: cat === c.id ? 'var(--coral)' : 'var(--surface)',
                color: cat === c.id ? '#0D0D0D' : 'var(--text-2)',
                border: cat === c.id ? '1px solid var(--coral)' : '1px solid var(--border)',
                borderRadius: 999, fontSize: 11, fontWeight: 600, letterSpacing: 0.04 + 'em', textTransform: 'uppercase',
                cursor: 'pointer', fontFamily: 'inherit',
              }}>{c.label}</button>
            ))}
          </div>
        </div>
        <div style={{ padding: '14px 16px', display: 'flex', flexDirection: 'column', gap: 14 }}>
          {list.slice(0, 5).map((p) => <ProofCard key={p.id} proof={p} compact />)}
        </div>
      </div>
    </PageShellMobile>
  );
}

// ────────────────────────────────────────────────────────────────────────
// LEADERBOARD
// ────────────────────────────────────────────────────────────────────────
function LeaderboardPage({ width = 1280, height = 900 }) {
  const [tab, setTab] = useStateW('weekly');
  const D = window.PROVE_DATA;
  const tabs = [
    { id: 'weekly', label: 'Weekly' },
    { id: 'alltime', label: 'All-time' },
    { id: 'category', label: 'By category' },
  ];
  const top3 = D.leaderboard.slice(0, 3);
  const rest = D.leaderboard.slice(3);

  return (
    <PageShell width={width} height={height} active="leaderboard">
      <div style={{ padding: '32px' }}>
        <PageHeader
          section="\u00a7 04 / standings"
          title="Leaderboard"
          sub="Ranked by REP. Resets Sundays at midnight local."
          actions={<FilterTabs tabs={tabs} value={tab} onChange={setTab} />}
        />

        <LeaderPodium rows={top3} />

        {/* Header row */}
        <div style={{
          display: 'grid',
          gridTemplateColumns: '60px 1fr 110px 130px 110px 130px',
          gap: 16, alignItems: 'center',
          height: 40, padding: '0 20px',
          borderBottom: '1px solid var(--border)',
          ...sectionLabelStyle,
        }}>
          <span>Rank</span>
          <span>User</span>
          <span style={{ textAlign: 'right' }}>Streak</span>
          <span style={{ textAlign: 'right' }}>REP</span>
          <span style={{ textAlign: 'right' }}>Backers</span>
          <span style={{ textAlign: 'right' }}>Coins</span>
        </div>
        <div style={{
          background: 'var(--surface)',
          border: '1px solid var(--border)',
          borderTop: 'none',
          borderRadius: '0 0 var(--radius-card) var(--radius-card)',
          overflow: 'hidden',
        }}>
          {rest.map((row) => <LeaderRow key={row.rank} row={row} />)}
        </div>
      </div>
    </PageShell>
  );
}

function LeaderboardPageMobile({ width = 390, height = 844 }) {
  const D = window.PROVE_DATA;
  return (
    <PageShellMobile width={width} height={height} active="leaderboard">
      <div style={{ background: 'var(--bg)', height: '100%', paddingBottom: 80, overflow: 'auto' }}>
        <div style={{ padding: '52px 16px 14px' }}>
          <h1 style={{ fontFamily: 'var(--display)', fontSize: 22, fontWeight: 800, letterSpacing: '-0.03em', textTransform: 'uppercase', color: '#fff', margin: 0 }}>Leaderboard</h1>
          <p style={{ fontSize: 11, color: 'var(--text-2)', marginTop: 4 }}>Ranked by REP. Resets Sundays.</p>
          <div style={{ marginTop: 12 }}>
            <FilterTabs tabs={[{ id: 'w', label: 'Weekly' }, { id: 'a', label: 'All-time' }]} value="w" onChange={() => {}} size="sm" />
          </div>
        </div>
        <div style={{ padding: '4px 12px', display: 'flex', flexDirection: 'column', gap: 6 }}>
          {D.leaderboard.map((row) => <LeaderRow key={row.rank} row={row} compact />)}
        </div>
      </div>
    </PageShellMobile>
  );
}

// ────────────────────────────────────────────────────────────────────────
// PROFILE (own + public variants)
// ────────────────────────────────────────────────────────────────────────
function ProfilePage({ width = 1280, height = 1500, variant = 'own', handle = 'maya.k' }) {
  const D = window.PROVE_DATA;
  const u = D.byHandle[handle];
  const [following, setFollowing] = useStateW(variant === 'public-following');
  const isPublic = variant.startsWith('public');
  const stats = [
    { v: variant === 'own' ? '47' : '47',   l: 'proofs' },
    { v: '198',    l: 'backers' },
    { v: '18,920', l: 'coins' },
    { v: '47',     l: 'day streak' },
  ];
  const gridProofs = Array.from({ length: 12 }, (_, i) => D.proofs[i % D.proofs.length]);

  return (
    <PageShell width={width} height={height} active="profile">
      <div style={{ maxWidth: 824, margin: '0 auto', padding: '32px' }}>
        {/* Hero card */}
        <div style={{
          background: 'linear-gradient(180deg, rgba(255,255,255,0.04) 0%, rgba(255,255,255,0.02) 100%)',
          border: '1px solid var(--border)',
          borderRadius: 'var(--radius-card)',
          padding: 32,
          marginBottom: 32,
          position: 'relative',
          overflow: 'hidden',
        }}>
          <div style={{ position: 'absolute', top: 0, left: 0, right: 0, height: 180,
            background: 'linear-gradient(180deg, rgba(255,97,85,0.14), transparent)',
            pointerEvents: 'none',
          }} />
          {/* Action row in top-right corner */}
          <div style={{ position: 'absolute', top: 24, right: 24, display: 'flex', gap: 8, zIndex: 2 }}>
            {variant === 'own' && <GhostButton icon="user" size="sm" onClick={() => (window.location.hash = '/settings')}>Edit</GhostButton>}
            {isPublic && (
              following
                ? <GhostButton size="sm" icon="check" onClick={() => setFollowing(false)}>Following</GhostButton>
                : <CoralButton  size="sm" onClick={() => setFollowing(true)}>Follow</CoralButton>
            )}
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: '160px 1fr', gap: 36, alignItems: 'center', position: 'relative', zIndex: 1 }}>
            <div style={{
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              filter: 'drop-shadow(0 0 28px rgba(255,97,85,0.5))',
              position: 'relative',
            }}>
              <StreakRing day={47} target={100} size={140} stroke={8} showLabel={false} />
              <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', pointerEvents: 'none' }}>
                <MonoNum size={56} weight={700} color="#fff" style={{ lineHeight: 1, letterSpacing: '-0.04em' }}>47</MonoNum>
                <div style={{ fontSize: 9, color: 'var(--coral)', textTransform: 'uppercase', letterSpacing: 0.18 + 'em', marginTop: 4, fontFamily: 'var(--mono)', fontWeight: 700 }}>day streak</div>
              </div>
            </div>
            <div>
              <h1 style={{
                fontFamily: 'var(--display)', fontSize: 32, fontWeight: 800,
                letterSpacing: '-0.03em', margin: 0,
                textTransform: 'uppercase', color: '#fff',
              }}>{u.handle}</h1>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 8, flexWrap: 'wrap' }}>
                <REPBadge score={6480} inline />
                <span style={{ fontSize: 13, color: 'var(--text-2)' }}>{u.name} \u00b7 Proving since Mar 2026</span>
              </div>
              <div style={{ display: 'flex', gap: 8, marginTop: 14 }}>
                <HabitPill habit={D.habits.lifting} dark />
                <HabitPill habit={D.habits.reading} dark />
              </div>
            </div>
          </div>

          {/* Stats row with dividers */}
          <div style={{
            marginTop: 28, paddingTop: 24,
            borderTop: '1px solid var(--border)',
            display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)',
            position: 'relative', zIndex: 1,
          }}>
            {stats.map((s, i) => (
              <div key={s.l} style={{
                padding: '0 24px',
                borderRight: i < stats.length - 1 ? '1px solid rgba(255,255,255,0.08)' : 'none',
                textAlign: i === 0 ? 'left' : 'center',
              }}>
                <MonoNum size={24} weight={700} color="#fff" style={{ display: 'block', lineHeight: 1, letterSpacing: '-0.02em' }}>{s.v}</MonoNum>
                <div style={{ fontSize: 11, color: 'var(--text-3)', textTransform: 'uppercase', letterSpacing: 0.1 + 'em', marginTop: 8, fontWeight: 500 }}>{s.l}</div>
              </div>
            ))}
          </div>
        </div>

        {/* Proof archive header */}
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 16 }}>
          <h2 style={{ fontFamily: 'var(--display)', fontSize: 20, fontWeight: 700, color: '#fff', margin: 0, textTransform: 'uppercase', letterSpacing: '-0.02em' }}>Proof archive</h2>
          <MonoNum size={12} color="var(--text-3)" weight={500}>47 entries \u00b7 0 missed</MonoNum>
        </div>

        {/* 3-col proof grid */}
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12, paddingBottom: 48 }}>
          {gridProofs.map((p, i) => (
            <div key={i}
              onClick={() => (window.location.hash = '/proof/' + p.id)}
              style={{
              position: 'relative', cursor: 'pointer',
              borderRadius: 'var(--radius-card-sm)', overflow: 'hidden',
              border: '1px solid var(--border)',
              transition: 'border-color 0.2s ease, transform 0.2s ease',
            }}
            onMouseEnter={(e) => { e.currentTarget.style.borderColor = 'var(--border-hi)'; e.currentTarget.style.transform = 'translateY(-2px)'; }}
            onMouseLeave={(e) => { e.currentTarget.style.borderColor = 'var(--border)'; e.currentTarget.style.transform = ''; }}
            >
              <BlurTile hue={D.habits[p.habit].hue} seed={i + 31} aspect="1/1" />
              <div style={{
                position: 'absolute', top: 10, left: 10,
                background: 'var(--coral)', color: '#0D0D0D',
                fontSize: 9, fontWeight: 700, padding: '3px 7px',
                letterSpacing: 0.08 + 'em', textTransform: 'uppercase',
                borderRadius: 4,
              }}>{D.habits[p.habit].label}</div>
              <div style={{
                position: 'absolute', top: 10, right: 10,
                background: 'rgba(0,0,0,0.7)', color: '#fff',
                fontFamily: 'var(--mono)', fontSize: 10, fontWeight: 600,
                padding: '3px 7px', borderRadius: 999,
              }}>d{47 - i}</div>
              <div style={{
                position: 'absolute', bottom: 10, right: 10,
                width: 22, height: 22, borderRadius: '50%',
                background: 'var(--coral)',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
              }}>
                {Icon.check({ size: 13, stroke: '#0D0D0D', strokeWidth: 2.4 })}
              </div>
            </div>
          ))}
        </div>
      </div>
    </PageShell>
  );
}

function ProfilePageMobile({ width = 390, height = 844 }) {
  const D = window.PROVE_DATA;
  const u = D.byHandle['maya.k'];
  const grid = Array.from({ length: 9 }, (_, i) => D.proofs[i % D.proofs.length]);
  return (
    <PageShellMobile width={width} height={height} active="profile">
      <div style={{ background: 'var(--bg)', height: '100%', paddingBottom: 80, overflow: 'auto' }}>
        <div style={{ padding: '60px 20px 20px', textAlign: 'center' }}>
          <div style={{ display: 'flex', justifyContent: 'center', marginBottom: 16 }}>
            <StreakRing day={47} target={100} size={120} stroke={7} />
          </div>
          <h1 style={{ fontFamily: 'var(--display)', fontSize: 24, fontWeight: 800, letterSpacing: '-0.03em', margin: 0, textTransform: 'uppercase', color: '#fff' }}>{u.handle}</h1>
          <div style={{ fontSize: 12, color: 'var(--text-2)', marginTop: 4 }}>{u.name}</div>
          <div style={{ marginTop: 10 }}>
            <REPBadge score={6480} inline />
          </div>
          <div style={{
            display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)',
            borderTop: '1px solid var(--border)', borderBottom: '1px solid var(--border)',
            padding: '14px 0', marginTop: 18,
          }}>
            {[{ v: '47', l: 'proofs' }, { v: '198', l: 'backers' }, { v: '18.9K', l: 'coins' }].map((s) => (
              <div key={s.l}>
                <MonoNum size={18} weight={700} color="#fff" style={{ display: 'block' }}>{s.v}</MonoNum>
                <div style={{ fontSize: 9, color: 'var(--text-3)', textTransform: 'uppercase', letterSpacing: 0.1 + 'em', marginTop: 4 }}>{s.l}</div>
              </div>
            ))}
          </div>
          <div style={{ display: 'flex', gap: 6, justifyContent: 'center', marginTop: 14 }}>
            <HabitPill habit={D.habits.lifting} dark size="xs" />
            <HabitPill habit={D.habits.reading} dark size="xs" />
          </div>
        </div>
        <div style={{ padding: '0 12px 12px' }}>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 4 }}>
            {grid.map((p, i) => (
              <div key={i}
                onClick={() => (window.location.hash = '/proof/' + p.id)}
                style={{ position: 'relative', borderRadius: 4, overflow: 'hidden', cursor: 'pointer' }}>
                <BlurTile hue={D.habits[p.habit].hue} seed={i + 41} aspect="1/1" />
                <div style={{ position: 'absolute', bottom: 3, left: 3, fontFamily: 'var(--mono)', fontSize: 8, color: '#fff', background: 'rgba(0,0,0,0.6)', padding: '1px 4px' }}>d{47 - i}</div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </PageShellMobile>
  );
}

// ────────────────────────────────────────────────────────────────────────
// SINGLE PROOF
// ────────────────────────────────────────────────────────────────────────
function SingleProofPage({ width = 1280, height = 1100 }) {
  const D = window.PROVE_DATA;
  const p = D.proofs[0];
  const u = D.byHandle[p.user];
  const h = D.habits[p.habit];
  const [back, setBack] = useStateW(p.back);
  const [doubt, setDoubt] = useStateW(p.doubt);
  const [modal, setModal] = useStateW(null);

  return (
    <PageShell width={width} height={height} active="feed">
      <div style={{ height: '100%', overflow: 'auto' }}>
        <div style={{ maxWidth: 760, margin: '0 auto', padding: '28px 32px 120px' }}>
          <div style={{ fontSize: 12, color: 'var(--text-3)', marginBottom: 14, fontFamily: 'var(--mono)' }}>
            ← Feed / proof / prove.app/p/maya-k-47
          </div>

          <div style={{ display: 'flex', alignItems: 'center', gap: 12, marginBottom: 20 }}>
            <Avatar user={u} size={48} />
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 17, fontWeight: 600, color: '#fff', display: 'flex', alignItems: 'center', gap: 10 }}>
                {u.handle}
                <REPBadge score={6480} inline />
              </div>
              <div style={{ fontSize: 13, color: 'var(--text-2)', marginTop: 2 }}>
                {u.name} · posted 6h ago inside PROVE Window
              </div>
            </div>
            <HabitPill habit={h} dark />
            <span style={{
              fontFamily: 'var(--mono)', fontSize: 14, fontWeight: 600,
              padding: '6px 12px', borderRadius: 999,
              background: 'rgba(255,97,85,0.08)', color: 'var(--coral)',
              border: '1px solid rgba(255,97,85,0.3)',
            }}>day {p.day}</span>
          </div>

          {/* video */}
          <div style={{
            position: 'relative', aspectRatio: '16/9',
            background: '#000', borderRadius: 'var(--radius-card)',
            overflow: 'hidden', marginBottom: 14,
          }}>
            <BlurTile hue={h.hue} seed={2} aspect="auto" style={{ position: 'absolute', inset: 0, aspectRatio: 'auto' }} />
            <PlayOverlay size={72} />
            <div style={{
              position: 'absolute', bottom: 0, left: 0, right: 0,
              padding: '24px 18px 12px',
              background: 'linear-gradient(180deg, transparent, rgba(0,0,0,0.7))',
              display: 'flex', alignItems: 'center', gap: 12,
            }}>
              <div style={{ flex: 1, height: 3, background: 'rgba(255,255,255,0.2)', borderRadius: 2, overflow: 'hidden' }}>
                <div style={{ width: '45%', height: '100%', background: 'var(--coral)' }} />
              </div>
              <MonoNum size={11} color="rgba(255,255,255,0.85)">0:14 / 0:32</MonoNum>
            </div>
          </div>

          <p style={{ fontSize: 16, lineHeight: 1.55, color: 'rgba(255,255,255,0.85)', margin: '0 0 24px' }}>
            "{p.caption}"
          </p>

          {/* Stake panel */}
          <div style={{
            background: 'var(--surface)',
            border: '1px solid var(--border)',
            padding: 22, borderRadius: 'var(--radius-card)',
            marginBottom: 16,
          }}>
            <div style={{
              fontSize: 11, letterSpacing: 0.1 + 'em', textTransform: 'uppercase',
              color: 'var(--text-2)', marginBottom: 14,
              display: 'flex', justifyContent: 'space-between',
            }}>
              <span>Live stake split</span>
              <MonoNum size={11} color="var(--text-2)">{(back + doubt).toLocaleString()} coins · 47 backers</MonoNum>
            </div>
            <OddsBar back={back} doubt={doubt} height={10} />
            <div style={{ display: 'flex', gap: 10, marginTop: 18 }}>
              <button onClick={() => setModal({ type: 'stake', side: 'back' })} style={{
                flex: 1, height: 44, padding: '0 18px',
                background: 'var(--coral)', color: '#0D0D0D',
                border: 'none', borderRadius: 999,
                fontSize: 13, fontWeight: 700,
                letterSpacing: 0.04 + 'em', textTransform: 'uppercase',
                cursor: 'pointer', fontFamily: 'inherit',
                display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
              }}>Back <MonoNum size={13} color="#0D0D0D" weight={700}>· {back.toLocaleString()}</MonoNum></button>
              <button onClick={() => setModal({ type: 'stake', side: 'doubt' })} style={{
                flex: 1, height: 44, padding: '0 18px',
                background: 'var(--surface)', color: '#fff',
                border: '1px solid var(--border-hi)', borderRadius: 999,
                fontSize: 13, fontWeight: 700,
                letterSpacing: 0.04 + 'em', textTransform: 'uppercase',
                cursor: 'pointer', fontFamily: 'inherit',
                display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,
              }}>Doubt <MonoNum size={13} color="#fff" weight={700}>· {doubt.toLocaleString()}</MonoNum></button>
            </div>
          </div>

          {/* reactions + comments + share */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 24, flexWrap: 'wrap' }}>
            {['🔥', '💪', '👀', '⚡'].map((emoji) => (
              <button key={emoji}
                onClick={() => setModal({ type: 'reactions' })}
                style={{
                padding: '8px 14px',
                background: 'var(--surface)',
                border: '1px solid var(--border)',
                borderRadius: 999, fontSize: 16,
                cursor: 'pointer', fontFamily: 'inherit',
                display: 'flex', alignItems: 'center', gap: 6,
              }}>{emoji} <MonoNum size={11} color="var(--text-2)">{Math.floor(Math.random() * 60 + 20)}</MonoNum></button>
            ))}
            <button onClick={() => setModal({ type: 'comments' })} style={{
              padding: '8px 14px', background: 'var(--surface)',
              border: '1px solid var(--border)', borderRadius: 999,
              color: '#fff', cursor: 'pointer', fontFamily: 'inherit', fontSize: 13,
              display: 'flex', alignItems: 'center', gap: 6,
            }}>
              {Icon.chat({ size: 14 })}
              <MonoNum size={11} color="var(--text-2)">{Math.floor(p.reactions * 0.18)}</MonoNum>
            </button>
            <button onClick={() => setModal({ type: 'reactions' })} style={{
              padding: '8px 14px', background: 'transparent',
              border: '1px solid var(--border)', borderRadius: 999,
              color: 'var(--text-2)', cursor: 'pointer', fontFamily: 'inherit', fontSize: 12,
              marginLeft: 'auto',
            }}>+ More</button>
          </div>
        </div>

        {/* sticky banner */}
        <div style={{
          position: 'absolute', bottom: 0, left: 220, right: 0,
          background: 'var(--coral)', color: '#0D0D0D',
          padding: '18px 32px',
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        }}>
          <div>
            <div style={{ fontSize: 16, fontWeight: 700 }}>Want to post your own proof?</div>
            <div style={{ fontSize: 13, opacity: 0.75, marginTop: 2 }}>Free during beta · iOS + Android</div>
          </div>
          <button
            onClick={() => (window.location.hash = '/signup')}
            style={{
            padding: '12px 22px', background: '#0D0D0D', color: '#fff',
            border: 'none', borderRadius: 999, fontSize: 14, fontWeight: 700,
            cursor: 'pointer', fontFamily: 'inherit',
            display: 'inline-flex', alignItems: 'center', gap: 10,
          }}>{Icon.apple({ size: 16, stroke: '#fff' })} Sign up free</button>
        </div>
      </div>

      <StakeModal open={modal?.type === 'stake'} onClose={() => setModal(null)}
        proof={{ ...p, back, doubt }} initialSide={modal?.side}
        onConfirm={(side, amt) => { if (side === 'back') setBack((b) => b + amt); else setDoubt((d) => d + amt); }}
      />
      <CommentsModal open={modal?.type === 'comments'} onClose={() => setModal(null)} proof={p} />
      <ReactionsModal open={modal?.type === 'reactions'} onClose={() => setModal(null)} />
    </PageShell>
  );
}

function SingleProofPageMobile({ width = 390, height = 844 }) {
  const D = window.PROVE_DATA;
  const p = D.proofs[0];
  const u = D.byHandle[p.user];
  const h = D.habits[p.habit];
  const [back, setBack] = useStateW(p.back);
  const [doubt, setDoubt] = useStateW(p.doubt);
  const [modal, setModal] = useStateW(null);

  return (
    <PageShellMobile width={width} height={height} active="feed" hideTabBar>
      <div style={{ background: 'var(--bg)', height: '100%', paddingBottom: 100, overflow: 'auto' }}>
        <div style={{ padding: '50px 14px 12px' }}>
          <div style={{ fontSize: 11, color: 'var(--text-3)', fontFamily: 'var(--mono)', marginBottom: 8 }}>← Back to feed</div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>
            <Avatar user={u} size={36} />
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 14, fontWeight: 600, color: '#fff' }}>{u.handle}</div>
              <div style={{ fontSize: 11, color: 'var(--text-2)' }}>6h ago · PROVE Window</div>
            </div>
            <span style={{ fontFamily: 'var(--mono)', fontSize: 12, padding: '4px 8px', borderRadius: 999, background: 'rgba(255,97,85,0.08)', color: 'var(--coral)', border: '1px solid rgba(255,97,85,0.3)' }}>day {p.day}</span>
          </div>
        </div>

        <div style={{ position: 'relative', aspectRatio: '9/16', maxHeight: 460 }}>
          <BlurTile hue={h.hue} seed={2} aspect="auto" style={{ position: 'absolute', inset: 0, aspectRatio: 'auto' }} />
          <PlayOverlay size={64} />
          <div style={{ position: 'absolute', bottom: 14, left: 14, right: 14, height: 3, background: 'rgba(255,255,255,0.2)', borderRadius: 2, overflow: 'hidden' }}>
            <div style={{ width: '45%', height: '100%', background: 'var(--coral)' }} />
          </div>
        </div>

        <div style={{ padding: 14 }}>
          <p style={{ fontSize: 14, lineHeight: 1.5, color: 'rgba(255,255,255,0.85)', margin: '0 0 16px' }}>"{p.caption}"</p>

          <div style={{
            background: 'var(--surface)', border: '1px solid var(--border)',
            padding: 14, borderRadius: 'var(--radius-card)', marginBottom: 14,
          }}>
            <OddsBar back={back} doubt={doubt} height={8} />
            <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>
              <button onClick={() => setModal({ type: 'stake', side: 'back' })}
                style={{ flex: 1, height: 38, background: 'var(--coral)', color: '#0D0D0D', border: 'none', borderRadius: 999, fontFamily: 'inherit', fontSize: 12, fontWeight: 700, letterSpacing: 0.06 + 'em', textTransform: 'uppercase', cursor: 'pointer' }}>
                Back · {back.toLocaleString()}
              </button>
              <button onClick={() => setModal({ type: 'stake', side: 'doubt' })}
                style={{ flex: 1, height: 38, background: 'var(--surface)', color: '#fff', border: '1px solid var(--border-hi)', borderRadius: 999, fontFamily: 'inherit', fontSize: 12, fontWeight: 700, letterSpacing: 0.06 + 'em', textTransform: 'uppercase', cursor: 'pointer' }}>
                Doubt · {doubt.toLocaleString()}
              </button>
            </div>
          </div>

          <div style={{ display: 'flex', gap: 6 }}>
            {['🔥', '💪', '👀', '⚡'].map((e) => (
              <button key={e} style={{ padding: '6px 12px', background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 999, fontSize: 14, cursor: 'pointer', fontFamily: 'inherit' }}>{e}</button>
            ))}
          </div>
        </div>

        <div style={{
          position: 'absolute', bottom: 0, left: 0, right: 0,
          background: 'var(--coral)', color: '#0D0D0D',
          padding: '12px 14px', display: 'flex', alignItems: 'center', gap: 10,
        }}>
          <div style={{ flex: 1, fontSize: 12, fontWeight: 700, lineHeight: 1.2 }}>
            Post your own proof?
            <div style={{ fontWeight: 500, fontSize: 10, opacity: 0.8, marginTop: 2 }}>Free during beta · iOS</div>
          </div>
          <button style={{ padding: '8px 14px', background: '#0D0D0D', color: '#fff', border: 'none', borderRadius: 999, fontSize: 11, fontWeight: 700, cursor: 'pointer', fontFamily: 'inherit', whiteSpace: 'nowrap' }}>Get App</button>
        </div>
      </div>
      <StakeModal open={modal?.type === 'stake'} onClose={() => setModal(null)} proof={{ ...p, back, doubt }} initialSide={modal?.side} sheet
        onConfirm={(side, amt) => { if (side === 'back') setBack((b) => b + amt); else setDoubt((d) => d + amt); }} />
    </PageShellMobile>
  );
}

Object.assign(window, {
  Icon, Sidebar, BottomTabBar, PageShell, PageShellMobile, AuthShell,
  FormField, CoralButton, GhostButton, AppleButton, OrDivider, FilterTabs,
  ProofCard, ProofCardBtn, EmptyState, LeaderRow, LeaderPodium,
  pageTitleStyle, sectionLabelStyle, metaBtnStyle, PageHeader,
  FeedPage, FeedPageMobile,
  ExplorePage, ExplorePageMobile,
  LeaderboardPage, LeaderboardPageMobile,
  ProfilePage, ProfilePageMobile,
  SingleProofPage, SingleProofPageMobile,
});
