/* eslint-disable */
/* CarExplorer — interactive 3D car overview.
   - Procedural low-poly car built in three.js
   - HTML overlay markers track 3D zone positions every frame
   - Click marker → camera tweens to zoomed close-up + side panel slides in
   - Side panel lists all parts in that category (each with a mini 3D thumb) */

const { useState: useState_c, useEffect: useEffect_c, useRef: useRef_c, useMemo: useMemo_c } = React;

// World coords: +x = front (hood), -x = rear (tailpipe), +z = visible side (3/4 view), +y = up
const CAR_ZONES = [
  { id: "lighting",   label: "Lighting",   category: "Bulbs / lighting",                  num: 1, pos: [1.65, 0.20,  0.42], cam: [3.6, 1.4,  2.0], target: [1.4, 0.0, 0.4] },
  { id: "wipers",     label: "Wipers",     category: "Wiper & screenwash items",          num: 2, pos: [0.55, 0.85,  0.20], cam: [2.0, 2.4,  1.8], target: [0.4, 0.7, 0.0] },
  { id: "oilfilter",  label: "Oil & filters", category: "Oil & filters",                  num: 3, pos: [0.95, 0.50, -0.20], cam: [2.2, 1.8,  2.0], target: [0.8, 0.3, 0.0] },
  { id: "belts",      label: "Belts",      category: "Belts & pulleys",                   num: 4, pos: [0.55, 0.55,  0.45], cam: [1.6, 1.8,  2.2], target: [0.4, 0.3, 0.3] },
  { id: "ignition",   label: "Ignition",   category: "Ignition/service ignition parts",   num: 5, pos: [0.20, 0.45,  0.00], cam: [1.6, 1.6,  2.4], target: [0.1, 0.2, 0.0] },
  { id: "batteries",  label: "Batteries",  category: "Batteries",                         num: 6, pos: [0.40, 0.40, -0.45], cam: [2.0, 1.6, -2.0], target: [0.3, 0.2, -0.4] },
  { id: "brakes",     label: "Brakes",     category: "Brake parts",                       num: 7, pos: [1.05,-0.25,  0.78], cam: [2.6, 0.8,  2.3], target: [1.0,-0.2, 0.7] },
  { id: "tyres",      label: "Tyres",      category: "Tyres",                             num: 8, pos: [-1.00,-0.25, 0.85], cam: [-2.2, 0.7, 2.5], target: [-1.0,-0.2, 0.7] },
  { id: "suspension", label: "Suspension", category: "Suspension parts",                  num: 9, pos: [0.05,-0.20,  0.62], cam: [0.4, 0.4,  2.7], target: [0.0,-0.1, 0.6] },
  { id: "exhaust",    label: "Exhaust",    category: "Exhaust / emissions parts",         num:10, pos: [-1.70,-0.15, 0.30], cam: [-3.0, 0.6, 1.6], target: [-1.6,-0.1, 0.2] },
];

const DEFAULT_CAM    = [4.2, 2.4, 4.4];
const DEFAULT_TARGET = [0, 0.1, 0];

function easeOutCubic(t) { return 1 - Math.pow(1 - t, 3); }
function round3(n) { return Math.round(n * 1000) / 1000; }

// Deep-clone helper so mutations to zonesRef don't mutate the source constant.
function _cloneZones() {
  return CAR_ZONES.map(z => ({ ...z, pos: [...z.pos], cam: [...z.cam], target: [...z.target] }));
}

