// Team page v3 — cinematic 80vh title card with two at-a-glance bands (this season / all-time),
// then Drivers · Trophy Cabinet · Livery Showroom (poster) · Stats · All Results.
// Reads window.TP (ur2d-teampage-data.js).
const TPD = window.TP;
const TP_DEFAULTS = /*EDITMODE-BEGIN*/{
  "team": "champion",
  "hero": "cinematic",
  "logoPos": "above",
  "switcher": "bar",
  "showroom": "poster",
  "showroomBg": "logo",
  "cabinet": "journey",
  "pods": "timeline",
  "logoBackdrop": false
}/*EDITMODE-END*/;
const tpPad = (n) => String(n).padStart(2, '0');
const tpMask = (k) => ({ '--m': `url("assets/minimaps/${k}.png")` });
const tpName = (w) => TPD.PEOPLE[w].name;
const tpOrd = (n) => n + TPD.ord(n);
// Driver name → that driver's career page on the final site (window.fddRouteOf, ur2d-final-driverdata.jsx); plain text elsewhere.
const TPDrv = ({ w, children }) => {
  const r = typeof window.fddRouteOf === 'function' ? window.fddRouteOf(w) : null;
  if (!r) return children;
  return <a className="tp-dlink" href={'#' + r} onClick={(e) => { if (e.metaKey || e.ctrlKey || e.shiftKey) return; e.preventDefault(); if (window.fdGo) window.fdGo(r); else window.location.hash = r; }}>{children}</a>;
};
const TPFlag = ({ cc, cls = 'tp-flag' }) => cc ? <img className={cls} src={typeof urFlagImg === 'function' ? urFlagImg(cc) : TPD.flag(cc)} alt="" loading="lazy" /> : null;
// pos given + minimap missing/404 → metal circle with "P1/P2/P3" instead of a blank mask.
const TPMap = ({ k, cls = 'tp-map', title, pos }) => {
  const ok = useTpMapOk(pos ? k : null);
  if (pos && ok === false) return <span className={cls + ' tp-nm q' + (pos <= 3 ? pos : 'x')} title={title}><b>{pos <= 3 ? 'P' + pos : pos}</b></span>;
  return <span className={cls} style={tpMask(k)} title={title}></span>;
};
const TPOrd = ({ n }) => <React.Fragment>{n}<sup>{TPD.ord(n)}</sup></React.Fragment>;
// Metal circuit glyph: pos 1/2/3 → gold/silver/bronze, anything else → team color.
// No minimap (missing key or file 404) → metal circle with "P1/P2/P3".
const _tpMapOk = {};
const useTpMapOk = (k) => {
  const [ok, setOk] = React.useState(() => k ? _tpMapOk[k] : false);
  React.useEffect(() => {
    if (!k) { setOk(false); return; }
    if (_tpMapOk[k] !== undefined) { setOk(_tpMapOk[k]); return; }
    let alive = true; const im = new Image();
    im.onload = () => { _tpMapOk[k] = true; if (alive) setOk(true); };
    im.onerror = () => { _tpMapOk[k] = false; if (alive) setOk(false); };
    im.src = `assets/minimaps/${k}.png`;
    return () => { alive = false; };
  }, [k]);
  return ok;
};
const TPGlyph = ({ map, pos, title, big }) => {
  const ok = useTpMapOk(map);
  const cls = 'tp-g p' + (pos <= 3 ? pos : 'x') + (big ? ' big' : '');
  return <span className={cls} title={title}>{ok === false ? <i className="nm"><b>{pos <= 3 ? 'P' + pos : pos}</b></i> : <i style={tpMask(map)}></i>}</span>;
};
const TP_SECS = [['drivers', 'Drivers'], ['trophies', 'Trophy Cabinet'], ['liveries', 'Livery Showroom'], ['stats', 'Stats'], ['results', 'Results']];
const TPCtx = React.createContext(null);
const useSel = () => React.useContext(TPCtx);
const tpSeason = (id) => TPD.seasons.find((x) => x.id === id) || TPD.seasons[0];
const tpIsLatest = (s) => s === TPD.seasons[0];
const TP_TEAMS = ['ONE', 'LSA', 'FLF', 'KMP', 'MZM', 'MAY', 'RKA', 'SCP', 'SGP'];
const TP_LG = [['ul', 'Ultimate'], ['hl', 'Horizon'], ['jl', 'Journeyman'], ['al', 'Apprentice']];
const tpLgSn = (s) => `${s.lg === 'HL' ? 'CL' : s.lg} ${s.sid || s.id}`; // [League] [Season] — "UL S19" (sid = raw label; id may carry a league prefix)
const tpEst = () => tpLgSn(TPD.seasons[TPD.seasons.length - 1]);

const tpOff = () => (window.TP_EMBED ? 72 : 0);
function tpScrollTo(id) {
  const el = document.getElementById(id);
  const h = el && (el.querySelector('.tp-sh') || el);
  if (h) window.scrollTo({ top: h.getBoundingClientRect().top + window.scrollY - 96 - tpOff(), behavior: 'smooth' });
}
function useTPSpy() {
  const [a, setA] = React.useState('overview');
  React.useEffect(() => {
    const f = () => {
      let cur = 'overview'; // hero / first view until the first section header reaches the bar
      TP_SECS.forEach(([id]) => { const el = document.getElementById(id); const h = el && (el.querySelector('.tp-sh') || el); if (h && h.getBoundingClientRect().top < 200 + tpOff()) cur = id; });
      setA(cur);
    };
    f();
    window.addEventListener('scroll', f, { passive: true });
    return () => window.removeEventListener('scroll', f);
  }, []);
  return a;
}

function TPNav() {
  return (
    <header className="tp-top"><div className="tp-wrap tp-nav">
      <a className="tp-brand" href="#"><img src="assets/ur2d-logo.png" alt="" /><span>Ultimate<em>Racing</em></span></a>
      <nav className="tp-links">{['Home', 'Standings', 'Calendar & Results', 'Teams', 'Drivers'].map((l) => <a key={l} href="#" className={l === 'Teams' ? 'on' : ''}>{l}</a>)}</nav>
    </div></header>
  );
}

// FRANCHISE MARK (user 2026-10-09): the house-style default logo for teams that never made one — rounded square in the team colour
// (store teamColors, else sampled from its liveries), code in condensed heavy type, ink auto-picked for contrast. Inline SVG so the page's
// Archivo font applies. Used wherever a team has no logo file (team page hero, Teams tiles, loading/fresh states).
function urFranchiseInk(hex) { // whichever ink (white / near-black) has the higher WCAG contrast against the fill
  const m = String(hex || '').match(/^#?([0-9a-f]{6})$/i); if (!m) return '#fff';
  const n = parseInt(m[1], 16), lin = (c) => { c /= 255; return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4); };
  const L = 0.2126 * lin(n >> 16) + 0.7152 * lin((n >> 8) & 255) + 0.0722 * lin(n & 255), Ld = 0.0034;
  return (1.05 / (L + 0.05)) >= ((L + 0.05) / (Ld + 0.05)) ? '#ffffff' : '#0b0b0b';
}
function URFranchiseMark({ code, color, className, title }) {
  const c = /^#?[0-9a-f]{6}$/i.test(String(color || '')) ? (String(color)[0] === '#' ? color : '#' + color) : '#3A3F45', ink = urFranchiseInk(c); // no colour on record → dark neutral (reads as 'unbranded', not washed-out)
  const s = String(code || '?').toUpperCase(), fs = s.length <= 2 ? 54 : s.length === 3 ? 46 : 37, gid = 'urfm-sheen';
  // Overwatch-League-style default: ONE shape (rounded square, team colour), the code centred, a soft top-light sheen. Nothing else.
  return (
    <svg className={'ur-fmark' + (className ? ' ' + className : '')} viewBox="0 0 120 120" role="img" aria-label={(title || s) + ' (no team logo)'}>
      <defs><linearGradient id={gid} x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor="#fff" stopOpacity="0.16" /><stop offset="0.55" stopColor="#fff" stopOpacity="0" /><stop offset="1" stopColor="#000" stopOpacity="0.2" /></linearGradient></defs>
      <rect x="6" y="6" width="108" height="108" rx="16" fill={c} />
      <rect x="6" y="6" width="108" height="108" rx="16" fill={'url(#' + gid + ')'} />
      <rect x="7" y="7" width="106" height="106" rx="15" fill="none" stroke={ink} strokeOpacity="0.16" strokeWidth="1.5" />
      <text x="60" y="61" textAnchor="middle" dominantBaseline="central" fill={ink}
        style={{ fontFamily: "'Archivo', system-ui, sans-serif", fontWeight: 900, fontStretch: '62%', fontSize: fs, letterSpacing: '0.03em' }}>{s}</text>
    </svg>);
}
Object.assign(window, { URFranchiseMark, urFranchiseInk });

// Hero bands: the first (marker) column grows to fit the widest season chip ("JL S18B") and BOTH rows share that width, so the
// stat columns to the right shift over instead of being overlapped, and the all-time row lines up with the season row (user 2026-10-09).
function tpBandsGutter(el) {
  if (!el) return;
  // Measure the CONTENT (chip + label are shrink-to-fit), never the .bl box — the box is the column, so it would only ever grow.
  const fit = () => { let w = 0; el.querySelectorAll('.tp-band .bl > *').forEach((c) => { w = Math.max(w, Math.ceil(c.getBoundingClientRect().width)); }); el.style.setProperty('--gutw', w + 'px'); };
  fit(); requestAnimationFrame(fit);
  if (!el.__tpRO && typeof ResizeObserver === 'function') { el.__tpRO = new ResizeObserver(fit); el.__tpRO.observe(el); }
  if (!el.__tpMO && typeof MutationObserver === 'function') { el.__tpMO = new MutationObserver(fit); el.__tpMO.observe(el, { childList: true, characterData: true, subtree: true }); } // season switch → new chip text
}

