// plant-extras.jsx — Mining infrastructure (shaft, headgear, winder, underground)
// plus the Eskom incoming yard and the living-plant animations.
//
// Layout convention used here:
//   The shaft + headgear sit on the LEFT side of the plant, BEFORE the ROM tip
//   (because ore comes UP the shaft and is fed INTO the processing plant).
//   The winder house sits next to the headgear, on the plant side, with
//   hoist cables passing over the sheave wheels at the top of the headgear
//   and down into the shaft.

const { useState: useState_px, useMemo: useMemo_px, useEffect: useEffect_px } = React;

// ════════════════════════════════════════════════════════════════════════════
// ANIMATION HELPERS
// ════════════════════════════════════════════════════════════════════════════

function BeltMaterial({ a, b, color = '#7a8593', dur = 1.6, dashLen = 6, gap = 14, width = 3 }) {
  const pa = iso(...a), pb = iso(...b);
  const total = dashLen + gap;
  return (
    <line x1={pa.X} y1={pa.Y} x2={pb.X} y2={pb.Y}
          stroke={color} strokeWidth={width}
          strokeDasharray={`${dashLen} ${gap}`}
          strokeLinecap="butt">
      <animate attributeName="stroke-dashoffset"
               from="0" to={-total} dur={`${dur}s`} repeatCount="indefinite" />
    </line>
  );
}

function MoverOnPath({ children, path, dur = 16, begin = 0 }) {
  return (
    <g>
      {children}
      <animateMotion dur={`${dur}s`} repeatCount="indefinite"
                     begin={`${begin}s`} path={path} rotate="0" />
    </g>
  );
}

function SheaveWheel({ cx, cy, r = 16, dur = 2.4, glow }) {
  return (
    <g>
      <circle cx={cx} cy={cy} r={r} fill="#13181f" stroke={glow || "#7a8593"} strokeWidth="1.6" />
      <circle cx={cx} cy={cy} r={r * 0.78} fill="none" stroke={glow ? glow : "#5a6473"} strokeWidth="0.8" />
      <g>
        <line x1={cx - r * 0.9} y1={cy} x2={cx + r * 0.9} y2={cy} stroke={glow ? glow : "#7a8593"} strokeWidth="1" />
        <line x1={cx} y1={cy - r * 0.9} x2={cx} y2={cy + r * 0.9} stroke={glow ? glow : "#7a8593"} strokeWidth="1" />
        <line x1={cx - r * 0.63} y1={cy - r * 0.63} x2={cx + r * 0.63} y2={cy + r * 0.63} stroke={glow ? glow : "#5a6473"} strokeWidth="0.7" />
        <line x1={cx - r * 0.63} y1={cy + r * 0.63} x2={cx + r * 0.63} y2={cy - r * 0.63} stroke={glow ? glow : "#5a6473"} strokeWidth="0.7" />
        <circle cx={cx} cy={cy} r="2.4" fill={glow ? glow : "#7a8593"} />
        <animateTransform attributeName="transform" type="rotate"
          from={`0 ${cx} ${cy}`} to={`360 ${cx} ${cy}`}
          dur={`${dur}s`} repeatCount="indefinite" />
      </g>
    </g>
  );
}

function ThickenerRake({ cx, cy, r = 110, dur = 60 }) {
  return (
    <g>
      <line x1={cx - r * 0.95} y1={cy} x2={cx + r * 0.95} y2={cy} stroke="#3a4250" strokeWidth="1" opacity="0.7" />
      <line x1={cx} y1={cy - r * 0.4} x2={cx} y2={cy + r * 0.4} stroke="#3a4250" strokeWidth="0.7" opacity="0.6" />
      {[0.3, 0.5, 0.7, 0.9].map((t, i) => (
        <line key={i} x1={cx - r * t} y1={cy - 2} x2={cx - r * t} y2={cy + 2} stroke="#3a4250" strokeWidth="0.6" />
      ))}
      <animateTransform attributeName="transform" type="rotate"
        from={`0 ${cx} ${cy}`} to={`360 ${cx} ${cy}`}
        dur={`${dur}s`} repeatCount="indefinite" />
    </g>
  );
}

function MillDrumSpin({ cx, cy, r = 36, dur = 6, dir = 1 }) {
  return (
    <g transform={`translate(${cx}, ${cy}) rotate(-30)`}>
      <g>
        <line x1={-r * 0.85} y1="0" x2={r * 0.85} y2="0" stroke="#3a4250" strokeWidth="0.8" />
        <line x1="0" y1={-r * 0.85} x2="0" y2={r * 0.85} stroke="#3a4250" strokeWidth="0.8" />
        <line x1={-r * 0.6} y1={-r * 0.6} x2={r * 0.6} y2={r * 0.6} stroke="#3a4250" strokeWidth="0.6" />
        <line x1={-r * 0.6} y1={r * 0.6} x2={r * 0.6} y2={-r * 0.6} stroke="#3a4250" strokeWidth="0.6" />
        <animateTransform attributeName="transform" type="rotate"
          from="0 0 0" to={`${360 * dir} 0 0`}
          dur={`${dur}s`} repeatCount="indefinite" />
      </g>
    </g>
  );
}

function ShaftCage({ x, y, zTop, zBot, w = 14, d = 14, h = 16, dur = 14, color = '#fbbf24' }) {
  const top = iso(x, y, zTop);
  const bot = iso(x, y, zBot);
  const dy = bot.Y - top.Y;
  return (
    <g>
      <g>
        <IsoBox x={x - w/2} y={y - d/2} z={zTop - h} w={w} d={d} h={h}
                top="#2a313b" right="#1a1f28" front="#10141a" edge={color} edgeWidth={0.7} />
        {(() => {
          const a = iso(x - w/2 + 2, y + d/2, zTop - h + 4);
          const b = iso(x + w/2 - 2, y + d/2, zTop - h + 4);
          const c = iso(x - w/2 + 2, y + d/2, zTop - h + 12);
          const d2 = iso(x + w/2 - 2, y + d/2, zTop - h + 12);
          return (
            <>
              <line x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke={color} strokeWidth="0.4" opacity="0.6" />
              <line x1={c.X} y1={c.Y} x2={d2.X} y2={d2.Y} stroke={color} strokeWidth="0.4" opacity="0.6" />
            </>
          );
        })()}
        <animateTransform attributeName="transform" type="translate"
          values={`0 0; 0 ${dy}; 0 ${dy}; 0 0; 0 0`}
          keyTimes="0; 0.4; 0.5; 0.9; 1"
          dur={`${dur}s`} repeatCount="indefinite" />
      </g>
    </g>
  );
}

function Worker({ x, y, z, range = 16, dur = 6, color = '#fbbf24' }) {
  const a = iso(x - range/2, y, z);
  const b = iso(x + range/2, y, z);
  return (
    <g>
      <rect x={a.X - 0.8} y={a.Y - 5} width="1.6" height="5" fill={color} />
      <circle cx={a.X} cy={a.Y - 6} r="1" fill={color} />
      <animateTransform attributeName="transform" type="translate"
        values={`0 0; ${b.X - a.X} 0; ${b.X - a.X} 0; 0 0; 0 0`}
        keyTimes="0; 0.45; 0.5; 0.95; 1"
        dur={`${dur}s`} repeatCount="indefinite" />
    </g>
  );
}

// ════════════════════════════════════════════════════════════════════════════
// MINE — shaft + headgear + winder house + underground (LEFT side of plant)
// ════════════════════════════════════════════════════════════════════════════

