/* Components for MMAFightCard.io home */

const { useState, useEffect, useRef, useMemo } = React;

// ── Icons ──────────────────────────────────────────────────────────────
const Arrow = ({ size = 14 }) => (
  <svg width={size} height={size} viewBox="0 0 16 16" fill="none">
    <path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="square"/>
  </svg>
);
const Dot = ({ color = "var(--red)", size = 8 }) => (
  <span style={{
    display: 'inline-block', width: size, height: size, borderRadius: '50%',
    background: color, boxShadow: `0 0 ${size*1.5}px ${color}`
  }} />
);

// ── Live pulse dot ──
const LivePulse = ({ color = "var(--red)" }) => (
  <span style={{ position: 'relative', display: 'inline-flex', width: 8, height: 8 }}>
    <span style={{
      position: 'absolute', inset: 0, borderRadius: '50%', background: color,
      animation: 'pulseRing 1.6s ease-out infinite'
    }} />
    <span style={{
      position: 'absolute', inset: 2, borderRadius: '50%', background: color
    }} />
  </span>
);

// ── Countdown ──────────────────────────────────────────────────────────
function useCountdown(targetIso) {
  const [now, setNow] = useState(() => Date.now());
  useEffect(() => {
    const id = setInterval(() => setNow(Date.now()), 1000);
    return () => clearInterval(id);
  }, []);
  const target = useMemo(() => new Date(targetIso).getTime(), [targetIso]);
  let diff = Math.max(0, target - now);
  const d = Math.floor(diff / 86400000); diff -= d * 86400000;
  const h = Math.floor(diff / 3600000);  diff -= h * 3600000;
  const m = Math.floor(diff / 60000);    diff -= m * 60000;
  const s = Math.floor(diff / 1000);
  if (target - now <= 0) {
    return { d: 0, h: 0, m: 0, s: 0, live: true };
  }
  return { d, h, m, s, live: false };
}

// ── Shared animation helpers ─────────────────────────────────────────
const prefersReducedMotion = () =>
  typeof window !== 'undefined' && window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;

// true once the element has scrolled into view (true straight away where IntersectionObserver is missing)
function useInView(threshold = 0.25) {
  const ref = useRef(null);
  const [seen, setSeen] = useState(false);
  useEffect(() => {
    const el = ref.current;
    if (!el || seen) return;
    if (typeof IntersectionObserver === 'undefined') { setSeen(true); return; }
    const io = new IntersectionObserver(([en]) => { if (en.isIntersecting) { setSeen(true); io.disconnect(); } }, { threshold });
    io.observe(el);
    return () => io.disconnect();
  }, []);
  return [ref, seen];
}

// counts from 0 to target once run is true
function useCountUp(target, run, ms = 1100) {
  const [v, setV] = useState(0);
  useEffect(() => {
    if (!run) return;
    if (prefersReducedMotion()) { setV(target); return; }
    const raf = window.requestAnimationFrame || ((cb) => setTimeout(() => cb(Date.now()), 16));
    let start = null, alive = true;
    const step = (t) => {
      if (!alive) return;
      if (start === null) start = t;
      const k = Math.min(1, (t - start) / ms);
      setV(Math.round(target * (1 - Math.pow(1 - k, 3))));
      if (k < 1) raf(step);
    };
    raf(step);
    return () => { alive = false; };
  }, [run, target]);
  return v;
}

// ── Fight-night phase + running order ────────────────────────────────
// pre: more than 24h out · tonight: within 24h of the main card · live: prelims under way until ~4h after main card start · done
const LIVE_WINDOW_H = 24;
function fightPhase(e, now) {
  const main = new Date(e.startsAt).getTime();
  const pre = e.prelimsAt ? new Date(e.prelimsAt).getTime() : main - 3 * 3600e3;
  if (now >= main + 4 * 3600e3) return 'done';
  if (now >= pre) return 'live';
  if (now >= main - LIVE_WINDOW_H * 3600e3) return 'tonight';
  return 'pre';
}
function useFightPhase(e) {
  const [now, setNow] = useState(() => Date.now());
  useEffect(() => { const id = setInterval(() => setNow(Date.now()), 15000); return () => clearInterval(id); }, []);
  return { phase: fightPhase(e, now), now };
}
// Estimated bout times. Prelims share the window before the main card evenly. Main card bouts
// (tier MAIN or CARD) start at the main card time and run 33 min apart on Fight Nights, 40 on
// numbered cards (Fight Matrix, 18 cards in 2026: main event bell a median 2h 36m after the main card start).
function runningOrder(e) {
  const main = new Date(e.startsAt).getTime();
  const pre = e.prelimsAt ? new Date(e.prelimsAt).getTime() : main - 3 * 3600e3;
  const order = [...CARD_LADDER].reverse();
  const prelims = order.filter((f) => f.tier === 'PRELIM');
  const mains = order.filter((f) => f.tier !== 'PRELIM');
  const slot = prelims.length ? (main - pre) / prelims.length : 0;
  const perBout = /^UFC \d+$/.test(e.promotion || '') ? 40 : 33;
  return [
    ...prelims.map((f, i) => ({ ...f, at: pre + i * slot })),
    ...mains.map((f, i) => ({ ...f, at: main + i * perBout * 60e3 })),
  ];
}
const melClock = (ms) => {
  try {
    return new Intl.DateTimeFormat('en-AU', { timeZone: 'Australia/Melbourne', hour: 'numeric', minute: '2-digit' })
      .format(new Date(ms)).replace(/\s?(am|pm)$/i, (m) => ' ' + m.trim().toUpperCase());
  } catch (err) { return ''; }
};