// League + team switching, layered over the hero (no separate bar). Three styles via Tweak.
const TP_TEAMNAMES = { ONE: 'OneTime', LSA: 'Leviosso Sports Art', FLF: 'Flow Force', KMP: 'Kenzer Motorsport', MZM: 'Mazzar Motorsport', MAY: 'Mayhem Racing', RKA: 'Rykar Auto', SCP: 'Scuderia Paracarro', SGP: 'StarGoat GP' };
function TPSwitch({ mode, inline }) {
  const { sel, setSel } = useSel();
  const [lgPick, setLg] = React.useState(null);
  const lg = lgPick || (TPD.nav && TPD.nav.league) || tpSeason(sel).lg.toLowerCase();
  React.useEffect(() => setLg(null), [sel]);
  const [menu, setMenu] = React.useState(null);
  // Real profiles (final site) carry TPD.nav: that league's current teams + a navigate callback. Sample profiles keep the UL list.
  const nav = TPD.nav;
  const teams = nav ? nav.teams(lg) : TP_TEAMS.map((x) => ({ short: x, name: TP_TEAMNAMES[x], mini: `assets/minilogos/${x}.png` }));
  const cur = TPD.TEAM.short, isCur = (x) => (TPD.TEAM.key && x.key ? x.key === TPD.TEAM.key : x.short === cur), ix = Math.max(0, teams.findIndex(isCur)); // key = DB id (former teams: codes repeat)
  const prev = teams[(ix - 1 + teams.length) % teams.length] || { short: '', name: '' }, next = teams[(ix + 1) % teams.length] || { short: '', name: '' };
  const stop = (e) => e.preventDefault();
  const pick = (e, x) => { e.preventDefault(); setMenu(null); if (nav && x && x.short) nav.go(lg, x.short, x); };
  const tmImg = (x, alt = '') => x.mini ? <img src={x.mini} alt={alt} /> : <span className="ph mono">{x.short}</span>;
  const lname = TP_LG.find((x) => x[0] === lg)[1];
  React.useEffect(() => { if (!menu) return; const f = () => setMenu(null); window.addEventListener('click', f); return () => window.removeEventListener('click', f); }, [menu]);
  const seasonSel = <label className="tp-ssel"><span className="mono">Season</span><select value={sel} onChange={(e) => setSel(e.target.value)}>{TPD.seasons.map((x) => <option key={x.id} value={x.id}>{x.id} · {x.lg}</option>)}</select></label>;
  const leagues = <div className="tp-swl">{TP_LG.map(([id, n]) => <button key={id} className={lg === id ? 'on' : ''} onClick={() => setLg(id)} title={n + ' League'}><img src={`assets/${id}-logo-cropped.png`} alt={id.toUpperCase()} /></button>)}</div>;
  if (mode === 'bar') return (
    <div className={'tp-ctx' + (inline ? ' inl' : '')} onClick={(e) => e.stopPropagation()}>
      <div className="tp-pop">
        <button className="tp-popb" onClick={() => setMenu(menu === 'lg' ? null : 'lg')} aria-expanded={menu === 'lg'} title="Change league"><img src={`assets/${lg}-logo-cropped.png`} alt={lname} /><i>▾</i></button>
        {menu === 'lg' && <div className="tp-popm lgs">{TP_LG.map(([id, n]) => <button key={id} className={lg === id ? 'on' : ''} onClick={() => { setLg(id); setMenu(null); }} title={n + ' League'}><img src={`assets/${id}-logo-cropped.png`} alt="" /><span className="mono">{n}</span></button>)}</div>}
      </div>
      {nav ? <div className="tp-tmrow" role="list" aria-label="Teams">{teams.map((x) => <a key={x.key || x.short} role="listitem" href="#" onClick={(e) => pick(e, x)} className={isCur(x) ? 'on' : ''} title={x.name} aria-current={isCur(x) ? 'page' : undefined}>{tmImg(x, x.short)}</a>)}</div> :
      <div className="tp-pop">
        <button className="tp-popb" onClick={() => setMenu(menu === 'tm' ? null : 'tm')} aria-expanded={menu === 'tm'} title="Change team">{TPD.TEAM.mini && <img className="tm" src={TPD.TEAM.mini} alt={TPD.TEAM.short} />}<span>{TPD.TEAM.short}</span><i>▾</i></button>
        {menu === 'tm' && <div className="tp-popm tms">{teams.length ? teams.map((x) => <a key={x.key || x.short} href="#" onClick={(e) => pick(e, x)} className={isCur(x) ? 'on' : ''} title={x.name}>{tmImg(x)}<span className="mono">{x.short}</span></a>) : <span className="mono">No teams</span>}</div>}
      </div>}
      <div className="tp-pop">
        <button className="tp-popb" onClick={() => setMenu(menu === 'ss' ? null : 'ss')} aria-expanded={menu === 'ss'} title="Change season"><span>{sel}</span><i>▾</i></button>
        {menu === 'ss' && <div className="tp-popm sss">{TPD.seasons.map((x) => <button key={x.id} className={sel === x.id ? 'on' : ''} onClick={() => { setSel(x.id); setMenu(null); }}><b>{x.id}</b><span className="mono">{x.lg}</span></button>)}</div>}
      </div>
    </div>
  );
  if (mode === 'arrows') return (
    <React.Fragment>
      <div className={'tp-sw tr' + (inline ? ' inl' : '')}>{leagues}{seasonSel}</div>
      <a href="#" onClick={(e) => pick(e, prev)} className="tp-side l" aria-label={'Previous team: ' + prev.name}><span className="ar">‹</span><span className="nm mono">{prev.name}</span></a>
      <a href="#" onClick={(e) => pick(e, next)} className="tp-side r" aria-label={'Next team: ' + next.name}><span className="nm mono">{next.name}</span><span className="ar">›</span></a>
    </React.Fragment>
  );
  if (mode === 'dropdown') return (
    <div className={'tp-sw tr dd' + (inline ? ' inl' : '')} onClick={(e) => e.stopPropagation()}>
      {seasonSel}
      <div className="tp-dd">
        <button className="tp-ddb" onClick={() => setMenu(menu === 'lg' ? null : 'lg')} aria-expanded={menu === 'lg'}><img src={`assets/${lg}-logo-cropped.png`} alt="" /><span>{lname} League</span><i>▾</i></button>
        {menu === 'lg' && <div className="tp-ddm">{TP_LG.map(([id, n]) => <button key={id} className={lg === id ? 'on' : ''} onClick={() => { setLg(id); setMenu(null); }}><img src={`assets/${id}-logo-cropped.png`} alt="" /><span>{n} League</span></button>)}</div>}
      </div>
      <div className="tp-dd">
        <button className="tp-ddb" onClick={() => setMenu(menu === 'tm' ? null : 'tm')} aria-expanded={menu === 'tm'}>{TPD.TEAM.mini && <img src={TPD.TEAM.mini} alt="" />}<span>{TPD.TEAM.name}</span><i>▾</i></button>
        {menu === 'tm' && <div className="tp-ddm">{teams.map((x) => <a key={x.key || x.short} href="#" onClick={(e) => pick(e, x)} className={isCur(x) ? 'on' : ''}>{tmImg(x)}<span>{x.name}</span></a>)}</div>}
      </div>
    </div>
  );
  return (
    <div className={'tp-sw tr hv' + (inline ? ' inl' : '')}>
      <div className="tp-hvchip">
        <img className="lgi" src={`assets/${lg}-logo-cropped.png`} alt={lname} />
        {seasonSel}
        {TPD.TEAM.mini && <img className="tmi" src={TPD.TEAM.mini} alt={TPD.TEAM.short} />}
        <span className="tp-hvcue mono">Switch ▾</span>
      </div>
      <div className="tp-hvpanel">
        <span className="mono h">League</span>
        {leagues}
        <span className="mono h">Team</span>
        <div className="tp-hvt">{teams.map((x) => <a key={x.key || x.short} href="#" onClick={(e) => pick(e, x)} className={isCur(x) ? 'on' : ''} title={x.name}>{tmImg(x, x.short)}<span>{x.name}</span></a>)}</div>
      </div>
    </div>
  );
}

// Renders the switcher into the site's crumb bar (#fdt-switch-slot) when that slot exists; inline otherwise.
function TPSwitchSlot(props) {
  const [slot, setSlot] = React.useState(null);
  React.useLayoutEffect(() => { setSlot(document.getElementById('fdt-switch-slot')); }, []);
  if (slot) return ReactDOM.createPortal(<TPSwitch {...props} inline />, slot);
  return document.getElementById('fdt-switch-slot') ? null : <TPSwitch {...props} />;
}

// League-history snapshot (2026-10-03): the team's record in its CURRENT league only (UL for UL teams), styled
// exactly like the season band above it. Variants via Tweak: 'stats' (numbers) | 'circuits' (podium glyphs).
function tpLeagueHist(lgArg) {
  const lg = lgArg || (TPD.seasons[0] && TPD.seasons[0].lg);
  const L = TPD.seasons.filter((s) => s.lg === lg && !s.preseason && s.rounds.some((r) => r.cells.some((c) => !c.dns)));
  if (!L.length) return null;
  const pos = L.map((s) => s.pos).filter((p) => typeof p === 'number');
  const pods = L.slice().reverse().flatMap((s) => s.rounds.flatMap((r) => r.cells.filter((c) => !c.dns && c.f && c.f <= 3).map((c) => ({ s, r, c }))));
  const D = {};
  L.forEach((s) => Object.entries(s.by || {}).forEach(([w, b]) => {
    const p = TPD.PEOPLE[w]; if (!p || p.vacant) return;
    const d = D[w] || (D[w] = { w, p, pts: 0, wins: 0, podiums: 0, n: 0 });
    d.pts = Math.round((d.pts + b.pts) * 10) / 10; d.wins += b.wins; d.podiums += b.podiums; d.n++;
  }));
  const legend = Object.values(D).sort((a, b) => b.pts - a.pts || b.wins - a.wins)[0] || null;
  if (legend) { // titles won with the team: their own drivers' titles + constructors' titles in seasons they raced for it
    legend.wdc = L.filter((s) => s.wdc === legend.w).length;
    legend.wcc = L.filter((s) => s.wcc && s.by && s.by[legend.w]).length;
  }
  return {
    lg, since: L[L.length - 1].id, seasons: L.length, best: pos.length ? Math.min(...pos) : null,
    wins: L.reduce((t, s) => t + (s.wins || 0), 0), podiums: L.reduce((t, s) => t + (s.podiums || 0), 0),
    oneTwo: L.reduce((t, s) => t + (s.oneTwo || 0), 0), titles: L.filter((s) => s.wcc).length,
    wcc: L.filter((s) => s.wcc).length, wdc: L.filter((s) => s.wdc).length, pods, legend,
  };
}
// One league-history band per league the team has raced in: current league first, then the others by tier
// (UL → CL → JL → AL). Leagues with no seasons are left out (user 2026-10-07).
function TPHistBand({ mode }) {
  const cur = TPD.seasons[0] && TPD.seasons[0].lg;
  const lgs = [cur, ...['UL', 'HL', 'JL', 'AL'].filter((x) => x !== cur && TPD.seasons.some((s) => s.lg === x))].filter(Boolean);
  return <React.Fragment>{lgs.map((lg) => <TPHistBandOne key={lg} lg={lg} mode={mode} />)}</React.Fragment>;
}
function TPHistBandOne({ lg, mode }) {
  const H = tpLeagueHist(lg);
  if (!H) return null;
  const lgName = TPD.LEAGUES[H.lg] || H.lg, d = H.legend;
  return (
    <div className="tp-band hist">
      <span className="bl"><span className="tp-chip">{H.lg === 'HL' ? 'CL' : H.lg}</span><i className="mono">Since {H.since}</i></span>
      <div className="bc"><span className="mono k" style={{ whiteSpace: 'nowrap' }}>All time stats in {lgName.replace(/ League$/, '')} League</span>
        <div className="tp-nstat two"><span><b>{H.seasons}</b><i className="mono">{H.seasons === 1 ? 'Season' : 'Seasons'}</i></span><span><b>{H.best ? 'P' + H.best : '—'}</b><i className="mono">Best finish</i></span></div>
      </div>
      {mode === 'circuits' ?
        <div className="bc wide"><span className="mono k">Podium circuits · {H.pods.length}</span>
          {H.pods.length ? <div className="tp-grow">{H.pods.map(({ s, r, c }, k) => <TPGlyph key={k} map={r.track.map} pos={c.f} title={`P${c.f} · ${s.id} R${r.n} ${r.track.gp} · ${tpName(c.who)}`} />)}</div> : null}
        </div> :
        <div className="bc wide"><span className="mono k" aria-hidden="true">&nbsp;</span>
          <div className="tp-nstat" style={{ gridTemplateColumns: 'repeat(5, minmax(0,1fr))' }}>{[['Wins', H.wins], ['Pods', H.podiums], ['1-2s', H.oneTwo], ['WDC', H.wdc], ['WCC', H.wcc]].map(([l, v]) => <span key={l}><b>{v}</b><i className="mono">{l}</i></span>)}</div>
        </div>}
      <div className="bc"><span className="mono k">Team legend</span>
        {d ? <div className="tp-lgbox">
          <div className="tp-lgmain"><div className="tp-blu"><span><em className="tp-dno">{d.p.num ? '#' + d.p.num : '—'}</em><TPFlag cc={d.p.cc} /><b><TPDrv w={d.w}>{d.p.name}</TPDrv></b></span></div>
          <div className="tp-lgd">{[['Pts', d.pts], ['Wins', d.wins], ['Pods', d.podiums]].map(([l, v]) => <span key={l}><b>{v}</b><i className="mono">{l}</i></span>)}</div></div>
          <div className="tp-lgt">{[['WDC', d.wdc, "drivers' titles"], ['WCC', d.wcc, "constructors' titles"]].map(([l, v, full]) =>
            <span key={l} className={'tw' + (v ? '' : ' z')} title={`${v} ${full} with ${TPD.TEAM.name}`}>
              <span className="w">{typeof URWreath === 'function' ? <URWreath size={44} color={v ? '#e2b857' : 'rgba(243,241,236,.28)'} /> : null}<b>{v}</b></span>
              <i className="mono">{l}</i>
            </span>)}</div>
        </div> : null}
      </div>
    </div>
  );
}

