// UR2D — FINAL DRAFT app ("Ultimate Racing Esports — Final.html").
// Composes the best of every prior exploration into one site:
//   · Home        = Home v2 layout (lights intro, race-week hero, livery marquee,
//                   standings wall, road ahead, ladder) + the old home's
//                   "drivers at the front" leader cards — nothing else.
//   · Standings   = URStandingsBroadcast (broadcast slate) + full-matrix strip.
//   · Cal&Results = URCalendarResults + full-matrix strip.
//   · Teams       = FDTeamsLanding (ur2d-final-teams.jsx, current rosters, Home-wall layout + flag texture);
//                   every tile → #team/<league>/<CODE> = FDTeamPage → TPTeamPage fed REAL sheet data
//                   (ur2d-final-teamdata.jsx). Tweak "Page" swaps the landing for the sample page / showcase.
//   · Matrix      = URStandingsWall fullscreen takeover ("view full matrix").
// Load order: shared → store → roster → home → pages → broadcast → wall →
//             home2-hero → home2-sections → THIS FILE (last).

const FD_NAV_H = 72;
const FD_INTRO_KEY = 'ur2d_final_intro_seen';

const FD_DEFAULTS = /*EDITMODE-BEGIN*/{
  "introLights": true,
  "heroMotion": true,
  "marqueeSpeed": 36,
  "carMarquee": false,
  "palette": ["#E10600", "#FF4D4D", "#B30500"],
  "podiumGlyphs": "below",
  "calres": "a",
  "podiumColors": "medal",
  "resultsView": "scroll",
  "racePoints": "off",
  "homeFlow": "pages",
  "homeTexture": true,
  "homeTextureOpacity": 0.05,
  "teamTexture": true,
  "pageWipe": true,
  "wipeDur": 500,
  "wipeHold": 150,
  "wipeLag": 80,
  "wipeCars": true,
  "wipeBand": "checker",
  "wipeLogo": true,
  "teamsPage": "landing",
  "teamsDrivers": false,
  "tpTeam": "champion",
  "tpHero": "cinematic",
  "tpLogoPos": "above",
  "tpSwitcher": "bar",
  "tpPeek": "hover",
  "tpLogoBackdrop": false,
  "tpCabinet": "journey",
  "tpPods": "timeline",
  "tpShowroom": "poster",
  "tpShowroomBg": "logo",
  "tpHist": "stats"
} /*EDITMODE-END*/;

function fdApplyPalette(p) {
  COLORS.red = p[0];COLORS.redLight = p[1];COLORS.redDeep = p[2];
  COLORS.magenta = p[0];COLORS.magentaLight = p[1];COLORS.magentaDark = p[2];
}