const RunningOrder = ({ e, now, live }) => {
  const rows = useMemo(() => runningOrder(e), [e.startsAt, e.prelimsAt]);
  let cur = -1;
  if (live) rows.forEach((r, i) => { if (r.at <= now) cur = i; });
  const boxRef = useRef(null);
  useEffect(() => {
    const box = boxRef.current;
    const el = box && box.querySelector('[data-now="1"]');
    if (box && el) box.scrollTop = Math.max(0, el.offsetTop - box.offsetTop - 40);
  }, [cur]);
  return (
    <div className="hero-data-card running-order" style={heroStyles.dataCard}>
      <div style={heroStyles.dataCardHeader}>
        <span className="mono" style={{ fontSize: 10, letterSpacing: 2, color: 'var(--red)' }}>RUNNING ORDER</span>
        <span className="mono" style={{ fontSize: 10, letterSpacing: 1.5, color: 'var(--muted)' }}>EST. · MELBOURNE TIME</span>
      </div>
      <div ref={boxRef} style={{ maxHeight: 232, overflowY: 'auto', marginRight: -8, paddingRight: 8 }}>
        {rows.map((r, i) => {
          const isNow = i === cur;
          const isNext = live ? i === cur + 1 : i === 0;
          const past = live && i < cur;
          return (
            <div key={i} data-now={isNow ? '1' : '0'} className={isNow ? 'ro-now' : ''} style={{
              display: 'grid', gridTemplateColumns: '64px 1fr auto', alignItems: 'center', gap: 10,
              padding: '7px 8px', borderRadius: 4, opacity: past ? 0.38 : 1,
              background: isNow ? 'rgba(255,59,59,0.12)' : 'transparent',
              borderLeft: `2px solid ${isNow ? 'var(--red)' : r.tier !== 'PRELIM' ? 'var(--gold-soft)' : 'var(--line)'}`,
            }}>
              <span className="mono" style={{ fontSize: 10, letterSpacing: 1, color: isNow ? 'var(--red)' : 'var(--muted)' }}>~{melClock(r.at)}</span>
              <span style={{ fontSize: 13, color: 'var(--text)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                {r.red} <span className="mono" style={{ fontSize: 9, color: 'var(--muted)' }}>VS</span> {r.blue}
              </span>
              <span className="mono" style={{ fontSize: 9, letterSpacing: 1.5, color: isNow ? 'var(--red)' : isNext ? 'var(--gold)' : 'var(--muted)' }}>
                {isNow ? 'NOW' : isNext ? (live ? 'NEXT' : 'OPENER') : r.div}
              </span>
            </div>
          );
        })}
      </div>
    </div>
  );
};

// ── Site Nav ────────────────────────────────────────────────────────────
const SiteNav = () => {
  const [pastOpen, setPastOpen] = useState(false);
  const closeTimer = useRef(null);

  const openPast = () => {
    if (closeTimer.current) { clearTimeout(closeTimer.current); closeTimer.current = null; }
    setPastOpen(true);
  };
  const closePast = () => {
    closeTimer.current = setTimeout(() => setPastOpen(false), 200);
  };

  return (
    <nav className="nav-bar" style={navStyles.bar}>
      <a href="/index.html" style={navStyles.logo}>
        <span style={{ color: 'var(--text)' }}>MMA</span>
        <span style={{ color: 'var(--red)' }}>·</span>
        <span style={{ color: 'var(--text)' }}>FIGHT</span>
        <span style={{ color: 'var(--blue)' }}>·</span>
        <span style={{ color: 'var(--text)' }}>CARD</span>
        <span style={{ color: 'var(--muted)', fontSize: 11, marginLeft: 6 }}>.io</span>
      </a>

      <div className="nav-center" style={navStyles.center}>
        {NAV_LINKS.map((l) => (
          <a key={l.label} href={l.href} style={{
            ...navStyles.link,
            ...(l.active ? navStyles.linkActive : {}),
          }}>
            {l.label}
          </a>
        ))}

        <div
          onMouseEnter={openPast}
          onMouseLeave={closePast}
          style={{ position: 'relative' }}
        >
          <button style={{ ...navStyles.link, display: 'flex', gap: 6, alignItems: 'center' }}>
            Past Events
            <svg width="9" height="6" viewBox="0 0 10 6" fill="none" style={{ transform: pastOpen ? 'rotate(180deg)' : 'none', transition: 'transform .2s' }}>
              <path d="M1 1l4 4 4-4" stroke="currentColor" strokeWidth="1.5"/>
            </svg>
          </button>
          {pastOpen && (
            <div style={navStyles.dropdown}>
              {PAST_NAV.map((e) => (
                <a key={e.name} href={e.href} style={navStyles.dropdownItem}>
                  <span style={{ fontFamily: 'var(--display)', letterSpacing: 1.5, fontSize: 13 }}>{e.name}</span>
                  <span style={{ fontFamily: 'var(--mono)', fontSize: 10, color: 'var(--muted)' }}>{e.date}</span>
                </a>
              ))}
            </div>
          )}
        </div>
      </div>

      <div style={navStyles.right}>
        <a href="/index.html" style={navStyles.cta}>
          Pick'em <Arrow />
        </a>
      </div>
    </nav>
  );
};

const navStyles = {
  bar: {
    position: 'sticky', top: 0, zIndex: 100,
    display: 'flex', alignItems: 'center', justifyContent: 'space-between',
    gap: 24, padding: '14px 32px',
    background: 'rgba(14,14,16,0.78)',
    backdropFilter: 'blur(14px)',
    WebkitBackdropFilter: 'blur(14px)',
    borderBottom: '1px solid var(--line)',
  },
  logo: {
    fontFamily: 'var(--display)', fontSize: 16, letterSpacing: 4,
    display: 'flex', alignItems: 'center', gap: 4,
  },
  center: { display: 'flex', alignItems: 'center', gap: 4 },
  link: {
    fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: 1.6,
    textTransform: 'uppercase', color: 'var(--text-soft)',
    padding: '8px 12px', borderRadius: 4, transition: 'background .15s, color .15s',
  },
  linkActive: { color: 'var(--text)', background: 'var(--surface)' },
  dropdown: {
    position: 'absolute', top: 'calc(100% + 6px)', right: 0,
    background: 'var(--bg-2)', border: '1px solid var(--line)',
    borderRadius: 6, minWidth: 240, overflow: 'hidden',
    boxShadow: '0 18px 40px rgba(0,0,0,0.4)',
  },
  dropdownItem: {
    display: 'flex', justifyContent: 'space-between', alignItems: 'center',
    padding: '12px 16px', borderBottom: '1px solid var(--line-soft)', gap: 18,
    color: 'var(--text-soft)',
  },
  right: { display: 'flex', alignItems: 'center', gap: 10 },
  statusChip: {
    display: 'inline-flex', alignItems: 'center', gap: 8,
    padding: '7px 12px', border: '1px solid var(--line)', borderRadius: 99,
    color: 'var(--text-soft)',
  },
  cta: {
    display: 'inline-flex', alignItems: 'center', gap: 6,
    fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: 1.6, textTransform: 'uppercase',
    padding: '8px 14px', background: 'var(--text)', color: 'var(--ink)',
    borderRadius: 4, fontWeight: 600,
  },
};

// ── Live Ticker ─────────────────────────────────────────────────────────
const LiveTicker = () => {
  const items = [...TICKER_ITEMS, ...TICKER_ITEMS]; // duplicate for seamless loop
  return (
    <div style={tickerStyles.wrap}>
      <div style={tickerStyles.tagBox}>
        <LivePulse color="var(--red)" />
        <span className="mono" style={{ fontSize: 10, letterSpacing: 2, color: 'var(--text)' }}>WIRE / 05.09</span>
      </div>
      <div style={tickerStyles.scroller}>
        <div style={tickerStyles.track}>
          {items.map((it, i) => {
            const c = it.emphasis === 'blue' ? 'var(--blue)' :
                      it.emphasis === 'red' ? 'var(--red)' :
                      it.emphasis === 'live' ? 'var(--red)' : 'var(--gold)';
            return (
              <span key={i} style={tickerStyles.item}>
                <span className="mono" style={{ color: c, fontSize: 10, letterSpacing: 2, fontWeight: 600 }}>{it.tag}</span>
                <span style={{ color: 'var(--text-soft)', fontSize: 13 }}>{it.text}</span>
                <span style={{ color: 'var(--muted-2)' }}>·</span>
              </span>
            );
          })}
        </div>
      </div>
    </div>
  );
};

const tickerStyles = {
  wrap: {
    display: 'flex', alignItems: 'stretch',
    borderBottom: '1px solid var(--line)',
    background: 'var(--bg)',
  },
  tagBox: {
    display: 'flex', alignItems: 'center', gap: 8,
    padding: '10px 18px', borderRight: '1px solid var(--line)',
    background: 'var(--bg-2)',
    flexShrink: 0,
  },
  scroller: { overflow: 'hidden', flex: 1, position: 'relative', display: 'flex', alignItems: 'center' },
  track: {
    display: 'flex', gap: 28, paddingLeft: 28,
    whiteSpace: 'nowrap',
    animation: 'tickerSlide 50s linear infinite',
  },
  item: { display: 'inline-flex', alignItems: 'center', gap: 10 },
};

// ── HERO ───────────────────────────────────────────────────────────────
const Hero = ({ accentMode }) => {
  const cd = useCountdown(FEATURED_EVENT.startsAt);
  const { phase, now } = useFightPhase(FEATURED_EVENT);
  const hot = phase === 'tonight' || phase === 'live';
  const calHref = FEATURED_EVENT.calId ? `/cal/${FEATURED_EVENT.calId}.ics` : null;
  const watch = hot && FEATURED_EVENT.watchAU;
  // Hero photo from /photos.js: the featured event's UFC.com key art when UFC_PHOTOS is on and upcoming.json has it,
  // otherwise random each visit from the pool, men's or women's to match the featured main event
  const photo = useMemo(() => {
    const M = window.MMA_PHOTOS;
    if (!M) return null;
    const row = (typeof UPCOMING_SCHEDULE !== 'undefined' ? UPCOMING_SCHEDULE : []).find(u => u.href === FEATURED_EVENT.href);
    return M.art(row && row.art) || M.random(M.isWomen(FEATURED_EVENT.divisionLabel) ? 'w' : 'm');
  }, []);

  return (
    <section className={'hero-wrap' + (hot ? ' hero-live' : '')} style={heroStyles.wrap}>
      {hot && (
        <div className="live-banner mono">
          <LivePulse color="#fff" />
          <span>{phase === 'live' ? 'LIVE NOW' : 'LIVE TONIGHT'}</span>
          <span style={{ opacity: 0.75 }}>
            {phase === 'live' ? 'Fight night is under way' : `Prelims ${melClock(new Date(FEATURED_EVENT.prelimsAt || FEATURED_EVENT.startsAt).getTime())} · Main card ${melClock(new Date(FEATURED_EVENT.startsAt).getTime())} Melbourne`}
          </span>
          {watch && (
            <a href={watch.url} target="_blank" rel="noopener" className="live-watch" style={{ marginLeft: 'auto', color: '#fff', textDecoration: 'underline', textUnderlineOffset: 3, whiteSpace: 'nowrap' }}>
              Watch in Australia on {watch.label} ↗
            </a>
          )}
        </div>
      )}
      {/* Backdrop with duotone */}
      <div className="hero-bg-img" style={photo ? { ...heroStyles.bgImg, backgroundImage: `url('${photo.url(2000)}'), url('/mmafightcard-backdrop.png')`, backgroundPosition: photo.pos, opacity: photo.o } : heroStyles.bgImg} />
      <div style={heroStyles.bgDuotone} />
      <div style={heroStyles.bgVignette} />
      <div className="hero-scanlines" />
      <div className="mono hero-credit" style={heroStyles.credit}
        dangerouslySetInnerHTML={{ __html: photo ? photo.credit : 'Photo · <a href="https://unsplash.com/@gfrshoots?utm_source=mmafightcard&utm_medium=referral" target="_blank" rel="noopener">Gabriel F Rodrigues</a> / <a href="https://unsplash.com/?utm_source=mmafightcard&utm_medium=referral" target="_blank" rel="noopener">Unsplash</a>' }} />

      {/* Top metadata strip */}
      <div className="meta-strip" style={heroStyles.metaStrip}>
        <span className="mono" style={{ color: 'var(--muted)', fontSize: 10, letterSpacing: 2 }}>ISSUE 292 · FIGHT NIGHT · LAS VEGAS, NV</span>
        <span className="mono" style={{ color: 'var(--muted)', fontSize: 10, letterSpacing: 2 }}>EST 2026 · MMAFIGHTCARD.IO</span>
      </div>

      <div className="hero-inner hero-grid" style={heroStyles.inner}>
        {/* Left: massive typography */}
        <div style={heroStyles.leftCol}>
          <div style={heroStyles.eyebrow}>
            <LivePulse color="var(--red)" />
            <span className="mono" style={{ color: 'var(--red)', letterSpacing: 2, fontSize: 11 }}>{hot ? (phase === 'live' ? 'LIVE NOW · ' : 'LIVE TONIGHT · ') : ''}THIS SAT · 10 / 31 / 2026</span>
          </div>

          <h1 className="hero-title" style={heroStyles.title}>
            <span style={{ display: 'block' }}>Fight</span>
            <span style={{ display: 'block', color: 'var(--text)' }}>
              Night<span className="serif italic" style={{ color: 'var(--gold)', fontFamily: 'var(--serif)', fontStyle: 'italic', letterSpacing: 0, fontWeight: 400 }}>,</span>
            </span>
          </h1>

          <p style={heroStyles.lede}>
            Every card. Every fight. Live odds, betting lines, tale-of-the-tape and post-fight breakdowns —
            for the people who actually watch the prelims.
          </p>

          <div style={heroStyles.heroActions}>
            <a href={FEATURED_EVENT.href} style={heroStyles.primaryBtn}>
              Moicano vs Nolan preview <Arrow />
            </a>
            {watch ? (
              <a href={watch.url} target="_blank" rel="noopener" style={{ ...heroStyles.secondaryBtn, background: 'var(--red)', borderColor: 'var(--red)', color: '#fff' }}>
                Watch live on {watch.label} ↗
              </a>
            ) : calHref && phase !== 'done' ? (
              <a href={calHref} style={{ ...heroStyles.secondaryBtn, ...(hot ? { borderColor: 'var(--red)', color: 'var(--text)' } : null) }}>
                + Add to calendar
              </a>
            ) : (
              <a href="#results" style={heroStyles.secondaryBtn}>
                Recent results
              </a>
            )}
          </div>
        </div>

        {/* Right: data column */}
        <div style={heroStyles.rightCol}>
          <div className="hero-data-card" style={heroStyles.dataCard}>
            <div style={heroStyles.dataCardHeader}>
              <span className="mono" style={{ fontSize: 10, letterSpacing: 2, color: phase === 'done' ? 'var(--gold)' : hot ? 'var(--red)' : 'var(--muted)' }}>
                {phase === 'done' ? 'EVENT COMPLETE' : phase === 'live' ? (cd.live ? 'MAIN CARD LIVE' : 'PRELIMS LIVE · MAIN CARD IN') : 'MAIN CARD IN'}
              </span>
              <span className="mono" style={{ fontSize: 10, letterSpacing: 2, color: 'var(--text-soft)' }}>{FEATURED_EVENT.broadcast}</span>
            </div>
            {phase === 'done' ? (
              <a href={FEATURED_EVENT.href} style={{ display: 'block', textDecoration: 'none', paddingTop: 6 }}>
                <div className="display" style={{ fontSize: 46, lineHeight: 1, color: 'var(--gold)', letterSpacing: 2 }}>RESULTS</div>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginTop: 10, color: 'var(--text-soft)', fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: 1.6 }}>
                  Full recap <Arrow />
                </div>
              </a>
            ) : cd.live ? (
              <div style={{ paddingTop: 6 }}>
                <div className="display live-now-text" style={{ fontSize: 46, lineHeight: 1, color: 'var(--red)', letterSpacing: 2 }}>LIVE NOW</div>
                <div className="mono" style={{ marginTop: 10, color: 'var(--text-soft)', fontSize: 11, letterSpacing: 1.6 }}>Main card on {FEATURED_EVENT.broadcast}</div>
              </div>
            ) : (
              <div className={'cd-row' + (cd.d > 0 ? ' cd-days' : '')} style={heroStyles.countdown}>
                {cd.d > 0 && <><CountdownCell label="DAYS" value={cd.d} /><span style={heroStyles.countdownColon}>:</span></>}
                <CountdownCell label="HRS" value={cd.h} />
                <span style={heroStyles.countdownColon}>:</span>
                <CountdownCell label="MIN" value={cd.m} />
                <span style={heroStyles.countdownColon}>:</span>
                <CountdownCell label="SEC" value={cd.s} pulse />
              </div>
            )}
          </div>

          {hot && <RunningOrder e={FEATURED_EVENT} now={now} live={phase === 'live'} />}

          <div style={heroStyles.statGrid}>
            <Stat label="Card" value={FEATURED_EVENT.fightCount} sub="fights" />
            <Stat label="Venue" value="APEX" sub={FEATURED_EVENT.city} />
            <Stat label="Main" value="8PM" sub={"ET / " + FEATURED_EVENT.broadcast} />
            <Stat label="Titles" value="0" sub="on the line" />
          </div>
        </div>
      </div>
    </section>
  );
};