function TPCine({ backdrop, sw, hist = 'stats' }) {
  const { sel } = useSel();
  const t = TPD.TEAM, s = tpSeason(sel), A = TPD.all, lw = A.lastWin, br = A.best;
  const pods = s.rounds.flatMap((r) => r.cells.filter((c) => c.f && c.f <= 3).map((c) => ({ r, c }))).sort((a, b) => a.c.f - b.c.f || a.r.n - b.r.n);
  const bestF = s.rounds.flatMap((r) => r.cells.map((c) => ({ r, c }))).filter((x) => x.c.f).sort((a, b) => a.c.f - b.c.f)[0];
  return (
    <section className="tp-cine" data-screen-label="Team hero">
      <div className="tp-cbg" aria-hidden="true">{backdrop && <img className="tp-cback" src={t.logo} alt="" />}</div>
      <TPSwitchSlot mode={sw} />
      <div className="tp-wrap tp-ctop">
        {(() => {
          const mark = t.logo ? <img className="tp-clogo" src={t.logo} alt={t.name + ' logo'} /> : <URFranchiseMark className="tp-clogo" code={t.short} color={t.color} title={t.name} />;
          const ls = TPD.seasons.find((x) => !x.live), champ = ls && ls.wcc && typeof URWreath === 'function';
          if (!champ) return mark;
          // Reigning constructors' champions: compact laurel badge beside the logo (last finished season = WCC).
          return <div className="tp-logorow">{mark}<div className="tp-reign" title={`Constructors' champions · ${ls.id} ${TPD.LEAGUES[ls.lg] || ls.lg}`}><span className="w"><URWreath size={80} color="#e2b857" /><b>{ls.id}</b></span><span className="tx"><b>Reigning champions</b><i className="mono">{TPD.LEAGUES[ls.lg] || ls.lg} · {ls.id}</i></span></div></div>;
        })()}
        <span className="mono tp-ckick">{TPD.LEAGUES[s.lg]} · Season {s.num || s.n}{!t.noEst && <React.Fragment> · <b>Est. {tpEst()}</b></React.Fragment>}</span>
        <h1 className="tp-name"><span>{t.lines[0]}<TPFlag cc={t.cc} cls="tp-flag-xl" /></span><span>{t.lines[1]}</span></h1>
        <div className="tp-ccar">{s.livery ? <img src={s.livery} alt={`${t.name} ${s.id} livery`} /> : <span className="ghost"></span>}</div>
      </div>
      <div className="tp-wrap tp-bands" ref={tpBandsGutter}>
        <div className="tp-band now">
          <span className="bl"><span className="tp-chip">{tpLgSn(s)}</span><i className="mono">{tpIsLatest(s) ? (s.preseason ? 'Pre-season' : s.live ? 'Live' : 'Final') : s.label}</i></span>
          <div className="bc"><span className="mono k">This season</span>
            <div className="tp-nstat two"><span><b><TPOrd n={s.pos} /></b><i className="mono">Position</i></span><span><b>{s.pts}</b><i className="mono">Points</i></span></div>
          </div>
          <div className="bc wide"><span className="mono k" aria-hidden="true">&nbsp;</span>
            <div className="tp-nstat">{[['Wins', s.wins], ['Pods', s.podiums], ['FLs', s.fl], ['Poles', s.poles]].map(([l, v]) => <span key={l}><b>{v}</b><i className="mono">{l}</i></span>)}</div>
          </div>
          <div className="bc"><span className="mono k">Lineup</span><div className="tp-blu">{s.drivers.filter((w) => !TPD.PEOPLE[w].vacant).map((w) => { const p = TPD.PEOPLE[w]; return <span key={w}><em className="tp-dno">{p.num ? '#' + p.num : '—'}</em><TPFlag cc={p.cc} /><b><TPDrv w={w}>{p.name}</TPDrv></b>{s.champ && s.champ[w] ? <em className={'tp-dcp' + (s.champ[w] <= 3 ? ' pod' : '')}>P{s.champ[w]}</em> : null}</span>; })}</div></div>
          {/* Season podium glyph row removed from the hero (2026-10-03) — count is in "This season", glyphs on the driver cards */}
        </div>
        {hist !== 'classic' ? <TPHistBand mode={hist} /> :
        <div className="tp-band all">
          <span className="bl"><span className="tp-chip">All-time</span><i className="mono">Since {tpEst()}</i></span>
          {A.titles.length ?
            <div className="bc"><span className="mono k">Titles</span>
              <div className="tp-nstat" style={{ gridTemplateColumns: 'repeat(2, minmax(0,1fr))' }}><span><b>{A.wcc}</b><i className="mono">Constructors</i></span><span><b>{A.wdc}</b><i className="mono">Drivers</i></span></div>
            </div> :
            <div className="bc"><span className="mono k">Best finish</span>
              <div className="tp-nstat" style={{ gridTemplateColumns: 'repeat(1, minmax(0,1fr))' }}><span><b>P{A.bestPos.pos} {A.bestPos.id} · {A.bestPos.lg}</b></span></div>
            </div>}
          <div className="bc"><span className="mono k">Last win</span>
            {lw ? <div className="tp-nstat" style={{ gridTemplateColumns: 'repeat(1, minmax(0,1fr))' }}><span><b>{lw.season} R{lw.n}</b><i className="mono">{lw.track.gp} · {tpName(lw.who)}</i></span></div>
              : <div className="tp-nstat" style={{ gridTemplateColumns: 'repeat(1, minmax(0,1fr))' }}><span><b>—</b></span></div>}
          </div>
          <div className="bc"><span className="mono k">Best result · {br.pts} pts</span>
            <div className="tp-nstat" style={{ gridTemplateColumns: '1fr' }}><span><b>{br.cells.filter((c) => !c.dns).sort((a, b) => (a.f || 99) - (b.f || 99)).map((c) => (c.f ? 'P' + c.f : 'DNF')).join(' · ')}</b><i className="mono">{br.last.season} R{br.last.n} · {br.track.gp}</i></span></div>
          </div>
          <div className="bc"><span className="mono k">Career</span>
            <div className="tp-nstat" style={{ gridTemplateColumns: 'repeat(4, minmax(0,1fr))' }}><span><b>{A.seasons}</b><i className="mono">Seasons</i></span><span><b>{A.starts}</b><i className="mono">Starts</i></span><span><b>{A.wins}</b><i className="mono">Wins</i></span><span><b>{A.podiums}</b><i className="mono">Podiums</i></span></div>
          </div>
        </div>}
      </div>
    </section>
  );
}

// Earlier "classic" hero: team-color wash, name + meta left, car right, one strip of five tiles.
function TPClassic({ sw, logoPos }) {
  const { sel } = useSel();
  const t = TPD.TEAM, s = tpSeason(sel), A = TPD.all, lw = A.lastWin, prev = TPD.seasons[TPD.seasons.indexOf(s) + 1];
  const pods = s.rounds.flatMap((r) => r.cells.filter((c) => c.f && c.f <= 3).map((c) => ({ r, c }))).sort((a, b) => a.c.f - b.c.f || a.r.n - b.r.n);
  return (
    <section className={'tp-cl logo-' + logoPos} data-screen-label="Team hero">
      <TPSwitch mode={sw} inline />
      <div className="tp-wrap">
        <div className="tp-clgrid">
          <div className="tp-clid">
            {t.logo ? <img className="tp-cllogo" src={t.logo} alt={t.name + ' logo'} /> : <URFranchiseMark className="tp-cllogo" code={t.short} color={t.color} title={t.name} />}
            <div>
              <span className="mono tp-clk">{TPD.LEAGUES[s.lg]} · Season {s.num || s.n}</span>
              <h1 className="tp-name"><span>{t.lines[0]}<TPFlag cc={t.cc} cls="tp-flag-xl" /></span><span>{t.lines[1]}</span></h1>
              <dl className="tp-clmeta"><dt>Owner</dt><dd>{t.owner}</dd><dt>Principal</dt><dd>{t.principal}</dd>{!t.noEst && <React.Fragment><dt>Est.</dt><dd>{tpEst()}</dd></React.Fragment>}</dl>
            </div>
          </div>
          <div className="tp-clcar">{s.livery ? <img src={s.livery} alt={`${t.name} ${s.id} livery`} /> : <span className="ghost"></span>}</div>
        </div>
        <div className="tp-clstrip">
          <div><span className="mono k">{s.id} · Constructors</span><b className="hi"><TPOrd n={s.pos} /></b><span className="sub">{s.pts} pts{prev ? ` · ${prev.pos < s.pos ? 'down' : prev.pos > s.pos ? 'up' : 'level'} from ${tpOrd(prev.pos)} in ${prev.id}` : ''}</span></div>
          <div><span className="mono k">{s.id} record</span><div className="rec">{[[s.wins, 'Wins'], [s.podiums, 'Podiums'], [s.poles, 'Poles'], [s.fl, 'FL']].map(([v, l]) => <span key={l}><b>{v}</b><i className="mono">{l}</i></span>)}</div>
            {pods.length > 0 && <div className="tp-grow sm">{pods.map(({ r, c }, k) => <TPGlyph key={k} map={r.track.map} pos={c.f} title={`P${c.f} · R${r.n} ${r.track.gp}`} />)}</div>}</div>
          <div><span className="mono k">Lineup</span><div className="lu">{s.drivers.filter((w) => !TPD.PEOPLE[w].vacant).map((w) => { const p = TPD.PEOPLE[w]; return <span key={w}><em className="tp-dno">{p.num ? '#' + p.num : '—'}</em><TPFlag cc={p.cc} /><b>{p.name}</b><i className="mono">{s.champ[w] ? tpOrd(s.champ[w]) : '—'}</i></span>; })}</div></div>
          <div><span className="mono k">Last win</span>{lw ? <div className="lwr"><TPGlyph map={lw.track.map} pos={1} big /><span><b>{lw.track.gp}</b><i className="mono">{lw.season} R{lw.n} · {tpName(lw.who)}</i></span></div> : null}</div>
          <div><span className="mono k">Titles</span>{A.titles.length ? <div className="tp-tsplit">{[['wcc', 'Constructors'], ['wdc', 'Drivers']].map(([k, l]) => { const L = A.titles.filter((x) => x.kind === k); return <div key={k}><b className={L.length ? 'gold' : 'nil'}>{L.length}</b><span className="mono">{l}</span><div className="tp-grow sm">{L.map((x) => <TPGlyph key={x.season} map={x.track.map} pos={1} title={`${k.toUpperCase()} ${x.season}${x.who ? ' · ' + tpName(x.who) : ''}`} />)}</div></div>; })}</div> : <React.Fragment><b className="nil">0</b><span className="sub">Best {tpOrd(A.bestPos.pos)} · {A.bestPos.id}</span></React.Fragment>}</div>
        </div>
      </div>
    </section>
  );
}

function TPSNav({ active, cabinet }) {
  return (
    <div className="tp-snav"><div className="tp-wrap">
      <a className="id" href="#" onClick={(e) => { e.preventDefault(); window.scrollTo({ top: 0, behavior: 'smooth' }); }}>{TPD.TEAM.mini && <img src={TPD.TEAM.mini} alt="" />}<span>{TPD.TEAM.name}</span></a>
      <nav><a href="#" className={active === 'overview' ? 'on' : ''} onClick={(e) => { e.preventDefault(); window.scrollTo({ top: 0, behavior: 'smooth' }); }}><i>00</i>Overview</a>{TP_SECS.map(([id, l], k) => <a key={id} href={'#' + id} className={active === id ? 'on' : ''} onClick={(e) => { e.preventDefault(); tpScrollTo(id); }}><i>{tpPad(k + 1)}</i>{id === 'trophies' && cabinet === 'journey' ? 'History' : l}</a>)}</nav>
    </div></div>
  );
}