// ─── ROUTING — hash-persisted so refresh keeps the page ──────────────────────
// A route is 'page' or 'page/param/…' (e.g. 'team/ul/LSA'); fdPageOf() gives the page segment.
const FD_PAGES = ['home', 'standings', 'calres', 'teamdrv', 'team', 'drivers', 'driver', 'history', 'matrix'];
const fdPageOf = (r) => String(r || '').split('/')[0];
const fdReadPage = () => {
  const h = (window.location.hash || '').replace(/^#\/?/, '');
  return FD_PAGES.includes(fdPageOf(h)) ? h : 'home';
};
// ─── PAGE WIPE — one dark panel sweeps left→right over route swaps (Lando-style), hiding
// the new page's mount + image loading. Only thin red stripes ride its edges (no full-screen
// red flash). Transform-only WAAPI animation → GPU-composited, no layout/paint per frame.
const FD_WIPE_EASE = 'cubic-bezier(.76,0,.24,1)';
const FD_WIPE_OFF = 'calc(-100% - 40px)', FD_WIPE_OUT = 'calc(100% + 40px)'; // edges sit outside the panel → fully off-screen
// Wipe direction follows nav order: going to a page further right sweeps L→R, further left sweeps R→L.
const FD_PAGE_ORDER = { home: 0, standings: 1, matrix: 1.5, calres: 2, teamdrv: 3, team: 3.5, drivers: 4, driver: 4.5, history: 5 };
const fdWipeDir = (from, to) => (FD_PAGE_ORDER[fdPageOf(to)] ?? 0) >= (FD_PAGE_ORDER[fdPageOf(from)] ?? 0) ? 1 : -1;
const fdWipeRef = React.createRef();
const fdWipeCfg = { dur: 500, hold: 150, lag: 80, cars: true, band: 'checker', logo: true }; // synced from Tweaks each FDApp render
// Linger: keep the cover up at least `hold` ms after it closed (settle time counts toward it).
const fdLinger = (t0) => new Promise((r) => setTimeout(r, Math.max(0, fdWipeCfg.hold - (performance.now() - t0))));
const FD_WIPE_TEAMS = ['ONE', 'LSA', 'FLF', 'MAY', 'ASX', 'SCP', 'SGP', 'KMP', 'MZM'];
const FD_WIPE_COLORS = { ONE: '#4C0ADB', LSA: '#950D0C', FLF: '#DE449E', KMP: '#C02323', MZM: '#E42577', MAY: '#C55710', ASX: '#8105DC', SCP: '#9F1919', SGP: '#D9C501' }; // sampled from S26 liveries
const FD_WIPE_CARS = FD_WIPE_TEAMS.map((x) => `assets/UL S26 Liveries/UL_S26_${x}.png`);
// Cars race across the DARK panel (under the logo) for the whole cover→linger→reveal, at their own pace:
// x keyframes (vw) at 0 / 50 / 100% of the run — different mid-points make them close up and overtake.
const FD_WIPE_CAR_SLOTS = [
  { y: '70%', x: [-30, 50, 128] },
  { y: '79%', x: [-52, 44, 140] },
  { y: '88%', x: [-70, 30, 122] }];
const FD_CHECKER = 'repeating-conic-gradient(#f3f1ec 0 25%, #0d0d0f 0 50%) 0 0 / 44px 44px';
const FDWipe = React.forwardRef((props, ref) => {
  const el = React.useRef(null), rim = React.useRef(null), fill = React.useRef(null), logo = React.useRef(null);
  const cars = [React.useRef(null), React.useRef(null), React.useRef(null)];
  const run = (node, from, to, dur, delay = 0) => node.animate([{ transform: `translate3d(${from},0,0)` }, { transform: `translate3d(${to},0,0)` }], { duration: dur, delay, easing: FD_WIPE_EASE, fill: 'both' }).finished;
  // Cover: flag LEADS (dark panel follows LAG ms later). Reveal: flag TRAILS. The lag gap is the flag band.
  const dir = React.useRef(1);
  const both = (cover, dur) => {
    const L = fdWipeCfg.lag, dLead = cover ? 0 : L, r = dir.current < 0;
    const off = r ? FD_WIPE_OUT : FD_WIPE_OFF, out = r ? FD_WIPE_OFF : FD_WIPE_OUT;
    const from = cover ? off : '0px', to = cover ? '0px' : out;
    const jobs = [run(el.current, from, to, dur, cover ? L : 0), run(rim.current, from, to, dur, dLead), run(fill.current, from, to, dur, dLead)];
    // Fail-safe: never wait on an animation forever (throttled/hidden tab, cancelled animation) — cap at dur + lag + slack.
    return Promise.race([Promise.all(jobs).catch(() => {}), new Promise((res) => setTimeout(res, dur + L + 400))]);
  };
  const all = () => [el, rim, fill, ...cars];
  React.useImperativeHandle(ref, () => ({
    async cover(d = 1) {
      dir.current = d < 0 ? -1 : 1;
      const rev = dir.current < 0;
      cars.forEach((c) => {
        const n = c.current;
        n.style.left = rev ? 'auto' : '0'; n.style.right = rev ? '0' : 'auto';
        n.style.flexDirection = rev ? 'row-reverse' : 'row';
        n.querySelector('img').style.transform = rev ? 'scaleX(-1)' : 'none';
        n.querySelector('span').style.marginRight = rev ? '0' : '6px'; n.querySelector('span').style.marginLeft = rev ? '6px' : '0';
      });
      fill.current.style.background = fdWipeCfg.band === 'red' ? COLORS.red : FD_CHECKER;
      logo.current.style.display = fdWipeCfg.logo ? 'block' : 'none';
      // Team logo when first entering a team page (fdWipeCfg.logoSrc, set by go()); UR2D mark otherwise.
      const tl = fdWipeCfg.logoSrc;
      logo.current.src = tl || 'assets/ur2d-logo.png';
      logo.current.style.mixBlendMode = tl ? 'normal' : 'screen';
      logo.current.style.filter = tl ? 'drop-shadow(0 0 40px rgba(0,0,0,.6))' : 'none';
      // lanes: below the logo when shown, centred when not
      const lanes = fdWipeCfg.logo ? ['70%', '79%', '88%'] : ['38%', '50%', '62%'];
      cars.forEach((c, i) => { c.current.style.top = lanes[i]; });
      const pool = [...FD_WIPE_TEAMS].sort(() => Math.random() - 0.5);
      cars.forEach((c, i) => { c.current.style.display = fdWipeCfg.cars ? 'flex' : 'none'; c.current.dataset.team = pool[i]; c.current.querySelector('span').style.background = `linear-gradient(${rev ? 270 : 90}deg, transparent, ${FD_WIPE_COLORS[pool[i]] || COLORS.red}cc)`; c.current.querySelectorAll('img').forEach((im) => { im.src = FD_WIPE_CARS[FD_WIPE_TEAMS.indexOf(pool[i])]; }); });
      all().forEach((r) => { r.current.style.visibility = 'visible'; });
      el.current.style.pointerEvents = 'auto';
      if (fdWipeCfg.cars) { // not awaited — spans cover + linger + reveal; starts once the panel is under way
        const D = fdWipeCfg.dur, T = D * 2 + fdWipeCfg.lag + fdWipeCfg.hold;
        FD_WIPE_CAR_SLOTS.forEach((c, i) => cars[i].current.animate(c.x.map((v) => ({ transform: `translate3d(${v * dir.current}vw,-50%,0)` })), { duration: T - D * 0.3, delay: D * 0.3, easing: 'linear', fill: 'both' }));
      }
      await both(true, fdWipeCfg.dur);
    },
    async reveal() {
      await both(false, fdWipeCfg.dur);
      this.reset();
    },
    reset() { // hard hide — used after reveal and as the error fallback so the cover can never strand the page
      all().forEach((r) => { if (!r.current) return; r.current.getAnimations().forEach((x) => x.cancel()); r.current.style.visibility = 'hidden'; });
      if (el.current) el.current.style.pointerEvents = 'none';
    }
  }), []);
  const edge = (side) => (
    <span aria-hidden style={{ position: 'absolute', top: 0, bottom: 0, [side]: -24, width: 24, display: 'flex', flexDirection: side === 'right' ? 'row' : 'row-reverse', gap: 5 }}>
      <i style={{ width: 8, background: COLORS.red }}></i>
      <i style={{ width: 3, background: COLORS.red, opacity: 0.55 }}></i>
    </span>);
  const layer = { position: 'fixed', inset: 0, visibility: 'hidden', pointerEvents: 'none', transform: `translate3d(${FD_WIPE_OFF},0,0)`, willChange: 'transform' };
  const carImg = { display: 'block', height: 'clamp(52px, 5.6vw, 92px)', width: 'auto', imageRendering: 'pixelated' };
  return (
    <React.Fragment>
      <div ref={fill} aria-hidden style={{ ...layer, zIndex: 299, background: FD_CHECKER }}></div>
      <div ref={el} aria-hidden style={{ ...layer, zIndex: 300, background: '#050507', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
        <img ref={logo} src="assets/ur2d-logo.png" alt="" style={{ height: 'clamp(90px, 13vw, 160px)', width: 'auto', mixBlendMode: 'screen' }} />
      </div>
      <div ref={rim} aria-hidden style={{ ...layer, zIndex: 301 }}>{edge('right')}{edge('left')}</div>
      {FD_WIPE_CAR_SLOTS.map((c, i) => (
        <div key={i} ref={cars[i]} aria-hidden style={{ position: 'fixed', left: 0, top: c.y, zIndex: 302, visibility: 'hidden', pointerEvents: 'none', display: 'flex', alignItems: 'center', transform: `translate3d(${c.x[0]}vw,-50%,0)`, willChange: 'transform' }}>
          {/* speed streak trailing the car */}
          <span style={{ width: 'clamp(80px, 12vw, 200px)', height: 3, background: `linear-gradient(90deg, transparent, ${COLORS.red}aa)`, marginRight: 6 }}></span>
          <img src={FD_WIPE_CARS[i]} alt="" style={carImg} />
        </div>
      ))}
    </React.Fragment>);
});
// While covered: wait two frames for the new page to paint, then for any on-screen images (capped).
const fdSettle = (cap = 700) => new Promise((res) => {
  setTimeout(res, cap + 200); // fail-safe: rAF never fires in hidden/throttled frames — don't strand the cover
  requestAnimationFrame(() => requestAnimationFrame(() => {
    const vh = window.innerHeight;
    const imgs = [...document.querySelectorAll('#root img')].filter((i) => !i.complete && i.getBoundingClientRect().top < vh);
    if (!imgs.length) return res();
    let n = imgs.length;
    const done = () => { if (--n <= 0) res(); };
    imgs.forEach((i) => { i.addEventListener('load', done, { once: true }); i.addEventListener('error', done, { once: true }); });
    setTimeout(res, cap);
  }));
});

// Home flow: Standings lives on the Home page (scroll, no wipe) when the "Home flow" tweak isn't 'pages'.
const fdScrollToStandings = (smooth) => {
  const el = document.getElementById('fd-home-standings');
  if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - FD_NAV_H + 1, behavior: smooth ? 'smooth' : 'auto' });
};
const fdOnHome = (p, flow) => p === 'home' || (flow && p === 'standings');

function useFDPage(wipeOn = true, flow = false) {
  const [page, setPageState] = React.useState(fdReadPage);
  const busy = React.useRef(false);
  const flowRef = React.useRef(flow); flowRef.current = flow;
  const land = (p) => { if (flowRef.current && p === 'standings') fdScrollToStandings(false); else window.scrollTo(0, 0); };
  // Scroll-spy on the flowed Home: update hash + nav highlight without navigating.
  const setQuiet = React.useCallback((p) => { history.replaceState(null, '', '#' + p); setPageState(p); }, []);
  React.useEffect(() => {
    const onHash = () => {const p = fdReadPage();ReactDOM.flushSync(() => setPageState(p));land(p);};
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, []);
  const go = React.useCallback(async (p) => {
    if (busy.current) return;
    const w = fdWipeRef.current;
    const cur = fdReadPage();
    if (flow && fdOnHome(cur, true) && fdOnHome(p, true)) { // same scrolling page → just scroll
      setQuiet(p);
      if (p === 'standings') fdScrollToStandings(true); else window.scrollTo({ top: 0, behavior: 'smooth' });
      return;
    }
    if (cur === p) {
      if (p === 'calres' && window.__fdCalInResults) { // results view → back to the full calendar poster
        const wipe = wipeOn && w && !ur2Reduced();
        busy.current = true;
        try {
          if (wipe) await w.cover(-1); // results → poster reads as "going back"
          const t0 = performance.now();
          window.dispatchEvent(new Event('fd-calres-reset'));
          window.scrollTo(0, 0);
          if (wipe) { await fdSettle(); await fdLinger(t0); await w.reveal(); }
        } finally {busy.current = false;}
        return;
      }
      window.scrollTo({ top: 0, behavior: 'smooth' });return;
    }
    if (!wipeOn || !w || ur2Reduced()) {window.location.hash = p;return;}
    // Team → team (switcher, prev/next): swap instantly, no wipe.
    if (fdPageOf(cur) === 'team' && fdPageOf(p) === 'team') {window.location.hash = p;return;}
    if (fdPageOf(cur) === 'driver' && fdPageOf(p) === 'driver') {window.location.hash = p;return;} // driver → driver (teammate links): instant
    busy.current = true;
    let swapped = false;
    try {
      const tp = fdPageOf(p) === 'team' ? p.split('/') : null;
      fdWipeCfg.logoSrc = !tp ? null : tp[1] === 'old' ? (typeof fdtOldLogoById === 'function' ? fdtOldLogoById(tp[2]) : null) : typeof fdtLogo === 'function' ? fdtLogo(decodeURIComponent(tp[2] || '')) : null;
      await w.cover(fdWipeDir(fdReadPage(), p));
      const t0 = performance.now();
      history.pushState(null, '', '#' + p); // no hashchange → we swap synchronously under the cover
      swapped = true;
      ReactDOM.flushSync(() => setPageState(p));
      land(p);
      await fdSettle();
      await fdLinger(t0);
      await w.reveal();
    } catch (e) {
      console.warn('[fd] page transition failed, swapping without it:', e);
      if (!swapped) { history.pushState(null, '', '#' + p); setPageState(p); land(p); }
      try { w.reset(); } catch (e2) {}
    } finally {busy.current = false;}
  }, [wipeOn, flow]);
  return [page, go, setQuiet];
}

// ─── NAV — slim Home-v2 bar, transparent over the hero, blurred once scrolled ─
const FD_NAV_ITEMS = [
['home', 'Home'],
['standings', 'Standings'],
['calres', 'Calendar & Results'],
['teamdrv', 'Teams'],
['drivers', 'Drivers'], // driver career pages live (2026-10-09)
['history', 'Champions']];


const FDNav = ({ page, go }) => {
  const [scrolled, setScrolled] = React.useState(() => window.scrollY > 40);
  React.useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 40);
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  const solid = scrolled || page !== 'home';
  // Publish the header's real height (it wraps on narrow widths) so sticky sub-navs dock flush under it.
  const hdr = React.useRef(null);
  React.useLayoutEffect(() => {
    const el = hdr.current; if (!el) return;
    const set = () => document.documentElement.style.setProperty('--fd-nav-h', el.getBoundingClientRect().height + 'px');
    set(); const ro = new ResizeObserver(set); ro.observe(el);
    return () => ro.disconnect();
  }, []);
  return (
    <header ref={hdr} style={{
      position: 'sticky', top: 0, zIndex: 80, minHeight: FD_NAV_H,
      display: 'flex', alignItems: 'center', flexWrap: 'wrap', gap: '4px 18px', padding: '8px 28px',
      background: solid ? 'rgba(5,5,7,0.88)' : 'rgba(5,5,7,0.62)',
      backdropFilter: 'blur(14px)',
      WebkitBackdropFilter: 'blur(14px)',
      borderBottom: solid ? `1px solid ${COLORS.hairline}` : '1px solid transparent',
      transition: 'background .25s ease, border-color .25s ease'
    }}>
      <button onClick={() => go('home')} style={{ all: 'unset', cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 13, flexShrink: 0 }}>
        <img src="assets/ur2d-logo.png" alt="UR2D" style={{ height: 36, width: 'auto', display: 'block', mixBlendMode: 'screen' }} />
        <span style={{ display: 'flex', flexDirection: 'column', lineHeight: 0.95 }}>
          <span style={{ fontFamily: 'Archivo', fontWeight: 900, fontSize: 16, letterSpacing: '0.05em', color: COLORS.text, textTransform: 'uppercase' }}>Ultimate Racing</span>
          <span style={{ fontFamily: 'Archivo', fontWeight: 800, fontSize: 11, letterSpacing: '0.42em', color: COLORS.red, textTransform: 'uppercase', marginTop: 3 }}>Esports</span>
        </span>
      </button>
      <span style={{ flex: 1 }}></span>
      <nav style={{ display: 'flex', gap: 2, alignItems: 'center', flexWrap: 'wrap' }}>
        {FD_NAV_ITEMS.map(([id, label]) => {
          const on = page === id || page === 'matrix' && id === 'standings' || page === 'team' && id === 'teamdrv' || page === 'driver' && id === 'drivers';
          return (
            <button key={id} onClick={() => go(id)} style={{
              all: 'unset', cursor: 'pointer', padding: '9px 11px', position: 'relative', whiteSpace: 'nowrap',
              fontFamily: 'Archivo', fontWeight: 700, fontSize: 12, letterSpacing: '0.12em',
              textTransform: 'uppercase', color: on ? COLORS.text : COLORS.textMute
            }}>
              {label}
              {on && <span style={{ position: 'absolute', left: 11, right: 11, bottom: 3, height: 2, background: COLORS.red }}></span>}
            </button>);

        })}
        <a href={URL_LEAGUE.brand.discord} target="_blank" rel="noopener" style={{
          marginLeft: 12, padding: '11px 16px', background: COLORS.red, color: '#fff',
          fontFamily: 'Archivo', fontWeight: 800, fontSize: 12, letterSpacing: '0.2em',
          textTransform: 'uppercase', textDecoration: 'none', whiteSpace: 'nowrap'
        }}>Join the grid →</a>
      </nav>
    </header>);

};

// ─── DRIVERS AT THE FRONT — one live leader card per league ──────────────────
// Store-driven: real livery from the season adapter, roster flag + car number,
// shared portrait slot id (same drop as the Teams/Standings pages).
const FDLeaderCard = ({ league, onOpen }) => {
  const L = LEAGUE_BY_ID[league];
  const sid = defaultDataSeasonId(league);
  const data = useStandings(league, sid);
  const leader = !data.preseason && data.drivers && data.drivers[0] || null; // pre-season: no leader yet
  const seasonTeam = leader && data.teams ? data.teams.find((t) => t.short === leader.team) : null;
  // No team this season (Independent) → the team they've raced the most for across all leagues (results DB), styled from
  // the newest season config that knows the code (aliases honoured). Team-less leagues (AL) keep "Solo driver".
  const teamBasedLg = !UR2D_ADAPTERS[league] || UR2D_ADAPTERS[league].teamBased !== false;
  const most = typeof useMostRacedTeam === 'function' ? useMostRacedTeam(leader && !seasonTeam && teamBasedLg ? leader.name : null) : null;
  const altTeam = React.useMemo(() => {
    if (!most) return null;
    const codes = [most.short, ...((typeof FDT_ALIAS !== 'undefined' && FDT_ALIAS[most.short]) || [])];
    const pick = (field) => { for (const ad of Object.values(UR2D_ADAPTERS)) for (const s of ad.seasons) for (const o of [s, s.liveSource || {}]) for (const c of codes) if (o[field] && o[field][c]) return o[field][c]; return null; };
    const logoCode = codes.find((c) => typeof UR_TEAM_LOGO !== 'undefined' && UR_TEAM_LOGO[c]);
    return { short: logoCode || most.short, name: pick('teamNames') || most.name, color: pick('teamColors'), livery: null }; // no livery: not this season's car
  }, [most]);
  const team = seasonTeam || altTeam;
  const accent = team && team.color || L.accent;
  // Independent with no car this season → the car they most recently raced in IN THIS LEAGUE (that season's livery file only).
  const lastCar = typeof useLastCar === 'function' ? useLastCar(leader && !seasonTeam && !leader.livery ? leader.name : null, league) : null;
  const livery = leader?.livery || team && team.livery || lastCar && lastCar.livery || null;
  const logoSrc = typeof UR_TEAM_LOGO !== 'undefined' && team && UR_TEAM_LOGO[team.short] || null;
  const who = leader && typeof resolvePerson === 'function' ? resolvePerson(leader.name) : null;
  const carNo = who && who.carNumber != null ? who.carNumber : null;
  const flag = leader && typeof getRosterCountry === 'function' ? getRosterCountry(leader.name) : null;
  const slotId = leader ? `ur-drv-${leader.name.toLowerCase().replace(/[^a-z0-9]/g, '-')}` : null;
  const chip = UR2_STATUS_CHIP[data.status] || UR2_STATUS_CHIP.empty;
  const label = data.season ? data.season.label : null;
  const [hover, setHover] = React.useState(false);

  return (
    <div style={{ display: 'flex', flexDirection: 'column' }}>
      <article
        onClick={onOpen}
        onMouseEnter={() => setHover(true)}
        onMouseLeave={() => setHover(false)}
        style={{
          position: 'relative', height: 540, background: COLORS.surface, overflow: 'hidden',
          border: `1px solid ${hover ? accent : COLORS.hairline}`, cursor: 'pointer',
          boxShadow: hover ? `0 20px 44px -20px ${accent}55, 0 0 0 1px ${accent}2e` : 'none',
          transform: hover ? 'translateY(-6px)' : 'none',
          transition: 'transform .25s ease, box-shadow .25s ease, border-color .25s ease'
        }}>
        <span aria-hidden style={{ position: 'absolute', left: 0, right: 0, top: 0, height: 3, background: accent, zIndex: 5 }}></span>
        {/* team-color wash */}
        <div aria-hidden style={{ position: 'absolute', inset: 0, background: `linear-gradient(160deg, ${accent}30 0%, ${accent}0a 34%, transparent 62%)`, zIndex: 1 }}></div>
        {/* ghost car number (career registry) — league mark when unregistered */}
        <div aria-hidden style={{
          position: 'absolute', right: -12, top: -20, zIndex: 1,
          fontFamily: 'Archivo', fontWeight: 900, fontSize: 200, lineHeight: 0.85, letterSpacing: '-0.05em',
          color: 'transparent', WebkitTextStroke: `2px ${accent}50`,
          fontVariantNumeric: 'tabular-nums', pointerEvents: 'none'
        }}>{carNo != null ? carNo : L.short}</div>
        {/* team logo backsplash */}
        {logoSrc && <img aria-hidden src={logoSrc} alt="" style={{ position: 'absolute', left: '50%', top: '44%', transform: 'translate(-50%, -50%)', width: 330, height: 330, objectFit: 'contain', opacity: 0.12, pointerEvents: 'none', zIndex: 1 }} />}

        {leader ?
        <React.Fragment>
            {/* centerpiece — the actual car, run vertically; portrait slot when no livery (AL) */}
            {livery ?
          <div style={{ position: 'absolute', top: 24, bottom: 130, left: 0, right: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 2, pointerEvents: 'none' }}>
                <img src={livery} alt="" onError={(e) => {e.target.style.display = 'none';}}
            style={{ width: 380, height: 'auto', transform: hover ? 'rotate(-90deg) translateX(12px)' : 'rotate(-90deg)', transition: 'transform .3s ease', filter: 'drop-shadow(0 18px 30px rgba(0,0,0,0.55))' }} />
              </div> :

          <div onClick={(e) => e.stopPropagation()} style={{ position: 'absolute', top: 3, bottom: 118, left: 0, right: 0, zIndex: 2 }}>
                <URImageSlot id={slotId} placeholder={`${leader.name} portrait`} shape="rect" style={{ width: '100%', height: '100%' }} />
              </div>
          }
            {/* readability scrim */}
            <div aria-hidden style={{ position: 'absolute', inset: 0, background: 'linear-gradient(180deg, transparent 44%, rgba(0,0,0,.92) 90%)', zIndex: 3, pointerEvents: 'none' }}></div>
            {/* name block */}
            <div style={{ position: 'absolute', bottom: 20, left: 22, right: 22, zIndex: 4, pointerEvents: 'none' }}>
              <div style={{ fontFamily: 'Archivo', fontWeight: 900, fontSize: 42, color: COLORS.text, letterSpacing: '-0.02em', lineHeight: 0.95, textTransform: 'uppercase', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{leader.name}</div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginTop: 12, fontFamily: 'JetBrains Mono', fontSize: 11, letterSpacing: '0.14em', color: COLORS.textMute, textTransform: 'uppercase', flexWrap: 'wrap' }}>
                {flag ? <FlagSvg kind={flag} w={22} h={14} /> : null}
                <span>{leader.wins ?? 0}W · {leader.podiums ?? 0} pod</span>
              </div>
              <div style={{ marginTop: 6, fontFamily: 'JetBrains Mono', fontSize: 11, letterSpacing: '0.14em', textTransform: 'uppercase', color: team ? accent : L.accent }}>{team ? team.name : 'Solo driver'}</div>
            </div>
          </React.Fragment> :

        <div style={{ position: 'absolute', inset: 0, zIndex: 4, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 14 }}>
            <span style={{ fontFamily: 'JetBrains Mono', fontSize: 11, letterSpacing: '0.3em', color: L.accent, textTransform: 'uppercase' }}>◆ {L.short}</span>
            <span style={{ fontFamily: 'Archivo', fontWeight: 900, fontSize: 24, color: COLORS.text, letterSpacing: '-0.01em' }}>Season pending</span>
            <span style={{ fontFamily: 'JetBrains Mono', fontSize: 10, letterSpacing: '0.22em', color: COLORS.textDim, textTransform: 'uppercase' }}>The grid forms soon</span>
          </div>
        }
      </article>

      {/* league strip beneath the card */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 13, marginTop: 14, padding: '0 2px' }}>
        <span style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: 56, height: 56, flexShrink: 0 }}>
          <img src={L.logo} alt={L.short} style={{ maxHeight: '100%', maxWidth: '100%', objectFit: 'contain', display: 'block' }} />
        </span>
        <span style={{ fontFamily: 'Archivo', fontWeight: 800, fontSize: 14, letterSpacing: '0.08em', color: COLORS.text, textTransform: 'uppercase', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
          {L.name}
        </span>
        <span style={{ flex: 1 }}></span>
        <span style={{ fontFamily: 'JetBrains Mono', fontSize: 10, letterSpacing: '0.22em', color: COLORS.textDim, textTransform: 'uppercase', flexShrink: 0 }}>{L.short}</span>
      </div>
    </div>);

};