const CountdownCell = ({ label, value, pulse }) => (
  <div style={{ textAlign: 'center', minWidth: 60 }}>
    <div className="mono" style={{
      fontSize: 56, lineHeight: 1, fontWeight: 500, letterSpacing: '-0.04em',
      color: 'var(--text)', fontVariantNumeric: 'tabular-nums',
      animation: pulse ? 'tickPulse 1s ease-out infinite' : 'none',
    }}>
      {String(value).padStart(2, '0')}
    </div>
    <div className="mono" style={{ fontSize: 9, letterSpacing: 2, color: 'var(--muted)', marginTop: 4 }}>{label}</div>
  </div>
);

const Stat = ({ label, value, sub }) => (
  <div style={{
    padding: '14px 16px', border: '1px solid var(--line)',
    background: 'rgba(24,24,28,0.6)', backdropFilter: 'blur(8px)',
    borderRadius: 6,
  }}>
    <div className="mono" style={{ fontSize: 9, letterSpacing: 2, color: 'var(--muted)' }}>{label.toUpperCase()}</div>
    <div className="display" style={{ fontSize: 28, lineHeight: 1, marginTop: 4, color: 'var(--text)' }}>{value}</div>
    <div className="mono" style={{ fontSize: 10, color: 'var(--text-soft)', marginTop: 4 }}>{sub}</div>
  </div>
);