function TPSection({ id, i, title, desc, children }) {
  return (
    <section id={id} className="tp-sec" data-screen-label={`${i} ${title}`}>
      <div className="tp-wrap">
        <header className="tp-sh"><span className="i">{i}</span><h2>{title}</h2><p>{desc}</p></header>
        {children}
      </div>
    </section>
  );
}
function TPAcc({ open, onToggle, head, children, cls }) {
  return (
    <div className={'tp-acc' + (open ? ' open' : '') + (cls ? ' ' + cls : '')}>
      <button className="tp-acch" onClick={onToggle} aria-expanded={open}>{head}<span className="tp-pm"></span></button>
      <div className="tp-accb"><div>{children}</div></div>
    </div>
  );
}
const TPSub = ({ i, title, meta }) => <div className="tp-sub"><span className="mono i">{i}</span><h3>{title}</h3><span className="mono">{meta}</span></div>;

function TPDrivers() {
  const { sel } = useSel();
  const s = tpSeason(sel), A = TPD.all, [open, setOpen] = React.useState(false);
  const res = tpIsLatest(s) ? TPD.PEOPLE[TPD.TEAM.reserve] : null;
  return (
    <TPSection id="drivers" i="01" title={`${s.id} Drivers`} desc={`The ${s.id} lineup. Each podium is drawn as the circuit it was scored at.`}>
      <div className={'tp-dcards' + (res ? ' has-res' : '')}>
        {s.drivers.filter((w) => !TPD.PEOPLE[w].vacant).map((w) => {
          const p = TPD.PEOPLE[w], st = s.by[w], pos = s.champ[w];
          const mine = s.rounds.map((r) => ({ r, c: r.cells.find((c) => c.who === w && !c.dns) }));
          const poles = mine.filter((x) => x.c && x.c.pole).length;
          const fins = mine.filter((x) => x.c && x.c.f).map((x) => x.c.f);
          const best = fins.length ? Math.min(...fins) : null;
          return (
            <article className="tp-dcard" key={w}>
              <span className="tp-dghost" aria-hidden="true">{p.num || ''}</span>
              <header><span className="tp-role">Main</span><TPFlag cc={p.cc} /></header>
              <h3><TPDrv w={w}>{p.name}</TPDrv></h3>
              <span className="mono car">{TPD.TEAM.short}-{s.num || s.n}</span>
              <div className="tp-dstats">
                <div><b>{pos ? 'P' + pos : '—'}</b><span className="mono">Drivers</span></div>
                <div><b className="hi">{st.pts}</b><span className="mono">Pts</span></div>
                <div><b>{st.wins}</b><span className="mono">Wins</span></div>
                <div><b>{st.podiums}</b><span className="mono">Podiums</span></div>
                <div><b>{poles}</b><span className="mono">Poles</span></div>
                <div><b>{fins.filter((f) => f <= 5).length}</b><span className="mono">Top 5</span></div>
                <div><b>{fins.filter((f) => f <= 10).length}</b><span className="mono">Top 10</span></div>
                <div><b>{best ? 'P' + best : '—'}</b><span className="mono">Best</span></div>
              </div>
              {/* Per-round "Form" strip removed (2026-10-03, user) — round-by-round lives in Stats + Results */}
              <div className="tp-dpods">
                <span className="mono h">Podium circuits</span>
                {st.glyphs.length ? <div className="tp-grow">{st.glyphs.map((g) => <TPGlyph key={g.round} map={g.map} pos={g.pos} big title={`P${g.pos} · R${g.round} ${g.gp}`} />)}</div> : null}
              </div>
            </article>
          );
        })}
        {res && (() => {
          const rh = TPD.TEAM.reserve, rs = s.by[rh];
          const subs = s.rounds.flatMap((r) => r.cells.filter((c) => c.who === rh).map((c) => ({ r, c, for: s.drivers[c.slot] })));
          const fins = subs.filter((x) => x.c.f).map((x) => x.c.f);
          return (
            <article className={'tp-dcard res' + (subs.length ? ' used' : '')}>
              <header><span className="tp-role o">Reserve</span><TPFlag cc={res.cc} /></header>
              <h3><TPDrv w={TPD.TEAM.reserve}>{res.name}</TPDrv></h3>
              {res.num ? <span className="mono car">Car {tpPad(res.num)}</span> : null}
              {subs.length ? (
                <React.Fragment>
                  <div className="tp-dstats">
                    <div><b>{subs.length}</b><span className="mono">Starts</span></div>
                    <div><b className="hi">{rs.pts}</b><span className="mono">Pts</span></div>
                    <div><b>{rs.wins}</b><span className="mono">Wins</span></div>
                    <div><b>{rs.podiums}</b><span className="mono">Podiums</span></div>
                    <div><b>{subs.filter((x) => x.c.pole).length}</b><span className="mono">Poles</span></div>
                    <div><b>{fins.filter((f) => f <= 5).length}</b><span className="mono">Top 5</span></div>
                    <div><b>{fins.filter((f) => f <= 10).length}</b><span className="mono">Top 10</span></div>
                    <div><b>{fins.length ? 'P' + Math.min(...fins) : '—'}</b><span className="mono">Best</span></div>
                  </div>
                  {/* stand-in chips removed (2026-10-03, user) */}
                </React.Fragment>
              ) : null}
            </article>
          );
        })()}
      </div>
      <TPAcc cls="tp-alld" open={open} onToggle={() => setOpen(!open)} head={<React.Fragment>
        <span className="lg"><b>All drivers</b><span className="mono">{A.drivers.length} drivers · {A.starts} starts · since {tpEst()}</span></span>
        <span className="flags">{A.drivers.slice(0, 8).map((d) => <TPFlag key={d.w} cc={d.p.cc} />)}{A.drivers.length > 8 && <i className="mono">+{A.drivers.length - 8}</i>}</span>
        <span className="mono cue">{open ? 'Hide' : 'Show all'}</span>
      </React.Fragment>}>
        <div className="tp-lh tp-arow"><span>#</span><span>Driver</span><span className="c-sea">Seasons</span><span className="r c-sta">Starts</span><span className="r">Pts</span><span className="r c-win">Wins</span><span className="r">Podiums</span></div>
        {A.drivers.map((d) => (
          <div className="tp-row tp-arow" key={d.w}>
            <span className="tp-num">{d.p.num ? '#' + d.p.num : '—'}</span>
            <span className="tp-dn"><TPFlag cc={d.p.cc} /><span><b><TPDrv w={d.w}>{d.p.name}</TPDrv></b>{(d.current || d.titles > 0) && <em className="mono">{[d.current && 'Current driver', d.titles > 0 && `${d.titles}× drivers' champion`].filter(Boolean).join(' · ')}</em>}</span></span>
            <span className="mono c-sea tp-mute">{d.span}</span>
            <span className="tp-v r c-sta">{d.starts}</span><span className="tp-v r">{d.pts}</span><span className="tp-v r c-win">{d.wins}</span><span className="tp-v r">{d.podiums}</span>
          </div>
        ))}
      </TPAcc>
    </TPSection>
  );
}

// Every trophy the team owns: titles (gold, WCC or WDC) + constructors' 2nd/3rd (silver/bronze).
function tpTrophies() {
  const A = TPD.all;
  return [...A.titles.map((x) => ({ ...x, pos: 1 })), ...A.places.map((p) => ({ season: p.season, lg: p.lg, kind: 'place', pos: p.pos, track: p.track, round: TPD.seasons.find((s) => s.id === p.season).rounds.length }))]
    .sort((a, b) => (a.pos === 1 ? 0 : 1) - (b.pos === 1 ? 0 : 1) || b.season.slice(1) - a.season.slice(1) || a.pos - b.pos);
}
const tpTroTitle = (x) => x.kind === 'wcc' ? "Constructors' champions" : x.kind === 'wdc' ? "Drivers' champion" : `${tpOrd(x.pos)} in the constructors'`;

function TPPodCloud({ jump, bySeason, merged }) {
  if (!bySeason.length) return null;
  if (merged) return <div className="tp-cloud">{bySeason.flatMap(({ p }) => p).map((g, k) => <button key={k} onClick={() => jump(g.season, g.n)} title={`P${g.pos} · ${g.season} R${g.n} ${g.gp} · ${tpName(g.who)}`}><TPGlyph map={g.map} pos={g.pos} /></button>)}</div>;
  return <div className="tp-ptl">{[...bySeason].reverse().map(({ s, p }) => (
    <div key={s.id} className="col"><div className="stack">{p.map((g, k) => <button key={k} onClick={() => jump(g.season, g.n)} title={`P${g.pos} · ${g.season} R${g.n} ${g.gp} · ${tpName(g.who)}`}><TPGlyph map={g.map} pos={g.pos} /></button>)}</div><span className="mono lab"><b>{s.id}</b>{p.length}</span></div>
  ))}</div>;
}

const TP_TIER = { JL: 1, HL: 2, UL: 3 };
function tpPromos() {
  const L = [...TPD.seasons].reverse(), out = [];
  L.forEach((s, k) => { const p = L[k - 1]; if (p && TP_TIER[s.lg] > TP_TIER[p.lg]) out.push({ season: s.id, from: p.lg, to: s.lg }); });
  return out.reverse();
}

// Trophy icon. WCC = solid gold cup; WDC = gold outline cup with a star; place = small solid silver/bronze.
function TPCup({ kind, cls = '' }) {
  const solid = kind !== 'wdc';
  return (
    <svg className={'tp-cup ' + kind + ' ' + cls} viewBox="0 0 48 56" aria-label={kind === 'wcc' ? "Constructors' Champions" : kind === 'wdc' ? "Drivers' Champion" : 'Constructors’ podium'}>
      <g fill={solid ? 'currentColor' : 'none'} stroke="currentColor" strokeWidth={solid ? 0 : 2.4} strokeLinejoin="round">
        <path d="M11 4h26v14c0 8-6 14-13 14S11 26 11 18z"></path>
        <path d="M21 32h6v8h-6z"></path>
        <path d="M13 44h22v6H13z"></path>
      </g>
      <path d="M11 9H4v4c0 5 4 8 8 8M37 9h7v4c0 5-4 8-8 8" fill="none" stroke="currentColor" strokeWidth="2.4"></path>
      {kind === 'wdc' && <path d="M24 10l2.2 4.6 5 .6-3.7 3.4 1 5-4.5-2.5-4.5 2.5 1-5-3.7-3.4 5-.6z" fill="currentColor"></path>}
    </svg>
  );
}