// Headgear / winder — proper four-legged lattice steel tower above the shaft
// with rear back-stays bracing against the rope pull, a crown sheave housing
// at the top, twin sheave wheels, and a mid-height inspection deck. The
// back-stays anchor on the FAR side of the shaft (away from the winder house)
// so they're in compression resisting the horizontal pull of the hoist rope.
function Equip_Headframe({ styleFor }) {
  const sx = -180, sy = 80;
  const headH = 220;            // total tower height
  const tHX = 22;               // tower half-width in x
  const tHY = 18;               // tower half-depth in y
  const sheaveZ = headH + 18;   // sheave-wheel centre height

  // Four-leg tower footprint corners (above the shaft)
  const corners = [
    [sx - tHX, sy - tHY], // NW
    [sx + tHX, sy - tHY], // NE
    [sx + tHX, sy + tHY], // SE
    [sx - tHX, sy + tHY], // SW
  ];

  // Back-stays anchor BEHIND the shaft (in the -x direction, opposite the
  // winder house at +x) and lean forward to the crown — that's the only way
  // a stay can resist the rope-pull from the winder.
  const stayBaseX = sx - 76;     // ground anchor x
  const stayTopX  = sx - tHX + 2; // meet tower just inside the back legs

  return (
    <>
      {/* ── Concrete pedestal / bank ─────────────────────────────────── */}
      <g data-disc="civils" style={styleFor('civils')}>
        <IsoBox x={sx - 30} y={sy - 26} z={0} w={60} d={52} h={12}
                top="#2a313b" right="#1a1f28" front="#10141a" edge="#5a6473" edgeWidth={0.7} />
        {/* Bank-level apron + skip-tipping deck reaching toward winder house */}
        <IsoBox x={sx + 30} y={sy - 20} z={0} w={38} d={40} h={6}
                top="#3a4250" right="#1f2630" front="#10141a" edge="#5a6473" edgeWidth={0.5} />
        {/* Back-stay concrete footing */}
        <IsoBox x={stayBaseX - 8} y={sy - 18} z={0} w={16} d={36} h={8}
                top="#2a313b" right="#1a1f28" front="#10141a" edge="#5a6473" edgeWidth={0.5} />
      </g>

      {/* ── Main 4-leg lattice tower ─────────────────────────────────── */}
      <g data-disc="civils mechanical" style={styleFor('civils')}>
        {/* Four vertical legs */}
        {corners.map(([cx, cy], i) => {
          const a = iso(cx, cy, 12), b = iso(cx, cy, headH);
          return <line key={`vl${i}`} x1={a.X} y1={a.Y} x2={b.X} y2={b.Y}
                       stroke="#7a8593" strokeWidth="1.7" />;
        })}
        {/* Horizontal buntons at five elevations — full rectangle each */}
        {[30, 70, 115, 160, headH].map((zz, ri) =>
          [0, 1, 2, 3].map((c) => {
            const c1 = corners[c], c2 = corners[(c + 1) % 4];
            const a = iso(c1[0], c1[1], zz), b = iso(c2[0], c2[1], zz);
            return <line key={`bt${ri}-${c}`} x1={a.X} y1={a.Y} x2={b.X} y2={b.Y}
                         stroke={SHADE.steelDim} strokeWidth="0.7" />;
          })
        )}
        {/* X-bracing on each face, segment by segment */}
        {[[30, 70], [70, 115], [115, 160], [160, headH]].map(([z1, z2], ri) =>
          [0, 1, 2, 3].map((c) => {
            const c1 = corners[c], c2 = corners[(c + 1) % 4];
            const a1 = iso(c1[0], c1[1], z1), b1 = iso(c2[0], c2[1], z2);
            const a2 = iso(c2[0], c2[1], z1), b2 = iso(c1[0], c1[1], z2);
            return (
              <React.Fragment key={`xb${ri}-${c}`}>
                <line x1={a1.X} y1={a1.Y} x2={b1.X} y2={b1.Y}
                      stroke={SHADE.steelDim} strokeWidth="0.45" />
                <line x1={a2.X} y1={a2.Y} x2={b2.X} y2={b2.Y}
                      stroke={SHADE.steelDim} strokeWidth="0.45" />
              </React.Fragment>
            );
          })
        )}
      </g>

      {/* ── Inspection deck at ~70% height ───────────────────────────── */}
      <g data-disc="civils" style={styleFor('civils')}>
        <IsoBox x={sx - tHX - 3} y={sy - tHY - 3} z={155}
                w={(tHX + 3) * 2} d={(tHY + 3) * 2} h={3}
                top="#3a4250" right="#1f2630" front="#10141a"
                edge={SHADE.yellow} edgeWidth={0.5} />
        {/* Handrail (a thin top-line above the deck) */}
        {(() => {
          const lp = corners.map(([cx, cy]) => iso(cx, cy, 162));
          return [0, 1, 2, 3].map((i) => (
            <line key={`hr${i}`} x1={lp[i].X} y1={lp[i].Y}
                  x2={lp[(i + 1) % 4].X} y2={lp[(i + 1) % 4].Y}
                  stroke={SHADE.yellow} strokeWidth="0.4" opacity="0.7" />
          ));
        })()}
      </g>

      {/* ── Back-stays — two big diagonal struts in compression ──────── */}
      <g data-disc="civils mechanical" style={styleFor('civils')}>
        {[sy - tHY, sy + tHY].map((yy, i) => {
          const a = iso(stayBaseX, yy, 8), b = iso(stayTopX, yy, headH);
          return <line key={`bs${i}`} x1={a.X} y1={a.Y} x2={b.X} y2={b.Y}
                       stroke="#7a8593" strokeWidth="1.6" />;
        })}
        {/* Lacing between the pair of back-stays at four elevations */}
        {[0.2, 0.4, 0.6, 0.8].map((t, i) => {
          const xx = stayBaseX + (stayTopX - stayBaseX) * t;
          const zz = 8 + (headH - 8) * t;
          const a = iso(xx, sy - tHY, zz), b = iso(xx, sy + tHY, zz);
          return <line key={`bsc${i}`} x1={a.X} y1={a.Y} x2={b.X} y2={b.Y}
                       stroke={SHADE.steelDim} strokeWidth="0.5" />;
        })}
        {/* Light X-bracing between back-stays */}
        {[[0.2, 0.4], [0.4, 0.6], [0.6, 0.8]].map(([t1, t2], i) => {
          const x1 = stayBaseX + (stayTopX - stayBaseX) * t1;
          const x2 = stayBaseX + (stayTopX - stayBaseX) * t2;
          const z1 = 8 + (headH - 8) * t1, z2 = 8 + (headH - 8) * t2;
          const a1 = iso(x1, sy - tHY, z1), b1 = iso(x2, sy + tHY, z2);
          const a2 = iso(x1, sy + tHY, z1), b2 = iso(x2, sy - tHY, z2);
          return (
            <React.Fragment key={`bsx${i}`}>
              <line x1={a1.X} y1={a1.Y} x2={b1.X} y2={b1.Y}
                    stroke={SHADE.steelDim} strokeWidth="0.4" />
              <line x1={a2.X} y1={a2.Y} x2={b2.X} y2={b2.Y}
                    stroke={SHADE.steelDim} strokeWidth="0.4" />
            </React.Fragment>
          );
        })}
      </g>

      {/* ── Crown sheave housing at the top ──────────────────────────── */}
      <g data-disc="mechanical" style={styleFor('mechanical')}>
        {/* Crown deck — proper rectangular cap, POSITIVE width this time */}
        <IsoBox x={sx - tHX - 4} y={sy - tHY - 4} z={headH}
                w={(tHX + 4) * 2} d={(tHY + 4) * 2} h={6}
                top="#1f2630" right="#13181f" front="#0a0d12"
                edge="#7a8593" edgeWidth={0.7} />
        {/* Sheave-axle housing — bright yellow industrial band */}
        <IsoBox x={sx - tHX - 6} y={sy - tHY - 8} z={headH + 6}
                w={(tHX + 6) * 2} d={(tHY + 8) * 2} h={6}
                top="#fbbf24" right="#c08820" front="#806010"
                edge="#7a8593" edgeWidth={0.6} />
        {/* Cab / hut roof on top of the crown */}
        <IsoBox x={sx - tHX} y={sy - tHY} z={headH + 12}
                w={tHX * 2} d={tHY * 2} h={14}
                top="#262d36" right="#171c23" front="#0d1218"
                edge="#7a8593" edgeWidth={0.6} />
        {/* Slim mast / lightning rod */}
        {(() => {
          const a = iso(sx, sy, headH + 26), b = iso(sx, sy, headH + 44);
          return <line x1={a.X} y1={a.Y} x2={b.X} y2={b.Y}
                       stroke="#7a8593" strokeWidth="0.7" />;
        })()}
        {/* Twin sheave wheels — outside the crown on the WINDER-HOUSE side,
           with horizontal axles perpendicular to the rope plane. They sit
           slightly proud of the crown so the ropes can spool past it. */}
        {(() => {
          const p1 = iso(sx + 4, sy - 10, sheaveZ);
          const p2 = iso(sx + 4, sy + 10, sheaveZ);
          return (
            <>
              <SheaveWheel cx={p1.X} cy={p1.Y} r={17} dur={2.6} />
              <SheaveWheel cx={p2.X} cy={p2.Y} r={17} dur={2.6} />
              {/* Axle bracket (short stub joining each sheave to the crown) */}
              <line x1={p1.X} y1={p1.Y} x2={p2.X} y2={p2.Y}
                    stroke="#5a6473" strokeWidth="1.2" />
            </>
          );
        })()}
      </g>

      {/* ── Hoist ropes ─────────────────────────────────────────────── */}
      <g data-disc="mechanical" style={styleFor('mechanical')}>
        {/* Down-leg: each sheave drops a rope straight into the shaft */}
        {[sy - 10, sy + 10].map((yy, i) => {
          const a = iso(sx + 4, yy, sheaveZ);
          const b = iso(sx, yy, 0);
          return <line key={`rd${i}`} x1={a.X} y1={a.Y} x2={b.X} y2={b.Y}
                       stroke="#3a4250" strokeWidth="0.85" />;
        })}
        {/* Cross-leg: rope from each sheave runs to the winder-house drum */}
        {[sy - 10, sy + 10].map((yy, i) => {
          const a = iso(sx + 4, yy, sheaveZ);
          const b = iso(20, yy, 60);
          return <line key={`rw${i}`} x1={a.X} y1={a.Y} x2={b.X} y2={b.Y}
                       stroke="#3a4250" strokeWidth="0.85" />;
        })}
      </g>

      {/* Label */}
      {(() => { const lp = iso(sx - 8, sy - 56, headH + 50); return (
        <text x={lp.X} y={lp.Y} textAnchor="middle" fontSize="10"
              fontFamily="'Source Sans 3'" fill="#7a8593" letterSpacing="0.12em" fontWeight="600">
          WINDER · SHAFT 1
        </text>
      );})()}
    </>
  );
}