const heroStyles = {
  wrap: {
    position: 'relative', minHeight: 640, overflow: 'hidden',
    borderBottom: '1px solid var(--line)',
  },
  bgImg: {
    position: 'absolute', inset: 0,
    // Default/fallback photo; Hero swaps in a random one from /photos.js (hotlinked, credited in the hero corner).
    backgroundImage: "url('https://images.unsplash.com/photo-1777305628889-13832df3e542?w=2000&q=70&auto=format&fit=crop'), url('/mmafightcard-backdrop.png')",
    backgroundSize: 'cover', backgroundPosition: 'center 35%',
    filter: 'grayscale(0.55) contrast(1.15) brightness(1.15)',
    opacity: 0.7,
    transform: 'scale(1.1)',
    transformOrigin: 'center top',
    willChange: 'transform',
  },
  bgDuotone: {
    position: 'absolute', inset: 0,
    background: 'linear-gradient(110deg, rgba(255,59,59,0.32) 0%, rgba(14,14,16,0.05) 38%, rgba(14,14,16,0.05) 62%, rgba(59,140,255,0.28) 100%)',
    mixBlendMode: 'multiply',
  },
  bgVignette: {
    position: 'absolute', inset: 0,
    background: 'radial-gradient(ellipse 100% 80% at 50% 100%, rgba(14,14,16,0.95) 0%, rgba(14,14,16,0.4) 50%, rgba(14,14,16,0.85) 100%)',
  },
  credit: {
    position: 'absolute', right: 16, bottom: 10, zIndex: 3,
    fontSize: 9, letterSpacing: 1.2, color: 'var(--muted)', opacity: 0.8,
  },
  metaStrip: {
    position: 'relative', zIndex: 2,
    display: 'flex', justifyContent: 'space-between',
    padding: '14px 32px', borderBottom: '1px solid rgba(255,255,255,0.06)',
  },
  inner: {
    position: 'relative', zIndex: 2,
    display: 'grid', gridTemplateColumns: '1.4fr 1fr',
    gap: 56, padding: '60px 32px 64px',
    maxWidth: 1320, margin: '0 auto',
  },
  leftCol: { display: 'flex', flexDirection: 'column', justifyContent: 'flex-end' },
  eyebrow: { display: 'flex', alignItems: 'center', gap: 10, marginBottom: 28 },
  title: {
    fontFamily: 'var(--display)',
    fontSize: 'clamp(80px, 13vw, 200px)',
    lineHeight: 0.85,
    letterSpacing: '-0.005em',
    color: 'var(--text)',
    fontWeight: 400,
  },
  lede: {
    maxWidth: 460, marginTop: 32,
    color: 'var(--text-soft)', fontSize: 16, lineHeight: 1.55,
  },
  heroActions: { display: 'flex', gap: 10, marginTop: 32 },
  primaryBtn: {
    display: 'inline-flex', alignItems: 'center', gap: 10,
    padding: '14px 22px', background: 'var(--text)', color: 'var(--ink)',
    fontFamily: 'var(--mono)', fontSize: 12, letterSpacing: 1.6, textTransform: 'uppercase',
    fontWeight: 600, borderRadius: 4,
  },
  secondaryBtn: {
    display: 'inline-flex', alignItems: 'center', gap: 10,
    padding: '14px 22px', border: '1px solid var(--line)', color: 'var(--text-soft)',
    fontFamily: 'var(--mono)', fontSize: 12, letterSpacing: 1.6, textTransform: 'uppercase',
    fontWeight: 500, borderRadius: 4,
  },
  rightCol: { display: 'flex', flexDirection: 'column', gap: 16, justifyContent: 'flex-end' },
  dataCard: {
    border: '1px solid var(--line)', borderRadius: 8,
    background: 'rgba(24,24,28,0.55)', backdropFilter: 'blur(10px)',
    padding: '20px 24px',
  },
  dataCardHeader: { display: 'flex', justifyContent: 'space-between', marginBottom: 14 },
  countdown: { display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', padding: '0 4px' },
  countdownColon: { fontFamily: 'var(--mono)', fontSize: 48, color: 'var(--muted-2)', alignSelf: 'flex-start', lineHeight: 1 },
  statGrid: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 },
};

// ── Featured Match-up Bento ──────────────────────────────────────────
const FeaturedMatchup = () => {
  const e = FEATURED_EVENT;
  return (
    <section className="feat-wrap scroll-reveal" style={featStyles.wrap}>
      {/* Section header */}
      <div style={featStyles.sectHeader}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 14 }}>
          <span className="mono" style={{ fontSize: 10, letterSpacing: 2, color: 'var(--muted)' }}>01 / FEATURED</span>
          <h2 className="display" style={{ fontSize: 30, letterSpacing: 1, color: 'var(--text)' }}>Main Event</h2>
          <span className="serif italic" style={{ color: 'var(--text-soft)', fontSize: 22 }}>tonight.</span>
        </div>
        <a href={e.href} style={featStyles.headerLink}>Full booklet <Arrow /></a>
      </div>

      <div className="bento-grid" style={featStyles.bento}>
        {/* Big VS card */}
        <a href={e.href} style={{ ...featStyles.cell, ...featStyles.vsCell }}>
          <div className="vs-split" aria-hidden="true" />
          <div className="vs-slash" aria-hidden="true" />
          <div style={featStyles.cornerStripe('var(--red-deep)', 'left')} />
          <div style={featStyles.cornerStripe('var(--blue-deep)', 'right')} />

          <div style={featStyles.vsHeader}>
            <span style={featStyles.tagPill('var(--red)')}>
              NEXT EVENT
            </span>
            <span style={featStyles.tagPill('var(--blue)')}>
              {e.promotion}
            </span>
            <span className="mono" style={{ marginLeft: 'auto', fontSize: 10, letterSpacing: 1.6, color: 'var(--muted)' }}>
              {e.venue} · {e.city}
            </span>
          </div>

          <div className="vs-body" style={featStyles.vsBody}>
            <FighterColumn fighter={e.red} side="red" />
            <div className="vs-axis" style={featStyles.vsAxis}>
              <div className="vs-line" style={featStyles.vsLine} />
              <div style={featStyles.vsBadge}>
                <span className="display" style={{ fontSize: 38, lineHeight: 1, letterSpacing: 2 }}>VS</span>
              </div>
              <div className="mono" style={featStyles.vsDivision}>{e.divisionLabel}</div>
              <div className="vs-line" style={featStyles.vsLine} />
            </div>
            <FighterColumn fighter={e.blue} side="blue" />
          </div>

          {/* Tape */}
          <div style={featStyles.tapeRow}>
            <TapeRow fighter={e.red} other={e.blue} side="red" />
          </div>
        </a>

        {/* Right column: Odds + Pick + Card */}
        <div style={featStyles.rightStack}>
          {/* Odds card */}
          <div style={featStyles.cell}>
            <div style={featStyles.cellHeader}>
              <span className="mono" style={{ fontSize: 10, letterSpacing: 2, color: 'var(--muted)' }}>02 / LIVE ODDS</span>
              <LivePulse color="var(--red)" />
            </div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginTop: 14 }}>
              <OddsRow name={`${e.red.first} ${e.red.last}`} odds={e.red.odds} pct={53} side="red" />
              <OddsRow name={`${e.blue.first} ${e.blue.last}`} odds={e.blue.odds} pct={47} side="blue" />
            </div>
            <div className="mono" style={{ fontSize: 10, letterSpacing: 1.5, color: 'var(--muted)', marginTop: 16 }}>
              Close on UFC.com, Moicano -125 to Nolan +105: Nolan is 11 years younger and 4 inches taller, Moicano has 11 submission wins
            </div>
          </div>

          {/* Community pick */}
          <div style={{ ...featStyles.cell, background: 'var(--cream)', color: 'var(--ink)', borderColor: 'var(--cream-line)' }}>
            <div style={{ ...featStyles.cellHeader, color: 'var(--ink-soft)' }}>
              <span className="mono" style={{ fontSize: 10, letterSpacing: 2 }}>03 / COMMUNITY PICK</span>
              <span className="mono" style={{ fontSize: 10, letterSpacing: 1.5 }}>early lines</span>
            </div>
            <div className="display" style={{ fontSize: 38, lineHeight: 1, marginTop: 12, color: 'var(--ink)' }}>
              47<span style={{ fontSize: 22, color: 'var(--ink-soft)' }}>%</span> <span className="serif italic" style={{ fontSize: 22, color: 'var(--ink-soft)' }}>take</span>
            </div>
            <div className="display" style={{ fontSize: 28, lineHeight: 1, marginTop: 4 }}>Nolan · Decision</div>
            <div style={{ display: 'flex', height: 6, marginTop: 18, borderRadius: 99, overflow: 'hidden' }}>
              <div style={{ flex: 53, background: 'var(--red)' }} />
              <div style={{ flex: 47, background: 'var(--blue)' }} />
            </div>
            <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 8 }}>
              <span className="mono" style={{ fontSize: 10, letterSpacing: 1.5, color: 'var(--ink-soft)' }}>MOICANO 53%</span>
              <span className="mono" style={{ fontSize: 10, letterSpacing: 1.5, color: 'var(--ink-soft)' }}>NOLAN 47%</span>
            </div>
          </div>
        </div>

        {/* Bottom row: card preview */}
        <div style={{ ...featStyles.cell, gridColumn: '1 / -1' }}>
          <div style={featStyles.cellHeader}>
            <span className="mono" style={{ fontSize: 10, letterSpacing: 2, color: 'var(--muted)' }}>04 / FULL CARD · 12 FIGHTS</span>
            <a href={e.href} className="mono" style={{ fontSize: 11, letterSpacing: 1.5, color: 'var(--text-soft)' }}>booklet ↗</a>
          </div>
          <CardLadder />
        </div>
      </div>
    </section>
  );
};

