// Side panels — Leaderboard, Focused car detail, Telemetry, Strategy, Pit log
const { useState: useStateP, useEffect: useEffectP, useMemo: useMemoP } = React;

function Leaderboard({ cars, focusedNo, onFocus, lap }) {
  const sorted = [...cars].sort((a,b) => a.pos - b.pos);
  return (
    <div className="panel">
      <div className="panel-head">
        <div className="panel-eyebrow">LIVE TIMING</div>
        <div className="panel-title">RUNNING ORDER</div>
        <div className="panel-meta">L{lap} · S/F</div>
      </div>
      <div className="lb">
        <div className="lb-row lb-head">
          <span>POS</span><span>NO</span><span>DRIVER</span><span>GAP</span><span>LAST</span><span>TYRE</span>
        </div>
        {sorted.map(c => {
          const podiumCls = c.pos === 1 ? "lb-p1" : c.pos === 2 ? "lb-p2" : c.pos === 3 ? "lb-p3" : "";
          const posCls = c.pos === 1 ? "lb-pos-gold" : c.pos === 2 ? "lb-pos-silver" : c.pos === 3 ? "lb-pos-bronze" : "";
          const inPit = c._inPit;
          const justPitted = c.tire_age <= 2 && c.pos > 3;
          return (
          <div key={c.no}
            className={`lb-row ${c.no === focusedNo ? "lb-focus" : ""} ${podiumCls} ${inPit ? "lb-pit" : ""} ${justPitted ? "lb-just-pitted" : ""}`}
            onClick={() => onFocus(c.no)}>
            <span className={`lb-pos ${posCls}`}>{String(c.pos).padStart(2,"0")}</span>
            <span className="lb-no" style={{ color: c.livery.accent === "#FFFFFF" ? "#fff" : c.livery.accent }}>{c.no}</span>
            <span className="lb-name">
              <span className="lb-livery" style={{ background: c.livery.primary, borderColor: c.livery.secondary }}/>
              {inPit ? <span className="lb-pit-badge">PIT</span> : null}
              <span className="lb-driver">{c.name.split(" ").slice(-1)[0]}</span>
              <span className="lb-team">{c.short}</span>
            </span>
            <span className={`lb-gap ${c.gap === "LEADER" ? "lb-gap-leader" : ""}`}>{c.gap}</span>
            <span className="lb-last">{c.last_lap}</span>
            <span className={`tyre tyre-${c.tire}`}>{c.tire}<sub>{c.tire_age}</sub></span>
          </div>
          );
        })}
      </div>
    </div>
  );
}

// CSS-painted livery card — original geometric livery art
function LiveryCard({ car }) {
  const { livery: L, no } = car;
  return (
    <div className="livery-card" aria-label={`${car.team} livery`}>
      <svg viewBox="0 0 320 140" preserveAspectRatio="xMidYMid slice" className="livery-svg">
        {/* base */}
        <rect width="320" height="140" fill={L.primary}/>
        {/* pattern */}
        {L.pattern === "stripe-diag" && (
          <g>
            <polygon points="0,0 90,0 50,140 0,140" fill={L.secondary}/>
            <polygon points="90,0 100,0 60,140 50,140" fill={L.accent}/>
          </g>
        )}
        {L.pattern === "stripe-vert" && (
          <g>
            <rect x="120" y="0" width="36" height="140" fill={L.secondary}/>
            <rect x="160" y="0" width="6" height="140" fill={L.accent}/>
          </g>
        )}
        {L.pattern === "stripe-horiz" && (
          <g>
            <rect x="0" y="50" width="320" height="14" fill={L.secondary}/>
            <rect x="0" y="68" width="320" height="3" fill={L.accent}/>
          </g>
        )}
        {L.pattern === "kintsugi" && (
          <g stroke={L.secondary} strokeWidth="2" fill="none" opacity="0.95">
            <path d="M 0 60 L 80 70 L 130 50 L 200 80 L 260 60 L 320 78"/>
            <path d="M 0 100 L 60 90 L 140 110 L 220 95 L 320 100"/>
            <circle cx="80" cy="70" r="3" fill={L.accent}/>
            <circle cx="200" cy="80" r="3" fill={L.accent}/>
            <circle cx="260" cy="60" r="3" fill={L.accent}/>
          </g>
        )}
        {/* wheels — abstract */}
        <rect x="20"  y="106" width="34" height="20" fill="#0B0B0B"/>
        <rect x="266" y="106" width="34" height="20" fill="#0B0B0B"/>
        {/* halo / cockpit hint */}
        <ellipse cx="160" cy="40" rx="36" ry="12" fill="#0B0B0B" opacity="0.85"/>
        {/* number panel */}
        <rect x="142" y="60" width="36" height="36" fill={L.secondary}/>
        <text x="160" y="88" textAnchor="middle" fontSize="28" fontWeight="900"
          fontFamily="Geist, sans-serif" fill={L.primary}>{no}</text>
      </svg>
      <div className="livery-overlay">
        <span>LIVERY · {car.team}</span>
        <span>{L.primary} / {L.secondary} / {L.accent}</span>
      </div>
    </div>
  );
}