function CarExplorer({ navigate, shop, openQuickView }) {
  const stageRef = useRef_c(null);
  const markersRef = useRef_c(null);
  const threeRef = useRef_c({});  // holds scene/camera/renderer/raf
  const [activeId, setActiveId] = useState_c(null);
  const [hoverId, setHoverId] = useState_c(null);
  const [ready, setReady] = useState_c(false);
  const [modelLoaded, setModelLoaded] = useState_c(false);
  const [loadProgress, setLoadProgress] = useState_c(0);
  const [loadError, setLoadError] = useState_c(null);

  // Alignment tool state
  const zonesRef = useRef_c(_cloneZones());
  const [zonesV, setZonesV] = useState_c(0);
  const bumpZones = () => setZonesV(v => v + 1);
  const [alignOpen, setAlignOpen] = useState_c(false);
  const [alignZoneIdx, setAlignZoneIdx] = useState_c(0);
  const [pickMode, setPickMode] = useState_c(null);   // null | 'pos'
  const [copyToast, setCopyToast] = useState_c(false);
  // Mirror state into refs for closure access inside the long-lived setup effect.
  const pickModeRef = useRef_c(null);
  const alignZoneIdxRef = useRef_c(0);
  useEffect_c(() => { pickModeRef.current = pickMode; }, [pickMode]);
  useEffect_c(() => { alignZoneIdxRef.current = alignZoneIdx; }, [alignZoneIdx]);

  const activeZone = useMemo_c(() => zonesRef.current.find(z => z.id === activeId), [activeId, zonesV]);

  // ---------- Setup three.js scene ----------
  useEffect_c(() => {
    const container = stageRef.current;
    if (!container || !window.THREE) return;
    const THREE = window.THREE;
    const w = Math.max(200, container.clientWidth);
    const h = Math.max(200, container.clientHeight);

    const scene = new THREE.Scene();
    scene.background = null;

    const camera = new THREE.PerspectiveCamera(35, w / h, 0.1, 200);
    camera.position.set(...DEFAULT_CAM);
    camera.lookAt(...DEFAULT_TARGET);

    const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
    renderer.setSize(w, h);
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    renderer.toneMapping = THREE.ACESFilmicToneMapping;
    renderer.toneMappingExposure = 1.05;
    if ("outputColorSpace" in renderer && THREE.SRGBColorSpace) renderer.outputColorSpace = THREE.SRGBColorSpace;
    else if ("outputEncoding" in renderer && THREE.sRGBEncoding) renderer.outputEncoding = THREE.sRGBEncoding;
    if ("physicallyCorrectLights" in renderer) renderer.physicallyCorrectLights = true;
    container.appendChild(renderer.domElement);

    // Environment map — PBR reflections off the body panels.
    if (typeof THREE.RoomEnvironment === "function" && typeof THREE.PMREMGenerator === "function") {
      const pmrem = new THREE.PMREMGenerator(renderer);
      pmrem.compileEquirectangularShader && pmrem.compileEquirectangularShader();
      scene.environment = pmrem.fromScene(new THREE.RoomEnvironment(renderer), 0.04).texture;
      pmrem.dispose();
    }

    // Lighting — studio rig: hemisphere ambient + three-point + warm bounce.
    const hemi = new THREE.HemisphereLight(0xeaf1ff, 0x2a2418, 0.85);
    hemi.position.set(0, 8, 0);
    scene.add(hemi);

    const key = new THREE.DirectionalLight(0xfff4e0, 3.4);
    key.position.set(5.5, 8, 6);
    scene.add(key);

    const fill = new THREE.DirectionalLight(0xb6cfff, 0.9);
    fill.position.set(-6, 4, 5);
    scene.add(fill);

    const rim = new THREE.DirectionalLight(0xffd0a8, 2.4);
    rim.position.set(-4, 5, -8);
    scene.add(rim);

    // Subtle warm bounce from below (sim ground reflection into the chassis).
    const bounce = new THREE.DirectionalLight(0xffd9b8, 0.35);
    bounce.position.set(0, -2.5, 4);
    scene.add(bounce);

    // ---------- Car group (FBX loads into this) ----------
    const carGroup = new THREE.Group();
    scene.add(carGroup);

    // Load Skoda Superb FBX. The model is normalized into the same coord box
    // the procedural car used so existing CAR_ZONES coordinates stay valid:
    //   length ~3.4 (x: -1.7..+1.7), ground plane at y = -0.65, front along +x.
    const TARGET_LENGTH = 3.4;
    const GROUND_Y = -0.65;
    if (typeof THREE.FBXLoader === "function") {
      const loader = new THREE.FBXLoader();
      loader.load(
        encodeURI("models/Skoda Superb.fbx"),
        (object) => {
          // Some FBX exports have non-PBR materials and very high emissive — soften.
          object.traverse((child) => {
            if (child.isMesh) {
              const mats = Array.isArray(child.material) ? child.material : [child.material];
              mats.forEach((m) => {
                if (!m) return;
                if ("emissive" in m && m.emissive && m.emissiveIntensity === undefined) m.emissiveIntensity = 0.0;
                if ("metalness" in m && m.metalness === undefined) m.metalness = 0.35;
                if ("roughness" in m && m.roughness === undefined) m.roughness = 0.55;
                m.side = THREE.FrontSide;
                m.needsUpdate = true;
              });
            }
          });

          // Bounding-box normalize: scale longest horizontal axis to TARGET_LENGTH,
          // then translate so the model is centered on origin (XZ) and sits on GROUND_Y.
          const box0 = new THREE.Box3().setFromObject(object);
          const size0 = box0.getSize(new THREE.Vector3());
          // FBX from automotive sources is usually Y-up; longer of x/z is the wheelbase axis.
          const longAxisLen = Math.max(size0.x, size0.z);
          const scale = TARGET_LENGTH / longAxisLen;
          object.scale.setScalar(scale);

          // If the car's long axis is Z (front along +Z), rotate -90° around Y to put it on +X.
          if (size0.z > size0.x) {
            object.rotation.y = -Math.PI / 2;
          }

          // Recompute bbox after scale + rotation, then recenter.
          const box1 = new THREE.Box3().setFromObject(object);
          const center1 = box1.getCenter(new THREE.Vector3());
          object.position.x -= center1.x;
          object.position.z -= center1.z;
          object.position.y -= box1.min.y;     // bottom to y=0
          object.position.y += GROUND_Y;       // then drop to ground plane

          carGroup.add(object);
          setModelLoaded(true);
        },
        (xhr) => {
          if (xhr.lengthComputable && xhr.total > 0) {
            setLoadProgress(Math.round((xhr.loaded / xhr.total) * 100));
          }
        },
        (err) => {
          console.error("Skoda Superb FBX failed to load:", err);
          setLoadError("Could not load Skoda Superb.fbx");
        }
      );
    } else {
      setLoadError("FBXLoader not available — check that fflate + FBXLoader scripts are loaded.");
    }

    // ---------- Ground shadow ----------
    const shadowGeo = new THREE.CircleGeometry(2.6, 48);
    shadowGeo.rotateX(-Math.PI / 2);
    const shadow = new THREE.Mesh(shadowGeo, new THREE.MeshBasicMaterial({ color: 0x000000, transparent: true, opacity: 0.22 }));
    shadow.position.y = -0.65;
    scene.add(shadow);

    // Floor grid (subtle, blueprint-feel)
    const gridGeo = new THREE.PlaneGeometry(20, 20, 20, 20);
    gridGeo.rotateX(-Math.PI / 2);
    const gridMat = new THREE.MeshBasicMaterial({ color: 0x444444, wireframe: true, transparent: true, opacity: 0.08 });
    const grid = new THREE.Mesh(gridGeo, gridMat);
    grid.position.y = -0.66;
    scene.add(grid);

    // ---------- Orbit controls (mouse-drag to look around) ----------
    const controls = new THREE.OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controls.dampingFactor = 0.08;
    controls.enablePan = false;
    controls.minDistance = 2.6;
    controls.maxDistance = 14;
    controls.minPolarAngle = 0.18;                 // keep camera above flat top-down
    controls.maxPolarAngle = Math.PI / 2 - 0.04;   // and just above the ground plane
    controls.target.set(DEFAULT_TARGET[0], DEFAULT_TARGET[1], DEFAULT_TARGET[2]);
    controls.autoRotate = true;
    controls.autoRotateSpeed = 0.55;
    controls.update();
    // Once the user grabs the camera, stop the auto turntable so we don't fight them.
    controls.addEventListener("start", () => { controls.autoRotate = false; });

    // Store refs
    threeRef.current = {
      THREE, scene, camera, renderer, carGroup, controls,
      anim: null,
    };
    setReady(true);

    // ---------- Raycaster click handler (alignment tool: pick marker pos) ----------
    const raycaster = new THREE.Raycaster();
    const ndc = new THREE.Vector2();
    const onCanvasClick = (ev) => {
      if (pickModeRef.current !== "pos") return;
      const rect = renderer.domElement.getBoundingClientRect();
      ndc.x = ((ev.clientX - rect.left) / rect.width) * 2 - 1;
      ndc.y = -((ev.clientY - rect.top) / rect.height) * 2 + 1;
      raycaster.setFromCamera(ndc, camera);
      const hits = raycaster.intersectObject(carGroup, true);
      if (hits.length) {
        const p = hits[0].point;
        // Hit point is world-space; carGroup sits at origin with no rotation, so
        // world == zone-local. Store with reasonable precision.
        const z = zonesRef.current[alignZoneIdxRef.current];
        if (z) {
          z.pos = [round3(p.x), round3(p.y), round3(p.z)];
          setPickMode(null);
          bumpZones();
        }
      }
    };
    renderer.domElement.addEventListener("click", onCanvasClick);

    // ---------- Render loop ----------
    const tickProject = () => {
      // Project each zone position to screen coords; update marker overlay
      if (!markersRef.current) return;
      const rect = container.getBoundingClientRect();
      const tmp = new THREE.Vector3();
      const markers = markersRef.current.children;
      const zones = zonesRef.current;
      zones.forEach((z, i) => {
        // Account for current car rotation
        tmp.set(...z.pos).applyMatrix4(carGroup.matrixWorld);
        tmp.project(camera);
        const x = (tmp.x * 0.5 + 0.5) * rect.width;
        const y = (-tmp.y * 0.5 + 0.5) * rect.height;
        const m = markers[i];
        if (!m) return;
        // Hide markers behind camera (z>1)
        const visible = tmp.z < 1;
        m.style.opacity = visible ? "" : "0";
        m.style.transform = `translate(${x}px, ${y}px)`;
      });
    };

    const tick = () => {
      const s = threeRef.current;
      if (!s) return;
      // Camera tween — drive both position and controls.target, then skip
      // controls.update() so OrbitControls doesn't fight the interpolation.
      if (s.anim) {
        const now = performance.now();
        const t = Math.min(1, (now - s.anim.start) / s.anim.dur);
        const e = easeOutCubic(t);
        camera.position.lerpVectors(s.anim.fromP, s.anim.toP, e);
        s.controls.target.lerpVectors(s.anim.fromT, s.anim.toT, e);
        camera.lookAt(s.controls.target);
        if (t >= 1) {
          s.anim = null;
          s.controls.update();  // sync internal spherical to new position+target
        }
      } else {
        s.controls.update();    // damping + autoRotate handled here when idle
      }
      renderer.render(scene, camera);
      tickProject();
      s.raf = requestAnimationFrame(tick);
    };
    tick();

    // Resize
    const ro = new ResizeObserver(() => {
      const w2 = Math.max(200, container.clientWidth);
      const h2 = Math.max(200, container.clientHeight);
      renderer.setSize(w2, h2);
      camera.aspect = w2 / h2;
      camera.updateProjectionMatrix();
    });
    ro.observe(container);

    // Cleanup
    return () => {
      const s = threeRef.current;
      if (s && s.raf) cancelAnimationFrame(s.raf);
      if (s && s.controls) s.controls.dispose();
      renderer.domElement.removeEventListener("click", onCanvasClick);
      ro.disconnect();
      renderer.dispose();
      if (renderer.domElement && renderer.domElement.parentNode) renderer.domElement.parentNode.removeChild(renderer.domElement);
      scene.traverse((obj) => {
        if (obj.geometry) obj.geometry.dispose();
        if (obj.material) obj.material.dispose();
      });
      threeRef.current = {};
    };
  }, []);

  // ---------- Trigger camera animations on active change ----------
  useEffect_c(() => {
    const s = threeRef.current;
    if (!s.camera || !s.THREE || !s.controls) return;
    const THREE = s.THREE;
    const fromP = s.camera.position.clone();
    const fromT = s.controls.target.clone();
    let toP, toT;
    if (activeZone) {
      toP = new THREE.Vector3(...activeZone.cam);
      toT = new THREE.Vector3(...activeZone.target);
      // Tightening the polar/distance limits so the close-up stays framed.
      s.controls.autoRotate = false;
    } else {
      toP = new THREE.Vector3(...DEFAULT_CAM);
      toT = new THREE.Vector3(...DEFAULT_TARGET);
    }
    s.anim = { fromP, toP, fromT, toT, start: performance.now(), dur: 900 };
  }, [activeId]);

  // ---------- Parts in active category ----------
  const partsInCategory = useMemo_c(() => {
    if (!activeZone) return [];
    return (window.PARTS_DATA || []).filter(p => p.category === activeZone.category);
  }, [activeId, zonesV]);

  // ---------- Alignment-tool helpers ----------
  const updateZoneField = (field, axis, value) => {
    const z = zonesRef.current[alignZoneIdx];
    if (!z) return;
    const next = [...z[field]];
    next[axis] = parseFloat(value);
    if (Number.isNaN(next[axis])) return;
    z[field] = next;
    bumpZones();
  };
  const useCurrentCamForZone = () => {
    const s = threeRef.current;
    if (!s.camera) return;
    const z = zonesRef.current[alignZoneIdx];
    if (!z) return;
    z.cam = [round3(s.camera.position.x), round3(s.camera.position.y), round3(s.camera.position.z)];
    bumpZones();
  };
  const useCurrentTargetForZone = () => {
    const s = threeRef.current;
    if (!s.controls) return;
    const z = zonesRef.current[alignZoneIdx];
    if (!z) return;
    z.target = [round3(s.controls.target.x), round3(s.controls.target.y), round3(s.controls.target.z)];
    bumpZones();
  };
  const previewZone = () => {
    const z = zonesRef.current[alignZoneIdx];
    if (!z) return;
    setActiveId(z.id);
  };
  const copyZonesJSON = () => {
    const body = zonesRef.current.map(z =>
      `  { id: "${z.id}", label: "${z.label}", category: "${z.category}", num: ${z.num}, ` +
      `pos: [${z.pos.map(round3).join(", ")}], ` +
      `cam: [${z.cam.map(round3).join(", ")}], ` +
      `target: [${z.target.map(round3).join(", ")}] },`
    ).join("\n");
    const text = "const CAR_ZONES = [\n" + body + "\n];";
    if (navigator.clipboard) {
      navigator.clipboard.writeText(text).then(
        () => { setCopyToast(true); setTimeout(() => setCopyToast(false), 1800); },
        () => { window.prompt("Copy zones:", text); }
      );
    } else {
      window.prompt("Copy zones:", text);
    }
  };
  const resetZones = () => {
    if (!window.confirm("Reset all zone positions to defaults?")) return;
    zonesRef.current = _cloneZones();
    setActiveId(null);
    bumpZones();
  };
  const currentZone = zonesRef.current[alignZoneIdx] || zonesRef.current[0];

  return (
    <section className="car-explorer-section">
      <div className="section-head">
        <div>
          <div className="eyebrow">Interactive parts atlas</div>
          <h2>Tap your car. <span className="accent">Find the part.</span></h2>
        </div>
        <div className="more">{activeZone ? `${partsInCategory.length} parts in ${activeZone.label}` : `${zonesRef.current.length} click zones`}</div>
      </div>

      <div className={"car-explorer" + (activeId ? " is-zoomed" : "") + (pickMode ? " is-picking" : "")}>
        <div className="car-stage" ref={stageRef} />

        {/* HTML markers, projected over scene */}
        <div className="car-markers" ref={markersRef}>
          {zonesRef.current.map(z => (
            <div
              key={z.id}
              className={"car-marker"
                + (activeId === z.id ? " active" : "")
                + (activeId && activeId !== z.id ? " hidden" : "")
                + (hoverId === z.id ? " hover" : "")}
              onClick={(e) => { e.stopPropagation(); setActiveId(z.id); }}
              onMouseEnter={() => setHoverId(z.id)}
              onMouseLeave={() => setHoverId(null)}
            >
              <div className="marker-line" />
              <div className="marker-dot">{String(z.num).padStart(2, "0")}</div>
              <div className="marker-label">
                <span className="ml-cat">{z.category}</span>
                <span className="ml-meta">{(window.PARTS_DATA || []).filter(p => p.category === z.category).length} parts</span>
              </div>
            </div>
          ))}
        </div>

        {/* Alignment tool — author-only overlay */}
        {!alignOpen && (
          <button className="align-toggle" onClick={() => setAlignOpen(true)} title="Align zone markers">
            ⚙ Align
          </button>
        )}
        {alignOpen && (
          <div className="align-tool">
            <div className="at-head">
              <span>Zone Alignment</span>
              <button className="at-close" onClick={() => { setAlignOpen(false); setPickMode(null); }}>✕</button>
            </div>
            <div className="at-body">
              <label className="at-label">Zone</label>
              <select value={alignZoneIdx} onChange={e => { setAlignZoneIdx(parseInt(e.target.value, 10)); setPickMode(null); }}>
                {zonesRef.current.map((z, i) => (
                  <option key={z.id} value={i}>
                    {String(z.num).padStart(2, "0")} — {z.category}
                  </option>
                ))}
              </select>

              <div className="at-section">
                <div className="at-label">Marker position (on car)</div>
                <div className="at-xyz">
                  <label>X<input type="number" step="0.05" value={currentZone.pos[0]} onChange={e => updateZoneField("pos", 0, e.target.value)} /></label>
                  <label>Y<input type="number" step="0.05" value={currentZone.pos[1]} onChange={e => updateZoneField("pos", 1, e.target.value)} /></label>
                  <label>Z<input type="number" step="0.05" value={currentZone.pos[2]} onChange={e => updateZoneField("pos", 2, e.target.value)} /></label>
                </div>
                <button
                  className={"at-btn" + (pickMode === "pos" ? " active" : "")}
                  onClick={() => setPickMode(pickMode === "pos" ? null : "pos")}
                >
                  {pickMode === "pos" ? "Click on car… (cancel)" : "Pick on car ▶"}
                </button>
                {pickMode === "pos" && <div className="at-hint">Click anywhere on the model to drop the marker.</div>}
              </div>

              <div className="at-section">
                <div className="at-label">Close-up camera position</div>
                <div className="at-xyz">
                  <label>X<input type="number" step="0.1" value={currentZone.cam[0]} onChange={e => updateZoneField("cam", 0, e.target.value)} /></label>
                  <label>Y<input type="number" step="0.1" value={currentZone.cam[1]} onChange={e => updateZoneField("cam", 1, e.target.value)} /></label>
                  <label>Z<input type="number" step="0.1" value={currentZone.cam[2]} onChange={e => updateZoneField("cam", 2, e.target.value)} /></label>
                </div>
                <button className="at-btn" onClick={useCurrentCamForZone}>Use current camera</button>
              </div>

              <div className="at-section">
                <div className="at-label">Look-at target</div>
                <div className="at-xyz">
                  <label>X<input type="number" step="0.05" value={currentZone.target[0]} onChange={e => updateZoneField("target", 0, e.target.value)} /></label>
                  <label>Y<input type="number" step="0.05" value={currentZone.target[1]} onChange={e => updateZoneField("target", 1, e.target.value)} /></label>
                  <label>Z<input type="number" step="0.05" value={currentZone.target[2]} onChange={e => updateZoneField("target", 2, e.target.value)} /></label>
                </div>
                <button className="at-btn" onClick={useCurrentTargetForZone}>Use current orbit target</button>
              </div>

              <div className="at-actions">
                <button className="at-btn" onClick={previewZone}>Preview zoom</button>
                <button className="at-btn primary" onClick={copyZonesJSON}>Copy JSON</button>
              </div>
              {copyToast && <div className="at-toast">Copied to clipboard</div>}
              <button className="at-btn ghost" onClick={resetZones} style={{ marginTop: 8 }}>Reset all zones</button>
            </div>
          </div>
        )}

        {/* Loading overlay while FBX downloads/parses */}
        {!modelLoaded && !loadError && (
          <div className="car-loading">
            <div className="cl-spinner" />
            <div className="cl-text">Loading Skoda Superb model… {loadProgress > 0 ? loadProgress + "%" : ""}</div>
          </div>
        )}
        {loadError && (
          <div className="car-loading">
            <div className="cl-text" style={{ color: "#ff8a5c" }}>{loadError}</div>
          </div>
        )}

        {/* Idle hint */}
        {!activeId && ready && modelLoaded && (
          <div className="car-hint">
            <span className="hint-dot" />
            <span>Click a numbered point to inspect the area</span>
          </div>
        )}

        {/* Index strip — list of zones */}
        {!activeId && (
          <div className="car-index">
            <div className="ci-head">Atlas index</div>
            {zonesRef.current.map(z => (
              <button
                key={z.id}
                className={"ci-row" + (hoverId === z.id ? " hover" : "")}
                onMouseEnter={() => setHoverId(z.id)}
                onMouseLeave={() => setHoverId(null)}
                onClick={() => setActiveId(z.id)}
              >
                <span className="ci-num">{String(z.num).padStart(2, "0")}</span>
                <span className="ci-name">{z.category}</span>
                <span className="ci-arr">→</span>
              </button>
            ))}
          </div>
        )}

        {/* Side panel — parts in active category */}
        <div className={"car-panel" + (activeId ? " open" : "")}>
          {activeZone && (
            <>
              <div className="cp-head">
                <button className="cp-back" onClick={() => setActiveId(null)}>
                  <svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"><path d="M9 11L4 7l5-4"/></svg>
                  Full car view
                </button>
                <div className="cp-num">{String(activeZone.num).padStart(2, "0")}</div>
              </div>
              <div className="cp-title-block">
                <div className="cp-eyebrow">Zone {String(activeZone.num).padStart(2, "0")}</div>
                <h3 className="cp-title">{activeZone.category}</h3>
                <div className="cp-meta">
                  {partsInCategory.length} {partsInCategory.length === 1 ? "part" : "parts"} catalogued for this area
                </div>
              </div>
              <div className="cp-parts">
                {partsInCategory.map(p => {
                  const brand = window.PartBrands[p.id] || "OEM";
                  const inCart = shop && shop.cart.some(c => c.id === p.id);
                  return (
                    <div className="cp-part" key={p.id} onClick={() => openQuickView && openQuickView(p.id)}>
                      <div className="cp-stage">
                        <window.ThumbViewer part={p} />
                      </div>
                      <div className="cp-info">
                        <div className="cp-cat">{brand} · {p.sku}</div>
                        <div className="cp-name">{p.name}</div>
                        <div className="cp-sub">{p.subtitle}</div>
                        <div className="cp-bottom">
                          <span className="cp-price">£{p.price}</span>
                          <button className="cp-add" onClick={(e) => { e.stopPropagation(); shop && shop.addToCart(p.id, 1); }}>
                            {inCart ? <><window.Icons.Check /> In cart</> : <><window.Icons.Plus /> Add</>}
                          </button>
                        </div>
                      </div>
                    </div>
                  );
                })}
              </div>
              <button
                className="btn btn-ghost btn-block"
                style={{ marginTop: 14 }}
                onClick={() => navigate({ name: "catalog", filter: activeZone.category })}
              >
                Browse all {activeZone.category.toLowerCase()} parts →
              </button>
            </>
          )}
        </div>
      </div>
    </section>
  );
}

window.CarExplorer = CarExplorer;