const FighterColumn = ({ fighter, side }) => {
  const isRed = side === 'red';
  const accent = isRed ? 'var(--red)' : 'var(--blue)';
  return (
    <div className="fighter-col" style={{
      display: 'flex', flexDirection: 'column',
      alignItems: isRed ? 'flex-start' : 'flex-end',
      textAlign: isRed ? 'left' : 'right',
      flex: '1 1 200px', gap: 8, padding: '4px 0',
      minWidth: 0,
    }}>
      <div className="mono" style={{ fontSize: 10, letterSpacing: 2, color: accent }}>
        {isRed ? `RED · ${fighter.rank}` : `${fighter.rank} · BLUE`}
      </div>
      <div className="display fighter-bigname" style={{ lineHeight: 0.9, letterSpacing: 1, color: 'var(--text)' }}>
        {fighter.first}<br />{fighter.last}
      </div>
      {fighter.nickname ? (
        <div className="serif italic" style={{ color: 'var(--text-soft)', fontSize: 18 }}>
          “{fighter.nickname.toLowerCase()}”
        </div>
      ) : null}
      <div className="mono" style={{ fontSize: 11, letterSpacing: 1.5, color: 'var(--muted)' }}>
        {fighter.flag} {fighter.country} · {fighter.record} · {fighter.streak}
      </div>
    </div>
  );
};