const FDDriversFront = ({ go, setLeague }) =>
<section id="thegrid" data-screen-label="Final — Drivers at the front" style={{ padding: '48px 44px 48px' }}>
    <UR2SectionHead
    kicker="Championship leaders · all four grids"
    title={<span>The drivers<br /><span style={{ color: COLORS.red }}>at the front.</span></span>}
    right={
    <div style={{ maxWidth: 340, color: COLORS.textMute, fontSize: 15, lineHeight: 1.55 }}>
          Four leagues, four championships in flight. Whose name sits on top of each table right now — open a card for the full grid.
        </div>
    } />
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(262px, 1fr))', gap: 18 }}>
      {LEAGUES.map((Lg) =>
    <FDLeaderCard key={Lg.id} league={Lg.id} onOpen={() => {setLeague(Lg.id);go('teamdrv');}} />
    )}
    </div>
  </section>;


// ─── MATRIX STRIP — "view full matrix" option on Standings + Cal&Results ─────
const FD_MINI_CELLS = [
'#C9A227', 'rgba(255,255,255,0.10)', 'rgba(255,255,255,0.07)', '#C7CBD1', 'rgba(255,255,255,0.10)',
'rgba(255,255,255,0.07)', '#C0813E', 'rgba(255,255,255,0.10)', 'rgba(255,255,255,0.07)', '#C9A227',
'rgba(255,255,255,0.10)', 'rgba(255,255,255,0.07)', '#C7CBD1', 'rgba(255,255,255,0.10)', '#C9A227'];