// ════════════════════════════════════════════════════════════════════════════
// UNDERGROUND — 2D SIDE-ELEVATION CROSS-SECTION (screen-space, not iso)
// Replaces the previous iso-projected Equip_Shaft, Equip_EarthCutaway and
// Equip_UndergroundLevels. The shaft connects to the iso headgear at its
// screen-space position, then descends into a tall vertical panel showing
// the deep underground in proper proportions — like a real mine schematic.
// ════════════════════════════════════════════════════════════════════════════
function Equip_Underground2D({ styleFor }) {
  // Iso projection of shaft top at world (-180, 80, 0):
  //   X = (-180 - 80) * 0.866 = -225.16
  //   Y = (-180 + 80) * 0.38 = -38.00
  const shaftX = -225;
  const surfaceY = -38;          // matches iso ground at the shaft
  const shaftHalfW = 14;

  // Top of the 2D earth panel — far enough below the surface plant ground
  // line that it doesn't cover any surface equipment.
  const panelTop = 110;          // earth cutaway begins here
  const panelLeft = -820;
  const panelRight = 380;
  const panelBottom = 2840;

  // Levels — depth in metres, drawn at 1 px/m below surface
  const yFor = (m) => surfaceY + m * 1.6;

  const levels = [
    { m: 100,  label: '-100 m',  zone: 'UPPER LEVELS' },
    { m: 280,  label: '-280 m',  zone: '' },
    { m: 480,  label: '-480 m',  zone: 'MAIN ORE ZONE' },
    { m: 720,  label: '-720 m',  zone: '' },
    { m: 980,  label: '-980 m',  zone: '' },
    { m: 1280, label: '-1280 m', zone: 'DEEP LEVELS' },
    { m: 1600, label: '-1600 m', zone: '' },
  ];

  // Strata bands as screen-Y ranges
  const strata = [
    { yT: panelTop,        yB: panelTop + 40,   fill: '#3d3526' },  // topsoil
    { yT: panelTop + 40,   yB: panelTop + 140,  fill: '#2f2a1f' },  // weathered
    { yT: panelTop + 140,  yB: panelTop + 420,  fill: '#241f17' },  // hard rock 1
    { yT: panelTop + 420,  yB: panelTop + 900,  fill: '#1f1a14' },  // hard rock 2
    { yT: panelTop + 900,  yB: panelTop + 1500, fill: '#1a1610' },  // deep rock
    { yT: panelTop + 1500, yB: panelBottom,     fill: '#2a2417' },  // ore zone
  ];

  // Pre-computed rock-texture dot positions
  const dots = Array.from({ length: 140 }, (_, i) => ({
    x: panelLeft + 20 + ((i * 137) % (panelRight - panelLeft - 40)),
    y: panelTop + 20 + ((i * 211) % (panelBottom - panelTop - 40)),
  }));

  return (
    <g>
      {/* ──── EARTH BACKGROUND + STRATA ─────────────────────────────────── */}
      <g data-disc="civils" style={styleFor('civils')}>
        {/* Backdrop */}
        <rect x={panelLeft} y={panelTop} width={panelRight - panelLeft}
              height={panelBottom - panelTop} fill="#1f1a14" />
        {strata.map((s, i) => (
          <rect key={i} x={panelLeft} y={s.yT} width={panelRight - panelLeft}
                height={s.yB - s.yT} fill={s.fill} opacity="0.88" />
        ))}
        {/* Strata separator lines */}
        {strata.slice(1).map((s, i) => (
          <line key={`sep${i}`} x1={panelLeft} y1={s.yT} x2={panelRight} y2={s.yT}
                stroke="#0e0c08" strokeWidth="0.6" opacity="0.5" />
        ))}
        {/* Rock-texture stippling */}
        {dots.map((d, i) => (
          <circle key={`dot${i}`} cx={d.x} cy={d.y} r="0.5" fill="#0a0807" opacity="0.6" />
        ))}
        {/* Ore vein — tilted polygon in the bottom strata */}
        <polygon
          points={`${panelLeft + 80},${panelBottom - 200} ${panelRight - 60},${panelBottom - 140} ${panelRight - 60},${panelBottom - 120} ${panelLeft + 80},${panelBottom - 180}`}
          fill="#c97a4f" stroke="#3a2010" strokeWidth="0.4" opacity="0.45" />
        {/* Outer outline */}
        <rect x={panelLeft} y={panelTop} width={panelRight - panelLeft}
              height={panelBottom - panelTop} fill="none" stroke="#3a3020" strokeWidth="0.8" />
        {/* Surface ground line */}
        <line x1={panelLeft} y1={panelTop} x2={panelRight} y2={panelTop} stroke="#4a3a2a" strokeWidth="1.4" />
        <text x={panelRight - 8} y={panelTop - 4} fontSize="8" fontFamily="'Source Sans 3'"
              fill="#7a6a4a" letterSpacing="0.1em" textAnchor="end">SURFACE</text>
        {/* Zone labels on right edge */}
        {[
          { y: panelTop + 200,  text: 'UPPER LEVELS' },
          { y: panelTop + 700,  text: 'MAIN ORE ZONES' },
          { y: panelTop + 1400, text: 'DEEP LEVELS' },
        ].map((z, i) => (
          <text key={i} x={panelRight + 6} y={z.y} fontSize="9" fontFamily="'Source Sans 3'"
                fill="#5a5040" letterSpacing="0.14em">{z.text}</text>
        ))}
      </g>

      {/* ──── SHAFT COLUMN ─────────────────────────────────────────────── */}
      <g data-disc="civils" style={styleFor('civils')}>
        {/* Main shaft cavity */}
        <rect x={shaftX - shaftHalfW} y={surfaceY}
              width={shaftHalfW * 2} height={panelBottom - surfaceY}
              fill="#08070a" stroke="#3a3020" strokeWidth="0.7" />
        {/* Concrete lining horizontal ticks */}
        {Array.from({ length: 56 }, (_, i) => surfaceY + 30 + i * 50)
          .filter((y) => y < panelBottom - 30)
          .map((y, i) => (
            <line key={i} x1={shaftX - shaftHalfW + 1} y1={y}
                  x2={shaftX + shaftHalfW - 1} y2={y}
                  stroke="#3a3020" strokeWidth="0.35" opacity="0.6" />
          ))}
        {/* Centre divide (skip on one side, cage on the other) */}
        <line x1={shaftX} y1={surfaceY} x2={shaftX} y2={panelBottom}
              stroke="#3a3020" strokeWidth="0.4" opacity="0.5" />
      </g>

      {/* ──── DRIFTS AT EACH LEVEL ─────────────────────────────────────── */}
      {levels.map((lvl, li) => {
        const driftY = yFor(lvl.m);
        const driftLeft = panelLeft + 30;
        const driftRight = shaftX - shaftHalfW;
        const driftH = 26;
        return (
          <g key={li} data-disc="civils" style={styleFor('civils')}>
            <rect x={driftLeft} y={driftY - driftH / 2}
                  width={driftRight - driftLeft} height={driftH}
                  fill="#1a1410" stroke="#3a3020" strokeWidth="0.6" />
            {/* Depth callout right of shaft */}
            <text x={shaftX + shaftHalfW + 8} y={driftY + 3}
                  fontSize="9" fontFamily="'Source Sans 3'"
                  fill="#7a6a4a" letterSpacing="0.06em">{lvl.label}</text>
          </g>
        );
      })}

      {/* ──── EQUIPMENT ON EACH LEVEL ──────────────────────────────────── */}

      {/* Level -100m: Substation + Workshop + level conveyor */}
      {(() => { const y = yFor(100); return (
        <g key="l100">
          {/* Substation */}
          <g data-disc="electrical civils" style={styleFor('electrical')}>
            <rect x={shaftX - 90} y={y - 12} width="36" height="20" fill="#262d36" stroke={SHADE.yellow} strokeWidth="0.6" />
            {[0, 1, 2, 3].map((i) => (
              <rect key={i} x={shaftX - 86 + i * 8} y={y - 10} width="6" height="14" fill="#2a313b" stroke={SHADE.yellow} strokeWidth="0.3" />
            ))}
            <text x={shaftX - 72} y={y + 18} fontSize="7" fontFamily="'Source Sans 3'" fill={SHADE.yellow} textAnchor="middle" letterSpacing="0.06em">U/G SUB</text>
          </g>
          {/* Workshop with worker dots */}
          <g data-disc="civils mechanical" style={styleFor('civils')}>
            <rect x={shaftX - 200} y={y - 12} width="80" height="20" fill="none" stroke="#5a6473" strokeWidth="0.7" />
            <rect x={shaftX - 175} y={y - 4} width="22" height="10" fill="#3a4250" stroke="#7a8593" strokeWidth="0.4" />
            <text x={shaftX - 160} y={y + 18} fontSize="7" fontFamily="'Source Sans 3'" fill="#7a6a4a" textAnchor="middle" letterSpacing="0.06em">WORKSHOP</text>
            <g data-disc="mechanical" style={styleFor('mechanical')}>
              {/* Walking worker */}
              <g>
                <rect x={shaftX - 140} y={y - 6} width="1.5" height="5" fill={SHADE.yellow} />
                <circle cx={shaftX - 139} cy={y - 7} r="1" fill={SHADE.yellow} />
                <animateTransform attributeName="transform" type="translate"
                  values="0 0; 30 0; 30 0; 0 0; 0 0" keyTimes="0; 0.45; 0.5; 0.95; 1"
                  dur="5s" repeatCount="indefinite" />
              </g>
            </g>
          </g>
          {/* Conveyor */}
          <g data-disc="bulk" style={styleFor('bulk')}>
            <line x1={shaftX - 350} y1={y - 4} x2={shaftX - 210} y2={y - 4} stroke="#7a8593" strokeWidth="2" />
            <line x1={shaftX - 350} y1={y - 4} x2={shaftX - 210} y2={y - 4}
                  stroke="#c97a4f" strokeWidth="2.4" strokeDasharray="6 14">
              <animate attributeName="stroke-dashoffset" from="0" to="-20" dur="2s" repeatCount="indefinite" />
            </line>
            <text x={shaftX - 280} y={y + 18} fontSize="7" fontFamily="'Source Sans 3'" fill="#7a6a4a" textAnchor="middle" letterSpacing="0.06em">LEVEL CONVEYOR</text>
          </g>
        </g>
      );})()}

      {/* Level -280m: Stope working face + LHD loader (animated) */}
      {(() => { const y = yFor(280); return (
        <g key="l280">
          {/* Stope (working face — tilted) */}
          <g data-disc="mechanical bulk" style={styleFor('bulk')}>
            <polygon points={`${shaftX - 480},${y - 12} ${shaftX - 510},${y + 12} ${shaftX - 460},${y + 12} ${shaftX - 440},${y - 12}`}
                     fill="#3a2818" stroke="#5a3a20" strokeWidth="0.5" />
            <text x={shaftX - 475} y={y + 24} fontSize="7" fontFamily="'Source Sans 3'" fill="#7a6a4a" textAnchor="middle" letterSpacing="0.06em">STOPE</text>
          </g>
          {/* Animated LHD loader */}
          <g data-disc="bulk mechanical" style={styleFor('bulk')}>
            <g>
              <rect x={-20} y={-4} width="20" height="8" fill="#3a4250" stroke={SHADE.yellow} strokeWidth="0.5" />
              <rect x={-26} y={-2} width="6" height="6" fill="#3a4250" stroke="#7a8593" strokeWidth="0.4" />
              <circle cx={-23} cy={2} r="0.6" fill={SHADE.yellow} />
              <animateTransform attributeName="transform" type="translate"
                values={`${shaftX - 60} ${y}; ${shaftX - 420} ${y}; ${shaftX - 420} ${y}; ${shaftX - 60} ${y}; ${shaftX - 60} ${y}`}
                keyTimes="0; 0.45; 0.5; 0.95; 1" dur="14s" repeatCount="indefinite" />
            </g>
          </g>
        </g>
      );})()}

      {/* Level -480m: Crosscut + ore pass */}
      {(() => { const y = yFor(480); return (
        <g key="l480">
          {/* Ore pass — vertical narrow chute connecting to level above */}
          <g data-disc="bulk civils" style={styleFor('bulk')}>
            <rect x={shaftX - 320} y={yFor(280) + 12} width="8" height={y - 12 - (yFor(280) + 12)}
                  fill="#3a2818" stroke="#5a3a20" strokeWidth="0.4" />
            {/* Animated ore falling */}
            {[0, 0.3, 0.6].map((b, i) => (
              <g key={i}>
                <circle r="1.6" fill="#c97a4f" />
                <animateMotion dur="2.5s" begin={`${b * 2.5}s`} repeatCount="indefinite"
                               path={`M ${shaftX - 316} ${yFor(280) + 12} L ${shaftX - 316} ${y - 12}`} />
              </g>
            ))}
            <text x={shaftX - 290} y={(y + yFor(280)) / 2} fontSize="6.5" fontFamily="'Source Sans 3'" fill="#7a6a4a">ORE PASS</text>
          </g>
          {/* Loading station */}
          <g data-disc="bulk mechanical" style={styleFor('bulk')}>
            <rect x={shaftX - 90} y={y - 12} width="40" height="20" fill="#262d36" stroke="#7a8593" strokeWidth="0.5" />
            <text x={shaftX - 70} y={y + 18} fontSize="7" fontFamily="'Source Sans 3'" fill="#7a6a4a" textAnchor="middle" letterSpacing="0.06em">LOADING STATION</text>
          </g>
          {/* Drill rig at far end */}
          <g data-disc="mechanical" style={styleFor('mechanical')}>
            <rect x={shaftX - 540} y={y - 8} width="16" height="14" fill="#3a4250" stroke="#7a8593" strokeWidth="0.4" />
            <line x1={shaftX - 524} y1={y} x2={shaftX - 510} y2={y - 6} stroke="#7a8593" strokeWidth="1.5" strokeLinecap="round" />
          </g>
        </g>
      );})()}

      {/* Level -720m: Pump station + stope */}
      {(() => { const y = yFor(720); return (
        <g key="l720">
          <g data-disc="electrical civils" style={styleFor('electrical')}>
            <rect x={shaftX - 90} y={y - 12} width="36" height="20" fill="#262d36" stroke={SHADE.yellow} strokeWidth="0.5" />
            <text x={shaftX - 72} y={y + 18} fontSize="7" fontFamily="'Source Sans 3'" fill={SHADE.yellow} textAnchor="middle" letterSpacing="0.06em">DEEP SUB</text>
          </g>
          <g data-disc="mechanical" style={styleFor('mechanical')}>
            <rect x={shaftX - 200} y={y - 12} width="60" height="20" fill="none" stroke="#5a6473" strokeWidth="0.6" />
            {[0, 1, 2].map((i) => (
              <circle key={i} cx={shaftX - 188 + i * 15} cy={y - 2} r="3.5" fill="#262d36" stroke="#7a8593" strokeWidth="0.4" />
            ))}
            <text x={shaftX - 170} y={y + 18} fontSize="7" fontFamily="'Source Sans 3'" fill="#7a6a4a" textAnchor="middle" letterSpacing="0.06em">PUMP STATION</text>
          </g>
          <g data-disc="bulk mechanical" style={styleFor('bulk')}>
            {/* LHD on this level too */}
            <g>
              <rect x={-20} y={-4} width="20" height="8" fill="#3a4250" stroke={SHADE.yellow} strokeWidth="0.5" />
              <circle cx={-17} cy={2} r="0.6" fill={SHADE.yellow} />
              <animateTransform attributeName="transform" type="translate"
                values={`${shaftX - 280} ${y}; ${shaftX - 480} ${y}; ${shaftX - 480} ${y}; ${shaftX - 280} ${y}; ${shaftX - 280} ${y}`}
                keyTimes="0; 0.45; 0.5; 0.95; 1" dur="20s" repeatCount="indefinite" />
            </g>
          </g>
        </g>
      );})()}

      {/* Level -980m: Workshop + ore pass */}
      {(() => { const y = yFor(980); return (
        <g key="l980">
          {/* Ore pass from above */}
          <g data-disc="bulk civils" style={styleFor('bulk')}>
            <rect x={shaftX - 360} y={yFor(720) + 12} width="8" height={y - 12 - (yFor(720) + 12)}
                  fill="#3a2818" stroke="#5a3a20" strokeWidth="0.4" />
            {[0, 0.3, 0.6].map((b, i) => (
              <g key={i}>
                <circle r="1.6" fill="#c97a4f" />
                <animateMotion dur="2.5s" begin={`${b * 2.5}s`} repeatCount="indefinite"
                               path={`M ${shaftX - 356} ${yFor(720) + 12} L ${shaftX - 356} ${y - 12}`} />
              </g>
            ))}
          </g>
          <g data-disc="civils mechanical" style={styleFor('civils')}>
            <rect x={shaftX - 200} y={y - 12} width="80" height="20" fill="none" stroke="#5a6473" strokeWidth="0.7" />
            <rect x={shaftX - 175} y={y - 4} width="22" height="10" fill="#3a4250" stroke="#7a8593" strokeWidth="0.4" />
            <text x={shaftX - 160} y={y + 18} fontSize="7" fontFamily="'Source Sans 3'" fill="#7a6a4a" textAnchor="middle" letterSpacing="0.06em">DEEP WORKSHOP</text>
          </g>
        </g>
      );})()}

      {/* Level -1280m: Loading station + drill bay */}
      {(() => { const y = yFor(1280); return (
        <g key="l1280">
          <g data-disc="bulk mechanical" style={styleFor('bulk')}>
            <rect x={shaftX - 90} y={y - 14} width="40" height="22" fill="#262d36" stroke="#7a8593" strokeWidth="0.5" />
            <text x={shaftX - 70} y={y + 18} fontSize="7" fontFamily="'Source Sans 3'" fill="#7a6a4a" textAnchor="middle" letterSpacing="0.06em">LOADING STATION</text>
          </g>
          <g data-disc="mechanical" style={styleFor('mechanical')}>
            <polygon points={`${shaftX - 520},${y - 12} ${shaftX - 560},${y + 12} ${shaftX - 480},${y + 12} ${shaftX - 460},${y - 12}`}
                     fill="#c97a4f" stroke="#3a2010" strokeWidth="0.5" opacity="0.6" />
            <rect x={shaftX - 440} y={y - 8} width="16" height="14" fill="#3a4250" stroke="#7a8593" strokeWidth="0.4" />
            <line x1={shaftX - 424} y1={y} x2={shaftX - 410} y2={y - 6} stroke="#7a8593" strokeWidth="1.5" strokeLinecap="round" />
            <text x={shaftX - 490} y={y + 24} fontSize="7" fontFamily="'Source Sans 3'" fill="#7a6a4a" textAnchor="middle" letterSpacing="0.06em">DRILL BAY · STOPE</text>
          </g>
        </g>
      );})()}

      {/* Level -1600m: Deepest level — central conveyor to surface, refuge bay */}
      {(() => { const y = yFor(1600); return (
        <g key="l1600">
          <g data-disc="bulk civils" style={styleFor('bulk')}>
            {/* Conveyor along entire drift */}
            <line x1={shaftX - 580} y1={y - 4} x2={shaftX - 50} y2={y - 4} stroke="#7a8593" strokeWidth="2.4" />
            <line x1={shaftX - 580} y1={y - 4} x2={shaftX - 50} y2={y - 4}
                  stroke="#c97a4f" strokeWidth="2.8" strokeDasharray="6 14">
              <animate attributeName="stroke-dashoffset" from="0" to="-20" dur="1.8s" repeatCount="indefinite" />
            </line>
            <text x={shaftX - 300} y={y + 18} fontSize="7" fontFamily="'Source Sans 3'" fill="#7a6a4a" textAnchor="middle" letterSpacing="0.06em">DEEP CONVEYOR · TO SHAFT</text>
          </g>
          <g data-disc="civils" style={styleFor('civils')}>
            <rect x={shaftX - 720} y={y - 14} width="60" height="22" fill="none" stroke="#5a6473" strokeWidth="0.7" />
            <text x={shaftX - 690} y={y + 22} fontSize="6.5" fontFamily="'Source Sans 3'" fill="#7a6a4a" textAnchor="middle">REFUGE BAY</text>
          </g>
        </g>
      );})()}

      {/* ──── ANIMATED CAGE + COUNTERWEIGHT IN SHAFT ───────────────────── */}
      <g data-disc="mechanical" style={styleFor('mechanical')}>
        {/* Cage (yellow border) — moves between near-top and near-bottom */}
        <g>
          <rect x={shaftX - 10} y={surfaceY + 4} width="9" height="14"
                fill="#2a313b" stroke={SHADE.yellow} strokeWidth="0.7" />
          <line x1={shaftX - 8} y1={surfaceY + 10} x2={shaftX - 3} y2={surfaceY + 10}
                stroke={SHADE.yellow} strokeWidth="0.3" opacity="0.6" />
          <animateTransform attributeName="transform" type="translate"
            values={`0 0; 0 ${panelBottom - 40 - (surfaceY + 4)}; 0 ${panelBottom - 40 - (surfaceY + 4)}; 0 0; 0 0`}
            keyTimes="0; 0.4; 0.5; 0.9; 1" dur="22s" repeatCount="indefinite" />
        </g>
        {/* Skip (counterweight side — orange edge to suggest ore) — opposite phase */}
        <g>
          <rect x={shaftX + 1} y={surfaceY + 4} width="9" height="14"
                fill="#2a313b" stroke="#c97a4f" strokeWidth="0.7" />
          <animateTransform attributeName="transform" type="translate"
            values={`0 ${panelBottom - 40 - (surfaceY + 4)}; 0 0; 0 0; 0 ${panelBottom - 40 - (surfaceY + 4)}; 0 ${panelBottom - 40 - (surfaceY + 4)}`}
            keyTimes="0; 0.4; 0.5; 0.9; 1" dur="22s" repeatCount="indefinite" />
        </g>
      </g>

      {/* ──── ORE HOISTED UP IN THE SKIP ──────────────────────────────── */}
      {/* Ore travels up the shaft inside the skip car (animated above), not as
         a free-floating vertical stream — so only a static label here. */}
      <g data-disc="bulk mechanical" style={styleFor('bulk')}>
        <text x={shaftX + shaftHalfW + 8} y={surfaceY + 32} fontSize="8"
              fontFamily="'Source Sans 3'" fill="#c97a4f" letterSpacing="0.1em">↑ ORE UP (SKIP)</text>
      </g>

      {/* ──── VENTILATION RAISES — vertical narrow shafts with airflow ─── */}
      <g data-disc="civils mechanical" style={styleFor('civils')}>
        {[shaftX - 540, shaftX - 740].map((vx, i) => (
          <React.Fragment key={i}>
            <rect x={vx - 5} y={panelTop} width="10" height={panelBottom - panelTop}
                  fill="#08070a" stroke="#3a3020" strokeWidth="0.4" />
            {/* Level intersections */}
            {levels.map((lvl, li) => {
              const ly = yFor(lvl.m);
              return <line key={li} x1={vx - 5} y1={ly} x2={vx + 5} y2={ly}
                           stroke="#3a3020" strokeWidth="0.4" />;
            })}
            {/* Airflow indicator — animated arrow */}
            <g data-disc="mechanical" style={styleFor('mechanical')}>
              {[0, 0.5].map((b, j) => (
                <g key={j}>
                  <circle r="1.2" fill="#5a8fc8" opacity="0.6" />
                  <animateMotion dur="5s" begin={`${b * 5}s`} repeatCount="indefinite"
                                 path={`M ${vx} ${panelBottom - 30} L ${vx} ${panelTop + 30}`} rotate="0" />
                </g>
              ))}
            </g>
            <text x={vx} y={panelTop - 4} fontSize="7" fontFamily="'Source Sans 3'"
                  fill="#5a8fc8" letterSpacing="0.06em" textAnchor="middle">VENT</text>
          </React.Fragment>
        ))}
      </g>
    </g>
  );
}