// "6'2\"" -> 74, "75\"" -> 75, 30 -> 30
const toInches = (v) => {
  if (typeof v === 'number') return v;
  const m = String(v || '').match(/(\d+)'\s*(\d+(?:\.\d+)?)?/);
  if (m) return Number(m[1]) * 12 + Number(m[2] || 0);
  const n = parseFloat(String(v || '').replace(/[^\d.]/g, ''));
  return isNaN(n) ? null : n;
};
const impliedPct = (ml) => (typeof ml !== 'number' ? null : ml < 0 ? (-ml / (-ml + 100)) * 100 : (100 / (ml + 100)) * 100);

// Animated tale of the tape: bars grow from the centre line once the card scrolls into view.
const TapeRow = ({ fighter, other, side }) => {
  const [ref, seen] = useInView(0.3);
  const pr = impliedPct(fighter.moneyline), pb = impliedPct(other.moneyline);
  const stats = [
    ['AGE', fighter.age, other.age, toInches(fighter.age), toInches(other.age), false],
    ['HEIGHT', fighter.height, other.height, toInches(fighter.height), toInches(other.height), true],
    ['REACH', fighter.reach, other.reach, toInches(fighter.reach), toInches(other.reach), true],
    ...(fighter.stance || other.stance ? [['STANCE', fighter.stance || '-', other.stance || '-', null, null, false]] : []),
    ...(pr && pb ? [['WIN %', Math.round(100 * pr / (pr + pb)) + '%', Math.round(100 * pb / (pr + pb)) + '%', pr, pb, true]] : []),
  ];
  return (
    <div ref={ref} className="tape-bars" style={{ borderTop: '1px solid var(--line)', marginTop: 24, paddingTop: 16, display: 'flex', flexDirection: 'column', gap: 9 }}>
      {stats.map(([label, l, r, ln, rn, edge], i) => {
        const max = Math.max(ln || 0, rn || 0) || 1;
        const lw = ln != null ? (ln / max) * 100 : 0, rw = rn != null ? (rn / max) * 100 : 0;
        const lEdge = edge && ln > rn, rEdge = edge && rn > ln;
        const delay = `${0.15 + i * 0.12}s`;
        return (
          <div key={label} className="tape-bar-row" style={{ display: 'grid', gridTemplateColumns: '64px 1fr 64px 1fr 64px', alignItems: 'center', gap: 10 }}>
            <span className="mono" style={{ fontSize: 13, fontWeight: 500, color: lEdge ? 'var(--red)' : 'var(--text)' }}>{l}</span>
            <div style={{ height: 6, background: 'var(--line-soft)', borderRadius: 99, overflow: 'hidden', display: 'flex', justifyContent: 'flex-end' }}>
              <div className="tape-fill" style={{ width: seen ? `${lw}%` : '0%', transitionDelay: delay, background: lEdge ? 'var(--red)' : 'rgba(255,59,59,0.38)', boxShadow: lEdge ? '0 0 10px var(--red)' : 'none' }} />
            </div>
            <span className="mono" style={{ fontSize: 9, letterSpacing: 1.5, color: 'var(--muted)', textAlign: 'center' }}>{label}</span>
            <div style={{ height: 6, background: 'var(--line-soft)', borderRadius: 99, overflow: 'hidden' }}>
              <div className="tape-fill" style={{ width: seen ? `${rw}%` : '0%', transitionDelay: delay, background: rEdge ? 'var(--blue)' : 'rgba(59,140,255,0.38)', boxShadow: rEdge ? '0 0 10px var(--blue)' : 'none' }} />
            </div>
            <span className="mono" style={{ fontSize: 13, fontWeight: 500, textAlign: 'right', color: rEdge ? 'var(--blue)' : 'var(--text)' }}>{r}</span>
          </div>
        );
      })}
    </div>
  );
};

const OddsRow = ({ name, odds, pct, side }) => {
  const [ref, mounted] = useInView(0.4);
  const ml = parseInt(String(odds).replace('\u2212', '-'), 10);
  const shown = useCountUp(Math.abs(ml) || 0, mounted);
  const oddsText = isNaN(ml) ? odds : (ml < 0 ? '\u2212' : '+') + shown;
  const isRed = side === 'red';
  const accent = isRed ? 'var(--red)' : 'var(--blue)';
  return (
    <div ref={ref} style={{ position: 'relative', padding: '12px 14px', border: '1px solid var(--line)', borderRadius: 6, overflow: 'hidden', background: 'var(--bg)' }}>
      <div className="odds-bar-fill" style={{
        position: 'absolute', top: 0, bottom: 0, left: 0,
        width: mounted ? `${pct}%` : '0%',
        background: `linear-gradient(90deg, ${accent}22, transparent)`,
        borderLeft: `2px solid ${accent}`,
      }} />
      <div style={{ position: 'relative', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
        <div>
          <div className="mono" style={{ fontSize: 9, letterSpacing: 2, color: accent }}>{isRed ? 'RED CORNER' : 'BLUE CORNER'}</div>
          <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--text)', marginTop: 2 }}>{name}</div>
        </div>
        <div className="mono" style={{ fontSize: 22, color: 'var(--text)', fontWeight: 500, fontVariantNumeric: 'tabular-nums' }}>{oddsText}</div>
      </div>
    </div>
  );
};

const CARD_LADDER = [
  { tier: 'MAIN',   red: 'Moicano',     blue: 'Nolan',      div: 'LW',  rds: 5 },
  { tier: 'CARD',   red: 'Brown',       blue: 'Smith',      div: 'WW',  rds: 3 },
  { tier: 'CARD',   red: 'Osbourne',    blue: 'Durden',     div: 'FL',  rds: 3 },
  { tier: 'CARD',   red: 'Y. Santos',   blue: 'L. Santos',  div: 'WBW', rds: 3 },
  { tier: 'CARD',   red: 'Lebosnoyani', blue: 'Hasanov',    div: 'WW',  rds: 3 },
  { tier: 'PRELIM', red: 'Marshall',    blue: 'Hope',       div: 'FW',  rds: 3 },
  { tier: 'PRELIM', red: 'Sezinando',   blue: 'Berggren',   div: 'WW',  rds: 3 },
  { tier: 'PRELIM', red: 'Erosa',       blue: 'Lee',        div: 'FW',  rds: 3 },
  { tier: 'PRELIM', red: 'Reese',       blue: 'Gall',       div: 'MW',  rds: 3 },
  { tier: 'PRELIM', red: 'Klein',       blue: 'Kropschot',  div: 'MW',  rds: 3 },
  { tier: 'PRELIM', red: 'Alencar',     blue: 'Rodriguez',  div: 'SW',  rds: 3 },
  { tier: 'PRELIM', red: 'Szabova',     blue: 'Lisboa',     div: 'WFL', rds: 3 },
];
const CardLadder = () => (
  <div style={{ marginTop: 14, borderTop: '1px solid var(--line-soft)' }}>
    {CARD_LADDER.map((f, i) => (
      <div key={i} className="card-row-item" style={{
        display: 'grid', gridTemplateColumns: '80px 1fr 60px 1fr 80px',
        alignItems: 'center', gap: 12, padding: '11px 4px',
        borderBottom: '1px solid var(--line-soft)',
        transitionDelay: `${i * 0.07}s`,
      }}>
        <span className="mono" style={{ fontSize: 10, letterSpacing: 1.5, color: f.tier === 'MAIN' ? 'var(--gold)' : 'var(--muted)' }}>
          {f.tier}
        </span>
        <span style={{ fontSize: 14, color: 'var(--text)', textAlign: 'right' }}>{f.red}</span>
        <span className="mono" style={{ fontSize: 10, letterSpacing: 1.5, color: 'var(--muted)', textAlign: 'center' }}>VS</span>
        <span style={{ fontSize: 14, color: 'var(--text)' }}>{f.blue}</span>
        <span className="mono" style={{ fontSize: 10, letterSpacing: 1.5, color: 'var(--text-soft)', textAlign: 'right' }}>
          {f.div} · {f.rds}R
        </span>
      </div>
    ))}
  </div>
);

const featStyles = {
  wrap: { padding: '80px 32px', maxWidth: 1320, margin: '0 auto' },
  sectHeader: {
    display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between',
    marginBottom: 28, paddingBottom: 18, borderBottom: '1px solid var(--line)',
  },
  headerLink: {
    fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: 1.6,
    textTransform: 'uppercase', color: 'var(--text-soft)',
    display: 'inline-flex', alignItems: 'center', gap: 6,
  },
  bento: { display: 'grid', gridTemplateColumns: '1.7fr 1fr', gap: 14 },
  cell: {
    position: 'relative', padding: 24,
    border: '1px solid var(--line)', borderRadius: 10,
    background: 'var(--bg-2)',
    overflow: 'hidden',
  },
  cellHeader: { display: 'flex', justifyContent: 'space-between', alignItems: 'center' },
  vsCell: {
    minHeight: 360, padding: '28px 32px',
    color: 'inherit', display: 'flex', flexDirection: 'column',
    background: 'linear-gradient(135deg, rgba(255,59,59,0.05) 0%, var(--bg-2) 50%, rgba(59,140,255,0.05) 100%)',
  },
  cornerStripe: (color, side) => ({
    position: 'absolute', top: 0, bottom: 0, [side]: 0, width: 4,
    background: color,
  }),
  vsHeader: { display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap', marginBottom: 28 },
  vsBody: { display: 'flex', alignItems: 'center', gap: 16, flex: 1, flexWrap: 'wrap' },
  vsAxis: { display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8, padding: '0 14px' },
  vsLine: { width: 1, height: 24, background: 'var(--line)' },
  vsBadge: {
    width: 80, height: 80, borderRadius: '50%',
    border: '1px solid var(--line)',
    display: 'flex', alignItems: 'center', justifyContent: 'center',
    color: 'var(--text)',
    background: 'rgba(14,14,16,0.7)',
  },
  vsDivision: {
    fontSize: 9, letterSpacing: 2, color: 'var(--muted)', textAlign: 'center', maxWidth: 80,
  },
  vsHeaderLine: { fontSize: 10, color: 'var(--muted)' },
  rightStack: { display: 'flex', flexDirection: 'column', gap: 14 },
  tagPill: (color) => ({
    display: 'inline-flex', alignItems: 'center', gap: 6,
    padding: '4px 10px', borderRadius: 99, border: `1px solid ${color}55`,
    color: color, background: `${color}11`,
    fontFamily: 'var(--mono)', fontSize: 10, letterSpacing: 2, fontWeight: 600,
  }),
  tapeRow: { marginTop: 'auto' },
};

// ── On Deck (next-next event teaser) ──────────────────────────────────
const OnDeck = () => {
  const e = (typeof UPCOMING_EVENT !== 'undefined') ? UPCOMING_EVENT : null;
  if (!e) return null;
  return (
    <a href={e.href} className="on-deck-strip scroll-reveal" style={onDeckStyles.wrap}>
      <div style={onDeckStyles.left}>
        <span style={onDeckStyles.labelGroup}>
          <LivePulse color="var(--gold)" />
          <span className="mono" style={onDeckStyles.label}>{e.label || 'ON DECK'}</span>
        </span>
        <span className="display" style={onDeckStyles.promo}>{e.promotion}</span>
        <span className="serif italic" style={onDeckStyles.matchup}>{e.matchup}</span>
      </div>
      <div style={onDeckStyles.right}>
        <span className="mono" style={onDeckStyles.date}>{e.dateShort} &middot; {e.venue}</span>
        <span className="mono" style={onDeckStyles.cta}>Preview <Arrow /></span>
      </div>
    </a>
  );
};

const onDeckStyles = {
  wrap: {
    display: 'flex', alignItems: 'center', justifyContent: 'space-between',
    flexWrap: 'wrap', gap: 16,
    maxWidth: 1320, margin: '0 auto', padding: '18px 32px',
    borderTop: '1px solid var(--line)', borderBottom: '1px solid var(--line)',
    textDecoration: 'none', transition: 'border-color .2s',
  },
  left: { display: 'flex', alignItems: 'baseline', gap: 12, flexWrap: 'wrap' },
  labelGroup: { display: 'inline-flex', alignItems: 'center', gap: 8 },
  label: { fontSize: 10, letterSpacing: 2, color: 'var(--gold)' },
  promo: { fontSize: 20, letterSpacing: 1, color: 'var(--text)' },
  matchup: { fontSize: 15, color: 'var(--text-soft)' },
  right: { display: 'flex', alignItems: 'center', gap: 16 },
  date: { fontSize: 11, letterSpacing: 1.5, color: 'var(--muted)' },
  cta: {
    fontSize: 11, letterSpacing: 1.6, textTransform: 'uppercase', color: 'var(--text-soft)',
    display: 'inline-flex', alignItems: 'center', gap: 6,
  },
};

// ── Upcoming Schedule ─────────────────────────────────────────────────
// Rows come from UPCOMING_SCHEDULE (data.jsx), generated from /upcoming.json by
// scripts/sync_upcoming.py. Events drop off 8 hours after their main card starts.
const melTime = (iso) => {
  try {
    return new Intl.DateTimeFormat('en-AU', { timeZone: 'Australia/Melbourne', weekday: 'short', hour: 'numeric', minute: '2-digit' })
      .format(new Date(iso)).replace(/\s?(am|pm)$/i, (m) => ' ' + m.trim().toUpperCase());
  } catch (err) { return ''; }
};
const shortDate = (iso) => {
  const [y, m, d] = iso.split('-').map(Number);
  const mon = ['JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'][m - 1];
  return { mon, day: String(d).padStart(2, '0') };
};

const UpcomingSchedule = () => {
  const all = (typeof UPCOMING_SCHEDULE !== 'undefined') ? UPCOMING_SCHEDULE : [];
  const now = Date.now();
  const rows = all.filter((e) => new Date(e.startsAt).getTime() + 8 * 3600e3 > now);
  if (!rows.length) return null;
  const featuredHref = (typeof FEATURED_EVENT !== 'undefined' && FEATURED_EVENT) ? FEATURED_EVENT.href : null;
  return (
    <section className="sched-wrap scroll-reveal" style={schedStyles.wrap} id="schedule">
      <div style={schedStyles.header}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 14, flexWrap: 'wrap' }}>
          <span className="mono" style={{ fontSize: 10, letterSpacing: 2, color: 'var(--muted)' }}>05 / SCHEDULE</span>
          <h2 className="display" style={{ fontSize: 30, letterSpacing: 1, color: 'var(--text)' }}>Upcoming Events</h2>
          <span className="serif italic" style={{ color: 'var(--text-soft)', fontSize: 22 }}>on the calendar.</span>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 16, flexWrap: 'wrap' }}>
          <span className="mono" style={{ fontSize: 10, letterSpacing: 1.6, color: 'var(--muted)' }}>MAIN CARD TIMES · ET / MELBOURNE</span>
          <a href="webcal://mmafightcard.io/cal/ufc-schedule.ics" className="mono" style={{ fontSize: 10, letterSpacing: 1.6, color: 'var(--gold)' }}>+ SUBSCRIBE IN CALENDAR</a>
          <a href="/cal/ufc-schedule.ics" className="mono" style={{ fontSize: 10, letterSpacing: 1.6, color: 'var(--text-soft)' }}>.ICS</a>
        </div>
      </div>
      <div>
        {rows.map((e, i) => {
          const d = shortDate(e.iso);
          const isFeat = !!e.href && e.href === featuredHref;
          const ppv = e.kind === 'PPV';
          const link = e.href || e.card || null;
          const Tag = link ? 'a' : 'div';
          return (
            <Tag key={e.id} {...(link ? { href: link } : {})} className="sched-row" style={{ ...schedStyles.row, ...(link ? null : { cursor: 'default' }) }}>
              <div style={schedStyles.date}>
                <span className="mono" style={{ fontSize: 10, letterSpacing: 2, color: 'var(--muted)' }}>{d.mon}</span>
                <span className="display" style={{ fontSize: 34, lineHeight: 1, color: 'var(--text)' }}>{d.day}</span>
              </div>
              <div style={{ minWidth: 0 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap', marginBottom: 4 }}>
                  <span className="mono" style={{ ...schedStyles.tag, ...(ppv ? schedStyles.tagPpv : null) }}>{e.label.toUpperCase()}</span>
                  {isFeat && <span className="mono" style={{ ...schedStyles.tag, ...schedStyles.tagFeat }}>FEATURED</span>}
                  <span className="mono" style={{ fontSize: 10, letterSpacing: 1.5, color: 'var(--muted)' }}>{e.division.toUpperCase()}</span>
                </div>
                <div className="display sched-matchup" style={schedStyles.matchup}>
                  {e.red}{e.redRank && <span style={schedStyles.rank}> {e.redRank}</span>}
                  <span className="serif italic" style={{ color: 'var(--muted)', fontSize: '0.62em' }}> vs </span>
                  {e.blue}{e.blueRank && <span style={schedStyles.rank}> {e.blueRank}</span>}
                </div>
                {(e.coMain || e.notable) && (
                  <div style={schedStyles.sub}>
                    {e.coMain && <span>Co-main: {e.coMain}</span>}
                    {e.coMain && e.notable && <span style={{ color: 'var(--muted-2)' }}> · </span>}
                    {e.notable && <span>Also: {e.notable}</span>}
                  </div>
                )}
              </div>
              <div className="sched-meta" style={schedStyles.meta}>
                <span className="mono" style={{ fontSize: 11, letterSpacing: 1.2, color: 'var(--text-soft)' }}>{e.venue}</span>
                <span className="mono" style={{ fontSize: 10, letterSpacing: 1.2, color: 'var(--muted)' }}>{e.city}</span>
                <span className="mono" style={{ fontSize: 10, letterSpacing: 1.2, color: 'var(--muted)', marginTop: 4 }}>
                  {e.mainET}{melTime(e.startsAt) ? ` · ${melTime(e.startsAt)} MEL` : ''}{e.fights ? ` · ${e.fights} FIGHTS` : ''}
                </span>
              </div>
              <div className="sched-cta" style={schedStyles.cta}>
                {e.href
                  ? <span className="mono" style={{ fontSize: 11, letterSpacing: 1.6, color: 'var(--gold)', display: 'inline-flex', alignItems: 'center', gap: 6 }}>PREVIEW <Arrow /></span>
                  : e.card
                  ? <span className="mono" style={{ fontSize: 11, letterSpacing: 1.6, color: 'var(--gold)', display: 'inline-flex', alignItems: 'center', gap: 6 }}>VIEW CARD <Arrow /></span>
                  : <span className="mono" style={{ fontSize: 10, letterSpacing: 1.6, color: 'var(--muted-2)' }}>{i === 0 ? 'PREVIEW SOON' : 'ANNOUNCED'}</span>}
              </div>
            </Tag>
          );
        })}
      </div>
    </section>
  );
};

const schedStyles = {
  wrap: { maxWidth: 1320, margin: '0 auto', padding: '72px 32px 80px' },
  header: {
    display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', flexWrap: 'wrap', gap: 12,
    paddingBottom: 18, marginBottom: 4, borderBottom: '1px solid var(--line)',
  },
  row: {
    display: 'grid', gridTemplateColumns: '64px 1fr 240px 120px', alignItems: 'center', gap: 20,
    padding: '18px 4px', borderBottom: '1px solid var(--line-soft)', textDecoration: 'none', color: 'inherit',
  },
  date: { display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 2 },
  tag: { fontSize: 9, letterSpacing: 1.8, padding: '3px 7px', border: '1px solid var(--line)', color: 'var(--text-soft)' },
  tagPpv: { borderColor: 'var(--red-deep)', color: 'var(--red)' },
  tagFeat: { borderColor: 'var(--gold-soft)', color: 'var(--gold)' },
  matchup: { fontSize: 26, letterSpacing: 0.8, color: 'var(--text)', lineHeight: 1.1 },
  rank: { fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: 1, color: 'var(--muted)', verticalAlign: 'middle' },
  sub: { fontSize: 13, color: 'var(--text-soft)', marginTop: 6, lineHeight: 1.45 },
  meta: { display: 'flex', flexDirection: 'column', gap: 2, alignItems: 'flex-start' },
  cta: { justifySelf: 'end' },
};

// ── Recent Results ────────────────────────────────────────────────────
const RecentResults = () => (
  <section className="results-wrap scroll-reveal" style={resultsStyles.wrap} id="results">
    <div style={resultsStyles.header}>
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 14 }}>
        <span className="mono" style={{ fontSize: 10, letterSpacing: 2, color: 'var(--ink-soft)' }}>06 / ARCHIVE</span>
        <h2 className="display" style={{ fontSize: 30, letterSpacing: 1, color: 'var(--ink)' }}>Recent Results</h2>
        <span className="serif italic" style={{ color: 'var(--ink-soft)', fontSize: 22 }}>archived.</span>
      </div>
      <a href="/results.html" className="mono" style={{ fontSize: 11, letterSpacing: 1.6, color: 'var(--ink)', textTransform: 'uppercase', display: 'inline-flex', alignItems: 'center', gap: 6 }}>
        View all results <Arrow />
      </a>
    </div>

    <div className="results-grid" style={resultsStyles.grid}>
      {PAST_EVENTS.map((ev, i) => (
        <ResultCard key={ev.id} ev={ev} idx={i} />
      ))}
    </div>
  </section>
);