const FDMatrixStrip = ({ go }) => {
  const [hover, setHover] = React.useState(false);
  return (
    <section data-screen-label="Final — Full matrix strip" style={{ position: 'relative', background: COLORS.slate, borderTop: `1px solid ${COLORS.hairline}`, overflow: 'hidden' }}>
      <div aria-hidden style={{
        position: 'absolute', inset: 0, opacity: 0.55,
        backgroundImage: 'linear-gradient(rgba(255,255,255,0.045) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.045) 1px, transparent 1px)',
        backgroundSize: '34px 26px'
      }}></div>
      <div aria-hidden style={{ position: 'absolute', right: -160, top: -160, width: 480, height: 480, borderRadius: '50%', background: `radial-gradient(circle, ${COLORS.red}26 0%, transparent 62%)`, filter: 'blur(30px)', pointerEvents: 'none' }}></div>
      <div style={{ position: 'relative', display: 'flex', alignItems: 'center', gap: 36, padding: '42px 44px', flexWrap: 'wrap' }}>
        <div aria-hidden style={{ display: 'grid', gridTemplateColumns: 'repeat(5, 15px)', gap: 4, flexShrink: 0 }}>
          {FD_MINI_CELLS.map((c, i) => <span key={i} style={{ width: 15, height: 15, background: c }}></span>)}
        </div>
        <div style={{ flex: 1, minWidth: 280 }}>
          <div style={{ fontFamily: 'JetBrains Mono', fontSize: 10, letterSpacing: '0.3em', color: COLORS.red, textTransform: 'uppercase', marginBottom: 10 }}>◆ The whole season on one wall</div>
          <div style={{ fontFamily: 'Archivo', fontWeight: 900, fontSize: 30, color: COLORS.text, letterSpacing: '-0.02em', lineHeight: 1 }}>
            {'Results & standings '}<span style={{ color: COLORS.red }}>matrix.</span>
          </div>
          <div style={{ fontFamily: 'Archivo', fontSize: 14, color: COLORS.textMute, marginTop: 10, lineHeight: 1.5, maxWidth: 560 }}>
            Every round, every driver — quali, finish and points in a single view. Copy it, download it, argue about it.
          </div>
        </div>
        <button
          onClick={() => go('matrix')}
          onMouseEnter={() => setHover(true)}
          onMouseLeave={() => setHover(false)}
          style={{
            all: 'unset', cursor: 'pointer', flexShrink: 0,
            background: COLORS.red, color: '#fff', padding: '16px 28px',
            fontFamily: 'Archivo', fontWeight: 800, fontSize: 13, letterSpacing: '0.22em', textTransform: 'uppercase',
            filter: hover ? 'brightness(1.12)' : 'none', transition: 'filter .15s ease'
          }}>View the full matrix →</button>
      </div>
    </section>);

};