// Compact story: one column per season, oldest → newest. Trophy on top, race podiums as pips, league underneath.
function TPJourney({ jump }) {
  const A = TPD.all, L = [...TPD.seasons].reverse(), n = L.length, promos = tpPromos();
  const jrRef = React.useRef(null);
  React.useLayoutEffect(() => { const el = jrRef.current; if (el && el.scrollWidth > el.clientWidth) el.scrollLeft = el.scrollWidth; }, [n, TPD.TEAM && TPD.TEAM.short]); // long histories open on the newest seasons
  const bands = []; L.forEach((s, k) => { const b = bands[bands.length - 1]; if (b && b.lg === s.lg) b.to = k; else bands.push({ lg: s.lg, from: k, to: k }); });
  return (
    <div className="tp-jr" ref={jrRef} style={{ '--n': n }}>
      <p className="tp-jsum mono"><span className="lg"><TPCup kind="wcc" /><b>{A.wcc}</b> WCC</span><span className="lg"><TPCup kind="wdc" /><b>{A.wdc}</b> WDC</span> · <b>{promos.length}</b> promotions · <b>{A.places.length}</b> constructors' podiums · <b>{A.podList.filter((g) => g.pos === 1).length}</b> wins · <b>{A.podList.length}</b> race podiums · <b>{n}</b> seasons</p>
      <div className="cols">{L.map((s, k) => {
        const t = A.titles.filter((x) => x.season === s.id), pods = A.podList.filter((g) => g.season === s.id).sort((a, b) => a.pos - b.pos);
        const pr = promos.find((p) => p.season === s.id), last = s.rounds[s.rounds.length - 1];
        const r = t[0] ? t[0].round : s.rounds.length;
        return (
          <div key={s.id} className={'c' + (t.length ? ' t' : s.pos <= 3 ? ' pl' : '')} style={{ alignContent: 'end', gridTemplateRows: t.length ? 'auto 96px auto 46px auto' : undefined }}>
            {pr && <span className="promo mono" title={`Promoted ${pr.from} → ${pr.to}`}>↑ {pr.to}</span>}
            {t.length > 0 && <span className="lab mono" style={{ alignItems: 'flex-start', gap: 10 }}>{t.map((x) => <span key={x.kind} className={'tk ' + x.kind}>{x.kind.toUpperCase()}{x.kind === 'wdc' && s.wdc ? <i>{tpName(s.wdc)}</i> : null}</span>)}</span>}
            <button className="tro" onClick={() => jump(s.id, r)} title={`${s.id} · ${tpOrd(s.pos)} in the constructors'`}>
              {t.length ? t.map((x) => <TPCup key={x.kind} kind={x.kind} cls={t.length > 1 ? 'half' : ''} />)
                : s.pos <= 3 ? <TPCup kind="place" cls={'p' + s.pos} /> : s.pos ? <span className="posc" style={{ display: 'grid', placeItems: 'center', width: 58, height: 58, marginBottom: 8, borderRadius: '50%', border: '2px solid var(--tc)', background: 'color-mix(in oklab, var(--tc) 22%, transparent)', color: 'var(--ink)', fontFamily: "'Archivo', sans-serif", fontStretch: '64%', fontWeight: 800, fontSize: 24, lineHeight: 1, transition: 'transform .2s' }}>{'P' + s.pos}</span> : <span className="slot"></span>}
            </button>
            <span className="lab mono" aria-hidden={t.length || s.pos > 3 ? 'true' : undefined} style={t.length || s.pos > 3 ? { visibility: 'hidden' } : undefined}>{tpOrd(s.pos)}</span>
            <div className="pips">{pods.map((g, i) => <button key={i} className={'p' + g.pos} onClick={() => jump(g.season, g.n)} title={`P${g.pos} · R${g.n} ${g.gp} · ${tpName(g.who)}`}></button>)}</div>
            <span className="sid"><b>{s.id}</b></span>
          </div>
        );
      })}</div>
      <div className="lgs">{bands.map((b) => <span key={b.from} style={{ gridColumn: `${b.from + 1} / ${b.to + 2}` }} className="mono">{TPD.LEAGUES[b.lg]}</span>)}</div>
    </div>
  );
}

// Every race trophy on one wall — flat by season, or one shelf per driver.
function TPTrophyWall({ jump }) {
  const A = TPD.all, [by, setBy] = React.useState('driver'), [open, setOpen] = React.useState(null);
  if (!A.podList.length) return null;
  // No minimap for the circuit (most archive rounds) → a solid metal medal with the position, so the line has no blank gaps.
  const cup = (g, k) => <button key={k} className={'cup p' + g.pos} onClick={() => jump(g.season, g.n)} title={`P${g.pos} · ${g.season} R${g.n} ${g.gp} · ${tpName(g.who)}`}>{g.map ? <TPMap k={g.map} cls="g" /> : <span className="gm">{g.pos}</span>}</button>;
  const drivers = A.drivers.map((d) => ({ d, p: A.podList.filter((g) => g.who === d.w).sort((a, b) => a.pos - b.pos) })).filter((x) => x.p.length);
  // By season: one shelf per season (newest first), same row layout as By driver; cups in round order.
  const seasons = TPD.seasons.map((s) => ({ s, p: A.podList.filter((g) => g.season === s.id).sort((a, b) => a.n - b.n || a.pos - b.pos) })).filter((x) => x.p.length);
  const shelf = (key, label, p, body) => (
    <div key={key} className="row">
      <span className="who">{label}<i className="mono">{p.filter((g) => g.pos === 1).length}W · {p.length}P</i></span>
      <div className="cups">{body || p.map(cup)}</div>
    </div>);
  // By driver: every podium on ONE line (newest season first, round order) + expand for a season-by-season breakdown.
  const multiLg = new Set(TPD.seasons.map((s) => s.lg)).size > 1;
  const lgTag = (s) => (multiLg ? (s.lg === 'HL' ? 'CL' : s.lg) + ' ' : '');
  const bySn = (p) => TPD.seasons.map((s) => ({ s, g: p.filter((x) => x.season === s.id).sort((a, b) => a.n - b.n || a.pos - b.pos) })).filter((x) => x.g.length);
  const drvRow = ({ d, p }) => {
    const isOpen = open === d.w, sn = bySn(p);
    return (
      <div key={d.w} className={'row drv' + (isOpen ? ' open' : '')}>
        <span className="who tog" role="button" tabIndex={0} aria-expanded={isOpen ? 'true' : 'false'} title={isOpen ? 'Hide the season breakdown' : 'Show podiums season by season'}
          onClick={() => setOpen(isOpen ? null : d.w)} onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setOpen(isOpen ? null : d.w); } }}>
          <TPFlag cc={d.p.cc} /><b>{d.p.name}</b><i className="mono">{p.filter((g) => g.pos === 1).length}W · {p.length}P <span aria-hidden="true">{isOpen ? '▴' : '▾'}</span></i></span>
        <div className="strip">{sn.flatMap(({ g }) => g).map(cup)}</div>
        {isOpen && <div className="det">{sn.map(({ s, g }) => (
          <div key={s.id} className="sr">
            <span className="mono sl">{lgTag(s)}{s.id}</span>
            <span className="mono sc">{g.filter((x) => x.pos === 1).length}W · {g.length}P</span>
            <div className="sgc">{g.map(cup)}</div>
          </div>))}</div>}
      </div>);
  };
  return (
    <div className="tp-twall">
      <div className="hd"><span className="mono">Trophy wall · {A.podList.length} race podiums</span>
        <div className="seg">{[['driver', 'By driver'], ['season', 'By season']].map(([k, l]) => <button key={k} className={by === k ? 'on' : ''} onClick={() => setBy(k)}>{l}</button>)}</div>
      </div>
      <div className="rows">{by === 'season' ?
        seasons.map(({ s, p }) => shelf(s.id, <React.Fragment><b>{s.id}</b><span className="mono lgt">{s.lg === 'HL' ? 'CL' : s.lg}</span></React.Fragment>, p)) :
        drivers.map(drvRow)}</div>
    </div>
  );
}

function TPCabinet({ mode, jump, pods = 'timeline' }) {
  const A = TPD.all, list = tpTrophies(), promos = tpPromos(), [pick, setPick] = React.useState(0);
  const x = list[Math.min(pick, list.length - 1)];
  const bySeason = TPD.seasons.map((s) => ({ s, p: A.podList.filter((g) => g.season === s.id) })).filter((g) => g.p.length);
  if (mode === 'journey') return (
    <TPSection id="trophies" i="02" title="History" desc="Every season the team has raced: league, constructors' finish, titles, promotions and race podiums."><TPJourney jump={jump} /><TPTrophyWall jump={jump} /></TPSection>
  );
  return (
    <TPSection id="trophies" i="02" title="Trophy Cabinet" desc="Titles and constructors' podiums, each drawn as the circuit where the season was decided. Click one to see that race.">
      {!list.length && !promos.length && !A.podList.length && (
        <div className="tp-void" aria-label="No honours yet">
          <div className="plinths">{[0, 1, 2].map((k) => <span key={k}><i></i></span>)}</div>
          <span className="shelf"></span>
          <p className="mono">The cabinet is waiting · best constructors' finish {tpOrd(A.bestPos.pos)} in {A.bestPos.id}</p>
        </div>
      )}
      {mode === 'honours' && (list.length > 0 || promos.length > 0 || A.podList.length > 0) && (() => {
        const ti = list.filter((t) => t.pos === 1), pl = list.filter((t) => t.pos > 1);
        return (
          <div className="tp-hon">
            {ti.length > 0 && <div className="tier"><span className="mono h">Championships</span><div className="tp-shelf">{ti.map((t) => (
              <button className="tp-tro p1" key={t.season + t.kind} onClick={() => jump(t.season, t.round)}>
                <span className="mono k">{t.kind === 'wdc' ? 'WDC' : 'WCC'} · {t.season} · {t.lg}</span>
                <span className="gw"><TPMap k={t.track.map} cls="g" pos={1} /></span><span className="pl"></span>
                <h3>{tpTroTitle(t)}</h3>
                <p className="mono">{t.kind === 'wdc' ? `${tpName(t.who)} · ` : ''}R{t.round} · {t.track.gp} →</p>
              </button>
            ))}</div></div>}
            {(promos.length > 0 || pl.length > 0) && <div className="tier row">
              {promos.length > 0 && <div><span className="mono h">Promotions</span><div className="tp-promos">{promos.map((p) => (
                <div key={p.season} className="pr"><img src={`assets/${p.to.toLowerCase()}-logo-cropped.png`} alt={p.to} /><span><b>{p.from} → {p.to}</b><i className="mono">{p.season} · up to {TPD.LEAGUES[p.to]}</i></span></div>
              ))}</div></div>}
              {pl.length > 0 && <div><span className="mono h">Constructors' podiums</span><div className="tp-plrow">{pl.map((t) => (
                <button key={t.season} className={'p' + t.pos} onClick={() => jump(t.season, t.round)}><TPMap k={t.track.map} cls="g" pos={t.pos} /><span><b>{tpOrd(t.pos)}</b><i className="mono">{t.season} · {t.lg}</i></span></button>
              ))}</div></div>}
            </div>}
            {A.podList.length > 0 && <div className="tier"><span className="mono h">Race podiums · {A.podList.length}</span><TPPodCloud jump={jump} bySeason={bySeason} merged /></div>}
          </div>
        );
      })()}
      {list.length > 0 && mode === 'glyphs' && (() => {
        const ti = list.filter((t) => t.pos === 1), pl = list.filter((t) => t.pos > 1);
        return (
          <React.Fragment>
            {ti.length > 0 && <div className="tp-cap mono tp-tcap"><span>Championships · {ti.length}</span><span>{A.wcc} constructors' · {A.wdc} drivers'</span></div>}
            {ti.length > 0 && <div className={'tp-shelf' + (pods === 'merged' ? ' merged' : '')}>{ti.map((t) => (
              <button className="tp-tro p1" key={t.season + t.kind} onClick={() => jump(t.season, t.round)}>
                <span className="mono k">{t.kind === 'wdc' ? 'WDC' : 'WCC'} · {t.season} · {t.lg}</span>
                <span className="gw"><TPMap k={t.track.map} cls="g" pos={1} /></span>
                <span className="pl"></span>
                <h3>{tpTroTitle(t)}</h3>
                <p className="mono">{t.kind === 'wdc' ? `${tpName(t.who)} · ` : ''}R{t.round} · {t.track.gp} →</p>
              </button>
            ))}{pods === 'merged' && <div className="tp-tro pods"><span className="mono k">Every race podium · {A.podList.length}</span><TPPodCloud jump={jump} bySeason={bySeason} merged /></div>}</div>}
            {pl.length > 0 && <div className="tp-cap mono tp-tcap"><span>Constructors' podiums · {pl.length}</span><span>Seasons finished 2nd or 3rd</span></div>}
            {pl.length > 0 && <div className="tp-plrow">{pl.map((t) => (
              <button key={t.season} className={'p' + t.pos} onClick={() => jump(t.season, t.round)}>
                <TPMap k={t.track.map} cls="g" pos={t.pos} />
                <span><b>{tpOrd(t.pos)}</b><i className="mono">{t.season} · {t.lg}</i></span>
              </button>
            ))}</div>}
          </React.Fragment>
        );
      })()}
      {list.length > 0 && mode === 'wall' && (
        <div className="tp-wall">
          <div className="tp-wsel">
            <div className={'gw p' + x.pos}><TPMap k={x.track.map} cls="g" pos={x.pos || 1} /></div>
            <span className="mono k">{x.season} · {TPD.LEAGUES[x.lg]}</span>
            <h3>{tpTroTitle(x)}</h3>
            <p>{x.kind === 'wdc' ? tpName(x.who) + ' · ' : ''}Decided at {x.track.circuit}, round {x.round}</p>
            <div className="ctl"><button onClick={() => setPick((pick - 1 + list.length) % list.length)}>←</button><span className="mono">{tpPad(pick + 1)} / {tpPad(list.length)}</span><button onClick={() => setPick((pick + 1) % list.length)}>→</button><button className="go" onClick={() => jump(x.season, x.round)}>View race →</button></div>
          </div>
          <div className="tp-wgrid">{list.map((t, k) => (
            <button key={t.season + t.kind} className={'p' + t.pos + (k === pick ? ' on' : '')} onClick={() => setPick(k)} title={`${t.season} · ${tpTroTitle(t)}`}>
              <TPMap k={t.track.map} cls="g" pos={t.pos || 1} /><span className="mono">{t.kind === 'wdc' ? 'WDC' : t.kind === 'wcc' ? 'WCC' : 'P' + t.pos} {t.season}</span>
            </button>
          ))}</div>
        </div>
      )}
      {mode !== 'honours' && A.podList.length > 0 && !(pods === 'merged' && mode === 'glyphs' && A.titles.length) && (
        <div className="tp-podwall">
          <div className="tp-cap mono"><span>Every race podium · {A.podList.length}</span><span>Click a circuit for the race</span></div>
          <TPPodCloud jump={jump} bySeason={bySeason} />
        </div>
      )}
    </TPSection>
  );
}