// Winder house — separate building containing the hoist drum.
function Equip_WinderHouse({ styleFor }) {
  const x0 = -10, y0 = 50, w = 80, d = 70, h = 56;
  return (
    <>
      <g data-disc="civils" style={styleFor('civils')}>
        <IsoBox x={x0 - 6} y={y0 - 6} z={0} w={w + 12} d={d + 12} h={6}
                top="#2a313b" right="#1a1f28" front="#10141a" edge="#5a6473" edgeWidth={0.7} />
        {/* Winder building shell */}
        <IsoBox x={x0} y={y0} z={6} w={w} d={d} h={h}
                top="#252b34" right="#1a1f28" front="#0d1218" edge="#5a6473" />
        {/* Pitched roof */}
        <IsoChevronRoof x={x0} y={y0} z={6 + h} w={w} d={d} peakH={12}
                        top="#262d36" side="#171c23" edge="#5a6473" />
        {/* Side window strip */}
        {[16, 32, 48].map((dx, i) => (
          <IsoBox key={i} x={x0 + dx} y={y0 + d - 1} z={28} w={10} d={1} h={12}
                  top="#1a2028" right="#11161d" front="#0a0d12" edge="#3a4250" edgeWidth={0.4} />
        ))}
      </g>
      {/* Winder drum (large horizontal cylinder visible at one end of the building) */}
      <g data-disc="mechanical" style={styleFor('mechanical')}>
        <IsoHCylinder x={x0 + 10} y={y0 + 18} z={16} length={56} r={18}
                      top="#262d36" shell="#171c23" end="#0c1117" edge="#7a8593" />
        {/* Drive motor at one end */}
        <g data-disc="electrical mechanical" style={styleFor('electrical')}>
          <IsoHCylinder x={x0 + 66} y={y0 + 28} z={20} length={20} r={9}
                        top="#2a313b" shell="#1a1f28" end="#10141a" edge={SHADE.yellow} edgeWidth={0.7} ring={false} />
        </g>
      </g>
      {(() => { const lp = iso(x0 + w / 2, y0 + d + 14, 4); return (
        <text x={lp.X} y={lp.Y} textAnchor="middle" fontSize="8" fontFamily="'Source Sans 3'" fill="#7a8593" letterSpacing="0.08em">
          WINDER HOUSE
        </text>
      );})()}
    </>
  );
}