const ResultCard = ({ ev, idx }) => {
  const winnerSide = ev.resultWinner;
  const accent = winnerSide === 'red' ? 'var(--red)' : 'var(--blue)';
  const special = !!ev.special;
  const hasPage = !!ev.href && ev.href !== '#';
  const Tag = hasPage ? 'a' : 'div';
  return (
    <Tag {...(hasPage ? { href: ev.href } : {})} className={special ? 'reveal-card is-landmark' : 'reveal-card'} style={{ ...resultsStyles.card, ...(special ? resultsStyles.cardSpecial : null), ...(hasPage ? null : { cursor: 'default' }), transitionDelay: `${idx * 0.06}s` }}>
      <div style={resultsStyles.cardTop}>
        <span className="mono" style={resultsStyles.cardNum}>{String(idx + 1).padStart(2, '0')}</span>
        <span className="mono" style={resultsStyles.cardKind}>{ev.kind.toUpperCase()}</span>
        {special && <span className="mono" style={resultsStyles.cardLandmark}>{ev.specialLabel || 'LANDMARK'}</span>}
        <span className="mono" style={{ ...resultsStyles.cardDate, marginLeft: 'auto' }}>{ev.dateNum}</span>
      </div>

      <div className="card-title-big" style={resultsStyles.cardTitle}>
        <span>{ev.title}</span>
        {ev.titleVs && <span className="serif italic" style={{ color: 'var(--ink-soft)', fontSize: '0.6em' }}> {ev.titleVs} </span>}
        <span style={{ color: 'var(--ink)' }}>{ev.title2}</span>
      </div>

      <div className="serif italic" style={resultsStyles.cardHeadline}>
        {ev.headline}.
      </div>

      <div style={resultsStyles.cardMatchup}>
        <div style={{ flex: 1 }}>
          <div className="mono" style={{ fontSize: 9, letterSpacing: 2, color: 'var(--red-deep)' }}>RED</div>
          <div style={{ fontSize: 14, color: 'var(--ink)', fontWeight: 600, marginTop: 2 }}>{ev.redFlag} {ev.redName}</div>
        </div>
        <span className="mono" style={{ fontSize: 10, color: 'var(--ink-soft)', letterSpacing: 1.5 }}>vs</span>
        <div style={{ flex: 1, textAlign: 'right' }}>
          <div className="mono" style={{ fontSize: 9, letterSpacing: 2, color: 'var(--blue-deep)' }}>BLUE</div>
          <div style={{ fontSize: 14, color: 'var(--ink)', fontWeight: 600, marginTop: 2, whiteSpace: 'nowrap' }}>{ev.blueName} {ev.blueFlag}</div>
        </div>
      </div>

      <div style={{ ...resultsStyles.resultBar, borderColor: accent }}>
        <span className="mono" style={{ fontSize: 10, letterSpacing: 2, color: accent }}>RESULT</span>
        <span style={{ fontSize: 13, color: 'var(--ink)', fontWeight: 500 }}>{ev.result}</span>
      </div>

      <div style={resultsStyles.cardStats}>
        <CardStat label="Fights" value={ev.fights} />
        <CardStat label="Finishes" value={ev.finishes} />
        <CardStat label="Bonuses" value={ev.bonuses} />
        <CardStat label="Venue" value={ev.city.split(',')[0]} small />
      </div>

      <div style={resultsStyles.cardFoot}>
        <span className="mono" style={{ fontSize: 11, letterSpacing: 1.5, color: 'var(--ink-soft)' }}>
          {ev.venue}
        </span>
        {hasPage ? (
          <span className="mono" style={{ fontSize: 11, letterSpacing: 1.5, color: 'var(--ink)', display: 'inline-flex', alignItems: 'center', gap: 6 }}>
            {/-results\.html$/.test(ev.href) ? 'Results' : 'Booklet'} <Arrow />
          </span>
        ) : (
          <span className="mono" style={{ fontSize: 11, letterSpacing: 1.5, color: 'var(--ink-soft)' }}>Page coming soon</span>
        )}
      </div>
    </Tag>
  );
};