function TPShowroom({ style = 'poster', bg = 'logo' }) {
  const { sel } = useSel();
  const L = TPD.seasons, t = TPD.TEAM, [i, setI] = React.useState(0), s0 = L[i], [v, setV] = React.useState(-1);
  React.useEffect(() => { swRef.current = false; setI(Math.max(0, L.findIndex((x) => x.id === sel))); setV(-1); }, [sel]);
  const sp = s0.specials || [], cur = v >= 0 && sp[v] ? sp[v] : null;
  const s = cur ? { ...s0, livery: cur.file, lname: cur.name || 'Special livery' } : s0;
  const go = (d) => { swRef.current = true; setV(-1); setI((k) => (k + d + L.length) % L.length); };
  const filmRef = React.useRef(null), swRef = React.useRef(false), [bar, setBar] = React.useState(null);
  React.useLayoutEffect(() => {
    const f = filmRef.current, b = f && f.querySelector('button.on');
    setBar(b ? { left: b.offsetLeft, width: b.offsetWidth } : null);
  }, [i, v, L.length]);
  // Film = every car newest first: within a season, specials (latest round first) precede the season car (raced from R1).
  const film = L.flatMap((x, k) => [...(x.specials || []).map((sx, j) => ({ k, j, sx })).sort((a, b) => (parseInt(b.sx.rounds, 10) || 0) - (parseInt(a.sx.rounds, 10) || 0)), { k, j: -1 }]); // round unknown (archive posts) → after the numbered ones
  // Per-livery stats: a special covers its own rounds; the season car covers the rest (whole season when no specials).
  const rs = (x) => { const m = String(x).match(/^(\d+)(?:-(\d+))?$/); return m ? Array.from({ length: (m[2] ? +m[2] : +m[1]) - +m[1] + 1 }, (_, k) => +m[1] + k) : []; };
  const spR = new Set(sp.flatMap((x) => rs(x.rounds))), scoped = !!cur || spR.size > 0;
  const lvR = (s0.rounds || []).filter((r) => (cur ? rs(cur.rounds).includes(r.n) : !spR.has(r.n)));
  const lvC = lvR.flatMap((r) => r.cells.filter((c) => !c.dns)), raced = lvR.filter((r) => r.cells.some((c) => !c.dns)).length;
  const st = !scoped ? s : { pts: Math.round(lvC.reduce((t, c) => t + (Number(c.pts) || 0), 0) * 10) / 10, wins: lvC.filter((c) => c.f === 1).length, podiums: lvC.filter((c) => c.f >= 1 && c.f <= 3).length, poles: lvC.filter((c) => c.pole).length };
  const nd = scoped && !raced, dv = (x) => (nd ? '—' : x);
  const spec = [scoped ? ['Races', raced || '—', 'hi'] : ['Constructors', s.wcc ? 'P1' : 'P' + s.pos, 'hi'], ['Points', dv(st.pts), 'hi'], ['Wins', dv(st.wins)], ['Podiums', dv(st.podiums)], ['Poles', dv(st.poles)]];
  const drove = cur ? [...new Set(lvC.map((c) => c.who))].filter((w) => TPD.PEOPLE[w]) : [], drivers = drove.length ? drove : s.drivers;
  return (
    <TPSection id="liveries" i="03" title="Livery Showroom" desc={`Every car ${t.short} has raced, newest first.`}>
      <div className={'tp-bleed tp-poster v-' + style + ' bg-' + bg}>
        {bg === 'logo' && <img className="tp-pbglogo" src={t.logo} alt="" aria-hidden="true" />}
        <div className="tp-wrap tp-pgrid">
          <div className="tp-pspec2">
            <div className="lv"><span className="mono">Livery</span><b>{s.lname || `${t.short}-${s.n}`}</b></div>
            <div className="hd sm"><b>{s.id}</b><span className="mono">{TPD.LEAGUES[s.lg]} · {s.label}</span></div>
            <dl>{spec.map(([k, v, c]) => <div key={k} className={c || ''}><dd>{v}</dd><dt className="mono">{k}</dt></div>)}</dl>
            <div className="dr"><span className="mono">Driven by</span>{drivers.map((w) => <b key={w}><em className="tp-dno">{TPD.PEOPLE[w].num ? '#' + TPD.PEOPLE[w].num : ''}</em>{tpName(w)}</b>)}</div>
          </div>
          <div className="tp-part" key={s.id + ':' + v}>
            {(style === 'poster' || style === 'solid') && bg === 'name' && <span className="tp-pname" aria-hidden="true" style={{ '--len': (s.lname || `${t.short}-${s.n}`).length }}>{s.lname || `${t.short}-${s.n}`}</span>}
            {style === 'stacked' && <React.Fragment><span className="tp-pst top" aria-hidden="true">{t.short}</span><span className="tp-pst bot" aria-hidden="true">{s.n}</span></React.Fragment>}
            {style === 'disc' && <span className="tp-disc" aria-hidden="true"></span>}
            {style === 'vertical' && <React.Fragment><span className="tp-pv l" aria-hidden="true">{t.lines[0]}</span><span className="tp-pv r" aria-hidden="true">{t.short}-{s.n}</span></React.Fragment>}
            {style === 'minimal' && <div className="tp-pmin"><img src={t.logo} alt="" /><i></i><b>{t.short}-{s.n}</b><span className="mono">{s.drivers.map(tpName).join(' · ')}</span></div>}
            {s.livery ? <img className="tp-pcar" src={s.livery} alt={`${t.short}-${s.n} livery`} /> : <span className="tp-pcar ghost"></span>}
            {!s.livery && <span className="tp-pna mono">Livery not archived yet</span>}
            <span className="tp-pcap"><b>{s.lname || `${t.short}-${s.n}`}</b><i className="mono">{t.name} · {s.id}{cur ? (cur.rounds ? ' · Round ' + cur.rounds : ' · Special') : ''}</i></span>
          </div>
          <div className="tp-pside">
            <span className="tp-pvert mono">{t.name} · {s.id}</span>
            {s.wcc && !cur && <span className="tp-pchamp mono">◆ Title car</span>}
            {cur && <span className="tp-pchamp mono">◆ {cur.rounds ? 'Round ' + cur.rounds + ' special' : 'Special livery'}</span>}
            <div className="tp-ctl"><button onClick={() => go(-1)}>← Prev</button><span className="mono">{tpPad(i + 1)} / {tpPad(L.length)}</span><button onClick={() => go(1)}>Next →</button></div>
          </div>
        </div>
      </div>
      <div className="tp-film" ref={filmRef}>{bar && <i className="tp-filmbar" aria-hidden="true" style={{ left: bar.left, width: bar.width }}></i>}{film.map(({ k, j, sx }) => {
        const x = L[k], on = k === i && j === v;
        return sx ? (
          <button key={x.id + ':' + sx.file} className={'sp' + (on ? ' on' : '')} onClick={() => { swRef.current = true; setI(k); setV(j); }}>
            <img src={sx.file} alt="" />
            <b>{sx.name || 'Special'}</b><span className="mono">{x.id} · {sx.rounds ? 'R' + sx.rounds : 'Special'}</span>
          </button>
        ) : (
          <button key={x.id} className={on ? 'on' : ''} onClick={() => { swRef.current = true; setI(k); setV(-1); }}>
            {x.livery ? <img src={x.livery} alt="" /> : <span className="ghost"></span>}
            <b>{t.short}-{x.n}</b><span className="mono">{x.lg} · {x.wcc ? 'Champions' : tpOrd(x.pos)}</span>
          </button>
        );
      })}</div>
    </TPSection>
  );
}

// Driver v driver: both teammates' running points total through the season, points per round underneath.
function TPTimeline({ s, hl, setHl }) {
  const n = s.rounds.length, W = s.drivers;
  const F = W.map((w) => s.rounds.map((r) => { const c = r.cells.find((c) => c.who === w && !c.dns); return c ? { f: c.f, pts: c.pts } : null; }));
  // Cumulative points after each round (a round the driver missed carries the total forward, drawn hollow).
  const C = F.map((a) => { let t = 0; return a.map((x) => { t += x ? x.pts : 0; return Math.round(t * 10) / 10; }); });
  const peak = Math.max(1, ...C.flat()), step = peak > 300 ? 100 : peak > 120 ? 50 : peak > 60 ? 25 : 10, top = Math.ceil(peak / step) * step;
  const X = (k) => (k + 0.5) / n * 100, Y = (v) => 94 - v / top * 88;
  const grid = []; for (let v = 0; v <= top; v += step) grid.push(v);
  const lead = C[0].map((v, k) => (v === C[1][k] ? null : v > C[1][k] ? 0 : 1)); // who leads the team battle after round k
  const up = s.rounds.map((r, k) => { const [x, y] = [F[0][k], F[1][k]]; const px = x ? x.pts : 0, py = y ? y.pts : 0; return px === py ? null : px > py ? 0 : 1; });
  return (
    <div className={'tp-tl pos vs' + (hl != null ? ' hl' + hl : '')} style={{ '--n': n }}>
      <div className="plot">
        {grid.map((v) => <span key={v} className="gl" style={{ top: Y(v) + '%' }}><i className="mono">{v}</i></span>)}
        {s.rounds.map((r, k) => lead[k] != null && <span key={'g' + k} className={'gap a' + lead[k]} style={{ left: X(k) + '%', top: Math.min(Y(C[0][k]), Y(C[1][k])) + '%', height: Math.abs(Y(C[0][k]) - Y(C[1][k])) + '%' }}></span>)}
        <svg viewBox="0 0 100 100" preserveAspectRatio="none" aria-hidden="true">
          {C.map((a, di) => <polyline key={di} className={'ln d' + di} points={a.map((v, k) => `${X(k)},${Y(v)}`).join(' ')} />)}
        </svg>
        {C.map((a, di) => a.map((v, k) => <span key={di + '-' + k} className={'pt d' + di + (!F[di][k] ? ' dnf' : '')} style={{ left: X(k) + '%', top: Y(v) + '%' }} title={`After R${k + 1} · ${tpName(W[di])} · ${v} pts${F[di][k] ? ` (+${F[di][k].pts}, ${F[di][k].f ? 'P' + F[di][k].f : 'DNF'})` : ' (did not race)'}`}>{(k === n - 1 || hl === di) && <i className="mono">{v}</i>}</span>))}
      </div>
      <div className="tp-strip">{s.rounds.map((r, k) => {
        // Minimap tint: hovered driver's finish, else the team's best finish that round — gold/silver/bronze when on the podium.
        const fs = (hl != null ? [F[hl][k]] : F.map((a) => a[k])).filter((x) => x && x.f).map((x) => x.f);
        const best = fs.length ? Math.min(...fs) : null;
        return (
        <div key={r.n} className="c">
          <TPMap k={r.track.map} cls={'tp-map sm' + (best && best <= 3 ? ' m' + best : '')} title={`${r.track.circuit}${best ? ` · ${hl != null ? tpName(W[hl]) : 'best'} P${best}` : ''}`} />
          {hl != null ? <b>+{F[hl][k] ? F[hl][k].pts : 0}</b>
            : <span className="pp">{F.map((a, di) => <b key={di} className={'d' + di + (up[k] === di ? ' up' : '')}>{a[k] ? a[k].pts : '–'}</b>)}</span>}
          <span className="gp" title={r.track.gp}>{r.track.cc ? <TPFlag cc={r.track.cc} cls="tp-flag tp-gpf" /> : <span className="tp-gpn">R{r.n}</span>}</span>
        </div>);
      })}</div>
      <div className="tp-key mono">{W.map((w, di) => <button key={w} className={hl === di ? 'on' : ''} onMouseEnter={() => setHl(di)} onMouseLeave={() => setHl(null)}><i className={'d' + di}></i>{tpName(w)} <em>{C[di][n - 1]}</em></button>)}<span className="note">{hl != null ? `${tpName(W[hl])} · running total and points per round` : 'Season points · points per round'}</span></div>
    </div>
  );
}