// ─── FOOTER — slim, in-site links ────────────────────────────────────────────
const fdFootLink = {
  all: 'unset', cursor: 'pointer',
  fontFamily: 'JetBrains Mono', fontSize: 10, letterSpacing: '0.2em', textTransform: 'uppercase',
  color: COLORS.textMute, borderBottom: `1px solid ${COLORS.hairline}`, paddingBottom: 3
};

const FDFooter = ({ go }) =>
<footer style={{ background: '#000', borderTop: `1px solid ${COLORS.hairline}`, padding: '38px 44px', display: 'flex', alignItems: 'center', gap: 26, flexWrap: 'wrap' }}>
    <LogoLockup size={34} mark="m2m" />
    <span style={{ fontFamily: 'JetBrains Mono', fontSize: 10, letterSpacing: '0.22em', textTransform: 'uppercase', color: COLORS.textDim }}>Made by mika2mika</span>
    <span style={{ flex: 1 }}></span>
    <nav style={{ display: 'flex', gap: 18, alignItems: 'center', flexWrap: 'wrap' }}>
      {FD_NAV_ITEMS.slice(1).map(([id, label]) =>
    <button key={id} onClick={() => go(id)} style={fdFootLink}>{label}</button>
    )}
      <a href={URL_LEAGUE.brand.discord} target="_blank" rel="noopener" style={{ ...fdFootLink, textDecoration: 'none', color: COLORS.text, borderBottomColor: COLORS.red }}>Discord ↗</a>
      <a href="Ultimate Racing Esports.html" style={{ ...fdFootLink, textDecoration: 'none' }}>Classic site →</a>
    </nav>
  </footer>;