// ROM tip on the processing plant (left → right).
function Equip_OreExtractionConveyor({ styleFor }) {
  return (
    <>
      <g data-disc="civils" style={styleFor('civils')}>
        {/* Shaft ore bin — a small surface bin near the shaft */}
        <IsoBox x={-160} y={50} z={6} w={30} d={30} h={28}
                top="#262d36" right="#171c23" front="#0d1218" edge="#7a8593" edgeWidth={0.6} />
      </g>
      <g data-disc="bulk" style={styleFor('bulk')}>
        {/* Surface conveyor from ore bin to ROM */}
        <IsoConveyor x1={-130} x2={20} z1={34} z2={20} y={50} w={18} covered={false} />
        {/* Animated ore */}
        <BeltMaterial a={[-130, 59, 38]} b={[20, 59, 24]} dur={2.0} color="#c97a4f" />
      </g>
      {(() => { const lp = iso(-50, 80, 14); return (
        <text x={lp.X} y={lp.Y} textAnchor="middle" fontSize="7" fontFamily="'Source Sans 3'" fill="#7a8593">SHAFT → ROM</text>
      );})()}
    </>
  );
}

// ════════════════════════════════════════════════════════════════════════════
// ESKOM YARD — unchanged location (back-middle of the plant)
// ════════════════════════════════════════════════════════════════════════════
function Equip_EskomYard({ styleFor }) {
  const x0 = 1100, y0 = 380;
  const w = 540, d = 130;
  return (
    <>
      <g data-disc="civils" style={styleFor('civils')}>
        <IsoBox x={x0} y={y0} z={0} w={w} d={d} h={6}
                top="#2a313b" right="#1a1f28" front="#10141a" edge="#5a6473" edgeWidth={0.7} />
        {(() => {
          const posts = [];
          for (let xx = x0; xx <= x0 + w; xx += 22) {
            const a = iso(xx, y0, 6), b = iso(xx, y0, 26);
            const c = iso(xx, y0 + d, 6), e = iso(xx, y0 + d, 26);
            posts.push(<line key={`f1-${xx}`} x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke="#3a4250" strokeWidth="0.4" opacity="0.7" />);
            posts.push(<line key={`f2-${xx}`} x1={c.X} y1={c.Y} x2={e.X} y2={e.Y} stroke="#3a4250" strokeWidth="0.4" opacity="0.7" />);
          }
          for (let yy = y0; yy <= y0 + d; yy += 22) {
            const a = iso(x0, yy, 6), b = iso(x0, yy, 26);
            const c = iso(x0 + w, yy, 6), e = iso(x0 + w, yy, 26);
            posts.push(<line key={`f3-${yy}`} x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke="#3a4250" strokeWidth="0.4" opacity="0.7" />);
            posts.push(<line key={`f4-${yy}`} x1={c.X} y1={c.Y} x2={e.X} y2={e.Y} stroke="#3a4250" strokeWidth="0.4" opacity="0.7" />);
          }
          [[[x0, y0], [x0 + w, y0]], [[x0, y0 + d], [x0 + w, y0 + d]],
           [[x0, y0], [x0, y0 + d]], [[x0 + w, y0], [x0 + w, y0 + d]]].forEach(([a, b], i) => {
            const pa = iso(a[0], a[1], 26), pb = iso(b[0], b[1], 26);
            posts.push(<line key={`rt${i}`} x1={pa.X} y1={pa.Y} x2={pb.X} y2={pb.Y} stroke="#3a4250" strokeWidth="0.4" opacity="0.7" />);
          });
          return posts;
        })()}
      </g>
      <g data-disc="electrical" style={styleFor('electrical')}>
        {[0, 1, 2, 3].map((bay) => {
          const bx = x0 + 60 + bay * 110;
          return (
            <React.Fragment key={bay}>
              {[bx - 16, bx + 16].map((cx, i) => {
                const a = iso(cx, y0 + 20, 6), b = iso(cx, y0 + 20, 130);
                return <line key={`g${i}`} x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke="#5a6473" strokeWidth="1.2" />;
              })}
              {(() => {
                const a = iso(bx - 16, y0 + 20, 130), b = iso(bx + 16, y0 + 20, 130);
                return <line x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke="#5a6473" strokeWidth="0.9" />;
              })()}
              {[bx - 16, bx, bx + 16].map((cx, i) => {
                const a = iso(cx, y0 + 20, 130), b = iso(cx, y0 + 20, 152);
                return <line key={`la${i}`} x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke={SHADE.yellow} strokeWidth="0.7" />;
              })}
              {[bx - 12, bx, bx + 12].map((cx, i) => {
                const a = iso(cx, y0 + 20, 126), b = iso(cx, y0 + 20, 118);
                return <line key={`si${i}`} x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke="#7a8593" strokeWidth="0.6" />;
              })}
              <IsoBox x={bx - 8} y={y0 + 50} z={32} w={16} d={8} h={6}
                      top="#2a313b" right="#1a1f28" front="#10141a" edge={SHADE.yellow} edgeWidth={0.5} />
              {(() => {
                const a = iso(bx, y0 + 54, 6), b = iso(bx, y0 + 54, 32);
                return <line x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke="#7a8593" strokeWidth="0.8" />;
              })()}
              <IsoVCylinder x={bx} y={y0 + 70} z={6} r={6} h={26}
                            top="#262d36" shell="#171c23" edge={SHADE.yellow} capRing={false} />
              <IsoBox x={bx - 4} y={y0 + 66} z={32} w={8} d={8} h={6}
                      top="#2a313b" right="#1a1f28" front="#10141a" edge={SHADE.yellow} edgeWidth={0.5} />
              <IsoVCylinder x={bx} y={y0 + 90} z={6} r={3} h={28}
                            top="#262d36" shell="#171c23" edge="#7a8593" capRing={false} />
              {(() => { const lp = iso(bx, y0 + 110, 4); return (
                <text x={lp.X} y={lp.Y} textAnchor="middle" fontSize="7" fontFamily="'Source Sans 3'" fill="#5a6473">
                  BAY {String(bay + 1).padStart(2, '0')}
                </text>
              );})()}
            </React.Fragment>
          );
        })}
        {(() => {
          const a = iso(x0 + 30, y0 + 30, 110), b = iso(x0 + w - 30, y0 + 30, 110);
          return <line x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke={SHADE.yellow} strokeWidth="2" opacity="0.8" />;
        })()}
        {(() => {
          const a = iso(x0 + 30, y0 + 60, 92), b = iso(x0 + w - 30, y0 + 60, 92);
          return <line x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke={SHADE.yellow} strokeWidth="1.5" opacity="0.7" />;
        })()}
        <IsoBox x={x0 + 240} y={y0 + d - 50} z={6} w={70} d={40} h={56}
                top="#2a313b" right="#1a1f28" front="#10141a" edge={SHADE.yellow} edgeWidth={1} />
        {[x0 + 252, x0 + 272, x0 + 292].map((bx, i) => {
          const a = iso(bx, y0 + d - 42, 62), b = iso(bx, y0 + d - 42, 82);
          return (
            <g key={i}>
              <line x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke="#7a8593" strokeWidth="1.4" />
              <circle cx={b.X} cy={b.Y} r="1.8" fill="#3a4250" stroke="#7a8593" strokeWidth="0.4" />
            </g>
          );
        })}
        {[0, 1, 2, 3, 4, 5].map((i) => {
          const px = x0 + 246 + i * 11;
          const a = iso(px, y0 + d - 12, 12), b = iso(px, y0 + d - 12, 56);
          return <line key={i} x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke="#3a4250" strokeWidth="0.5" />;
        })}
        <IsoHCylinder x={x0 + 244} y={y0 + 8} z={62} length={62} r={7}
                      top="#262d36" shell="#171c23" end="#0d1218" edge={SHADE.yellow} edgeWidth={0.6} ring={false} />
        <IsoBox x={x0 + 20} y={y0 + 90} z={6} w={36} d={32} h={24}
                top="#262d36" right="#171c23" front="#0d1218" edge={SHADE.yellow} edgeWidth={0.7} />
        {/* Incoming HV transmission lines — supported by lattice pylons
            stepping back from the yard into the distance */}
        {(() => {
          // Pylon footprint positions (world coords) from yard back to off-screen.
          // Pylons sit BEHIND the yard (lower y) and march away from the camera.
          const pylons = [
            { x: x0 + 220, y: y0 - 90,  h: 160 },
            { x: x0 + 60,  y: y0 - 230, h: 180 },
          ];
          // Yard-side bus attachment points (top of each bay's lightning arrestor)
          const yardConns = [
            [x0 + 60,  y0 + 20, 150],
            [x0 + 170, y0 + 20, 150],
            [x0 + 280, y0 + 20, 150],
            [x0 + 390, y0 + 20, 150],
          ];
          // For each pylon, three cross-arm conductor anchor points
          const conductorsAt = (p) => [
            { x: p.x - 22, y: p.y, z: p.h - 6 },
            { x: p.x,      y: p.y, z: p.h + 2 },
            { x: p.x + 22, y: p.y, z: p.h - 6 },
          ];

          const out = [];

          // ── Draw each pylon (lattice steel transmission tower) ──
          pylons.forEach((p, i) => {
            const baseHalf = 14;          // half-width at ground
            const topHalf  = 5;           // half-width at top of tower body
            const bodyH    = p.h - 14;    // tower body height (below cross-arms)
            // Four corner legs, tapered
            const legs = [
              [-baseHalf, -baseHalf, -topHalf, -topHalf],
              [ baseHalf, -baseHalf,  topHalf, -topHalf],
              [-baseHalf,  baseHalf, -topHalf,  topHalf],
              [ baseHalf,  baseHalf,  topHalf,  topHalf],
            ];
            legs.forEach(([bx, by, tx, ty], li) => {
              const a = iso(p.x + bx, p.y + by, 0);
              const b = iso(p.x + tx, p.y + ty, bodyH);
              out.push(<line key={`py${i}-leg${li}`} x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke="#5a6473" strokeWidth="0.9" />);
            });
            // Horizontal bracing rings at four heights
            [0.25, 0.5, 0.75, 1].forEach((t, ri) => {
              const z = bodyH * t;
              const half = baseHalf + (topHalf - baseHalf) * t;
              const corners = [
                [-half, -half], [ half, -half],
                [ half,  half], [-half,  half],
              ];
              for (let c = 0; c < 4; c++) {
                const [ax, ay] = corners[c];
                const [bx2, by2] = corners[(c + 1) % 4];
                const a = iso(p.x + ax, p.y + ay, z);
                const b = iso(p.x + bx2, p.y + by2, z);
                out.push(<line key={`py${i}-ring${ri}-${c}`} x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke="#3a4250" strokeWidth="0.5" opacity="0.8" />);
              }
            });
            // X-bracing between rings on the front + back faces
            [0, 1, 2].forEach((seg) => {
              const t1 = 0.25 * seg, t2 = 0.25 * (seg + 1);
              const z1 = bodyH * t1, z2 = bodyH * t2;
              const h1 = baseHalf + (topHalf - baseHalf) * t1;
              const h2 = baseHalf + (topHalf - baseHalf) * t2;
              // front face (lower y)
              {
                const a1 = iso(p.x - h1, p.y - h1, z1);
                const b1 = iso(p.x + h2, p.y - h2, z2);
                const a2 = iso(p.x + h1, p.y - h1, z1);
                const b2 = iso(p.x - h2, p.y - h2, z2);
                out.push(<line key={`py${i}-xf-${seg}-a`} x1={a1.X} y1={a1.Y} x2={b1.X} y2={b1.Y} stroke="#3a4250" strokeWidth="0.4" opacity="0.7" />);
                out.push(<line key={`py${i}-xf-${seg}-b`} x1={a2.X} y1={a2.Y} x2={b2.X} y2={b2.Y} stroke="#3a4250" strokeWidth="0.4" opacity="0.7" />);
              }
              // side face (right)
              {
                const a1 = iso(p.x + h1, p.y - h1, z1);
                const b1 = iso(p.x + h2, p.y + h2, z2);
                const a2 = iso(p.x + h1, p.y + h1, z1);
                const b2 = iso(p.x + h2, p.y - h2, z2);
                out.push(<line key={`py${i}-xs-${seg}-a`} x1={a1.X} y1={a1.Y} x2={b1.X} y2={b1.Y} stroke="#3a4250" strokeWidth="0.4" opacity="0.7" />);
                out.push(<line key={`py${i}-xs-${seg}-b`} x1={a2.X} y1={a2.Y} x2={b2.X} y2={b2.Y} stroke="#3a4250" strokeWidth="0.4" opacity="0.7" />);
              }
            });
            // Cross-arms (the wide horizontal yokes that carry the conductors).
            // One stepped, two-tier arrangement so it reads as a real HV tower.
            const arms = [
              { z: bodyH + 4, len: 26 },
              { z: bodyH + 12, len: 18 },
            ];
            arms.forEach((arm, ai) => {
              const za = arm.z;
              // Top chord
              const la = iso(p.x - arm.len, p.y, za);
              const lb = iso(p.x + arm.len, p.y, za);
              out.push(<line key={`py${i}-arm${ai}-top`} x1={la.X} y1={la.Y} x2={lb.X} y2={lb.Y} stroke="#5a6473" strokeWidth="0.9" />);
              // Diagonal braces from tower body up to arm tips
              const bodyL = iso(p.x - topHalf, p.y, bodyH);
              const bodyR = iso(p.x + topHalf, p.y, bodyH);
              out.push(<line key={`py${i}-arm${ai}-bL`} x1={bodyL.X} y1={bodyL.Y} x2={la.X} y2={la.Y} stroke="#5a6473" strokeWidth="0.7" />);
              out.push(<line key={`py${i}-arm${ai}-bR`} x1={bodyR.X} y1={bodyR.Y} x2={lb.X} y2={lb.Y} stroke="#5a6473" strokeWidth="0.7" />);
            });
            // Insulator strings hanging from the lower (long) cross-arm
            conductorsAt(p).forEach((cp, ci) => {
              const top = iso(cp.x, cp.y, bodyH + 4);
              const bot = iso(cp.x, cp.y, cp.z);
              out.push(<line key={`py${i}-ins${ci}`} x1={top.X} y1={top.Y} x2={bot.X} y2={bot.Y} stroke="#7a8593" strokeWidth="0.5" />);
              out.push(<circle key={`py${i}-insd${ci}`} cx={bot.X} cy={bot.Y} r="1" fill="#3a4250" stroke="#7a8593" strokeWidth="0.3" />);
            });
          });

          // ── String conductors: yard → pylon[0] → pylon[1] → off-screen ──
          const offscreen = { x: x0 - 320, y: y0 - 360, h: 200 };
          const chain = [pylons[0], pylons[1], offscreen];
          // For each of three conductors, follow successive pylon anchor points.
          // Yard side connects to four bus risers — group them onto the three conductors.
          const yardGroups = [
            [yardConns[0], yardConns[1]],
            [yardConns[1], yardConns[2]],
            [yardConns[2], yardConns[3]],
          ];
          for (let ci = 0; ci < 3; ci++) {
            // From each yard riser in the group to the first pylon anchor
            const firstAnchor = conductorsAt(pylons[0])[ci];
            yardGroups[ci].forEach((yc, yi) => {
              const a = iso(yc[0], yc[1], yc[2]);
              const b = iso(firstAnchor.x, firstAnchor.y, firstAnchor.z);
              out.push(<line key={`cd-y-${ci}-${yi}`} x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke={SHADE.yellow} strokeWidth="0.8" opacity="0.7" />);
            });
            // Pylon-to-pylon span (gentle sag in screen space)
            for (let pi = 0; pi < chain.length - 1; pi++) {
              const fromP = chain[pi];
              const toP = chain[pi + 1];
              const fromAnchor = fromP === offscreen ? null : conductorsAt(fromP)[ci];
              const toAnchor = toP === offscreen ? null : conductorsAt(toP)[ci];
              const fa = fromAnchor
                ? iso(fromAnchor.x, fromAnchor.y, fromAnchor.z)
                : iso(fromP.x + (ci - 1) * 20, fromP.y, fromP.h - 6);
              const ta = toAnchor
                ? iso(toAnchor.x, toAnchor.y, toAnchor.z)
                : iso(toP.x + (ci - 1) * 20, toP.y, toP.h - 6);
              // Sag: midpoint is dropped a bit
              const mx = (fa.X + ta.X) / 2;
              const my = (fa.Y + ta.Y) / 2 + 6;
              out.push(
                <path key={`cd-${ci}-${pi}`}
                      d={`M ${fa.X} ${fa.Y} Q ${mx} ${my} ${ta.X} ${ta.Y}`}
                      fill="none" stroke={SHADE.yellow} strokeWidth="0.8" opacity="0.7" />
              );
            }
          }
          // Earth wire (single shield wire at very top — thinner, dimmer)
          {
            const peaks = pylons.map((p) => iso(p.x, p.y, p.h + 16));
            for (let i = 0; i < peaks.length - 1; i++) {
              const fa = peaks[i], ta = peaks[i + 1];
              const mx = (fa.X + ta.X) / 2;
              const my = (fa.Y + ta.Y) / 2 + 4;
              out.push(
                <path key={`ew-${i}`}
                      d={`M ${fa.X} ${fa.Y} Q ${mx} ${my} ${ta.X} ${ta.Y}`}
                      fill="none" stroke={SHADE.yellow} strokeWidth="0.4" opacity="0.45" />
              );
            }
            // last span out to off-screen
            const lastPeak = peaks[peaks.length - 1];
            const off = iso(offscreen.x, offscreen.y, offscreen.h + 16);
            out.push(
              <line key="ew-off" x1={lastPeak.X} y1={lastPeak.Y} x2={off.X} y2={off.Y}
                    stroke={SHADE.yellow} strokeWidth="0.4" opacity="0.4" />
            );
          }

          return out;
        })()}
        {/* Outgoing feeder to existing plant substation */}
        {(() => {
          const a = iso(x0 + 275, y0 + d - 30, 60);
          const b = iso(750, 300, 50);
          return <line x1={a.X} y1={a.Y} x2={b.X} y2={b.Y} stroke={SHADE.yellow} strokeWidth="1" opacity="0.7" />;
        })()}
      </g>
      {(() => { const lp = iso(x0 + w / 2, y0 + d + 16, 8); return (
        <text x={lp.X} y={lp.Y} textAnchor="middle" fontSize="9" fontFamily="'Source Sans 3'" fill={SHADE.yellow} letterSpacing="0.1em">
          ESKOM 132 kV INCOMING YARD
        </text>
      );})()}
    </>
  );
}