// Season by season: faint points bars with a hairline constructors'-position line over them.
function TPBump() {
  const L = [...TPD.seasons].reverse(), n = L.length, max = Math.max(...L.map((s) => s.pts));
  const X = (k) => (k + 0.5) / n * 100, Y = (p) => 6 + (p - 1) / 9 * 50;
  const bands = []; L.forEach((s, k) => { const b = bands[bands.length - 1]; if (b && b.lg === s.lg) b.to = k; else bands.push({ lg: s.lg, from: k, to: k }); });
  return (
    <div className="tp-mx" style={{ '--n': n }}>
      <div className="plot">
        <div className="bars">{L.map((s) => <span key={s.id} className={s.wcc ? 't' : ''}><i style={{ height: `${s.pts / max * 62}%` }}><em className="mono">{s.pts}</em></i></span>)}</div>
        <svg viewBox="0 0 100 100" preserveAspectRatio="none" aria-hidden="true"><polyline points={L.map((s, k) => `${X(k)},${Y(s.pos)}`).join(' ')} /></svg>
        {L.map((s, k) => <span key={s.id} className={'d' + (s.wcc ? ' t' : '')} style={{ left: X(k) + '%', top: Y(s.pos) + '%' }} title={`${s.id} · ${tpOrd(s.pos)} · ${s.pts} pts`}><i className="mono">P{s.pos}</i></span>)}
      </div>
      <div className="x">{L.map((s) => <span key={s.id} className="mono">{s.id}</span>)}</div>
      <div className="lgs">{bands.map((b) => <span key={b.from} style={{ gridColumn: `${b.from + 1} / ${b.to + 2}` }} className="mono">{TPD.LEAGUES[b.lg]}</span>)}</div>
    </div>
  );
}

// Every teammate pairing across all seasons, aggregated (newest pairing first).
function tpPairings() {
  const m = new Map();
  TPD.seasons.forEach((s) => {
    const [w0, w1] = s.drivers, key = [w0, w1].sort().join('|');
    if (!m.has(key)) m.set(key, { key, d: [w0, w1], seasons: [], q: [0, 0], r: [0, 0], pts: [0, 0], podiums: [0, 0], wins: [0, 0] });
    const p = m.get(key), ix = p.d[0] === w0 ? [0, 1] : [1, 0];
    p.seasons.push(s.id);
    [0, 1].forEach((k) => {
      const w = s.drivers[k], st = s.by[w], t = ix[k];
      p.q[t] += s.h2h.q[k]; p.r[t] += s.h2h.r[k]; p.pts[t] += st.pts; p.podiums[t] += st.podiums; p.wins[t] += st.wins;
    });
  });
  return [...m.values()];
}

// Shared bar rows: Qualifying / Race / Points / Podiums / Wins
function TPH2HBars({ names, rows, hl, setHl, tag }) {
  return (
    <div className="tp-h2h">
      <div className="tp-cap mono"><span>Teammate head-to-head</span><span>{tag}</span></div>
      <div className="nm"><b className={hl === 0 ? 'on' : ''} onMouseEnter={() => setHl && setHl(0)} onMouseLeave={() => setHl && setHl(null)}><i className="k"></i>{names[0]}</b><b className={hl === 1 ? 'on' : ''} onMouseEnter={() => setHl && setHl(1)} onMouseLeave={() => setHl && setHl(null)}>{names[1]}<i className="k a"></i></b></div>
      {rows.map(([lab, [x, y]]) => (
        <div className="tp-hr" key={lab}>
          <span className="v">{x}</span>
          <span className="bar l"><i style={{ width: `${x + y ? x / (x + y) * 100 : 0}%` }}></i></span>
          <span className="lab mono">{lab}</span>
          <span className="bar rt"><i style={{ width: `${x + y ? y / (x + y) * 100 : 0}%` }}></i></span>
          <span className="v r">{y}</span>
        </div>
      ))}
    </div>
  );
}

function TPStats() {
  const { sel } = useSel();
  // Local season pick — only drives this Head-to-Head block; follows the page season when that changes.
  const [ls, setLs] = React.useState(sel);
  React.useEffect(() => setLs(sel), [sel]);
  const all = ls === 'all';
  const s = tpSeason(all ? sel : ls), A = TPD.all;
  const [hl, setHl] = React.useState(null);
  const pairs = React.useMemo(tpPairings, [TPD.TEAM.short]);
  const [pk, setPk] = React.useState(0);
  const pr = pairs[Math.min(pk, pairs.length - 1)];
  const [a, b] = s.drivers.map((w) => ({ p: TPD.PEOPLE[w], st: s.by[w] }));
  const h2h = [['Qualifying', s.h2h.q], ['Race', s.h2h.r], ['Points', [a.st.pts, b.st.pts]], ['Podiums', [a.st.podiums, b.st.podiums]], ['Wins', [a.st.wins, b.st.wins]]];
  const span = (p) => p.seasons.length > 1 ? `${p.seasons[p.seasons.length - 1]}–${p.seasons[0]}` : p.seasons[0];
  const pc = (v) => Math.round(v / A.starts * 100) + '%';
  const bd = A.bestDriver;
  return (
    <TPSection id="stats" i="04" title="Stats" desc={`${s.id} round by round, then the record since ${tpEst()}.`}>
      <TPSub i="A" title="Driver Head-to-Head" meta={all ? `${pairs.length} pairings · since ${tpEst()}` : `${s.id} · ${TPD.LEAGUES[s.lg]} · ${tpOrd(s.pos)} · ${s.pts} pts`} />
      <div className="tp-lsel" role="tablist" aria-label="Head-to-head season">
        <button className={all ? 'on' : ''} onClick={() => setLs('all')}>All-time</button>
        <span className="sep"></span>
        {TPD.seasons.map((x) => <button key={x.id} className={!all && ls === x.id ? 'on' : ''} onClick={() => setLs(x.id)}>{x.id}<i>{x.lg}</i></button>)}
      </div>
      {all ?
        <div className="tp-duo">
          <div className="tp-pairs">
            <div className="tp-cap mono"><span>Every teammate pairing</span><span>Pick one</span></div>
            {pairs.map((p, k) => (
              <button key={p.key} className={p === pr ? 'on' : ''} onClick={() => setPk(k)}>
                <b>{tpName(p.d[0])} <em>v</em> {tpName(p.d[1])}</b>
                <span className="mono">{span(p)} · {p.seasons.length} season{p.seasons.length > 1 ? 's' : ''}</span>
                <span className="mono rec">Q {p.q[0]}–{p.q[1]} · R {p.r[0]}–{p.r[1]}</span>
              </button>
            ))}
          </div>
          <TPH2HBars names={pr.d.map(tpName)} tag={span(pr)} rows={[['Qualifying', pr.q], ['Race', pr.r], ['Points', pr.pts], ['Podiums', pr.podiums], ['Wins', pr.wins]]} />
        </div> :
        <div className="tp-duo">
          <div><div className="tp-cap mono"><span>Driver v driver · points through the season</span><span>Hover a driver</span></div><TPTimeline s={s} hl={hl} setHl={setHl} /></div>
          <TPH2HBars names={[a.p.name, b.p.name]} tag={s.id} rows={h2h} hl={hl} setHl={setHl} />
        </div>}
      <TPSub i="B" title="All-time" meta={`${A.seasons} seasons · since ${tpEst()}`} />
      {/* TPBump (position/points by season) removed from the page — component kept above if wanted back */}
      <div className="tp-nstat tp-allstats">{[['Starts', A.starts], ['Wins', A.wins, pc(A.wins)], ['Podiums', A.podiums, pc(A.podiums)], ['Top 10s', A.top10, pc(A.top10)], ['One-twos', A.oneTwo], ['Double podiums', A.dbl], ['Poles', A.poles], ['Fastest laps', A.fl]].map(([l, v, p]) => <span key={l}><b>{v}{p && <em>{p}</em>}</b><i className="mono">{l}</i></span>)}</div>
      <TPSub i="C" title="Records" meta={`Best driver and best team result · since ${tpEst()}`} />
      <div className="tp-feat">
        <div className="tp-bdrv">
          <span className="tp-rhd"><b>Team legend</b><i className="mono">Most points scored for {TPD.TEAM.name}</i></span>
          <div className="big"><em className="tp-dno big">{bd.p.num ? '#' + bd.p.num : ''}</em><TPFlag cc={bd.p.cc} cls="tp-flag-l" /><TPDrv w={bd.w}>{bd.p.name}</TPDrv></div>
          <div className="tp-nstat">{[['Points', bd.pts], ['Wins', bd.wins], ['Podiums', bd.podiums], [bd.titles ? 'Titles' : 'Seasons', bd.titles || bd.nSeasons]].map(([l, v]) => <span key={l}><b>{v}</b><i className="mono">{l}</i></span>)}</div>
          <span className="mono tp-rsub">Raced for the team · {bd.span}</span>
          {(() => { // every podium the legend scored for this team, oldest → newest
            const si = (id) => TPD.seasons.findIndex((x) => x.id === id);
            const gl = (A.podList || []).filter((g) => g.who === bd.w).sort((a, b) => si(b.season) - si(a.season) || a.n - b.n);
            return gl.length ? <div className="tp-bglyphs"><span className="mono tp-rsub">{gl.length} {gl.length === 1 ? 'podium' : 'podiums'} for {TPD.TEAM.short}</span><div className="tp-grow">{gl.map((g, k) => <TPGlyph key={k} map={g.map} pos={g.pos} title={`P${g.pos} · ${g.season} R${g.n} · ${g.gp}`} />)}</div></div> : null;
          })()}
        </div>
        <TPResultCard r={A.best} kind="best" />
      </div>
      <TPRecords />
    </TPSection>
  );
}