const CardStat = ({ label, value, small }) => (
  <div>
    <div className="mono" style={{ fontSize: 9, letterSpacing: 1.5, color: 'var(--ink-soft)' }}>{label.toUpperCase()}</div>
    <div className="display" style={{ fontSize: small ? 18 : 24, color: small ? 'var(--ink)' : 'var(--gold)', marginTop: 2, lineHeight: 1 }}>{value}</div>
  </div>
);

const resultsStyles = {
  wrap: {
    background: 'var(--cream)',
    color: 'var(--ink)',
    padding: '80px 32px',
  },
  header: {
    display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between',
    marginBottom: 28, paddingBottom: 18, borderBottom: '1px solid var(--cream-line)',
    maxWidth: 1320, margin: '0 auto 28px',
  },
  headerLink: {
    fontFamily: 'var(--mono)', fontSize: 11, letterSpacing: 1.6,
    textTransform: 'uppercase', display: 'inline-flex', alignItems: 'center', gap: 6,
  },
  grid: {
    display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(360px, 1fr))', gap: 14,
    maxWidth: 1320, margin: '0 auto',
  },
  card: {
    display: 'flex', flexDirection: 'column',
    padding: 22, background: 'var(--cream-2)',
    border: '1px solid var(--cream-line)', borderRadius: 10,
    color: 'var(--ink)',
    transition: 'transform .2s, border-color .2s',
  },
  cardTop: { display: 'flex', alignItems: 'center', gap: 10, marginBottom: 14 },
  cardNum: { fontSize: 11, letterSpacing: 1.5, color: 'var(--ink-soft)', fontWeight: 600 },
  cardKind: { fontSize: 9, letterSpacing: 2, color: 'var(--ink-soft)', padding: '3px 8px', border: '1px solid var(--cream-line)', borderRadius: 4 },
  cardDate: { fontSize: 11, letterSpacing: 1.5, color: 'var(--ink-soft)' },
  cardSpecial: {
    borderColor: 'rgba(217,194,122,0.45)',
    background: 'linear-gradient(160deg, var(--cream-2) 0%, rgba(217,194,122,0.06) 100%)',
  },
  cardLandmark: {
    fontSize: 9, letterSpacing: 2, padding: '3px 8px', borderRadius: 4,
    color: 'var(--gold)', border: '1px solid rgba(217,194,122,0.4)',
    background: 'rgba(217,194,122,0.08)',
  },
  cardTitle: {
    fontFamily: 'var(--display)', fontSize: 44, lineHeight: 0.95,
    letterSpacing: 1, color: 'var(--ink)',
  },
  cardHeadline: {
    fontFamily: 'var(--serif)', fontSize: 20, marginTop: 8, color: 'var(--ink-soft)',
    fontStyle: 'italic',
  },
  cardMatchup: {
    display: 'flex', alignItems: 'center', gap: 12,
    padding: '14px 0', marginTop: 16,
    borderTop: '1px solid var(--cream-line)',
    borderBottom: '1px solid var(--cream-line)',
  },
  resultBar: {
    display: 'flex', alignItems: 'center', justifyContent: 'space-between',
    padding: '10px 12px', marginTop: 12,
    borderLeft: '3px solid', background: 'rgba(255,59,59,0.09)',
    borderRadius: '0 4px 4px 0',
  },
  cardStats: {
    display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 12,
    padding: '14px 0', marginTop: 4,
  },
  cardFoot: {
    display: 'flex', justifyContent: 'space-between', alignItems: 'center',
    paddingTop: 12, borderTop: '1px solid var(--cream-line)', marginTop: 'auto',
  },
};

// ── Footer ────────────────────────────────────────────────────────────
const Footer = () => (
  <footer style={footerStyles.wrap}>
    <div className="footer-inner" style={footerStyles.inner}>
      <div style={footerStyles.brandCol}>
        <div className="display" style={{ fontSize: 34, letterSpacing: 3 }}>
          MMA<span style={{ color: 'var(--red)' }}>·</span>FIGHT<span style={{ color: 'var(--blue)' }}>·</span>CARD
        </div>
        <p className="serif italic" style={{ fontSize: 22, color: 'var(--text-soft)', marginTop: 14, lineHeight: 1.3 }}>
          Made for the fans who came for the prelims.
        </p>
      </div>

      <div className="footer-cols" style={footerStyles.cols}>
        <FooterCol title="Cards" items={['Tonight', 'Schedule', 'Past Events', 'Rankings']} />
        <FooterCol title="Tools" items={['Pick\'em', 'Tale of Tape', 'Odds Tracker', 'Stats DB']} />
        <FooterCol title="Site" items={['About', 'Sources', 'Newsletter', 'Contact']} />
      </div>
    </div>

    <div className="footer-bottom" style={footerStyles.bottom}>
      <span className="mono" style={{ fontSize: 10, letterSpacing: 2, color: 'var(--muted)' }}>
        © 2026 MMAFIGHTCARD.IO · An independent fan project · Not affiliated with any promotion
      </span>
      <span className="mono" style={{ fontSize: 10, letterSpacing: 2, color: 'var(--muted)' }}>
        Odds & stats from public data · For entertainment purposes
      </span>
    </div>
  </footer>
);

const FooterCol = ({ title, items }) => (
  <div>
    <div className="mono" style={{ fontSize: 10, letterSpacing: 2, color: 'var(--muted)', marginBottom: 14 }}>{title.toUpperCase()}</div>
    <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
      {/* No destinations yet — rendered as labels rather than dead links. */}
      {items.map(it => (
        <span key={it} style={{ color: 'var(--muted)', fontSize: 14 }}>{it}</span>
      ))}
    </div>
  </div>
);

const footerStyles = {
  wrap: { borderTop: '1px solid var(--line)', background: 'var(--bg)' },
  inner: {
    display: 'grid', gridTemplateColumns: '1.4fr 1fr',
    gap: 60, padding: '70px 32px 40px', maxWidth: 1320, margin: '0 auto',
  },
  brandCol: {},
  cols: { display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 24 },
  bottom: {
    display: 'flex', justifyContent: 'space-between', flexWrap: 'wrap', gap: 16,
    padding: '20px 32px', borderTop: '1px solid var(--line-soft)',
    maxWidth: 1320, margin: '0 auto',
  },
};

// Export all
Object.assign(window, {
  SiteNav, LiveTicker, Hero, FeaturedMatchup, OnDeck, UpcomingSchedule, RecentResults, Footer,
});