// ════════════════════════════════════════════════════════════════════════════
// LIVING-PLANT OVERLAYS — drawn on top of static equipment
// ════════════════════════════════════════════════════════════════════════════
function PlantLifeOverlays({ styleFor }) {
  return (
    <>
      <g data-disc="bulk" style={styleFor('bulk')}>
        <BeltMaterial a={[300, 43, 70]} b={[600, 43, 230]} dur={2.4} color="#c97a4f" />
      </g>
      <g data-disc="bulk" style={styleFor('bulk')}>
        <BeltMaterial a={[745, 71, 22]} b={[905, 71, 112]} dur={1.8} color="#c97a4f" />
      </g>
      <g data-disc="mechanical" style={styleFor('mechanical')}>
        {(() => { const p = iso(1410, 100, 36); return <ThickenerRake cx={p.X} cy={p.Y} r={42} dur={45} />; })()}
      </g>
      <g data-disc="mechanical" style={styleFor('mechanical')}>
        {(() => { const p = iso(2780, 230, 46); return <ThickenerRake cx={p.X} cy={p.Y} r={64} dur={60} />; })()}
      </g>
      <g data-disc="mechanical" style={styleFor('mechanical')}>
        {(() => { const p = iso(925, -15, 118); return <MillDrumSpin cx={p.X} cy={p.Y} r={42} dur={5.5} />; })()}
      </g>
      <g data-disc="mechanical" style={styleFor('mechanical')}>
        {(() => { const p = iso(925, 110, 110); return <MillDrumSpin cx={p.X} cy={p.Y} r={36} dur={7} dir={-1} />; })()}
      </g>
      <g data-disc="mechanical" style={styleFor('mechanical')}>
        <Worker x={1450} y={75} z={70} range={20} dur={6} />
        <Worker x={1820} y={75} z={70} range={26} dur={7.5} />
        <Worker x={2200} y={75} z={70} range={22} dur={6.5} />
      </g>
    </>
  );
}

Object.assign(window, {
  BeltMaterial, MoverOnPath, SheaveWheel, ThickenerRake, MillDrumSpin, ShaftCage, Worker,
  Equip_EskomYard, Equip_Headframe, Equip_WinderHouse,
  Equip_OreExtractionConveyor, PlantLifeOverlays,
});