// Extra team records — each derived from the same round data.
function TPRecords() {
  const A = TPD.all, L = TPD.seasons;
  const rounds = [...L].reverse().flatMap((s) => s.rounds.map((r) => ({ s, r })));
  const streak = (f) => { let best = 0, cur = 0, end = null, bEnd = null; rounds.forEach((x) => { if (f(x.r)) { cur++; end = x; if (cur > best) { best = cur; bEnd = end; } } else cur = 0; }); return { n: best, end: bEnd }; };
  const ptsStreak = streak((r) => r.pts > 0), podStreak = streak((r) => r.cells.some((c) => c.f && c.f <= 3));
  const bestSeason = L.reduce((m, s) => (s.pts > m.pts ? s : m), L[0]);
  const byWins = [...A.drivers].sort((x, y) => y.wins - x.wins)[0];
  const circ = {}; A.podList.forEach((g) => { circ[g.map] = circ[g.map] || { n: 0, g }; circ[g.map].n++; });
  const topC = Object.values(circ).sort((x, y) => y.n - x.n)[0];
  let first = null; for (const x of rounds) { const c = x.r.cells.find((c) => c.f === 1); if (c) { first = { ...x, c }; break; } }
  const wr = A.worst;
  const tiles = [
    ['Best season', bestSeason.id, `${bestSeason.pts} pts · ${tpOrd(bestSeason.pos)} · ${bestSeason.lg}`],
    ['Most wins · driver', byWins.wins ? byWins.wins : '—', byWins.wins ? byWins.p.name : '', null, byWins.p.cc],
    ['Points streak', ptsStreak.n, ptsStreak.end ? `rounds in a row · to ${ptsStreak.end.s.id} R${ptsStreak.end.r.n}` : 'rounds in a row'],
    ['Podium streak', podStreak.n || '—', podStreak.n ? `rounds in a row · to ${podStreak.end.s.id} R${podStreak.end.r.n}` : ''],
    ['Best circuit', topC ? topC.n : '—', topC ? `podiums at ${topC.g.gp}` : '', topC && topC.g.map],
    ['First win', first ? `${first.s.id} R${first.r.n}` : '—', first ? `${first.r.track.gp} · ${tpName(first.c.who)}` : '', first && first.r.track.map],
    ['Worst result', wr.label, `${wr.pts} pts · ${wr.last.season} R${wr.last.n} ${wr.track.gp}`, wr.track.map, null, true],
    ['One-twos', A.oneTwo, `${A.dbl} double podiums`],
    ['Poles · fastest laps', `${A.poles} · ${A.fl}`, `across ${A.starts} starts`]];
  return (
    <div className="tp-recs">{tiles.map(([k, v, sub, map, cc, dim]) => (
      <div key={k} className={'tp-rec' + (dim ? ' dim' : '')}>
        <span className="mono k" style={{ fontSize: 14 }}>{k}</span>
        <b>{cc && <TPFlag cc={cc} />}{v}</b>
        <span className="sub">{sub}</span>
        {map && <TPMap k={map} cls="tp-map rmap" />}
      </div>
    ))}</div>
  );
}

function TPResultCard({ r, kind }) {
  return (
    <div className={'tp-rc ' + kind} style={{ position: 'relative', isolation: 'isolate', overflow: 'hidden' }}>
      {r.track.img && <span className="rcbg" aria-hidden="true" style={{ position: 'absolute', inset: 0, zIndex: -1, pointerEvents: 'none', backgroundSize: 'cover', backgroundPosition: 'center', opacity: kind === 'worst' ? 0.22 : 0.42, filter: kind === 'worst' ? 'grayscale(1)' : 'none', backgroundImage: `linear-gradient(90deg, rgba(11,11,11,.3) 0%, rgba(11,11,11,.82) 48%, rgba(11,11,11,.94) 100%), url("assets/tracks/sm/${r.track.img}.jpg")` }}></span>}
      <div className="rcm" style={{ display: 'grid', justifyItems: 'center', gap: 16, minWidth: 0 }}>
        <TPMap k={r.track.map} cls="tp-map big" />
        {r.track.cc && <TPFlag cc={r.track.cc} cls="tp-flag tp-rcflag" />}
      </div>
      <div className="body">
        <span className="tp-rhd"><b>{kind === 'best' ? 'Best team result' : 'Worst team result'}</b><i className="mono">{r.byFinish ? (kind === 'best' ? 'Best combined finish in one round' : 'Worst combined finish in one round') : 'Most points in one round'}</i></span>
        <b className="trk">{r.track.circuit}</b>
        <span className="mono tp-rsub">{r.track.gp} · {r.last.season} R{r.last.n} · {TPD.fmtFull(r.last.date)}</span>
        <div className="fig">
          {r.cells.filter((c) => !c.dns).slice().sort((a, b) => (a.f || 99) - (b.f || 99)).map((c) => <span key={c.who}><b>{c.f ? 'P' + c.f : 'DNF'}</b><i className="mono">{tpName(c.who)}</i></span>)}
          <span><b>{r.pts}</b><i className="mono">Points</i></span>
          <span><b>{r.count}×</b><i className="mono">Achieved</i></span>
        </div>
      </div>
    </div>
  );
}

const TPFin = ({ c }) => {
  const tags = [c.sub && tpName(c.who), c.pole && 'Pole', c.fl && 'FL'].filter(Boolean);
  return <span className={'tp-fin' + (!c.f ? ' out' : c.f <= 3 ? ' pod' : '')}><b>{c.f ? 'P' + c.f : c.dns ? '—' : 'DNF'}</b>{tags.length > 0 && <i className="mono">{tags.join(' · ')}</i>}</span>;
};

function TPRoundRows({ s, focus }) {
  const dn = s.drivers.map(tpName);
  return (
    <React.Fragment>
      <div className="tp-lh tp-rrow"><span>Rnd</span><span>Location</span><span className="tp-date">Date</span><span>{dn[0]}</span><span>{dn[1]}</span><span className="tp-cmap">Circuit</span><span className="r">Pts</span></div>
      {s.rounds.map((r) => (
        <div className={'tp-row tp-rrow' + (focus && focus.season === s.id && focus.n === r.n ? ' focus' : '')} key={r.n} id={`r-${s.id}-${r.n}`}>
          <span className="tp-num">{tpPad(r.n)}</span>
          <span className="tp-loc"><TPFlag cc={r.track.cc} /><span><b>{r.track.gp}</b><i className="mono">{r.track.circuit}</i></span>{r.track.img && <img className="tp-peek" src={`assets/tracks/sm/${r.track.img}.jpg`} alt="" loading="lazy" />}</span>
          <span className="tp-date mono">{TPD.fmtDay(r.date)}</span>
          {r.cells.map((c, k) => <TPFin key={k} c={c} />)}
          <TPMap k={r.track.map} />
          <span className="tp-v r">{r.pts}</span>
        </div>
      ))}
    </React.Fragment>
  );
}

function TPResults() {
  const { sel, focus } = useSel();
  const s = tpSeason(sel);
  const others = TPD.seasons.filter((x) => x.id !== s.id);
  const [open, setOpen] = React.useState(() => new Set());
  const [more, setMore] = React.useState(false);
  const tog = (id) => setOpen((o) => { const n = new Set(o); if (n.has(id)) n.delete(id); else n.add(id); return n; });
  const shown = more ? others : others.slice(0, 3);
  return (
    <TPSection id="results" i="05" title="Results" desc="">
      <TPRoundRows s={s} focus={focus} />
      {others.length > 0 && <div className="tp-cap mono tp-tcap"><span>Other seasons · {others.length}</span><span>Open a season to see every round</span></div>}
      {shown.map((x) => (
        <TPAcc key={x.id} open={open.has(x.id)} onToggle={() => tog(x.id)} head={<React.Fragment>
          <span className="yr">{x.id}</span>
          <span className="lg"><b>{TPD.LEAGUES[x.lg]}</b><span className="mono">{x.label} · {x.rounds.length} rounds · {x.drivers.map(tpName).join(' & ')}</span></span>
          <span className={'fig' + (x.wcc ? ' gold' : '')}><b><TPOrd n={x.pos} /></b><span className="mono">{x.wcc ? 'Champions' : 'Constructors'}</span></span>
          <span className="fig tp-hide-s"><b>{x.pts}</b><span className="mono">Points</span></span>
        </React.Fragment>}>
          <TPRoundRows s={x} focus={focus} />
        </TPAcc>
      ))}
      {others.length > 3 && (
        <button className="tp-more" onClick={() => setMore(!more)}>
          <span>{more ? 'Show fewer seasons' : `Show ${others.length - 3} more seasons`}</span>
          <span className="mono">back to {tpEst()}</span>
        </button>
      )}
    </TPSection>
  );
}

function TPFooter() {
  return (
    <footer className="tp-foot"><div className="tp-wrap">
      <div className="tp-fl"><img src="assets/ur2d-logo.png" alt="" /><span className="mono">© 2026 Ultimate Racing Esports</span></div>
      <span className="mono">Layout preview · figures are sample data</span>
    </div></footer>
  );
}

function TPPage({ t, embed }) {
  const [sel, setSel] = React.useState(TPD.seasons[0].id);
  const [focus, setFocus] = React.useState(null);
  const active = useTPSpy();
  const jump = (season, n) => {
    setSel(season); setFocus({ season, n });
    setTimeout(() => { const el = document.getElementById(`r-${season}-${n}`); if (el) window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 180 - tpOff(), behavior: 'smooth' }); }, 60);
  };
  return (
    <TPCtx.Provider value={{ sel, setSel, focus }}>
      {!embed && <TPNav />}
      {embed && <TPSNav active={active} cabinet={t.cabinet} />}
      {t.hero === 'classic' ? <TPClassic sw={t.switcher} logoPos={t.logoPos} /> : <TPCine backdrop={t.logoBackdrop} sw={t.switcher} hist={t.hist} />}
      {!embed && <TPSNav active={active} cabinet={t.cabinet} />}
      <main><TPDrivers /><TPCabinet mode={t.cabinet} pods={t.pods} jump={jump} /><TPShowroom style={t.showroom} bg={t.showroomBg} /><TPStats /><TPResults /></main>
      {!embed && <TPFooter />}
    </TPCtx.Provider>
  );
}

// Mountable team page. Standalone (Team Page.html) or embedded in the final site (window.TP_EMBED: no own nav/footer, offsets clear the site nav).
function TPTeamPage({ t, embed }) {
  Object.assign(TPD, { nav: null }, TPD.profiles[t.team] || TPD.profiles.champion);
  return <div className={'tp-root' + (embed ? ' embed' : '') + (t.peek === 'always' ? ' tp-peek-on' : '')} style={{ '--tc': TPD.TEAM.color }}><TPPage t={t} embed={embed} key={t.team} /></div>;
}

function TPApp() {
  const [t, setTweak] = useTweaks(TP_DEFAULTS);
  return (
    <React.Fragment>
      <TPTeamPage t={t} />
      <TweaksPanel title="Tweaks">
        <TweakSection label="Sample team" />
        <TweakRadio label="Team" value={t.team} options={['champion', 'midtable', 'backmarker']} onChange={(v) => setTweak('team', v)} />
        <TweakSection label="Hero" />
        <TweakRadio label="Layout" value={t.hero} options={['cinematic', 'classic']} onChange={(v) => setTweak('hero', v)} />
        {t.hero === 'classic' && <TweakRadio label="Logo" value={t.logoPos} options={['above', 'right']} onChange={(v) => setTweak('logoPos', v)} />}
        <TweakRadio label="League / team switcher" value={t.switcher} options={['bar', 'arrows', 'dropdown', 'hover']} onChange={(v) => setTweak('switcher', v)} />
        <TweakToggle label="Large logo backdrop" value={t.logoBackdrop} onChange={(v) => setTweak('logoBackdrop', v)} />
        <TweakSection label="Trophy cabinet" />
        <TweakRadio label="Layout" value={t.cabinet} options={['journey', 'glyphs', 'wall', 'honours']} onChange={(v) => setTweak('cabinet', v)} />
        <TweakRadio label="Race podiums" value={t.pods} options={['timeline', 'merged']} onChange={(v) => setTweak('pods', v)} />
        <TweakSection label="Livery showroom" />
        <TweakRadio label="Backdrop" value={t.showroomBg} options={['logo', 'texture', 'name']} onChange={(v) => setTweak('showroomBg', v)} />
        <TweakSelect label="Style" value={t.showroom} options={['poster', 'stacked', 'disc', 'vertical', 'solid', 'minimal']} onChange={(v) => setTweak('showroom', v)} />
      </TweaksPanel>
    </React.Fragment>
  );
}

Object.assign(window, { TPTeamPage, TP_DEFAULTS, TPFlag, TPMap, TPGlyph, TPOrd, TPCup, TPAcc, TPSection, TPSub, TPTimeline, TPH2HBars, tpBandsGutter }); // parts shared with driver pages
if (!window.TP_EMBED) ReactDOM.createRoot(document.getElementById('root')).render(<TPApp />);