// ─── HOME — Home v2 layout + drivers-at-the-front ────────────────────────────
const FDHomeStandings = ({ go, league, setLeague }) =>
<div id="fd-home-standings" data-screen-label="Final — Home standings">
    <URStandingsBroadcast league={league} setLeague={setLeague} />
    <FDMatrixStrip go={go} />
  </div>;

// One continuous backdrop for everything under the hero: starts at the hero's black, warms slightly,
// poster crosshair texture + soft red glows (plain gradients — no blur filters) → sections flow, no hard rules.
const fdHomeBody = () => ({
  position: 'relative',
  backgroundColor: '#070506',
  backgroundImage: [
    "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='26' height='26'%3E%3Cpath d='M13 9.5v7M9.5 13h7' stroke='rgba(255,255,255,0.035)' stroke-width='1'/%3E%3C/svg%3E\")",
    `radial-gradient(50% 22% at 88% 16%, ${COLORS.red}1c, transparent 70%)`,
    `radial-gradient(45% 20% at 6% 46%, ${COLORS.red}12, transparent 70%)`,
    `radial-gradient(50% 22% at 92% 78%, ${COLORS.red}14, transparent 70%)`,
    'linear-gradient(180deg, #000 0, #080506 700px, #0d0607 55%, #060405 100%)'
  ].join(', '),
  backgroundSize: '26px 26px, 100% 100%, 100% 100%, 100% 100%, 100% 100%'
});

// Home's backdrop (body gradient + sticky checkered-flag texture) for other pages, e.g. the Teams landing.
const FDBackdrop = ({ t, children }) =>
<div style={fdHomeBody()}>
    {t.homeTexture && <div aria-hidden style={{ position: 'sticky', top: 0, height: '100vh', marginBottom: '-100vh', zIndex: 0, pointerEvents: 'none', backgroundImage: 'url("assets/textures/checker-flag.jpg")', backgroundSize: 'cover', backgroundPosition: 'center', opacity: t.homeTextureOpacity, willChange: 'transform' }}></div>}
    <div style={{ position: 'relative', zIndex: 1 }}>{children}</div>
  </div>;

const FDHome = ({ t, go, league, setLeague }) =>
<div data-screen-label="Final — Home">
    {/* hero slides beneath the transparent sticky nav */}
    <div style={{ marginTop: -FD_NAV_H }}>
      <UR2Hero motion={t.heroMotion} nav={<div style={{ height: FD_NAV_H + 12 }}></div>} />
    </div>
    {t.carMarquee !== false && <UR2CarMarquee speed={t.marqueeSpeed} />}
    <div style={fdHomeBody()}>
    {/* Muted checkered-flag texture — sticky viewport layer (composited, no repaint on scroll) */}
    {t.homeTexture && <div aria-hidden style={{ position: 'sticky', top: 0, height: '100vh', marginBottom: '-100vh', zIndex: 0, pointerEvents: 'none', backgroundImage: 'url("assets/textures/checker-flag.jpg")', backgroundSize: 'cover', backgroundPosition: 'center', opacity: t.homeTextureOpacity, willChange: 'transform' }}></div>}
    <div style={{ position: 'relative', zIndex: 1 }}>
    <FDDriversFront go={go} setLeague={setLeague} />
    <FDRule />
    <FDAbout go={go} setLeague={setLeague} />
    <FDRule />
    {t.homeFlow === 'above' && <FDHomeStandings go={go} league={league} setLeague={setLeague} />}
    {t.homeFlow === 'below' && <FDHomeStandings go={go} league={league} setLeague={setLeague} />}
    <FDRule />
    <FDTeamWall go={go} setLeague={setLeague} />
    <FDRule />
    <FDJoin />
    </div>
    </div>
  </div>;