// Per-class side-profile car silhouette renderer for the hero photo card.
// Returns an <svg> element designed to fill its container.
function ClassHeroScene({ car, carClass }) {
  const cls = (carClass && carClass.id) || "open_wheel";
  const L = car.livery;
  const accent = L.accent === "#FFFFFF" ? "#E8E4DC" : L.accent;
  const skyTop = "#0A1322";
  const skyMid = "#142235";
  const horizon = "#1A2B3F";

  // Side-profile car geometries, drawn at 1000×620 viewBox; cars sit on y≈420 ground line
  const Car = () => {
    const cx = 500, cy = 420; // body baseline
    if (cls === "gt") return (
      <g transform={`translate(${cx-280} ${cy-110})`}>
        {/* GT silhouette — low coupe */}
        <path d="M 20 130 L 60 80 L 200 50 L 380 50 L 460 70 L 540 110 L 540 150 L 20 150 Z"
              fill={L.primary} stroke="#000" strokeWidth="2"/>
        <path d="M 90 80 L 200 60 L 360 60 L 440 80 L 440 110 L 90 110 Z" fill="#0B0F18" opacity="0.92"/>
        <rect x="90" y="115" width="360" height="6" fill={L.secondary}/>
        <rect x="180" y="125" width="160" height="3" fill={accent}/>
        <text x="280" y="142" fontSize="22" fontWeight="900" fontFamily="Geist, sans-serif" fill={accent} textAnchor="middle">{car.no}</text>
        {/* wheels */}
        <circle cx="120" cy="150" r="34" fill="#050810"/>
        <circle cx="120" cy="150" r="22" fill="#1a1a1a"/>
        <circle cx="120" cy="150" r="6" fill={accent}/>
        <circle cx="440" cy="150" r="34" fill="#050810"/>
        <circle cx="440" cy="150" r="22" fill="#1a1a1a"/>
        <circle cx="440" cy="150" r="6" fill={accent}/>
        {/* spoiler */}
        <rect x="500" y="60" width="50" height="6" fill={L.secondary}/>
        <rect x="540" y="58" width="6" height="14" fill={L.secondary}/>
      </g>
    );
    if (cls === "stock") return (
      <g transform={`translate(${cx-300} ${cy-130})`}>
        {/* Stock car — tall greenhouse, fenders */}
        <path d="M 10 160 L 30 110 L 100 90 L 150 50 L 460 50 L 510 90 L 580 110 L 600 160 L 10 160 Z"
              fill={L.primary} stroke="#000" strokeWidth="2"/>
        <path d="M 160 60 L 300 60 L 300 100 L 160 100 Z" fill="#0B0F18" opacity="0.92"/>
        <path d="M 310 60 L 450 60 L 480 100 L 310 100 Z" fill="#0B0F18" opacity="0.92"/>
        <rect x="155" y="60" width="2" height="40" fill="#000"/>
        <rect x="305" y="60" width="2" height="40" fill="#000"/>
        {/* number circle */}
        <circle cx="305" cy="125" r="28" fill="#fff" stroke={L.secondary} strokeWidth="3"/>
        <text x="305" y="135" fontSize="28" fontWeight="900" fontFamily="Geist, sans-serif" fill="#000" textAnchor="middle">{car.no}</text>
        {/* livery stripe */}
        <rect x="100" y="105" width="430" height="10" fill={L.secondary}/>
        <rect x="100" y="118" width="430" height="3" fill={accent}/>
        {/* wheels */}
        <circle cx="130" cy="160" r="36" fill="#050810"/>
        <circle cx="130" cy="160" r="24" fill="#1a1a1a"/>
        <circle cx="130" cy="160" r="6" fill={accent}/>
        <circle cx="490" cy="160" r="36" fill="#050810"/>
        <circle cx="490" cy="160" r="24" fill="#1a1a1a"/>
        <circle cx="490" cy="160" r="6" fill={accent}/>
      </g>
    );
    if (cls === "prototype") return (
      <g transform={`translate(${cx-310} ${cy-95})`}>
        {/* LMH — very low, fender humps, fin */}
        <path d="M 0 130 L 30 100 L 110 78 L 200 50 L 230 50 L 250 70 L 380 70 L 420 50 L 470 50 L 540 78 L 600 100 L 620 130 L 0 130 Z"
              fill={L.primary} stroke="#000" strokeWidth="2"/>
        {/* canopy */}
        <path d="M 240 70 L 260 50 L 380 50 L 400 70 Z" fill="#0B0F18" opacity="0.92"/>
        {/* shark fin */}
        <path d="M 380 50 L 380 12 L 470 50 Z" fill={L.primary} stroke="#000" strokeWidth="1.5"/>
        <rect x="385" y="22" width="60" height="3" fill={accent}/>
        {/* livery diag */}
        <path d="M 60 90 L 150 70 L 180 90 L 90 110 Z" fill={L.secondary}/>
        <path d="M 90 110 L 180 90 L 195 100 L 105 120 Z" fill={accent}/>
        <text x="320" y="105" fontSize="20" fontWeight="900" fontFamily="Geist, sans-serif" fill={accent} textAnchor="middle">{car.no}</text>
        {/* wheels */}
        <circle cx="130" cy="130" r="28" fill="#050810"/>
        <circle cx="130" cy="130" r="18" fill="#1a1a1a"/>
        <circle cx="130" cy="130" r="5" fill={accent}/>
        <circle cx="500" cy="130" r="28" fill="#050810"/>
        <circle cx="500" cy="130" r="18" fill="#1a1a1a"/>
        <circle cx="500" cy="130" r="5" fill={accent}/>
      </g>
    );
    if (cls === "e_spec") return (
      <g transform={`translate(${cx-290} ${cy-95})`}>
        {/* E-Spec — covered front wheels, exposed rear */}
        <path d="M 10 130 L 40 105 L 130 95 L 170 50 L 380 50 L 420 75 L 460 80 L 460 110 L 540 110 L 560 130 L 10 130 Z"
              fill={L.primary} stroke="#000" strokeWidth="2"/>
        {/* halo cockpit */}
        <path d="M 200 60 L 210 35 L 360 35 L 370 60 Z" fill="#0B0F18" opacity="0.95"/>
        <path d="M 215 35 Q 285 18 355 35" fill="none" stroke="#0B0F18" strokeWidth="6"/>
        {/* livery */}
        <rect x="40" y="90" width="380" height="5" fill={L.secondary}/>
        <rect x="40" y="98" width="380" height="2" fill={accent}/>
        <text x="290" y="115" fontSize="20" fontWeight="900" fontFamily="Geist, sans-serif" fill={accent} textAnchor="middle">{car.no}</text>
        {/* lightning */}
        <polygon points="100,72 112,90 104,90 116,108 110,90 118,90" fill="#3DD68C"/>
        {/* covered front wheel */}
        <path d="M 90 130 A 40 40 0 0 1 170 130 Z" fill={L.primary} stroke="#000" strokeWidth="2"/>
        <circle cx="130" cy="130" r="22" fill="#050810"/>
        <circle cx="130" cy="130" r="14" fill="#1a1a1a"/>
        <circle cx="130" cy="130" r="4" fill="#3DD68C"/>
        {/* exposed rear wheel */}
        <circle cx="490" cy="130" r="32" fill="#050810"/>
        <circle cx="490" cy="130" r="22" fill="#1a1a1a"/>
        <circle cx="490" cy="130" r="5" fill="#3DD68C"/>
      </g>
    );
    // fallback open-wheel silhouette (only used if real photo missing)
    return (
      <g transform={`translate(${cx-290} ${cy-90})`}>
        <rect x="180" y="80" width="240" height="20" fill={L.primary} stroke="#000"/>
        <path d="M 60 120 L 130 95 L 180 95 L 180 105 L 130 110 L 80 130 Z" fill={L.primary} stroke="#000"/>
        <path d="M 420 95 L 540 95 L 580 130 L 420 110 Z" fill={L.primary} stroke="#000"/>
        <rect x="250" y="62" width="100" height="22" fill="#0B0F18"/>
        <text x="300" y="80" fontSize="18" fontWeight="900" fontFamily="Geist, sans-serif" fill={accent} textAnchor="middle">{car.no}</text>
        {[120, 480].map(x => <g key={x}><circle cx={x} cy="125" r="32" fill="#050810"/><circle cx={x} cy="125" r="20" fill="#1a1a1a"/><circle cx={x} cy="125" r="5" fill={accent}/></g>)}
      </g>
    );
  };

  return (
    <svg viewBox="0 0 1000 620" preserveAspectRatio="xMidYMid slice"
         style={{ position: "absolute", inset: 0, width: "100%", height: "100%", display: "block" }}>
      <defs>
        <linearGradient id={`sky-${cls}-${car.no}`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={skyTop}/>
          <stop offset="55%" stopColor={skyMid}/>
          <stop offset="100%" stopColor={horizon}/>
        </linearGradient>
        <radialGradient id={`glow-${cls}-${car.no}`} cx="50%" cy="78%" r="60%">
          <stop offset="0%" stopColor={`${accent}30`}/>
          <stop offset="100%" stopColor="transparent"/>
        </radialGradient>
      </defs>
      <rect width="1000" height="620" fill={`url(#sky-${cls}-${car.no})`}/>
      {/* distant hills */}
      <path d="M 0 360 L 120 320 L 220 350 L 340 300 L 460 340 L 600 310 L 740 360 L 880 330 L 1000 350 L 1000 460 L 0 460 Z" fill="#0E1A2A" opacity="0.85"/>
      <path d="M 0 400 L 160 380 L 300 410 L 440 370 L 600 400 L 760 380 L 900 410 L 1000 395 L 1000 470 L 0 470 Z" fill="#0A1422" opacity="0.9"/>
      {/* track tarmac */}
      <path d="M 0 470 L 1000 470 L 1000 540 L 0 540 Z" fill="#13161B"/>
      <path d="M 0 470 L 1000 470" stroke="#3a3f46" strokeWidth="1"/>
      {/* dashed centerline */}
      <line x1="0" y1="510" x2="1000" y2="510" stroke="#3a3f46" strokeWidth="1.5" strokeDasharray="22 18" opacity="0.7"/>
      {/* curb */}
      <g>
        {Array.from({length: 24}).map((_, i) => (
          <rect key={i} x={i*42} y="465" width="42" height="6" fill={i%2 ? "#C8102E" : "#E8E4DC"}/>
        ))}
      </g>
      {/* armco shadow */}
      <rect x="0" y="455" width="1000" height="3" fill="#5BB7E2" opacity="0.25"/>
      {/* ground glow */}
      <rect x="0" y="380" width="1000" height="240" fill={`url(#glow-${cls}-${car.no})`}/>
      {/* the car */}
      <g style={{ filter: "drop-shadow(0 14px 16px rgba(0,0,0,0.55))" }}>
        <Car/>
      </g>
      {/* speed streaks */}
      <g opacity="0.45" stroke={accent} strokeWidth="1.2">
        <line x1="40" y1="430" x2="160" y2="430"/>
        <line x1="60" y1="448" x2="200" y2="448"/>
        <line x1="20" y1="465" x2="120" y2="465"/>
        <line x1="820" y1="425" x2="960" y2="425"/>
        <line x1="780" y1="445" x2="940" y2="445"/>
      </g>
    </svg>
  );
}

window.ClassHeroScene = ClassHeroScene;
// Each car gets a different framing/zoom of the same hero shot so they feel distinct,
// tinted with the car's accent color and stamped with its number.
function PhotoCard({ car, label, onZoom, carClass }) {
  const cls = (carClass && carClass.id) || "open_wheel";
  const tint = car.livery.accent === "#FFFFFF" ? car.livery.primary : car.livery.accent;

  // Real photos available per class
  const REAL_PHOTOS = {
    open_wheel: "assets/photos/laguna-action-01.jpg",
    gt: "assets/photos/gt-action-01.png",
    stock: "assets/photos/stock-action-01.png",
    prototype: "assets/photos/prototype-action-01.png",
    e_spec: "assets/photos/espec-action-01.png",
  };
  const realPhoto = REAL_PHOTOS[cls];
  const useReal = !!realPhoto;

  // Per-car framing for open-wheel (real photo)
  const FRAMINGS_OW = {
    7:  { x: 58, y: 38, scale: 1.35 },
    22: { x: 22, y: 42, scale: 1.55 },
    11: { x: 12, y: 44, scale: 1.7 },
    4:  { x: 28, y: 44, scale: 1.5 },
    19: { x: 62, y: 36, scale: 1.25 },
    33: { x: 18, y: 46, scale: 1.65 },
    88: { x: 32, y: 42, scale: 1.45 },
    51: { x: 64, y: 40, scale: 1.3 },
    6:  { x: 26, y: 44, scale: 1.55 },
    14: { x: 14, y: 46, scale: 1.7 },
    9:  { x: 60, y: 38, scale: 1.35 },
    27: { x: 30, y: 44, scale: 1.5 },
  };
  // GT photo framings — different crops of the GT hero shot
  const FRAMINGS_GT = {
    7:  { x: 50, y: 50, scale: 1.15 },
    22: { x: 30, y: 52, scale: 1.4 },
    11: { x: 65, y: 48, scale: 1.3 },
    4:  { x: 45, y: 55, scale: 1.5 },
    19: { x: 25, y: 50, scale: 1.45 },
    33: { x: 55, y: 45, scale: 1.25 },
    88: { x: 40, y: 52, scale: 1.35 },
    51: { x: 60, y: 50, scale: 1.4 },
    6:  { x: 35, y: 55, scale: 1.5 },
    14: { x: 70, y: 48, scale: 1.3 },
    9:  { x: 50, y: 50, scale: 1.55 },
    27: { x: 45, y: 53, scale: 1.4 },
  };
  // Stock photo framings — different crops of the stock hero shot
  const FRAMINGS_STOCK = {
    7:  { x: 50, y: 55, scale: 1.2 },
    22: { x: 30, y: 58, scale: 1.4 },
    11: { x: 65, y: 52, scale: 1.3 },
    4:  { x: 45, y: 60, scale: 1.5 },
    19: { x: 25, y: 55, scale: 1.45 },
    33: { x: 55, y: 50, scale: 1.25 },
    88: { x: 40, y: 58, scale: 1.35 },
    51: { x: 60, y: 55, scale: 1.4 },
    6:  { x: 35, y: 60, scale: 1.5 },
    14: { x: 70, y: 52, scale: 1.3 },
    9:  { x: 50, y: 55, scale: 1.55 },
    27: { x: 45, y: 58, scale: 1.4 },
  };
  // Prototype photo framings
  const FRAMINGS_PROTO = {
    7:  { x: 50, y: 50, scale: 1.2 },
    22: { x: 35, y: 52, scale: 1.4 },
    11: { x: 60, y: 50, scale: 1.3 },
    4:  { x: 45, y: 55, scale: 1.5 },
    19: { x: 30, y: 50, scale: 1.45 },
    33: { x: 55, y: 48, scale: 1.25 },
    88: { x: 40, y: 52, scale: 1.35 },
    51: { x: 60, y: 50, scale: 1.4 },
    6:  { x: 38, y: 55, scale: 1.5 },
    14: { x: 65, y: 48, scale: 1.3 },
    9:  { x: 50, y: 52, scale: 1.55 },
    27: { x: 45, y: 53, scale: 1.4 },
  };
  // E-Spec photo framings — different crops of the e-spec hero shot
  const FRAMINGS_ESPEC = {
    7:  { x: 50, y: 60, scale: 1.2 },
    22: { x: 30, y: 55, scale: 1.4 },
    11: { x: 70, y: 55, scale: 1.3 },
    4:  { x: 50, y: 65, scale: 1.5 },
    19: { x: 25, y: 58, scale: 1.45 },
    33: { x: 60, y: 50, scale: 1.25 },
    88: { x: 40, y: 60, scale: 1.35 },
    51: { x: 65, y: 55, scale: 1.4 },
    6:  { x: 45, y: 65, scale: 1.5 },
    14: { x: 35, y: 50, scale: 1.3 },
    9:  { x: 55, y: 60, scale: 1.55 },
    27: { x: 50, y: 58, scale: 1.4 },
  };
  const framings = cls === "gt" ? FRAMINGS_GT
    : cls === "stock" ? FRAMINGS_STOCK
    : cls === "prototype" ? FRAMINGS_PROTO
    : cls === "e_spec" ? FRAMINGS_ESPEC
    : FRAMINGS_OW;
  const f = framings[car.no] || { x: 50, y: 50, scale: 1.3 };
  const photoMeta = cls === "open_wheel"
    ? "APEX MEDIA POOL · LAGUNA SECA"
    : cls === "gt"
      ? "APEX GT-X MEDIA POOL · ENDURANCE"
      : cls === "stock"
        ? "APEX STOCK MEDIA POOL · OVAL"
        : cls === "prototype"
          ? "APEX LMH MEDIA POOL · PADDOCK"
          : cls === "e_spec"
            ? "APEX E-SPEC MEDIA POOL · DOCKLANDS"
            : `APEX ${(carClass && carClass.short) || ""} · LIVERY RENDER`;

  return (
    <div className="photo-card photo-card-real" onClick={onZoom} role={onZoom ? "button" : undefined} tabIndex={onZoom ? 0 : undefined}>
      {useReal ? (
        <div
          className="photo-img"
          style={{
            backgroundImage: `url('${realPhoto}')`,
            backgroundPosition: `${f.x}% ${f.y}%`,
            backgroundSize: `${f.scale * 100}% auto`,
          }}
        />
      ) : (
        <window.ClassHeroScene car={car} carClass={carClass}/>
      )}
      <div className="photo-tint" style={{ background: `linear-gradient(135deg, ${tint}33 0%, transparent 40%, transparent 70%, ${car.livery.primary}55 100%)` }}/>
      <div className="photo-scanlines"/>
      <div className="photo-corner photo-corner-tl"/>
      <div className="photo-corner photo-corner-tr"/>
      <div className="photo-corner photo-corner-bl"/>
      <div className="photo-corner photo-corner-br"/>
      <div className="photo-stamp">
        <span className="photo-stamp-no" style={{ color: tint }}>#{String(car.no).padStart(2,"0")}</span>
        <span className="photo-stamp-team">{car.team}</span>
      </div>
      {onZoom && <div className="photo-zoom-hint">⤢ ZOOM</div>}
      <div className="photo-overlay">
        <span className="photo-label">{label}</span>
        <span className="photo-meta">{photoMeta}</span>
      </div>
    </div>
  );
}

// Fullscreen lightbox — click the photo or use the ZOOM button on the track
function PhotoLightbox({ car, onClose, carClass }) {
  useEffectP(() => {
    const onKey = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => { window.removeEventListener("keydown", onKey); document.body.style.overflow = ""; };
  }, [onClose]);
  if (!car) return null;
  const tint = car.livery.accent === "#FFFFFF" ? car.livery.primary : car.livery.accent;
  // Pick the right photo + per-car framing so the lightbox is a close-up of THIS car
  const cls = (carClass && carClass.id) || "open_wheel";
  const REAL_PHOTOS = {
    open_wheel: "assets/photos/laguna-action-01.jpg",
    gt: "assets/photos/gt-action-01.png",
    stock: "assets/photos/stock-action-01.png",
    prototype: "assets/photos/prototype-action-01.png",
    e_spec: "assets/photos/espec-action-01.png",
  };
  const realPhoto = REAL_PHOTOS[cls];
  // Reuse the same per-car framings PhotoCard uses, with extra zoom for the close-up
  const FRAMINGS_OW = {
    7: { x: 58, y: 38, scale: 1.35 }, 22: { x: 22, y: 42, scale: 1.55 },
    11: { x: 12, y: 44, scale: 1.7 }, 4: { x: 28, y: 44, scale: 1.5 },
    19: { x: 62, y: 36, scale: 1.25 }, 33: { x: 18, y: 46, scale: 1.65 },
    88: { x: 32, y: 42, scale: 1.45 }, 51: { x: 64, y: 40, scale: 1.3 },
    6: { x: 26, y: 44, scale: 1.55 }, 14: { x: 14, y: 46, scale: 1.7 },
    9: { x: 60, y: 38, scale: 1.35 }, 27: { x: 30, y: 44, scale: 1.5 },
  };
  const FRAMINGS_GT = {
    7: { x: 50, y: 50, scale: 1.15 }, 22: { x: 30, y: 52, scale: 1.4 },
    11: { x: 65, y: 48, scale: 1.3 }, 4: { x: 45, y: 55, scale: 1.5 },
    19: { x: 25, y: 50, scale: 1.45 }, 33: { x: 55, y: 45, scale: 1.25 },
    88: { x: 40, y: 52, scale: 1.35 }, 51: { x: 60, y: 50, scale: 1.4 },
    6: { x: 35, y: 55, scale: 1.5 }, 14: { x: 70, y: 48, scale: 1.3 },
    9: { x: 50, y: 50, scale: 1.55 }, 27: { x: 45, y: 53, scale: 1.4 },
  };
  const FRAMINGS_STOCK = {
    7: { x: 50, y: 55, scale: 1.2 }, 22: { x: 30, y: 58, scale: 1.4 },
    11: { x: 65, y: 52, scale: 1.3 }, 4: { x: 45, y: 60, scale: 1.5 },
    19: { x: 25, y: 55, scale: 1.45 }, 33: { x: 55, y: 50, scale: 1.25 },
    88: { x: 40, y: 58, scale: 1.35 }, 51: { x: 60, y: 55, scale: 1.4 },
    6: { x: 35, y: 60, scale: 1.5 }, 14: { x: 70, y: 52, scale: 1.3 },
    9: { x: 50, y: 55, scale: 1.55 }, 27: { x: 45, y: 58, scale: 1.4 },
  };
  const FRAMINGS_PROTO = {
    7: { x: 50, y: 50, scale: 1.2 }, 22: { x: 35, y: 52, scale: 1.4 },
    11: { x: 60, y: 50, scale: 1.3 }, 4: { x: 45, y: 55, scale: 1.5 },
    19: { x: 30, y: 50, scale: 1.45 }, 33: { x: 55, y: 48, scale: 1.25 },
    88: { x: 40, y: 52, scale: 1.35 }, 51: { x: 60, y: 50, scale: 1.4 },
    6: { x: 38, y: 55, scale: 1.5 }, 14: { x: 65, y: 48, scale: 1.3 },
    9: { x: 50, y: 52, scale: 1.55 }, 27: { x: 45, y: 53, scale: 1.4 },
  };
  const FRAMINGS_ESPEC = {
    7: { x: 50, y: 60, scale: 1.2 }, 22: { x: 30, y: 55, scale: 1.4 },
    11: { x: 70, y: 55, scale: 1.3 }, 4: { x: 50, y: 65, scale: 1.5 },
    19: { x: 25, y: 58, scale: 1.45 }, 33: { x: 60, y: 50, scale: 1.25 },
    88: { x: 40, y: 60, scale: 1.35 }, 51: { x: 65, y: 55, scale: 1.4 },
    6: { x: 45, y: 65, scale: 1.5 }, 14: { x: 35, y: 50, scale: 1.3 },
    9: { x: 55, y: 60, scale: 1.55 }, 27: { x: 50, y: 58, scale: 1.4 },
  };
  const framings = cls === "gt" ? FRAMINGS_GT
    : cls === "stock" ? FRAMINGS_STOCK
    : cls === "prototype" ? FRAMINGS_PROTO
    : cls === "e_spec" ? FRAMINGS_ESPEC
    : FRAMINGS_OW;
  const f = framings[car.no] || { x: 50, y: 50, scale: 1.3 };
  // Push in a touch further on top of cover for a true close-up of THIS car
  const closeUpScale = Math.max(1.1, f.scale * 0.95);
  return (
    <div className="lightbox" onClick={onClose}>
      <div className="lightbox-photo lightbox-photo-closeup" onClick={(e) => e.stopPropagation()}>
        {realPhoto ? (
          <div
            className={`lightbox-img lb-photo-${cls}`}
            style={{
              backgroundPosition: `${f.x}% ${f.y}%`,
              transform: `scale(${closeUpScale})`,
              transformOrigin: `${f.x}% ${f.y}%`,
            }}
            role="img"
            aria-label={`#${car.no} ${car.name} close-up`}
          />
        ) : (
          <div style={{ position: "absolute", inset: 0 }}>
            <window.ClassHeroScene car={car} carClass={carClass}/>
          </div>
        )}
        <div className="lightbox-tint" style={{ background: `linear-gradient(180deg, transparent 60%, rgba(0,0,0,0.8))` }}/>
        <div className="lightbox-corner lightbox-corner-tl" style={{ borderColor: tint }}/>
        <div className="lightbox-corner lightbox-corner-tr" style={{ borderColor: tint }}/>
        <div className="lightbox-corner lightbox-corner-bl" style={{ borderColor: tint }}/>
        <div className="lightbox-corner lightbox-corner-br" style={{ borderColor: tint }}/>
        <div className="lightbox-meta-tl">
          <div className="lightbox-eyebrow" style={{ color: tint }}>FOCUSED · POS {String(car.pos).padStart(2,"0")}</div>
          <div className="lightbox-no" style={{ color: tint }}>{String(car.no).padStart(2,"0")}</div>
          <div className="lightbox-driver">{car.name}</div>
          <div className="lightbox-team">{car.team} · {car.country}</div>
        </div>
        <div className="lightbox-meta-tr">
          <div className="lightbox-eyebrow">LAGUNA SECA · L{47}</div>
          <div className="lightbox-stat"><span>LAST</span><b>{car.last_lap}</b></div>
          <div className="lightbox-stat"><span>BEST</span><b>{car.best_lap}</b></div>
          <div className="lightbox-stat"><span>GAP</span><b>{car.gap}</b></div>
          <div className="lightbox-stat"><span>TYRE</span><b>{car.tire}<sub>{car.tire_age}</sub></b></div>
        </div>
        <div className="lightbox-caption">
          <span className="lightbox-cap-l">CAR #{car.no} · {car.name} · {car.team}</span>
          <span className="lightbox-cap-r">PRESS ESC OR CLICK TO CLOSE</span>
        </div>
      </div>
    </div>
  );
}

function FocusedCar({ car, onZoomPhoto }) {
  if (!car) return null;
  return (
    <div className="panel focus-panel">
      <div className="panel-head focus-head">
        <div>
          <div className="panel-eyebrow">FOCUSED CAR · POS {String(car.pos).padStart(2,"0")}</div>
          <div className="focus-no" style={{ color: car.livery.accent === "#FFFFFF" ? "#fff" : car.livery.accent }}>
            {String(car.no).padStart(2,"0")}
          </div>
        </div>
        <div className="focus-flag">
          <div className="focus-country">{car.country}</div>
          <div className="focus-driver">{car.name}</div>
          <div className="focus-team">{car.team}</div>
        </div>
      </div>

      <PhotoCard car={car} label={`#${car.no} · ${car.name.split(" ").slice(-1)[0]} · LAP ${47}`} onZoom={onZoomPhoto}/>

      <div className="focus-grid">
        <div>
          <div className="kv-label">CHASSIS</div>
          <div className="kv-val">{car.chassis}</div>
        </div>
        <div>
          <div className="kv-label">ENGINE</div>
          <div className="kv-val">{car.engine}</div>
        </div>
        <div>
          <div className="kv-label">CREW CHIEF</div>
          <div className="kv-val">{car.crew_chief}</div>
        </div>
        <div>
          <div className="kv-label">RACE ENGINEER</div>
          <div className="kv-val">{car.race_engineer}</div>
        </div>
      </div>

      <LiveryCard car={car}/>

      <div className="sponsors">
        <div className="kv-label">SPONSORS</div>
        <div className="sponsor-tier">
          <div className="tier-label">TITLE</div>
          <div className="tier-row"><span className="sponsor-chip sponsor-title">{car.sponsors.title}</span></div>
        </div>
        <div className="sponsor-tier">
          <div className="tier-label">PRIMARY</div>
          <div className="tier-row">
            {car.sponsors.primary.map((s,i) => <span key={i} className="sponsor-chip sponsor-primary">{s}</span>)}
          </div>
        </div>
        <div className="sponsor-tier">
          <div className="tier-label">SUPPORT</div>
          <div className="tier-row">
            {car.sponsors.support.map((s,i) => <span key={i} className="sponsor-chip">{s}</span>)}
          </div>
        </div>
      </div>
    </div>
  );
}

function Telemetry({ car, sample, carClass }) {
  if (!car) return null;
  const points = useMemoP(() => window.APEX_DATA.generateTelemetry(car.no), [car.no]);
  // Ghost: fastest car (#7 Voss) for comparison
  const ghostPoints = useMemoP(() => window.APEX_DATA.generateTelemetry(7), []);
  const idx = sample % 100;
  const [minSpd, maxSpd] = (carClass && carClass.speedRange) || [80, 310];

  // Animate sparkline reveal on car switch
  const [reveal, setReveal] = useStateP(0);
  useEffectP(() => {
    setReveal(0);
    let raf, start;
    const tick = (now) => {
      if (!start) start = now;
      const t = Math.min(1, (now - start) / 600);
      setReveal(t);
      if (t < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [car.no]);

  const W = 320, H = 80;
  const throttleD = points.map((p, i) => `${i===0?"M":"L"} ${(i/99)*W} ${H - (p.throttle/100)*H}`).join(" ");
  const brakeD    = points.map((p, i) => `${i===0?"M":"L"} ${(i/99)*W} ${H - (p.brake/100)*H}`).join(" ");
  const remapSpeed = (baseSpeed) => {
    const t = (baseSpeed - 80) / (310 - 80);
    return minSpd + t * (maxSpd - minSpd);
  };
  const speedNorm = (s) => H - ((s - minSpd) / (maxSpd - minSpd)) * H;
  const speedD    = points.map((p, i) => `${i===0?"M":"L"} ${(i/99)*W} ${speedNorm(remapSpeed(p.speed))}`).join(" ");
  const ghostD    = ghostPoints.map((p, i) => `${i===0?"M":"L"} ${(i/99)*W} ${speedNorm(remapSpeed(p.speed))}`).join(" ");

  const cur = points[idx];
  const ghost = ghostPoints[idx];
  const curSpeed = remapSpeed(cur.speed);
  const ghostSpeed = remapSpeed(ghost.speed);
  const speedDelta = curSpeed - ghostSpeed;

  // Fixed gear lookup: monotonic mapping from speed → gear (1..8)
  const gearFromSpeed = (s) => {
    const t = (s - minSpd) / (maxSpd - minSpd);
    if (t < 0.10) return 1;
    if (t < 0.20) return 2;
    if (t < 0.32) return 3;
    if (t < 0.46) return 4;
    if (t < 0.60) return 5;
    if (t < 0.74) return 6;
    if (t < 0.88) return 7;
    return 8;
  };
  const gear = gearFromSpeed(curSpeed);

  return (
    <div className="panel telemetry-panel">
      <div className="panel-head">
        <div className="panel-eyebrow">TELEMETRY · LIVE</div>
        <div className="panel-title">CAR #{car.no} · {car.name.split(" ").slice(-1)[0]}</div>
      </div>

      {/* Big speed + gear hero, with vertical T/B mini-meters */}
      <div className="telem-hero">
        <div className="telem-meters">
          <div className="telem-meter">
            <div className="telem-meter-l">T</div>
            <div className="telem-meter-bar">
              <div className="telem-meter-fill telem-fill-throttle" style={{ height: `${cur.throttle}%` }}/>
            </div>
            <div className="telem-meter-v">{Math.round(cur.throttle)}</div>
          </div>
          <div className="telem-meter">
            <div className="telem-meter-l">B</div>
            <div className="telem-meter-bar">
              <div className="telem-meter-fill telem-fill-brake" style={{ height: `${cur.brake}%` }}/>
            </div>
            <div className="telem-meter-v">{Math.round(cur.brake)}</div>
          </div>
        </div>
        <div className="telem-speedo">
          <div className="telem-stat-l">SPEED · KPH</div>
          <div className="telem-speedo-v">{Math.round(curSpeed)}</div>
          <div className={`telem-speed-delta ${speedDelta >= 0 ? "good" : "bad"}`}>
            {speedDelta >= 0 ? "+" : ""}{speedDelta.toFixed(0)} <small>vs VOSS</small>
          </div>
        </div>
        <div className="telem-gear">
          <div className="telem-stat-l">GEAR</div>
          <div className="telem-gear-v">{gear}</div>
          <div className="telem-gear-strip">
            {[1,2,3,4,5,6,7,8].map(n => (
              <span key={n} className={`telem-gear-pip ${n === gear ? "on" : n < gear ? "past" : ""}`}/>
            ))}
          </div>
        </div>
      </div>

      <div className="trace-wrap">
        <div className="trace-label">
          <span style={{color:"#7DC383"}}>THROTTLE</span>
          <span style={{color:"#C8102E"}}>BRAKE</span>
        </div>
        <svg viewBox={`0 0 ${W} ${H}`} className="trace-svg" preserveAspectRatio="none">
          <line x1="0" y1={H} x2={W} y2={H} stroke="#222" strokeWidth="1"/>
          <line x1="0" y1="0" x2={W} y2="0" stroke="#222" strokeWidth="1"/>
          <path d={throttleD} fill="none" stroke="#7DC383" strokeWidth="1.4"
            pathLength="1" strokeDasharray="1" strokeDashoffset={1 - reveal}/>
          <path d={brakeD}    fill="none" stroke="#C8102E" strokeWidth="1.4"
            pathLength="1" strokeDasharray="1" strokeDashoffset={1 - reveal}/>
          <line x1={(idx/99)*W} y1="0" x2={(idx/99)*W} y2={H} stroke="#fff" strokeWidth="0.8" opacity="0.6"/>
        </svg>
      </div>

      <div className="trace-wrap">
        <div className="trace-label">
          <span style={{color:"#5BB7E2"}}>SPEED · KPH</span>
          <span style={{color:"rgba(232,228,220,0.4)"}}>GHOST · #07 VOSS</span>
        </div>
        <svg viewBox={`0 0 ${W} ${H}`} className="trace-svg" preserveAspectRatio="none">
          <line x1="0" y1={H} x2={W} y2={H} stroke="#222" strokeWidth="1"/>
          <line x1="0" y1="0" x2={W} y2="0" stroke="#222" strokeWidth="1"/>
          {car.no !== 7 && (
            <path d={ghostD} fill="none" stroke="rgba(232,228,220,0.32)" strokeWidth="1"
              strokeDasharray="2 2"
              pathLength="1"/>
          )}
          <path d={speedD} fill="none" stroke="#5BB7E2" strokeWidth="1.4"
            pathLength="1" strokeDasharray="1" strokeDashoffset={1 - reveal}/>
          <line x1={(idx/99)*W} y1="0" x2={(idx/99)*W} y2={H} stroke="#fff" strokeWidth="0.8" opacity="0.6"/>
        </svg>
      </div>

      <div className="sectors-row">
        {car.sectors.map((s,i) => (
          <div key={i} className={`sector sector-${s.state}`}>
            <span className="sector-l">{s.s}</span>
            <span className="sector-t">{s.t}</span>
          </div>
        ))}
      </div>

      <div className="delta-row">
        <span className="kv-label">Δ TO LEADER</span>
        <span className="delta-val">{car.gap === "LEADER" ? "—" : car.gap}</span>
        <span className="kv-label">BEST</span>
        <span className="delta-val">{car.best_lap}</span>
      </div>
    </div>
  );
}

function StrategyPanel({ car, carClass }) {
  if (!car) return null;
  const tankKg = (carClass && carClass.tank_kg) || 60;
  const cliffLap = (carClass && carClass.tyre_cliff_lap) || 65;
  const burn = (carClass && carClass.fuel_kg_per_lap) || 0.45;
  const isElectric = carClass && carClass.id === "e_spec";
  const fuelPct = isElectric ? car.fuel : (car.fuel / tankKg) * 100;
  const tireWear = Math.min(100, (car.tire_age / cliffLap) * 100);
  const lapsLeft = isElectric ? Math.round(car.fuel * 0.5) : Math.round(car.fuel / burn);
  return (
    <div className="panel strategy-panel">
      <div className="panel-head">
        <div className="panel-eyebrow">STRATEGY · #{car.no}{carClass ? ` · ${carClass.short}` : ""}</div>
      </div>
      <div className="strat-grid">
        <div className="strat-cell">
          <div className="kv-label">{isElectric ? "ENERGY" : "FUEL"}</div>
          <div className="strat-bar">
            <div className="strat-bar-fill" style={{ width: `${fuelPct}%`, background: isElectric ? "#3DD68C" : "#5BB7E2" }}/>
          </div>
          <div className="strat-num">{isElectric ? `${Math.round(car.fuel)}%` : `${car.fuel.toFixed(1)} kg`} <small>~{lapsLeft} laps</small></div>
        </div>
        <div className="strat-cell">
          <div className="kv-label">TYRE WEAR · {car.tire}</div>
          <div className="strat-bar">
            <div className="strat-bar-fill" style={{ width: `${tireWear}%`, background: tireWear > 70 ? "#C8102E" : tireWear > 45 ? "#C9A24A" : "#7DC383" }}/>
          </div>
          <div className="strat-num">{car.tire_age} <small>laps · cliff @ ~{cliffLap}</small></div>
        </div>
        <div className="strat-cell strat-window">
          <div className="kv-label">{isElectric ? "ATTACK MODE" : "PIT WINDOW"}</div>
          <div className="strat-num">{isElectric ? "ARMED" : "L52"} {!isElectric && <span className="hud-of">→ L58</span>}</div>
          <div className="strat-sub">{isElectric ? `4× 35kW BOOST AVAIL.` : `UNDERCUT THREAT: P${car.pos+1}`}</div>
        </div>
      </div>
    </div>
  );
}

function PitLog() {
  const log = window.APEX_DATA.PIT_LOG;
  return (
    <div className="panel pit-panel">
      <div className="panel-head">
        <div className="panel-eyebrow">PIT REPLAY · LAST 6</div>
      </div>
      <div className="pit-list">
        {log.map((p, i) => (
          <div key={i} className="pit-row">
            <span className="pit-lap">L{p.lap}</span>
            <span className="pit-no">#{p.no}</span>
            <span className="pit-team">{p.team}</span>
            <span className="pit-action">{p.action}</span>
            <span className={`pit-dur ${p.duration < 2.45 ? "good" : p.duration > 2.55 ? "bad" : ""}`}>{p.duration.toFixed(2)}s</span>
            <span className="pit-notes">{p.notes}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

function TopBar({ track, trackEvent, trackId, onTrackChange, raceState, classId, onClassChange }) {
  const [open, setOpen] = React.useState(false);
  const [classOpen, setClassOpen] = React.useState(false);
  const carClass = window.CAR_CLASSES[classId];
  const w = track.weather;
  return (
    <div className="topbar">
      <div className="topbar-left">
        <div className="brand">
          <span className="brand-mark">▲</span>
          <span className="brand-name">APEX</span>
          <span className="brand-tag">SERIES · COMPANION</span>
        </div>
        <div className="topbar-divider"/>
        <div className="topbar-event">
          <div className="event-eyebrow">{trackEvent.round} · {trackEvent.date}</div>
          <div className="event-title">{trackEvent.event}</div>
        </div>
        <div className="topbar-divider"/>
        <div className="track-selector-wrap">
          <button className="track-selector class-selector" onClick={() => setClassOpen(o => !o)} aria-haspopup="listbox" aria-expanded={classOpen}>
            <div className="ts-eyebrow">CAR CLASS</div>
            <div className="ts-row">
              <span className="cls-icon" style={{ color: carClass.accent }}>
                <svg viewBox="0 0 48 32" width="36" height="22"><g>{carClass.icon}</g></svg>
              </span>
              <span className="ts-name">{carClass.name}</span>
              <svg className={classOpen?"ts-caret ts-caret-up":"ts-caret"} viewBox="0 0 12 12" width="10" height="10">
                <path d="M 2 4 L 6 8 L 10 4" stroke="currentColor" strokeWidth="1.5" fill="none" strokeLinecap="round"/>
              </svg>
            </div>
          </button>
          {classOpen && (
            <div className="track-menu track-menu-classes" role="listbox">
              <div className="track-menu-head">SELECT CLASS · {window.CAR_CLASS_LIST.length}</div>
              {window.CAR_CLASS_LIST.map(id => {
                const c = window.CAR_CLASSES[id];
                const active = id === classId;
                return (
                  <button
                    key={id}
                    className={active ? "track-menu-item class-menu-item active" : "track-menu-item class-menu-item"}
                    onClick={() => { onClassChange(id); setClassOpen(false); }}
                    role="option"
                    aria-selected={active}>
                    <div className="tmi-mini cls-mini" style={{ color: active ? c.accent : "rgba(232,228,220,0.6)" }}>
                      <svg viewBox="0 0 48 32" preserveAspectRatio="xMidYMid meet"><g>{c.icon}</g></svg>
                    </div>
                    <div className="tmi-info">
                      <div className="tmi-name">{c.name}</div>
                      <div className="tmi-meta">{c.eyebrow}</div>
                      <div className="tmi-event" style={{ color: active ? c.accent : "rgba(232,228,220,0.55)" }}>{c.tagline}</div>
                    </div>
                    {active && <span className="tmi-tick" style={{ color: c.accent }}>●</span>}
                  </button>
                );
              })}
            </div>
          )}
        </div>
        <div className="topbar-divider"/>
        <div className="track-selector-wrap">
          <button className="track-selector" onClick={() => setOpen(o => !o)} aria-haspopup="listbox" aria-expanded={open}>
            <div className="ts-eyebrow">CIRCUIT</div>
            <div className="ts-row">
              <span className="ts-name">{track.short}</span>
              <span className="ts-country">{track.country}</span>
              <svg className={open?"ts-caret ts-caret-up":"ts-caret"} viewBox="0 0 12 12" width="10" height="10">
                <path d="M 2 4 L 6 8 L 10 4" stroke="currentColor" strokeWidth="1.5" fill="none" strokeLinecap="round"/>
              </svg>
            </div>
          </button>
          {open && (
            <div className="track-menu track-menu-tracks" role="listbox">
              <div className="track-menu-head">SELECT CIRCUIT · {window.TRACK_LIST.length}</div>
              {window.TRACK_LIST.map(id => {
                const t = window.TRACKS[id];
                const ev = window.TRACK_EVENTS[id];
                const active = id === trackId;
                return (
                  <button
                    key={id}
                    className={active ? "track-menu-item active" : "track-menu-item"}
                    onClick={() => { onTrackChange(id); setOpen(false); }}
                    role="option"
                    aria-selected={active}>
                    <div className="tmi-mini">
                      <svg viewBox="0 0 1000 560" preserveAspectRatio="xMidYMid meet">
                        <path d={t.path} fill="none" stroke={active ? "#5BB7E2" : "rgba(232,228,220,0.5)"} strokeWidth="6" strokeLinecap="round" strokeLinejoin="round"/>
                      </svg>
                    </div>
                    <div className="tmi-info">
                      <div className="tmi-name">{t.short}</div>
                      <div className="tmi-meta">{t.country} · {t.length_mi.toFixed(2)} MI · {t.turns_count} TURNS</div>
                      <div className="tmi-event">{ev.round} · {ev.event}</div>
                    </div>
                    {active && <span className="tmi-tick">●</span>}
                  </button>
                );
              })}
            </div>
          )}
        </div>
      </div>
      <div className="topbar-right">
        <div className="weather">
          <span className="kv-label">AIR</span><span className="kv-val">{w.air_c}°</span>
          <span className="kv-label">TRACK</span><span className="kv-val">{w.track_c}°</span>
          <span className="kv-label">WIND</span><span className="kv-val">{w.wind_kph} kph</span>
          <span className="kv-label">COND</span><span className="kv-val">{w.condition}</span>
        </div>
        <div className="fastest">
          <span className="kv-label">FASTEST LAP</span>
          <span className="kv-val">{raceState.fastest_lap.time}</span>
          <span className="kv-sub">#{raceState.fastest_lap.car} {raceState.fastest_lap.driver} · L{raceState.fastest_lap.lap}</span>
        </div>
      </div>
    </div>
  );
}

// Stylized helmet portrait — driver "photo" rendered as a livery-painted helmet
function HelmetPortrait({ car, size = 200 }) {
  const h = car.helmet || { primary: car.livery.primary, secondary: car.livery.secondary, visor: "#0B0B0B" };
  const id = `helm-${car.no}`;
  return (
    <svg viewBox="0 0 200 200" width={size} height={size} className="helmet-svg" aria-label={`${car.name} helmet`}>
      <defs>
        <radialGradient id={`${id}-light`} cx="35%" cy="25%" r="65%">
          <stop offset="0%" stopColor="rgba(255,255,255,0.35)"/>
          <stop offset="60%" stopColor="rgba(255,255,255,0.05)"/>
          <stop offset="100%" stopColor="rgba(0,0,0,0.45)"/>
        </radialGradient>
        <linearGradient id={`${id}-visor`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="rgba(255,255,255,0.45)"/>
          <stop offset="40%" stopColor={h.visor}/>
          <stop offset="100%" stopColor="rgba(0,0,0,0.95)"/>
        </linearGradient>
        <clipPath id={`${id}-clip`}>
          <path d="M 40 95 C 40 50, 75 30, 100 30 C 125 30, 160 50, 160 95 L 160 130 C 160 152, 145 160, 125 160 L 75 160 C 55 160, 40 152, 40 130 Z"/>
        </clipPath>
      </defs>
      {/* Backing frame */}
      <rect width="200" height="200" fill="#04060A"/>
      {/* Cross-hairs */}
      <g stroke="rgba(91,183,226,0.18)" strokeWidth="0.5">
        <line x1="0" y1="100" x2="200" y2="100"/>
        <line x1="100" y1="0" x2="100" y2="200"/>
      </g>
      {/* Helmet shell */}
      <g clipPath={`url(#${id}-clip)`}>
        <rect width="200" height="200" fill={h.primary}/>
        {/* livery stripe */}
        <rect x="0" y="58" width="200" height="14" fill={h.secondary}/>
        <rect x="0" y="76" width="200" height="3" fill={car.livery.accent}/>
        {/* number on side */}
        <text x="160" y="135" fontSize="34" fontWeight="900" fontFamily="Geist, sans-serif"
          fill={h.secondary} textAnchor="end" letterSpacing="-1">{car.no}</text>
      </g>
      {/* Visor cutout */}
      <path d="M 58 80 C 58 70, 70 64, 100 64 C 130 64, 142 70, 142 80 L 142 100 C 142 108, 130 112, 100 112 C 70 112, 58 108, 58 100 Z"
        fill={`url(#${id}-visor)`} stroke="rgba(0,0,0,0.5)" strokeWidth="1"/>
      {/* Helmet outline */}
      <path d="M 40 95 C 40 50, 75 30, 100 30 C 125 30, 160 50, 160 95 L 160 130 C 160 152, 145 160, 125 160 L 75 160 C 55 160, 40 152, 40 130 Z"
        fill="none" stroke="rgba(0,0,0,0.7)" strokeWidth="1"/>
      {/* Light overlay */}
      <path d="M 40 95 C 40 50, 75 30, 100 30 C 125 30, 160 50, 160 95 L 160 130 C 160 152, 145 160, 125 160 L 75 160 C 55 160, 40 152, 40 130 Z"
        fill={`url(#${id}-light)`}/>
    </svg>
  );
}

// Stylized crew portrait — silhouette with team color
function CrewPortrait({ name, accent, kind, size = 88 }) {
  const id = `crew-${name.replace(/\s+/g, "-")}`;
  return (
    <svg viewBox="0 0 100 100" width={size} height={size} className="crew-svg">
      <defs>
        <linearGradient id={`${id}-bg`} x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#0C0F14"/>
          <stop offset="100%" stopColor="#04060A"/>
        </linearGradient>
      </defs>
      <rect width="100" height="100" fill={`url(#${id}-bg)`}/>
      <g stroke="rgba(91,183,226,0.12)" strokeWidth="0.4">
        <line x1="0" y1="50" x2="100" y2="50"/>
        <line x1="50" y1="0" x2="50" y2="100"/>
      </g>
      {/* shoulder */}
      <path d="M 8 100 C 12 78, 30 70, 50 70 C 70 70, 88 78, 92 100 Z" fill={accent} opacity="0.85"/>
      {/* head silhouette */}
      <circle cx="50" cy="45" r="18" fill="#E8E4DC" opacity="0.92"/>
      {/* cap shadow */}
      {kind === "chief" && (
        <path d="M 32 38 C 36 28, 64 28, 68 38 L 70 42 L 30 42 Z" fill="#0B0B0B"/>
      )}
      {kind === "engineer" && (
        <g>
          {/* headset band */}
          <path d="M 34 32 C 40 22, 60 22, 66 32" fill="none" stroke="#0B0B0B" strokeWidth="2.5"/>
          <circle cx="33" cy="44" r="3" fill="#0B0B0B"/>
        </g>
      )}
      {/* Subtle frame */}
      <rect x="0.5" y="0.5" width="99" height="99" fill="none" stroke="rgba(91,183,226,0.25)" strokeWidth="1"/>
    </svg>
  );
}

// Driver tab — the cockpit experience. POV up top, then live driver-load metrics
// (heart rate, g-force, brake pressure) derived from telemetry, then radio handle
// + signature line, with full bio/crew tucked into a collapsible ABOUT section.
function DriverProfile({ car, onZoomPhoto, carClass, cars, track, raceProgress, sample }) {
  if (!car) return null;
  const [aboutOpen, setAboutOpen] = useStateP(false);
  const accent = car.livery.accent === "#FFFFFF" ? car.livery.primary : car.livery.accent;

  // Pull live telemetry sample so the load metrics tick with the rest of the app.
  const tele = useMemoP(() => window.APEX_DATA.generateTelemetry(car.no), [car.no]);
  const cur = tele.length ? tele[sample % 100] : { speed: 0, throttle: 0, brake: 0 };
  const [minSpd, maxSpd] = (carClass && carClass.speedRange) || [80, 310];
  const speedKph = Math.round(minSpd + ((cur.speed - 80) / (310 - 80)) * (maxSpd - minSpd));

  // Estimated lateral g — peaks during corners (low throttle + some brake or coast).
  // Scale: 0..5g typical for open-wheel. We approximate cornering load from how
  // far speed has dropped below max (i.e. driver is committed to a corner).
  const speedRatio = Math.min(1, Math.max(0, (cur.speed - 80) / (310 - 80)));
  const cornerLoad = Math.max(0, 1 - speedRatio) * (cur.throttle < 60 ? 1 : 0.4);
  const gLateral = (1.2 + cornerLoad * 3.6).toFixed(1); // 1.2g cruising → ~4.8g peak
  const gLong = (cur.brake / 100 * 4.5 + cur.throttle / 100 * 1.6).toFixed(1);

  // Estimated heart rate: ~145 baseline, climbs with brake intensity & corner load.
  // Real APEX/F1 drivers run 160-190bpm during a stint.
  const hr = Math.round(148 + cur.brake * 0.28 + cornerLoad * 22);

  // Steering input — rough proxy: high during corners, low on straights.
  const steerDeg = Math.round(cornerLoad * 110 + (cur.brake > 40 ? 18 : 0));

  // Famous corner notes lifted from track data — the visceral driver intelligence.
  const corkscrewNote = "5.5-storey blind drop. Brake on the dirt patch.";
  const handleMatch = car.bio && car.bio.match(/known on the radio as ['"]([^'"]+)['"]/i);
  const radioHandle = handleMatch ? handleMatch[1] : null;

  // Pull a single visceral sentence out of the bio for the headline quote.
  const bioSentences = car.bio ? car.bio.split(/(?<=[.!?])\s+/) : [];
  const signatureLine = bioSentences.find(s => /aggressive|smooth|cool|surgical|methodical|brilliant|fastest|famous|wins|cult|quiet/i.test(s)) || bioSentences[1] || bioSentences[0] || "";

  return (
    <div className="panel driver-panel">
      <div className="panel-head">
        <div className="panel-eyebrow" style={{color: accent}}>IN THE COCKPIT · #{car.no}</div>
        <div className="panel-title">{car.name}</div>
        <div className="dr-team-line" style={{color: "var(--muted)"}}>{car.team} · {car.country} · AGE {car.age}</div>
      </div>

      {/* Big POV view — fan's window into the driver's perspective */}
      {window.DriverView && (
        <div className="dr-pov-wrap">
          <window.DriverView car={car} track={track} cars={cars} raceProgress={raceProgress} sample={sample} carClass={carClass}/>
        </div>
      )}

      {/* Driver load — the physical demand right now */}
      <div className="dr-section">
        <div className="kv-label">DRIVER LOAD · LIVE</div>
        <div className="dr-load-grid">
          <DrLoadStat label="HEART RATE" value={hr} unit="BPM" max={200} fillColor="#C8102E" pulse/>
          <DrLoadStat label="LATERAL G" value={gLateral} unit="g" max={5} fillColor={accent}/>
          <DrLoadStat label="LONG. G" value={gLong} unit="g" max={5} fillColor="#5BB7E2"/>
          <DrLoadStat label="STEERING" value={steerDeg} unit="°" max={140} fillColor="#7DC383"/>
        </div>
      </div>

      {/* Radio handle + signature line — what announcers say about them */}
      <div className="dr-section dr-quote-block" style={{borderColor: `${accent}40`}}>
        {radioHandle && (
          <div className="dr-handle">
            <span className="kv-label">RADIO HANDLE</span>
            <span className="dr-handle-v" style={{color: accent}}>“{radioHandle}”</span>
          </div>
        )}
        <p className="dr-signature">{signatureLine}</p>
      </div>

      {/* Corkscrew driver notes — Laguna-specific */}
      {track.id === "laguna_seca" && (
        <div className="dr-section dr-corner-card">
          <div className="kv-label" style={{color: accent}}>SIGNATURE CORNER · TURN 8</div>
          <div className="dr-corner-name">THE CORKSCREW</div>
          <p className="dr-corner-note">{corkscrewNote}</p>
          <div className="dr-corner-meta">
            <div><span className="kv-label">APPROACH</span><b>~210 KPH</b></div>
            <div><span className="kv-label">EXIT</span><b>~95 KPH</b></div>
            <div><span className="kv-label">DROP</span><b>17.5 M</b></div>
          </div>
        </div>
      )}

      {/* About — collapsed by default to keep the experience focused */}
      <button
        className="dr-about-toggle"
        onClick={() => setAboutOpen(v => !v)}
        aria-expanded={aboutOpen}>
        <span className="kv-label" style={{color: aboutOpen ? accent : "var(--muted)"}}>
          {aboutOpen ? "▾ HIDE BIOGRAPHY" : "▸ ABOUT THE DRIVER & CREW"}
        </span>
      </button>

      {aboutOpen && (
        <div className="dr-about">
          <div className="driver-hero" style={{marginTop: 10}}>
            <div className="driver-portrait">
              <window.HelmetPortrait car={car} size={140}/>
              <div className="driver-portrait-frame"/>
            </div>
            <div className="driver-meta">
              <div className="kv-label">BIO</div>
              <p className="dr-bio">{car.bio}</p>
            </div>
          </div>

          <div className="crew-block">
            <div className="kv-label" style={{marginBottom: 8}}>CREW</div>
            <div className="crew-row">
              <window.CrewPortrait name={car.crew_chief} accent={accent} kind="chief"/>
              <div className="crew-info">
                <div className="crew-role">CREW CHIEF</div>
                <div className="crew-name">{car.crew_chief}</div>
                <div className="crew-bio">{car.crew_chief_bio}</div>
              </div>
            </div>
            <div className="crew-row">
              <window.CrewPortrait name={car.race_engineer} accent={accent} kind="engineer"/>
              <div className="crew-info">
                <div className="crew-role">RACE ENGINEER</div>
                <div className="crew-name">{car.race_engineer}</div>
                <div className="crew-bio">{car.race_engineer_bio}</div>
              </div>
            </div>
          </div>

          <div className="focus-grid">
            <div><div className="kv-label">CHASSIS</div><div className="kv-val">{car.chassis}</div></div>
            <div><div className="kv-label">ENGINE</div><div className="kv-val">{car.engine}</div></div>
          </div>
          <window.LiveryCard car={car}/>
        </div>
      )}
    </div>
  );
}

// Compact bar-stat for driver load metrics
function DrLoadStat({ label, value, unit, max, fillColor, pulse }) {
  const pct = Math.min(100, (parseFloat(value) / max) * 100);
  return (
    <div className="dr-load-stat">
      <div className="kv-label">{label}</div>
      <div className="dr-load-row">
        <div className={`dr-load-v ${pulse ? "dr-load-pulse" : ""}`}>
          {value}<span className="dr-load-unit">{unit}</span>
        </div>
      </div>
      <div className="dr-load-bar">
        <div className="dr-load-fill" style={{width: `${pct}%`, background: fillColor}}/>
      </div>
    </div>
  );
}

Object.assign(window, { Leaderboard, FocusedCar, Telemetry, StrategyPanel, PitLog, TopBar, LiveryCard, PhotoCard, PhotoLightbox, DriverProfile, HelmetPortrait, CrewPortrait });