// ─── APP ─────────────────────────────────────────────────────────────────────
function FDApp() {
  const [t, setTweak] = useTweaks(FD_DEFAULTS);
  fdApplyPalette(t.palette);

  Object.assign(fdWipeCfg, { dur: t.wipeDur, hold: t.wipeHold, lag: t.wipeLag, cars: t.wipeCars !== false, band: t.wipeBand, logo: t.wipeLogo !== false });
  const flow = t.homeFlow === 'above' || t.homeFlow === 'below';
  const [route, go, setQuiet] = useFDPage(t.pageWipe !== false, flow);
  const page = fdPageOf(route);
  const tpT = { texture: t.teamTexture !== false && t.homeTexture !== false, texOpacity: t.homeTextureOpacity, peek: t.tpPeek, hero: t.tpHero, logoPos: t.tpLogoPos, switcher: t.tpSwitcher, logoBackdrop: t.tpLogoBackdrop, cabinet: t.tpCabinet, pods: t.tpPods, showroom: t.tpShowroom, showroomBg: t.tpShowroomBg, hist: t.tpHist };
  const [teamLg, teamCode] = page === 'team' ? route.split('/').slice(1).map((x) => { try { return decodeURIComponent(x); } catch (e) { return x; } }) : [];
  const driverKey = page === 'driver' ? (() => { const x = route.split('/').slice(1).join('/'); try { return decodeURIComponent(x); } catch (e) { return x; } })() : null;
  const [league, setLeague] = useLeagueState('ul');
  const onHome = fdOnHome(page, flow);
  React.useEffect(() => { window.fdGo = go; return () => { if (window.fdGo === go) window.fdGo = null; }; }, [go]);
  // Flowed Home: nav highlight follows the scroll (Standings once its table reaches mid-screen).
  React.useEffect(() => {
    if (!flow || !onHome) return;
    const f = () => {
      const el = document.getElementById('fd-home-standings');
      if (!el) return;
      const r = el.getBoundingClientRect();
      const want = r.top < window.innerHeight * 0.45 && r.bottom > FD_NAV_H + 40 ? 'standings' : 'home';
      if (fdReadPage() !== want) setQuiet(want);
    };
    window.addEventListener('scroll', f, { passive: true });
    return () => window.removeEventListener('scroll', f);
  }, [flow, onHome, setQuiet]);
  // Landing on #standings with the flowed Home (refresh / deep link) → jump to the section.
  React.useEffect(() => { if (flow && fdReadPage() === 'standings') requestAnimationFrame(() => fdScrollToStandings(false)); }, [flow]);

  // Start-light intro — once per session, home landings only, skippable.
  const [introOn, setIntroOn] = React.useState(() =>
  t.introLights !== false && !ur2Reduced() && !sessionStorage.getItem(FD_INTRO_KEY) && fdReadPage() === 'home');
  const introDone = React.useCallback(() => {
    sessionStorage.setItem(FD_INTRO_KEY, '1');
    setIntroOn(false);
  }, []);

  // Esc closes the fullscreen matrix
  React.useEffect(() => {
    if (page !== 'matrix') return;
    const onKey = (e) => {if (e.key === 'Escape') go('standings');};
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [page, go]);

  const tweaks =
  <TweaksPanel title="Tweaks">
      <TweakSection label="Home texture" />
      <TweakToggle label="Checkered flag" value={t.homeTexture} onChange={(v) => setTweak('homeTexture', v)} />
      {t.homeTexture && <TweakSlider label="Strength" min={0.01} max={0.25} step={0.01} value={t.homeTextureOpacity} onChange={(v) => setTweak('homeTextureOpacity', v)} />}

      <TweakSection label="Home flow" />
      <TweakRadio label="Standings" value={t.homeFlow} options={[{ value: 'pages', label: 'Own page' }, { value: 'below', label: 'Below leaders' }, { value: 'above', label: 'Above leaders' }]} onChange={(v) => setTweak('homeFlow', v)} />

      <TweakSection label="Intro" />
      <TweakToggle label="Start lights on load" value={t.introLights} onChange={(v) => setTweak('introLights', v)} />
      <TweakButton label="Replay start lights" onClick={() => {go('home');setIntroOn(true);}} />

      <TweakSection label="Motion" />
      <TweakToggle label="Hero drift + sweep" value={t.heroMotion} onChange={(v) => setTweak('heroMotion', v)} />
      <TweakSection label="Page wipe" />
      <TweakToggle label="Wipe between pages" value={t.pageWipe} onChange={(v) => setTweak('pageWipe', v)} />
      {t.pageWipe &&
      <React.Fragment>
          <TweakSlider label="Intro / outro (ms)" min={200} max={1200} step={20} value={t.wipeDur} onChange={(v) => setTweak('wipeDur', v)} />
          <TweakSlider label="Linger (ms)" min={0} max={1500} step={25} value={t.wipeHold} onChange={(v) => setTweak('wipeHold', v)} />
          <TweakRadio label="Flag band" value={t.wipeBand} options={[{ value: 'checker', label: 'Checkered' }, { value: 'red', label: 'Red' }]} onChange={(v) => setTweak('wipeBand', v)} />
          <TweakToggle label="Cars" value={t.wipeCars} onChange={(v) => setTweak('wipeCars', v)} />
          <TweakToggle label="Logo" value={t.wipeLogo} onChange={(v) => setTweak('wipeLogo', v)} />
          <TweakSlider label="Flag lag (ms)" min={0} max={200} step={10} value={t.wipeLag} onChange={(v) => setTweak('wipeLag', v)} />
          <TweakButton label="Preview wipe" onClick={async () => { const w = fdWipeRef.current; if (!w) return; await w.cover(); const t0 = performance.now(); await fdLinger(t0); await w.reveal(); }} />
        </React.Fragment>
      }
      <TweakToggle label="Car marquee" value={t.carMarquee !== false} onChange={(v) => setTweak('carMarquee', v)} />
      <TweakSlider label="Marquee lap time (s)" min={14} max={90} step={1} value={t.marqueeSpeed} onChange={(v) => setTweak('marqueeSpeed', v)} />

      <TweakSection label="Accent palette" />
      <TweakColor
      label="Red palette"
      value={t.palette}
      options={[
      ['#E10600', '#FF4D4D', '#B30500'],
      ['#FF1F1F', '#FF6E6E', '#C00000'],
      ['#A0153E', '#D4365F', '#700E2A'],
      ['#FF4D2E', '#FF8466', '#C42E10']]
      }
      onChange={(v) => setTweak('palette', v)} />

      <TweakSection label="Teams page" />
      <TweakRadio label="Page" value={t.teamsPage} options={[{ value: 'landing', label: 'Landing' }, { value: 'team', label: 'Sample page' }, { value: 'showcase', label: 'Showcase' }]} onChange={(v) => setTweak('teamsPage', v)} />
      <TweakToggle label="Flag texture on team pages" value={t.teamTexture !== false} onChange={(v) => setTweak('teamTexture', v)} />
      {t.teamsPage === 'landing' && <TweakToggle label="Show drivers on tiles" value={!!t.teamsDrivers} onChange={(v) => setTweak('teamsDrivers', v)} />}
      {t.teamsPage === 'showcase' ?
      <TweakRadio label="Podium glyphs" value={t.podiumGlyphs} options={['below', 'right']} onChange={(v) => setTweak('podiumGlyphs', v)} /> :
      <React.Fragment>
          {t.teamsPage === 'team' && <TweakRadio label="Sample team" value={t.tpTeam} options={['champion', 'midtable', 'backmarker']} onChange={(v) => setTweak('tpTeam', v)} />}
          <TweakRadio label="Hero" value={t.tpHero} options={['cinematic', 'classic']} onChange={(v) => setTweak('tpHero', v)} />
          {t.tpHero === 'classic' && <TweakRadio label="Logo" value={t.tpLogoPos} options={['above', 'right']} onChange={(v) => setTweak('tpLogoPos', v)} />}
          <TweakRadio label="League history band" value={t.tpHist} options={[{ value: 'stats', label: 'Stats' }, { value: 'circuits', label: 'Circuits' }, { value: 'classic', label: 'Old' }]} onChange={(v) => setTweak('tpHist', v)} />
          <TweakRadio label="League / team switcher" value={t.tpSwitcher} options={['bar', 'arrows', 'dropdown', 'hover']} onChange={(v) => setTweak('tpSwitcher', v)} />
          <TweakRadio label="Results · track image" value={t.tpPeek || 'hover'} options={[{ value: 'hover', label: 'On hover' }, { value: 'always', label: 'Always, faded' }]} onChange={(v) => setTweak('tpPeek', v)} />
          <TweakToggle label="Large logo backdrop" value={t.tpLogoBackdrop} onChange={(v) => setTweak('tpLogoBackdrop', v)} />
          <TweakRadio label="History / trophies" value={t.tpCabinet} options={[{ value: 'journey', label: 'History' }, { value: 'glyphs', label: 'Glyphs' }, { value: 'wall', label: 'Wall' }, { value: 'honours', label: 'Honours' }]} onChange={(v) => setTweak('tpCabinet', v)} />
          <TweakRadio label="Race podiums" value={t.tpPods} options={['timeline', 'merged']} onChange={(v) => setTweak('tpPods', v)} />
          <TweakRadio label="Showroom backdrop" value={t.tpShowroomBg} options={['logo', 'texture', 'name']} onChange={(v) => setTweak('tpShowroomBg', v)} />
          <TweakSelect label="Showroom style" value={t.tpShowroom} options={['poster', 'stacked', 'disc', 'vertical', 'solid', 'minimal']} onChange={(v) => setTweak('tpShowroom', v)} />
        </React.Fragment>
      }

      <TweakSection label="Calendar & results" />
      <TweakRadio label="Layout" value={t.calres} options={['default', 'a', 'b']} onChange={(v) => setTweak('calres', v)} />
      <TweakRadio label="Podium colours" value={t.podiumColors} options={['medal', 'team']} onChange={(v) => setTweak('podiumColors', v)} />
      <TweakRadio label="Results" value={t.resultsView} options={['grid', 'list', 'scroll']} onChange={(v) => setTweak('resultsView', v)} />

      <TweakSection label="Matrix" />
      <TweakRadio
      label="Per-race points"
      value={t.racePoints}
      options={[{ value: 'off', label: 'Off' }, { value: 'incell', label: 'In cell' }, { value: 'column', label: 'Column' }]}
      onChange={(v) => setTweak('racePoints', v)} />
    </TweaksPanel>;


  // Fullscreen matrix takeover — no nav/footer, Esc or "Back" returns.
  if (page === 'matrix') {
    return (
      <div data-screen-label="Final — Results & standings matrix" style={{ background: COLORS.slate, minHeight: '100vh' }}>
        <URStandingsWall league={league} setLeague={setLeague} racePoints={t.racePoints} onBack={() => go('standings')} />
        {tweaks}
      </div>);

  }

  return (
    <div style={{ background: '#000', color: COLORS.text, minHeight: '100%' }}>
      {introOn && <UR2IntroLights onDone={introDone} />}
      <FDNav page={page} go={go} />

      {onHome && <FDHome t={t} go={go} league={league} setLeague={setLeague} />}

      {page === 'standings' && !flow &&
      <div data-screen-label="Final — Standings">
          <URStandingsBroadcast league={league} setLeague={setLeague} />
          <URStandingsGraph league={league} />
          <FDMatrixStrip go={go} />
        </div>
      }

      {page === 'calres' &&
      <div data-screen-label="Final — Calendar & Results">
          <FDCalendarGate t={t} matrixStrip={<FDMatrixStrip go={go} />} />
        </div>
      }

      {page === 'teamdrv' && (t.teamsPage === 'landing' ?
      <FDBackdrop t={t}><FDTeamsLanding go={go} showDrivers={!!t.teamsDrivers} /></FDBackdrop> :
      t.teamsPage === 'showcase' ?
      <div data-screen-label="Final — Teams">
          <URDriversEditorial league={league} setLeague={setLeague} podiumGlyphs={t.podiumGlyphs} />
        </div> :
      <div data-screen-label="Final — Team page (sample)">
          <TPTeamPage embed t={{ ...tpT, team: t.tpTeam }} />
        </div>)
      }

      {page === 'team' && <FDTeamPage key={route} league={teamLg} short={teamCode} go={go} tp={tpT} />}

      {page === 'drivers' && <FDBackdrop t={t}><FDDriversLanding go={go} /></FDBackdrop>}

      {page === 'driver' && <FDDriverPage key={route} dkey={driverKey} go={go} tp={tpT} />}

      {page === 'history' &&
      <div data-screen-label="Final — Legends">
          <div id="hall-of-champions"><URHallOfChampions /></div>
          <section id="hall-of-fame" style={{ padding: '72px 44px 110px', borderTop: `1px solid ${COLORS.hairline}`, borderBottom: `1px solid ${COLORS.hairline}` }}>
            <h2 style={{ margin: 0, fontFamily: 'Archivo', fontWeight: 900, fontSize: 'clamp(30px, 3.4vw, 48px)', color: COLORS.text, textTransform: 'uppercase', letterSpacing: '-0.02em', lineHeight: 0.95 }}>Hall of Fame</h2>
            <p style={{ margin: '14px 0 0', maxWidth: 440, fontFamily: 'Archivo', fontSize: 15, lineHeight: 1.5, color: COLORS.textMute }}>Inducted drivers, team owners and staff.</p>
            <div style={{ marginTop: 18, fontFamily: 'JetBrains Mono', fontSize: 11, letterSpacing: '0.22em', color: COLORS.textDim, textTransform: 'uppercase' }}>Under construction</div>
          </section>
        </div>
      }

      <FDFooter go={go} />
      {tweaks}
    </div>);

}

ReactDOM.createRoot(document.getElementById('root')).render(<React.Fragment><FDApp /><FDWipe ref={fdWipeRef} /></React.Fragment>);