// CDN-compatible: React and ReactDOM loaded globally from index.html
/* import React, { useState } from 'react'; */
const { useState, useEffect, useRef } = React;

// ════════════════════════════════════════════════
// COLOR PALETTE
// ════════════════════════════════════════════════
const C = {
  // Layout
  bg:           '#f0f4f8',
  panel:        '#ffffff',
  panelAlt:     '#f8fafc',
  border:       '#cbd5e1',
  borderStrong: '#94a3b8',
  text:         '#0f172a',
  textMuted:    '#475569',
  textLight:    '#94a3b8',
  // Accent
  blue:         '#0284c7',
  blueLight:    '#e0f2fe',
  // Status
  green:        '#15803d',
  greenBg:      '#dcfce7',
  greenBorder:  '#86efac',
  red:          '#dc2626',
  redBg:        '#fee2e2',
  redBorder:    '#fca5a5',
  orange:       '#ea580c',
  orangeBg:     '#fff7ed',
  yellow:       '#ca8a04',
  yellowBg:     '#fefce8',
  // Pipe / Flow colors
  rawCold:      '#0ea5e9',
  preheating:   '#f59e0b',
  heating:      '#f97316',
  hotTemp:      '#ef4444',
  pasteurized:  '#16a34a',
  cooling:      '#0891b2',
  coldStorage:  '#0284c7',
  diverted:     '#dc2626',
  deadLeg:      '#94a3b8',
  cip:          '#9333ea',
  // SVG component fills
  tankFill:     '#dbeafe',
  pheFill:      '#fef3c7',
  coolerFill:   '#cffafe',
  valveBody:    '#e2e8f0',
  pumpBody:     '#e0f2fe',
  hotJacket:    '#fed7aa',
};

// ════════════════════════════════════════════════
// PMO CONSTANTS
// ════════════════════════════════════════════════
const PMO = {
  htst: {
    standard: { tempF: 161, tempC: 72,  holdSec: 15,   label: 'Standard Milk' },
    highFat:  { tempF: 166, tempC: 74,  holdSec: 15,   label: '≥10% Fat / ≥18% Solids' },
    eggnog:   { tempF: 175, tempC: 80,  holdSec: 25,   label: 'Eggnog' },
    alt1:     { tempF: 191, tempC: 89,  holdSec: 1.0,  label: '191°F / 1.0 sec' },
    alt2:     { tempF: 194, tempC: 90,  holdSec: 0.5,  label: '194°F / 0.5 sec' },
    alt3:     { tempF: 201, tempC: 94,  holdSec: 0.1,  label: '201°F / 0.1 sec' },
    alt4:     { tempF: 204, tempC: 96,  holdSec: 0.05, label: '204°F / 0.05 sec' },
    alt5:     { tempF: 212, tempC: 100, holdSec: 0.01, label: '212°F / 0.01 sec' },
  },
  regenMinDeltaP_psi: 1.0,
  maxStorageTemp_F:   45,
};

// ════════════════════════════════════════════════
// DIVERT CONDITIONS — ALL 12
// ════════════════════════════════════════════════
const DIVERT_CONDITIONS = [
  {
    id: 'TEMP_LOW',
    label: 'Holding Tube Temp Below Minimum',
    pmoRef: 'PMO §16p(B)(3) — TLC',
    check: (p, req) => p.holdTemp >= req.tempF,
    display: (p, req) => `${p.holdTemp.toFixed(1)}°F vs ${req.tempF}°F min`,
    explanation: 'The Thermal Limit Controller (TLC) sensor at the holding tube outlet de-energizes the FDD solenoid whenever temperature drops below the legal minimum. Forward flow is mechanically blocked. The system was sealed by the Regulatory Agency and cannot be overridden.',
  },
  {
    id: 'HOLD_TIME_SHORT',
    label: 'Holding Time Below Minimum',
    pmoRef: 'PMO §16p(B)(2)(3) — Timing Pump',
    check: (p, req) => p.calcHoldSec >= req.holdSec,
    display: (p, req) => `${p.calcHoldSec.toFixed(3)}s vs ${req.holdSec}s min`,
    explanation: 'Holding time is calculated for the FASTEST particle through the tube. If flow rate is too high or tube too short, product exits before completing the required hold. The timing pump speed is sealed at a maximum by the Regulatory Agency.',
  },
  {
    id: 'REGEN_DP',
    label: 'Regenerator ΔP Failure (< 1 PSI)',
    pmoRef: 'PMO §16p(B)(4) — DPC',
    check: (p) => (p.regenPastPSI - p.regenRawPSI) >= 1.0,
    display: (p) => `ΔP = ${(p.regenPastPSI - p.regenRawPSI).toFixed(1)} PSI (need ≥1.0)`,
    explanation: 'Pasteurized product must ALWAYS exceed raw milk pressure in the regenerator by ≥1 PSI (6.9 kPa). This ensures any pinhole leak flows pasteurized→raw, never raw→pasteurized. The Differential Pressure Controller trips the FDD to divert if this margin is lost.',
  },
  {
    id: 'STARTUP',
    label: 'Startup — System Not Yet At Temperature',
    pmoRef: 'PMO §16p(B)(3) — TLC Cut-In',
    check: (p) => p.systemState !== 'startup',
    display: () => 'System must reach min temp before forward flow allowed',
    explanation: 'At startup, all flow diverts until the holding tube outlet sensor confirms temperature at or above minimum. The water/product used for heating is diverted to drain or balance tank. Forward flow is blocked until temperature is achieved and sustained.',
  },
  {
    id: 'FLOW_EXCEEDED',
    label: 'Flow Rate Exceeds Sealed Maximum',
    pmoRef: 'PMO §16p(B)(2) — Timing Pump Sealed',
    check: (p) => p.flowGPH <= p.sealedMaxGPH,
    display: (p) => `${Math.round(p.flowGPH)} GPH vs sealed max ${p.sealedMaxGPH} GPH`,
    explanation: 'The timing pump is tested and sealed at a maximum speed corresponding to the minimum legal hold time. Exceeding this rate means the fastest milk particle exits the holding tube before completing the required hold time.',
  },
  {
    id: 'POWER_LOSS',
    label: 'Power / Signal Loss (Fail-Safe Divert)',
    pmoRef: 'PMO §16p(B)(2) — FDD Fail-Safe Design',
    check: (p) => p.powerState === 'normal',
    display: () => 'FDD solenoid de-energized → spring return to divert',
    explanation: 'The FDD is fail-safe to DIVERT. The solenoid is energized to hold the valve in forward position. Any power loss, signal loss, or controller fault causes a spring to automatically drive the valve to divert. Product cannot flow forward without an active control signal.',
  },
  {
    id: 'RECORDER_FAIL',
    label: 'Temperature Recorder Malfunction',
    pmoRef: 'PMO §16p(B)(1) — Recorder-Controller Required',
    check: (p) => p.recorderState === 'ok',
    display: () => 'Recording thermometer must be functional and calibrated',
    explanation: 'A recording thermometer that continuously charts holding tube outlet temperature is required by PMO. If it malfunctions or goes out of calibration, the pasteurization record cannot be verified, processing must stop, and the FDD must divert.',
  },
  {
    id: 'VAT_OUTLET_EARLY',
    label: 'VAT: Outlet Opened Before Hold Complete',
    pmoRef: 'PMO §16p(A) — Vat Outlet Valve',
    vatOnly: true,
    check: (p) => !(p.vatOutletOpen && p.vatHoldElapsed < p.vatHoldRequired),
    display: (p) => `${p.vatHoldElapsed}/${p.vatHoldRequired} min`,
    explanation: 'The VAT outlet valve must remain CLOSED and physically disconnected for the entire hold period. Opening early means milk has not completed the required hold and is not legally pasteurized.',
  },
  {
    id: 'VAT_TEMP_DROP',
    label: 'VAT: Temperature Drop During Hold',
    pmoRef: 'PMO §16p(A) — Vat Temperature',
    vatOnly: true,
    check: (p, req) => !(p.vatPhase === 'holding' && p.vatTemp < req.tempF),
    display: (p, req) => `${p.vatTemp}°F vs ${req.tempF}°F — hold timer resets if temp drops`,
    explanation: 'Vat temperature must be maintained at or above minimum for the ENTIRE hold period. Any drop resets the 30-minute timer to zero. The vat must be reheated before a new hold can begin.',
  },
  {
    id: 'HHST_FDD_POS',
    label: 'HHST: FDD Must Be Downstream of Cooler',
    pmoRef: 'PMO §16p(B) — HHST FDD Placement',
    hhstOnly: true,
    check: (p) => p.fddPlacement === 'downstream-of-cooler',
    display: () => 'HHST requires FDD after cooler, not before',
    explanation: 'For HHST systems, the FDD must be located downstream of the cooling section. Unlike HTST, product at HHST temperatures is under high pressure and cannot be returned directly to the balance tank. This is a fundamental design requirement.',
  },
  {
    id: 'BALANCE_TANK',
    label: 'Balance Tank Overflow Margin < 12 Inches',
    pmoRef: 'PMO §16p(B)(4) — CLT Elevation',
    check: (p) => p.overflowMarginIn >= 12,
    display: (p) => `${p.overflowMarginIn.toFixed(1)}" margin (need ≥12")`,
    explanation: 'The constant-level tank overflow must be at least 12 inches below the lowest milk-contact level in the regenerator. This gravity barrier prevents raw milk from siphoning into the pasteurized product circuit if pressure is lost.',
  },
  {
    id: 'CIP_ACTIVE',
    label: 'CIP / Sanitation In Progress',
    pmoRef: 'PMO §16p(B) — Product/CIP Separation',
    check: (p) => p.systemState !== 'cip',
    display: () => 'No product processing during CIP cycles',
    explanation: 'During CIP and sanitation cycles, caustic and acid solutions are circulating through the product-contact surfaces. The FDD must be in divert and milk must not enter the system. Forward flow cannot resume until CIP is complete, the system is rinsed, and brought back to pasteurization temperature.',
  },
];

// ════════════════════════════════════════════════
// PIPE STATE DEFINITIONS
// ════════════════════════════════════════════════
const PIPE_STATES = {
  RAW_COLD:     { color: C.rawCold,     dasharray: '10 5', animated: true },
  PREHEATING:   { color: C.preheating,  dasharray: '10 5', animated: true },
  HEATING:      { color: C.heating,     dasharray: '10 5', animated: true },
  HOT_TEMP:     { color: C.hotTemp,     dasharray: '10 5', animated: true },
  PASTEURIZED:  { color: C.pasteurized, dasharray: '10 5', animated: true },
  COOLING:      { color: C.cooling,     dasharray: '10 5', animated: true },
  DIVERTED:     { color: C.diverted,    dasharray: '10 6', animated: true },
  DEAD_LEG:     { color: C.deadLeg,     dasharray: '3 9',  animated: false },
  COLD_STORAGE: { color: C.coldStorage, dasharray: '10 5', animated: true },
};

// ════════════════════════════════════════════════
// ANIMATED PIPE
// ════════════════════════════════════════════════
function AnimatedPipe({ d, state, flowRate = 3000, reverse = false }) {
  const ps = PIPE_STATES[state] || PIPE_STATES.DEAD_LEG;
  const duration = ps.animated ? Math.max(0.4, 3 / (flowRate / 1000)).toFixed(2) : '9999';
  const animName = reverse ? 'pipFlowRev' : 'pipFlowFwd';
  return (
    <path
      d={d}
      fill="none"
      stroke={ps.color}
      strokeWidth={5}
      strokeLinecap="round"
      strokeLinejoin="round"
      strokeDasharray={ps.dasharray}
      style={{
        animation: ps.animated ? `${animName} ${duration}s linear infinite` : 'none',
      }}
    />
  );
}

// ════════════════════════════════════════════════
// FDD VALVE
// ════════════════════════════════════════════════
function FDDValve({ x, y, state }) {
  const isForward = state === 'forward';
  const ledColor  = isForward ? C.green : C.red;
  const discRot   = isForward ? 0 : 90;

  return (
    <g>
      {/* Solenoid body */}
      <rect
        x={x - 15} y={y - 46} width={30} height={20} rx={3}
        fill={isForward ? C.green + '44' : 'none'}
        stroke={isForward ? C.green : C.red}
        strokeWidth={1.5}
      />
      <text x={x} y={y - 33} textAnchor="middle" fontSize={7} fill={isForward ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">
        SOLENOID
      </text>
      {/* Stem */}
      <line x1={x} y1={y - 26} x2={x} y2={y - 22} stroke={C.border} strokeWidth={2} />
      {/* Status LED */}
      <circle cx={x + 20} cy={y - 40} r={5} fill={ledColor} style={{ filter: `drop-shadow(0 0 4px ${ledColor})` }} />
      {/* LED label */}
      <text x={x + 32} y={y - 37} fontSize={7} fill={ledColor} fontFamily="'Share Tech Mono', monospace">
        {isForward ? 'FWD' : 'DIV'}
      </text>

      {/* Valve body */}
      <circle cx={x} cy={y} r={22} fill={C.panel} stroke={C.border} strokeWidth={2} />

      {/* Port stubs */}
      {/* Inlet (left) */}
      <line x1={x - 38} y1={y} x2={x - 22} y2={y} stroke={C.rawCold} strokeWidth={4} strokeLinecap="round" />
      {/* Forward outlet (right) */}
      <line x1={x + 22} y1={y} x2={x + 38} y2={y} stroke={isForward ? C.pasteurized : C.deadLeg} strokeWidth={4} strokeLinecap="round" />
      {/* Divert outlet (down) */}
      <line x1={x} y1={y + 22} x2={x} y2={y + 38} stroke={!isForward ? C.diverted : C.deadLeg} strokeWidth={4} strokeLinecap="round" />

      {/* Leak escape stub (between outlet seats) */}
      <line x1={x + 10} y1={y + 22} x2={x + 10} y2={y + 32} stroke={C.border} strokeWidth={1.5} />
      <circle cx={x + 10} cy={y + 34} r={3} fill="none" stroke={C.border} strokeWidth={1.5} />

      {/* Rotating plug disc */}
      <g style={{
        transform: `rotate(${discRot}deg)`,
        transformOrigin: `${x}px ${y}px`,
        transition: 'transform 0.35s ease-in-out',
      }}>
        <rect x={x - 17} y={y - 5} width={34} height={10} rx={4}
          fill={isForward ? C.pasteurized : C.diverted} opacity={0.85}
        />
      </g>

      {/* Blocked port X markers */}
      {/* Forward X when diverting */}
      {!isForward && (
        <g>
          <line x1={x + 28} y1={y - 5} x2={x + 38} y2={y + 5} stroke={C.red} strokeWidth={2} />
          <line x1={x + 38} y1={y - 5} x2={x + 28} y2={y + 5} stroke={C.red} strokeWidth={2} />
        </g>
      )}
      {/* Divert X when forwarding */}
      {isForward && (
        <g>
          <line x1={x - 5} y1={y + 28} x2={x + 5} y2={y + 38} stroke={C.red} strokeWidth={2} />
          <line x1={x + 5} y1={y + 28} x2={x - 5} y2={y + 38} stroke={C.red} strokeWidth={2} />
        </g>
      )}

      {/* Port labels */}
      <text x={x - 50} y={y + 18} textAnchor="middle" fontSize={7} fill={C.rawCold} fontFamily="'Share Tech Mono', monospace">INLET</text>
      <text x={x + 56} y={y + 18} textAnchor="middle" fontSize={7} fill={isForward ? C.pasteurized : C.deadLeg} fontFamily="'Share Tech Mono', monospace">{isForward ? '▶FWD' : 'FWD✕'}</text>
      <text x={x} y={y + 56} textAnchor="middle" fontSize={7} fill={!isForward ? C.diverted : C.deadLeg} fontFamily="'Share Tech Mono', monospace">{!isForward ? '▼DIV' : 'DIV✕'}</text>

      {/* Center label */}
      <text x={x} y={y + 4} textAnchor="middle" fontSize={9} fill="#0f172a" fontWeight="bold" fontFamily="'Share Tech Mono', monospace">FDD</text>
    </g>
  );
}

// ════════════════════════════════════════════════
// HTST REGEN DIAGRAM — MAIN SVG
// ════════════════════════════════════════════════
function HTSTRegenDiagram({ params, fddState, req, calcHoldSec }) {
  const { regenRawPSI, regenPastPSI, flowGPH, holdTemp, finalCoolF, overflowMarginIn } = params;
  const deltaP    = regenPastPSI - regenRawPSI;
  const deltaPOk  = deltaP >= 1.0;
  const storageOk = finalCoolF <= PMO.maxStorageTemp_F;
  const holdOk    = calcHoldSec >= req.holdSec;
  const tempOk    = holdTemp >= req.tempF;

  // Pipe states for forward / divert paths
  const fwdState  = fddState === 'forward' ? 'PASTEURIZED' : 'DEAD_LEG';
  const divState  = fddState === 'divert'  ? 'DIVERTED'    : 'DEAD_LEG';
  const coolState = fddState === 'forward' ? 'COOLING'     : 'DEAD_LEG';
  const stgState  = fddState === 'forward' ? (storageOk ? 'COLD_STORAGE' : 'HOT_TEMP') : 'DEAD_LEG';

  // Layout — ONE regen block, two rows
  const RAW_Y  = 130;  // Row 1: raw milk pipe centerline
  const PAST_Y = 200;  // Row 2: pasteurized return pipe centerline (bottom half of regen)
  const DIV_Y  = 410;  // Divert pipe horizontal run
  // Regen block: x=230–390, top y=80, height=160, mid at y=160
  const RG = { x: 230, y: 80, w: 160, h: 160 };
  const FDD_X = 840;

  return (
    <svg viewBox="0 0 960 520" width="100%" style={{ background: '#f8fafc', display: 'block' }}>

      <defs>
        <pattern id="grid-htst-regen" width="40" height="40" patternUnits="userSpaceOnUse">
          <path d="M 40 0 L 0 0 0 40" fill="none" stroke="#e2e8f0" strokeWidth="0.5"/>
        </pattern>
        <marker id="arr-grn" markerWidth="7" markerHeight="7" refX="5" refY="3.5" orient="auto">
          <path d="M0,0 L0,7 L7,3.5 z" fill={C.pasteurized} />
        </marker>
        <marker id="arr-red" markerWidth="7" markerHeight="7" refX="5" refY="3.5" orient="auto">
          <path d="M0,0 L0,7 L7,3.5 z" fill="#dc2626" />
        </marker>
      </defs>
      <rect width="960" height="520" fill="#f8fafc" rx="8" />
      <rect width="960" height="520" fill="url(#grid-htst-regen)" />

      {/* ── BALANCE TANK ─────────────────────────── */}
      {/* Tank walls (open top, 3 sides) */}
      <polyline points="10,75 10,195 80,195 80,75" fill="none" stroke={C.border} strokeWidth={2.5} />
      {/* Overflow notch in right wall */}
      <line x1="80" y1="88" x2="80" y2="102" stroke="#f8fafc" strokeWidth={5} />
      {/* Overflow standpipe */}
      <line x1="80" y1="95" x2="97" y2="95" stroke={C.border} strokeWidth={2} />
      <line x1="97" y1="75" x2="97" y2="95" stroke={C.border} strokeWidth={2} />
      {/* Milk fill */}
      <rect x="11" y="148" width="68" height="46" fill={C.rawCold} fillOpacity={0.13} />
      <path d="M11,148 Q24,145 36,148 Q52,151 64,148 Q72,145 79,148" fill="none" stroke={C.rawCold} strokeWidth={1.5} />
      {/* Labels (below tank, clear of pasteurized path at y=200) */}
      <text x="45" y="248" textAnchor="middle" fontSize={8} fill={C.blue} fontFamily="'Share Tech Mono', monospace">BALANCE TANK</text>
      <text x="45" y="258" textAnchor="middle" fontSize={8} fill={C.blue} fontFamily="'Share Tech Mono', monospace">/ CLT</text>
      <text x="45" y="270" textAnchor="middle" fontSize={8} fill={overflowMarginIn >= 12 ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">
        {`↕${overflowMarginIn.toFixed(0)}" ovf margin`}
      </text>

      {/* ── PIPE: BT → Booster ───────────────────── */}
      <AnimatedPipe d={`M 80 ${RAW_Y} H 130`} state="RAW_COLD" flowRate={flowGPH} />

      {/* ── BOOSTER PUMP ─────────────────────────── */}
      <circle cx={148} cy={RAW_Y} r={18} fill={C.panel} stroke={C.border} strokeWidth={2} />
      {[0, 60, 120, 180, 240, 300].map(deg => {
        const r2 = (deg * Math.PI) / 180;
        return <line key={deg} x1={148} y1={RAW_Y} x2={148 + 13 * Math.cos(r2)} y2={RAW_Y + 13 * Math.sin(r2)} stroke={C.blue} strokeWidth={2} strokeLinecap="round" />;
      })}
      <circle cx={148} cy={RAW_Y} r={4} fill={C.blue} />
      <text x={148} y={RAW_Y + 30} textAnchor="middle" fontSize={8} fill={C.blue} fontFamily="'Share Tech Mono', monospace">BOOSTER</text>

      {/* ── PIPE: Booster → REGEN RAW IN ─────────── */}
      <AnimatedPipe d={`M 166 ${RAW_Y} H 230`} state="RAW_COLD" flowRate={flowGPH} />

      {/* ════════════════════════════════════════════
          REGEN BLOCK — single physical unit
          Top half  = RAW side  (flow →, y=RAW_Y=130)
          Bottom half = PAST side (flow ←, y=PAST_Y=200)
          ════════════════════════════════════════════ */}
      {/* Outer box */}
      <rect x={RG.x} y={RG.y} width={RG.w} height={RG.h}
        fill={C.panel} stroke={C.border} strokeWidth={2.5} rx={4} />
      {/* Top half tint — raw side */}
      <rect x={RG.x + 2} y={RG.y + 2} width={RG.w - 4} height={RG.h / 2 - 2}
        fill={C.rawCold} fillOpacity={0.09} rx={2} />
      {/* Bottom half tint — past side */}
      <rect x={RG.x + 2} y={RG.y + RG.h / 2} width={RG.w - 4} height={RG.h / 2 - 2}
        fill={C.pasteurized} fillOpacity={0.09} rx={2} />
      {/* Midpoint dashed divider */}
      <line x1={RG.x} y1={RG.y + RG.h / 2} x2={RG.x + RG.w} y2={RG.y + RG.h / 2}
        stroke={C.border} strokeWidth={1.5} strokeDasharray="6 3" />
      {/* Plate fins (decorative vertical lines) */}
      {[0,1,2,3,4,5].map(i =>
        <line key={i} x1={RG.x + 18 + i * 22} y1={RG.y + 3} x2={RG.x + 18 + i * 22} y2={RG.y + RG.h - 3}
          stroke={C.border} strokeWidth={0.75} opacity={0.35} />
      )}
      {/* Title */}
      <text x={RG.x + RG.w / 2} y={RG.y + 19} textAnchor="middle" fontSize={10} fill="#0f172a" fontWeight="bold" fontFamily="'Share Tech Mono', monospace">REGEN PHE</text>
      {/* RAW side label + right-pointing arrow */}
      <text x={RG.x + RG.w / 2} y={RAW_Y + 5} textAnchor="middle" fontSize={8} fill={C.rawCold} fontFamily="'Share Tech Mono', monospace">→ RAW →</text>
      {/* PAST side label + left-pointing arrow */}
      <text x={RG.x + RG.w / 2} y={PAST_Y + 5} textAnchor="middle" fontSize={8}
        fill={fddState === 'forward' ? C.pasteurized : C.deadLeg} fontFamily="'Share Tech Mono', monospace">← PAST ←</text>

      {/* Pressure gauge — raw side (above block, left) */}
      <circle cx={RG.x + 40} cy={RG.y - 24} r={13} fill={C.panel} stroke={C.border} strokeWidth={1.5} />
      <text x={RG.x + 40} y={RG.y - 20} textAnchor="middle" fontSize={9} fill={C.rawCold} fontFamily="'Share Tech Mono', monospace">{regenRawPSI}</text>
      <text x={RG.x + 40} y={RG.y - 40} textAnchor="middle" fontSize={7} fill={C.rawCold} fontFamily="'Share Tech Mono', monospace">RAW PSI</text>
      <line x1={RG.x + 40} y1={RG.y - 11} x2={RG.x + 40} y2={RG.y} stroke={C.border} strokeWidth={1} />
      {/* Pressure gauge — past side (above block, right) */}
      <circle cx={RG.x + 120} cy={RG.y - 24} r={13} fill={C.panel} stroke={C.border} strokeWidth={1.5} />
      <text x={RG.x + 120} y={RG.y - 20} textAnchor="middle" fontSize={9} fill={C.pasteurized} fontFamily="'Share Tech Mono', monospace">{regenPastPSI}</text>
      <text x={RG.x + 120} y={RG.y - 40} textAnchor="middle" fontSize={7} fill={C.pasteurized} fontFamily="'Share Tech Mono', monospace">PST PSI</text>
      <line x1={RG.x + 120} y1={RG.y - 11} x2={RG.x + 120} y2={RG.y} stroke={C.border} strokeWidth={1} />
      {/* ΔP display */}
      <text x={RG.x + RG.w / 2} y={RG.y - 50} textAnchor="middle" fontSize={9}
        fill={deltaPOk ? C.green : C.red} fontWeight="bold" fontFamily="'Share Tech Mono', monospace">
        {`ΔP = ${deltaP.toFixed(1)} PSI ${deltaPOk ? '✓' : '✗ DIVERT'}`}
      </text>

      {/* ── PIPE: REGEN RAW OUT → Timing Pump ─────── */}
      <AnimatedPipe d={`M 390 ${RAW_Y} H 430`} state="PREHEATING" flowRate={flowGPH} />

      {/* ── TIMING PUMP ───────────────────────────── */}
      <circle cx={450} cy={RAW_Y} r={18} fill={C.panel} stroke={C.border} strokeWidth={2} />
      {[0, 60, 120, 180, 240, 300].map(deg => {
        const r2 = (deg * Math.PI) / 180;
        return <line key={deg} x1={450} y1={RAW_Y} x2={450 + 13 * Math.cos(r2)} y2={RAW_Y + 13 * Math.sin(r2)} stroke={C.orange} strokeWidth={2} strokeLinecap="round" />;
      })}
      <circle cx={450} cy={RAW_Y} r={4} fill={C.orange} />
      {/* SEALED badge */}
      <rect x={433} y={RAW_Y - 32} width={34} height={11} rx={3} fill="#7c3aed" />
      <text x={450} y={RAW_Y - 24} textAnchor="middle" fontSize={6} fill="white" fontFamily="'Share Tech Mono', monospace">SEALED</text>
      <text x={450} y={RAW_Y + 30} textAnchor="middle" fontSize={7} fill={C.orange} fontFamily="'Share Tech Mono', monospace">TIMING PUMP</text>

      {/* ── PIPE: Timing Pump → Heater ────────────── */}
      <AnimatedPipe d={`M 468 ${RAW_Y} H 510`} state="PREHEATING" flowRate={flowGPH} />

      {/* ── HEATER PHE ───────────────────────────── */}
      <rect x={510} y={RAW_Y - 40} width={80} height={80} fill={C.panel} stroke={C.orange} strokeWidth={2} rx={3} />
      {[0,1,2,3].map(i => (
        <polyline key={i}
          points={`${520 + i * 16},${RAW_Y - 40} ${528 + i * 16},${RAW_Y} ${520 + i * 16},${RAW_Y + 40}`}
          fill="none" stroke={C.orange} strokeWidth={1.5} opacity={0.5}
        />
      ))}
      <text x={550} y={RAW_Y - 8} textAnchor="middle" fontSize={10} fill={C.orange} fontWeight="bold" fontFamily="'Share Tech Mono', monospace">HEATER</text>
      <text x={550} y={RAW_Y + 5} textAnchor="middle" fontSize={8} fill={C.orange} fontFamily="'Share Tech Mono', monospace">PHE</text>
      <text x={550} y={RAW_Y + 52} textAnchor="middle" fontSize={7} fill={C.orange} fontFamily="'Share Tech Mono', monospace">STEAM / HOT WATER</text>

      {/* ── PIPE: Heater → Holding Tube entry ─────── */}
      <AnimatedPipe d={`M 590 ${RAW_Y} H 612 V ${RAW_Y - 20}`} state="HEATING" flowRate={flowGPH} />

      {/* ── HOLDING TUBE (3-pass serpentine) ──────── */}
      <rect x={607} y={RAW_Y - 32} width={138} height={56} fill={C.hotTemp} fillOpacity={0.04} rx={4}
        stroke={C.hotTemp} strokeWidth={0.5} strokeOpacity={0.2} />
      {/* Run 1 → */}
      <AnimatedPipe d={`M 612 ${RAW_Y - 20} H 738`} state="HOT_TEMP" flowRate={flowGPH} />
      {/* Right bend ↓ */}
      <AnimatedPipe d={`M 738 ${RAW_Y - 20} V ${RAW_Y - 2}`} state="HOT_TEMP" flowRate={flowGPH} />
      {/* Run 2 ← */}
      <AnimatedPipe d={`M 738 ${RAW_Y - 2} H 614`} state="HOT_TEMP" flowRate={flowGPH} reverse />
      {/* Left bend ↓ */}
      <AnimatedPipe d={`M 614 ${RAW_Y - 2} V ${RAW_Y + 16}`} state="HOT_TEMP" flowRate={flowGPH} />
      {/* Run 3 → */}
      <AnimatedPipe d={`M 614 ${RAW_Y + 16} H 738`} state="HOT_TEMP" flowRate={flowGPH} />
      {/* Labels */}
      <text x={672} y={RAW_Y + 38} textAnchor="middle" fontSize={8} fill={C.hotTemp} fontFamily="'Share Tech Mono', monospace">HOLDING TUBE</text>
      <text x={672} y={RAW_Y + 49} textAnchor="middle" fontSize={8} fill={holdOk ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">
        {`calc: ${calcHoldSec.toFixed(3)}s`}
      </text>
      <text x={672} y={RAW_Y + 60} textAnchor="middle" fontSize={8} fill={holdOk ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">
        {`min:  ${req.holdSec}s ${holdOk ? '✓' : '✗'}`}
      </text>

      {/* ── PIPE: HT exit → TLC ──────────────────── */}
      <AnimatedPipe d={`M 738 ${RAW_Y + 16} L 756 ${RAW_Y}`} state="HOT_TEMP" flowRate={flowGPH} />

      {/* ── TLC SENSOR (diamond) ─────────────────── */}
      <polygon
        points={`778,${RAW_Y - 22} 800,${RAW_Y} 778,${RAW_Y + 22} 756,${RAW_Y}`}
        fill={C.panel} stroke={tempOk ? C.hotTemp : C.red} strokeWidth={2}
      />
      <text x={778} y={RAW_Y - 4} textAnchor="middle" fontSize={8} fill="#0f172a" fontWeight="bold" fontFamily="'Share Tech Mono', monospace">TLC</text>
      <text x={778} y={RAW_Y + 8} textAnchor="middle" fontSize={8} fill={tempOk ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">
        {`${holdTemp.toFixed(1)}°F`}
      </text>
      <text x={778} y={RAW_Y + 38} textAnchor="middle" fontSize={7} fill={tempOk ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">
        {tempOk ? 'TEMP ✓' : '⚠ BELOW MIN'}
      </text>

      {/* ── PIPE: TLC → FDD ──────────────────────── */}
      <AnimatedPipe d={`M 800 ${RAW_Y} H 802`} state="HOT_TEMP" flowRate={flowGPH} />

      {/* ── FDD VALVE ────────────────────────────── */}
      <FDDValve x={FDD_X} y={RAW_Y} state={fddState} />
      <text x={FDD_X} y={RAW_Y + 44} textAnchor="middle" fontSize={7} fill={C.border} fontFamily="'Share Tech Mono', monospace">FDD — fwd if temp ≥ min</text>

      {/* ════════════════════════════════════════════
          PASTEURIZED RETURN PATH (right → left)
          FDD forward outlet → right stub → drop to PAST_Y
          → long horizontal LEFT → REGEN PAST IN (x=390)
          [through regen bottom half]
          → REGEN PAST OUT (x=230) → Cooler → Storage
          ════════════════════════════════════════════ */}
      {/* FDD forward outlet stub + vertical drop to PAST_Y */}
      <AnimatedPipe d={`M ${FDD_X + 22} ${RAW_Y} H 878 V ${PAST_Y}`} state={fwdState} flowRate={flowGPH} />
      {/* Long horizontal return (right → left) from x=878 to REGEN PAST IN x=390 */}
      <AnimatedPipe d={`M 878 ${PAST_Y} H 390`} state={fwdState} flowRate={flowGPH} reverse />
      {/* REGEN PAST OUT → Cooler right edge */}
      <AnimatedPipe d={`M 230 ${PAST_Y} H 170`} state={coolState} flowRate={flowGPH} reverse />
      {/* Direction label on return run */}
      <text x={590} y={PAST_Y - 8} textAnchor="middle" fontSize={7.5}
        fill={fddState === 'forward' ? C.pasteurized : C.deadLeg} fontFamily="'Share Tech Mono', monospace">
        ← PASTEURIZED — RETURNS THROUGH REGEN (PMO Appendix H Step 8)
      </text>

      {/* ── COOLER PHE ───────────────────────────── */}
      <rect x={100} y={PAST_Y - 32} width={70} height={64} fill={C.panel}
        stroke={fddState === 'forward' ? C.cooling : C.deadLeg}
        strokeWidth={fddState === 'forward' ? 2 : 1} rx={3}
        opacity={fddState === 'forward' ? 1 : 0.35}
      />
      {[0,1,2].map(i => (
        <polyline key={i}
          points={`${110 + i * 18},${PAST_Y - 32} ${116 + i * 18},${PAST_Y} ${110 + i * 18},${PAST_Y + 32}`}
          fill="none" stroke={fddState === 'forward' ? C.cooling : C.deadLeg}
          strokeWidth={1.5} opacity={fddState === 'forward' ? 0.55 : 0.15}
        />
      ))}
      <text x={135} y={PAST_Y - 10} textAnchor="middle" fontSize={9}
        fill={fddState === 'forward' ? C.cooling : C.deadLeg} fontWeight="bold" fontFamily="'Share Tech Mono', monospace">COOLER</text>
      <text x={135} y={PAST_Y + 3} textAnchor="middle" fontSize={8}
        fill={fddState === 'forward' ? C.cooling : C.deadLeg} fontFamily="'Share Tech Mono', monospace">PHE</text>
      <text x={135} y={PAST_Y + 46} textAnchor="middle" fontSize={7}
        fill={fddState === 'forward' ? C.cooling : C.deadLeg} fontFamily="'Share Tech Mono', monospace">ICE WATER/GLYCOL</text>
      <text x={135} y={PAST_Y + 58} textAnchor="middle" fontSize={8}
        fill={storageOk ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">
        {`OUT: ${finalCoolF}°F ${storageOk ? '✓' : '⚠'}`}
      </text>

      {/* ── PIPE: Cooler left edge → Storage ─────── */}
      <AnimatedPipe d={`M 100 ${PAST_Y} H 57`} state={stgState} flowRate={flowGPH} reverse />
      {/* Storage arrow (pointing left) */}
      <polygon points={`57,${PAST_Y - 4} 44,${PAST_Y} 57,${PAST_Y + 4}`}
        fill={fddState === 'forward' ? (storageOk ? C.coldStorage : C.red) : C.deadLeg} />
      <text x={30} y={PAST_Y - 6} textAnchor="middle" fontSize={7}
        fill={fddState === 'forward' ? (storageOk ? C.coldStorage : C.red) : C.deadLeg} fontFamily="'Share Tech Mono', monospace">TO</text>
      <text x={30} y={PAST_Y + 4} textAnchor="middle" fontSize={7}
        fill={fddState === 'forward' ? (storageOk ? C.coldStorage : C.red) : C.deadLeg} fontFamily="'Share Tech Mono', monospace">STORAGE</text>
      <text x={30} y={PAST_Y + 14} textAnchor="middle" fontSize={7}
        fill={fddState === 'forward' ? (storageOk ? C.coldStorage : C.red) : C.deadLeg} fontFamily="'Share Tech Mono', monospace">≤45°F</text>
      {fddState === 'forward' && !storageOk && (
        <text x={30} y={PAST_Y + 24} textAnchor="middle" fontSize={7} fill={C.red} fontFamily="'Share Tech Mono', monospace">⚠ TOO WARM</text>
      )}

      {/* ════════════════════════════════════════════
          DIVERT RETURN PATH (dashed red)
          FDD divert outlet → down to DIV_Y
          → left all the way → up to Balance Tank top
          ════════════════════════════════════════════ */}
      <AnimatedPipe
        d={`M ${FDD_X} ${RAW_Y + 22} V ${DIV_Y} H 45 V 75`}
        state={divState} flowRate={flowGPH}
      />
      <text x={450} y={DIV_Y + 15} textAnchor="middle" fontSize={8}
        fill={fddState === 'divert' ? '#dc2626' : C.deadLeg} fontFamily="'Share Tech Mono', monospace">
        {fddState === 'divert'
          ? '← DIVERT — RETURNS TO CONSTANT LEVEL TANK (PMO Step 7)'
          : '─── DIVERT PATH (inactive) ───'}
      </text>

      {/* ── TITLE ────────────────────────────────── */}
      <text x={480} y={500} textAnchor="middle" fontSize={8} fill={C.border} fontFamily="'Share Tech Mono', monospace">
        HTST — REGENERATIVE PASTEURIZER FLOW DIAGRAM (PMO Appendix H)
      </text>
    </svg>
  );
}

// ════════════════════════════════════════════════
// TOOLTIP
// ════════════════════════════════════════════════
function Tooltip({ tip }) {
  if (!tip) return null;
  return (
    <div style={{
      position: 'fixed', left: tip.x + 14, top: tip.y + 10,
      maxWidth: 280, background: '#0d1e30', border: `1px solid ${C.blue}`,
      borderRadius: 5, padding: '8px 10px', pointerEvents: 'none', zIndex: 1000,
      boxShadow: `0 0 14px ${C.blue}44`,
    }}>
      <div style={{ fontSize: 11, fontWeight: 700, color: C.blue, fontFamily: "'Share Tech Mono', monospace", marginBottom: 4 }}>
        {tip.title}
      </div>
      {tip.body && (
        <div style={{ fontSize: 10, color: '#475569', fontFamily: "'Share Tech Mono', monospace", lineHeight: 1.5, marginBottom: 4 }}>
          {tip.body}
        </div>
      )}
      {tip.currentValue && (
        <div style={{ fontSize: 10, color: C.yellow, fontFamily: "'Share Tech Mono', monospace", marginTop: 3 }}>
          ▶ {tip.currentValue}
        </div>
      )}
      {tip.pmoRef && (
        <div style={{ fontSize: 9, color: '#475569', fontFamily: "'Share Tech Mono', monospace", marginTop: 3 }}>
          {tip.pmoRef}
        </div>
      )}
    </div>
  );
}

// ════════════════════════════════════════════════
// OPERATOR SOP DATA
// ════════════════════════════════════════════════
const SOPS = [
  {
    id: 'startup',
    title: 'Startup — Water Phase',
    steps: [
      'Verify CIP is complete, system rinsed, and all valves are in correct position.',
      'Confirm recorder/controller is ON and probe is calibrated.',
      'Check balance tank (CLT) has adequate water for startup.',
      'Start booster pump first to pressurize the raw side.',
      'Start timing pump at sealed maximum speed.',
      'Open steam/hot water to heater — begin heating water.',
      'All flow diverts until TLC reaches minimum pasteurization temp.',
      'Watch regen ΔP — pasteurized side must be ≥ raw + 1 PSI.',
      'When TLC confirms minimum temp: FDD automatically shifts to forward.',
      'Confirm recorder chart is running and tracing temperature.',
    ],
  },
  {
    id: 'w2p',
    title: 'Water → Product Transition',
    steps: [
      'Hold water phase at least 5–10 min after FDD goes to forward.',
      'Verify temperature is stable and regen ΔP is holding ≥ 1 PSI.',
      'Open product inlet — product enters the balance tank.',
      'Monitor balance tank level as product displaces water.',
      'Divert or hold early fill until first on-spec product is confirmed.',
      'Collect first-product sample for QA/lab check.',
      'Log water-to-product transition time on regulatory record.',
    ],
  },
  {
    id: 'production',
    title: 'Running Production — Checks',
    steps: [
      'Check TLC temperature every 15–30 min; compare to recorder chart.',
      'Monitor balance tank level — never allow to run empty or overflow.',
      'Verify regen ΔP reads ≥ 1 PSI continuously.',
      'Review recorder chart at end of each hour; initial if required by state.',
      'Log flow rate and temperature on shift log per regulatory requirements.',
      'Report any FDD divert event immediately to QA supervisor.',
      'Do not adjust timing pump speed — it is sealed by regulatory authority.',
    ],
  },
  {
    id: 'dest',
    title: 'Destination Change (Silo / Tank Switch)',
    steps: [
      'Confirm destination silo/tank is empty, clean, and ready to receive.',
      'Notify receiving area before switching.',
      'Estimate line volume between FDD forward outlet and new destination.',
      'Close valve to current destination.',
      'Open valve to new destination.',
      'The pipe fill volume to the new tank contains mix — account for it in batch records.',
      'Log exact time of switch, from-tank, and to-tank in batch record.',
    ],
  },
  {
    id: 'p2w',
    title: 'Product → Water / End of Run',
    steps: [
      'Stop product feed — allow balance tank level to drop near-empty (do not run dry).',
      'Introduce water (or designated displacement fluid) into balance tank.',
      'Continue running — product is pushed forward through heater and cooler by water.',
      'When water reaches fill/packaging point, divert or shut off.',
      'Reduce steam to heater — allow water to cool the system.',
      'Shut down timing pump, then booster pump.',
      'Drain remaining water. Begin CIP startup per sanitation SOP.',
    ],
  },
  {
    id: 'divert',
    title: 'Unexpected FDD Divert — Response',
    steps: [
      '⚠ Product past the divert point is NOT pasteurized — place it on hold immediately.',
      'Do NOT attempt to force forward flow — determine the root cause first.',
      'Check TLC temp: if low, wait — system auto-returns to forward when temp recovers.',
      'Check recorder: is the chart running and showing correct temperature trace?',
      'Check regen ΔP: if < 1 PSI, inspect booster pump, timing pump, and line pressures.',
      'Check for power/signal loss at the controller or FDD solenoid wiring.',
      'When all conditions pass, system will return to forward automatically.',
      'Notify QA supervisor — diverted product must be evaluated before release.',
      'Log divert time, cause, duration, and corrective action in regulatory record.',
    ],
  },
];

// ════════════════════════════════════════════════
// OPERATOR SOP PANEL
// ════════════════════════════════════════════════
function OperatorSOPPanel() {
  const [openId, setOpenId] = useState(null);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
      <div style={{
        padding: '8px 12px', background: C.panel,
        borderBottom: `1px solid ${C.border}`,
        fontFamily: "'Share Tech Mono', monospace", fontSize: 11, color: C.orange,
        letterSpacing: 1, flexShrink: 0,
      }}>
        OPERATOR PROCEDURES
      </div>

      <div style={{ overflowY: 'auto', flex: 1 }}>
        {SOPS.map(sop => {
          const isOpen = openId === sop.id;
          return (
            <div key={sop.id} style={{ borderBottom: `1px solid ${C.border}` }}>
              <div
                onClick={() => setOpenId(isOpen ? null : sop.id)}
                style={{
                  padding: '9px 10px', cursor: 'pointer',
                  display: 'flex', justifyContent: 'space-between', alignItems: 'center',
                  background: isOpen ? C.border + '55' : 'transparent',
                  transition: 'background 0.15s',
                }}
                onMouseEnter={e => { if (!isOpen) e.currentTarget.style.background = C.border + '33'; }}
                onMouseLeave={e => { if (!isOpen) e.currentTarget.style.background = 'transparent'; }}
              >
                <span style={{
                  fontSize: 10, color: isOpen ? C.orange : '#c8e0f0',
                  fontFamily: "'Rajdhani', sans-serif", fontWeight: 600, lineHeight: 1.3,
                }}>
                  {sop.title}
                </span>
                <span style={{ fontSize: 10, color: C.orange, marginLeft: 6, flexShrink: 0 }}>
                  {isOpen ? '▲' : '▼'}
                </span>
              </div>

              {isOpen && (
                <div style={{ padding: '6px 10px 12px 10px', background: '#06101a' }}>
                  {sop.steps.map((step, i) => (
                    <div key={i} style={{ display: 'flex', gap: 8, marginBottom: 7, alignItems: 'flex-start' }}>
                      <span style={{
                        flexShrink: 0, width: 17, height: 17,
                        background: C.orange + '22', border: `1px solid ${C.orange}55`,
                        borderRadius: '50%', fontSize: 8, color: C.orange,
                        fontFamily: "'Share Tech Mono', monospace",
                        display: 'flex', alignItems: 'center', justifyContent: 'center',
                      }}>
                        {i + 1}
                      </span>
                      <span style={{
                        fontSize: 10, color: '#b8d0e8',
                        fontFamily: "'Rajdhani', sans-serif", lineHeight: 1.5,
                      }}>
                        {step}
                      </span>
                    </div>
                  ))}
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ════════════════════════════════════════════════
// DIVERT CONDITIONS PANEL
// ════════════════════════════════════════════════
function DivertConditionsPanel({ conditionResults, tab, onToggleOverride }) {
  const [hoverId, setHoverId] = useState(null);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
      <div style={{
        padding: '8px 12px', background: C.panel,
        borderBottom: `1px solid ${C.border}`,
        fontFamily: "'Share Tech Mono', monospace", fontSize: 11, color: C.blue,
        letterSpacing: 1,
      }}>
        PMO DIVERT CONDITIONS
      </div>

      <div style={{ overflowY: 'auto', flex: 1 }}>
        {conditionResults.map(c => {
          const na = !c.applicable;
          const color = na ? C.deadLeg : (c.passing ? C.green : C.red);
          const isHovered = hoverId === c.id;

          return (
            <div
              key={c.id}
              onClick={() => !na && onToggleOverride(c.id)}
              onMouseEnter={() => setHoverId(c.id)}
              onMouseLeave={() => setHoverId(null)}
              style={{
                padding: '7px 10px',
                borderBottom: `1px solid ${C.border}`,
                cursor: na ? 'default' : 'pointer',
                background: isHovered ? C.border + '55' : 'transparent',
                opacity: na ? 0.4 : 1,
                position: 'relative',
                transition: 'background 0.15s',
              }}
            >
              <div style={{ display: 'flex', alignItems: 'flex-start', gap: 6 }}>
                <span style={{ fontSize: 12, flexShrink: 0, marginTop: 1 }}>
                  {na ? '—' : (c.passing ? '✅' : '❌')}
                </span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{
                    fontSize: 10, color: color,
                    fontFamily: "'Rajdhani', sans-serif", fontWeight: 600,
                    lineHeight: 1.3,
                  }}>
                    {c.label}
                  </div>
                  {!na && (
                    <div style={{
                      fontSize: 9, color: c.passing ? C.green + 'bb' : C.red + 'bb',
                      fontFamily: "'Share Tech Mono', monospace",
                      marginTop: 2,
                    }}>
                      {c.displayVal}
                    </div>
                  )}
                  {na && (
                    <div style={{ fontSize: 9, color: C.deadLeg, fontFamily: "'Share Tech Mono', monospace", marginTop: 2 }}>
                      N/A for {tab} mode
                    </div>
                  )}
                  <div style={{ fontSize: 8, color: C.border, fontFamily: "'Share Tech Mono', monospace", marginTop: 2 }}>
                    {c.pmoRef}
                  </div>
                </div>
              </div>

              {/* Tooltip on hover */}
              {isHovered && c.explanation && !na && (
                <div style={{
                  position: 'absolute',
                  right: '100%',
                  top: 0,
                  width: 260,
                  background: '#1a2e44',
                  border: `1px solid ${C.blue}`,
                  borderRadius: 6,
                  padding: '10px 12px',
                  fontSize: 10,
                  color: '#c8e0f0',
                  fontFamily: "'Rajdhani', sans-serif",
                  lineHeight: 1.5,
                  zIndex: 100,
                  boxShadow: '0 4px 20px rgba(0,0,0,0.5)',
                  pointerEvents: 'none',
                }}>
                  <div style={{ color: C.blue, fontWeight: 700, marginBottom: 6, fontSize: 11 }}>{c.label}</div>
                  {c.explanation}
                  <div style={{ marginTop: 8, color: C.yellow, fontSize: 9 }}>{c.pmoRef}</div>
                  {!na && <div style={{ marginTop: 6, color: C.border, fontSize: 9 }}>Click row to force violation</div>}
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ════════════════════════════════════════════════
// SLIDER COMPONENT
// ════════════════════════════════════════════════
function Slider({ label, min, max, step = 1, value, onChange, unit = '', color = C.blue }) {
  return (
    <div style={{ marginBottom: 12 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 3 }}>
        <span style={{ fontSize: 10, color: '#64748b', fontFamily: "'Rajdhani', sans-serif" }}>{label}</span>
        <span style={{ fontSize: 10, color: color, fontFamily: "'Share Tech Mono', monospace", fontWeight: 600 }}>
          {typeof value === 'number' ? value.toFixed(step < 1 ? 1 : 0) : value}{unit}
        </span>
      </div>
      <input
        type="range" min={min} max={max} step={step} value={value}
        onChange={e => onChange(parseFloat(e.target.value))}
        style={{ width: '100%', accentColor: color, cursor: 'pointer' }}
      />
      <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 8, color: C.deadLeg, fontFamily: "'Share Tech Mono', monospace" }}>
        <span>{min}{unit}</span><span>{max}{unit}</span>
      </div>
    </div>
  );
}

// ════════════════════════════════════════════════
// VAT DIAGRAM
// ════════════════════════════════════════════════
function VATDiagram({ params, req }) {
  const { vatTemp, vatHoldElapsed, vatHoldRequired, vatOutletOpen, vatPhase, finalCoolF } = params;
  const tempOk          = vatTemp >= req.tempF;
  const holdComplete    = vatHoldElapsed >= vatHoldRequired;
  const earlyViolation  = vatOutletOpen && vatHoldElapsed < vatHoldRequired;
  const tempDropViolation = vatPhase === 'holding' && !tempOk;
  const storageOk       = finalCoolF <= PMO.maxStorageTemp_F;
  const outletFlowing   = vatOutletOpen && holdComplete;

  // Thermometer geometry
  const thermX = 385, thermTop = 95, thermH = 215, tempMin = 130, tempMax = 220;
  const fillPct  = Math.max(0, Math.min(1, (vatTemp - tempMin) / (tempMax - tempMin)));
  const fillH    = thermH * fillPct;
  const fillY    = thermTop + thermH - fillH;
  const minPct   = (req.tempF - tempMin) / (tempMax - tempMin);
  const minLineY = thermTop + thermH * (1 - minPct);

  // Timer formatting (vatHoldElapsed in minutes)
  const eFmt = t => `${String(Math.floor(t)).padStart(2,'0')}:${String(Math.round((t%1)*60)).padStart(2,'0')}`;

  // Vat fill color: orange during heat, shift blue if temp drops
  const vatFill = tempOk ? C.heating + '28' : C.rawCold + '1a';

  return (
    <svg viewBox="0 0 960 480" width="100%" style={{ background: '#f8fafc', display: 'block' }}>
      <defs>
        <pattern id="grid-vat" width="40" height="40" patternUnits="userSpaceOnUse">
          <path d="M 40 0 L 0 0 0 40" fill="none" stroke="#e2e8f0" strokeWidth="0.5"/>
        </pattern>
      </defs>
      <rect width="960" height="480" fill="#f8fafc" rx="8" />
      <rect width="960" height="480" fill="url(#grid-vat)" />

      {/* ── RAW MILK INLET ───────────────────────── */}
      <AnimatedPipe d="M 30 230 H 148" state="RAW_COLD" flowRate={800} />
      {/* Disconnected stub end */}
      <line x1={148} y1={216} x2={148} y2={244} stroke={C.rawCold} strokeWidth={3} strokeLinecap="round" />
      <text x={80} y={256} textAnchor="middle" fontSize={8} fill={C.rawCold} fontFamily="'Share Tech Mono', monospace">RAW MILK INLET</text>
      <text x={80} y={268} textAnchor="middle" fontSize={8} fill={C.yellow} fontFamily="'Share Tech Mono', monospace">⚡ DISCONNECTED</text>
      <text x={80} y={279} textAnchor="middle" fontSize={8} fill={C.yellow} fontFamily="'Share Tech Mono', monospace">DURING HOLD</text>

      {/* ── VAT TANK ─────────────────────────────── */}
      {/* Hot water jacket (outer) */}
      <rect x={148} y={75} width={222} height={270} fill={C.orange} fillOpacity={0.06}
        stroke={C.orange} strokeWidth={1.5} rx={5}
        style={{ animation: tempDropViolation ? 'pulse 1.5s ease-in-out infinite' : 'none' }}
      />
      {/* Jacket flow arrows */}
      <text x={151} y={210} fontSize={8} fill={C.orange} fontFamily="'Share Tech Mono', monospace"
        style={{ writingMode: 'vertical-rl', transform: 'rotate(180deg)', transformOrigin: '151px 210px' }}>
        HOT WATER JACKET ↑
      </text>
      {/* Inner vessel */}
      <rect x={162} y={88} width={196} height={248} fill={vatFill} stroke={C.border} strokeWidth={2} rx={3} />

      {/* Milk fill wave */}
      <path d="M 164,155 Q 188,151 212,155 Q 236,159 260,155 Q 284,151 308,155 Q 332,159 356,155" fill="none" stroke={C.rawCold} strokeWidth={1.5} opacity={0.5} />

      {/* Temperature display inside vat */}
      <text x={260} y={205} textAnchor="middle" fontSize={22} fill={tempOk ? C.orange : C.red} fontWeight="bold" fontFamily="'Share Tech Mono', monospace"
        style={{ animation: tempDropViolation ? 'pulse 1s ease-in-out infinite' : 'none' }}>
        {vatTemp}°F
      </text>
      <text x={260} y={223} textAnchor="middle" fontSize={10} fill={tempOk ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">
        {tempOk ? `≥ ${req.tempF}°F MIN ✓` : `⚠ BELOW ${req.tempF}°F MIN`}
      </text>
      {tempDropViolation && (
        <text x={260} y={240} textAnchor="middle" fontSize={9} fill={C.red} fontFamily="'Share Tech Mono', monospace"
          style={{ animation: 'pulse 0.8s ease-in-out infinite' }}>
          HOLD TIMER RESETS!
        </text>
      )}

      {/* Agitator shaft */}
      <line x1={260} y1={90} x2={260} y2={334} stroke={C.green + 'aa'} strokeWidth={2} />
      {/* Motor on top */}
      <rect x={246} y={74} width={28} height={16} fill={C.panel} stroke={C.green} strokeWidth={1.5} rx={2} />
      <text x={260} y={85} textAnchor="middle" fontSize={7} fill={C.green} fontFamily="'Share Tech Mono', monospace">MOT</text>
      {/* Rotating paddles */}
      <g style={{ transformOrigin: '260px 210px', animation: 'agitatorSpin 3s linear infinite' }}>
        <line x1={218} y1={160} x2={302} y2={160} stroke={C.green} strokeWidth={3} strokeLinecap="round" strokeOpacity={0.75} />
        <line x1={218} y1={210} x2={302} y2={210} stroke={C.green} strokeWidth={3} strokeLinecap="round" strokeOpacity={0.75} />
        <line x1={218} y1={260} x2={302} y2={260} stroke={C.green} strokeWidth={3} strokeLinecap="round" strokeOpacity={0.75} />
      </g>

      {/* Label */}
      <text x={260} y={65} textAnchor="middle" fontSize={12} fill="#0f172a" fontWeight="bold" fontFamily="'Share Tech Mono', monospace">VAT PASTEURIZER</text>
      <text x={260} y={76} textAnchor="middle" fontSize={8} fill={C.orange} fontFamily="'Share Tech Mono', monospace">HOT WATER JACKETED — CONTINUOUS AGITATION</text>

      {/* ── THERMOMETER ──────────────────────────── */}
      <rect x={thermX} y={thermTop} width={16} height={thermH} fill={C.bg} stroke={C.border} strokeWidth={1.5} rx={3} />
      <rect x={thermX + 1} y={fillY} width={14} height={fillH} fill={tempOk ? C.orange : C.red} rx={2} opacity={0.85} />
      {/* Min line */}
      <line x1={thermX - 7} y1={minLineY} x2={thermX + 26} y2={minLineY}
        stroke={tempOk ? C.green : C.red} strokeWidth={2} strokeDasharray="4 2" />
      <text x={thermX + 30} y={minLineY + 4} fontSize={8} fill={tempOk ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">
        {req.tempF}°F min
      </text>
      <text x={thermX + 8} y={thermTop - 8} textAnchor="middle" fontSize={8} fill={C.border} fontFamily="'Share Tech Mono', monospace">°F</text>
      {/* Scale ticks */}
      {[140, 160, 180, 200, 220].map(t => {
        const pct = (t - tempMin) / (tempMax - tempMin);
        const ty  = thermTop + thermH * (1 - pct);
        return (
          <g key={t}>
            <line x1={thermX - 5} y1={ty} x2={thermX} y2={ty} stroke={C.border} strokeWidth={1} />
            <text x={thermX - 8} y={ty + 3} textAnchor="end" fontSize={7} fill={C.border} fontFamily="'Share Tech Mono', monospace">{t}</text>
          </g>
        );
      })}

      {/* ── HOLD TIMER ───────────────────────────── */}
      <rect x={172} y={350} width={176} height={58} fill={C.panel}
        stroke={tempDropViolation ? C.red : (holdComplete ? C.green : C.border)}
        strokeWidth={1.5} rx={4}
        style={{ animation: tempDropViolation ? 'pulse 1s ease-in-out infinite' : 'none' }}
      />
      <text x={260} y={366} textAnchor="middle" fontSize={8} fill={C.border} fontFamily="'Share Tech Mono', monospace">HOLD TIMER</text>
      <text x={260} y={386} textAnchor="middle" fontSize={18} fill={holdComplete ? C.green : (tempDropViolation ? C.red : C.yellow)}
        fontWeight="bold" fontFamily="'Share Tech Mono', monospace">
        {eFmt(vatHoldElapsed)} / {eFmt(vatHoldRequired)}
      </text>
      <text x={260} y={402} textAnchor="middle" fontSize={8}
        fill={holdComplete ? C.green : (tempDropViolation ? C.red : '#64748b')}
        fontFamily="'Share Tech Mono', monospace">
        {holdComplete ? '✓ HOLD COMPLETE — Outlet may open' : (tempDropViolation ? '⚠ TEMP DROP — TIMER RESET' : 'HOLD IN PROGRESS')}
      </text>

      {/* ── OUTLET VALVE ─────────────────────────── */}
      {/* Pipe from vat right side */}
      <line x1={358} y1={270} x2={448} y2={270}
        stroke={outletFlowing ? C.pasteurized : C.deadLeg} strokeWidth={4} strokeLinecap="round"
        strokeDasharray={outletFlowing ? 'none' : '3 8'}
      />
      {/* Ball valve circle */}
      <circle cx={464} cy={270} r={20} fill={C.panel}
        stroke={earlyViolation ? C.red : (vatOutletOpen ? (holdComplete ? C.green : C.yellow) : C.green)}
        strokeWidth={2}
        style={{ animation: earlyViolation ? 'pulse 0.7s ease-in-out infinite' : 'none' }}
      />
      {/* Valve disc */}
      {!vatOutletOpen
        ? <line x1={464} y1={252} x2={464} y2={288} stroke={C.green} strokeWidth={4} strokeLinecap="round" />
        : <line x1={446} y1={270} x2={482} y2={270} stroke={earlyViolation ? C.red : C.green} strokeWidth={4} strokeLinecap="round" />
      }
      {/* Lock when closed */}
      {!vatOutletOpen && <text x={464} y={248} textAnchor="middle" fontSize={13} fill={C.green}>🔒</text>}
      {/* Early open violation */}
      {earlyViolation && (
        <g>
          <text x={464} y={308} textAnchor="middle" fontSize={10} fill={C.red} fontWeight="bold"
            fontFamily="'Share Tech Mono', monospace" style={{ animation: 'pulse 0.7s ease-in-out infinite' }}>
            ⚠ PREMATURE OPEN
          </text>
          <text x={464} y={320} textAnchor="middle" fontSize={8} fill={C.red} fontFamily="'Share Tech Mono', monospace">
            PMO §16p(A) VIOLATION
          </text>
        </g>
      )}
      <text x={464} y={338} textAnchor="middle" fontSize={8}
        fill={earlyViolation ? C.red : (vatOutletOpen ? C.green : C.green)}
        fontFamily="'Share Tech Mono', monospace">
        OUTLET VALVE — {vatOutletOpen ? 'OPEN' : 'CLOSED DURING HOLD'}
      </text>

      {/* ── PIPE: Valve → Cooler ─────────────────── */}
      {outletFlowing
        ? <AnimatedPipe d="M 484 270 H 565" state="PASTEURIZED" flowRate={800} />
        : <line x1={484} y1={270} x2={565} y2={270} stroke={C.deadLeg} strokeWidth={4} strokeLinecap="round" strokeDasharray="3 9" />
      }

      {/* ── COOLER ───────────────────────────────── */}
      <rect x={565} y={245} width={72} height={56} fill={C.panel}
        stroke={outletFlowing ? C.cooling : C.deadLeg} strokeWidth={outletFlowing ? 2 : 1} rx={3} opacity={outletFlowing ? 1 : 0.35} />
      {[0,1,2].map(i => (
        <polyline key={i}
          points={`${575 + i*18},245 ${581+i*18},273 ${575+i*18},301`}
          fill="none" stroke={outletFlowing ? C.cooling : C.deadLeg} strokeWidth={1.5} opacity={outletFlowing ? 0.55 : 0.15}
        />
      ))}
      <text x={601} y={268} textAnchor="middle" fontSize={9} fill={outletFlowing ? C.cooling : C.deadLeg} fontWeight="bold" fontFamily="'Share Tech Mono', monospace">COOLER</text>
      <text x={601} y={280} textAnchor="middle" fontSize={8} fill={outletFlowing ? C.cooling : C.deadLeg} fontFamily="'Share Tech Mono', monospace">PHE</text>
      <text x={601} y={312} textAnchor="middle" fontSize={7} fill={outletFlowing ? C.cooling : C.deadLeg} fontFamily="'Share Tech Mono', monospace">ICE WATER/GLYCOL</text>

      {/* ── PIPE: Cooler → Storage ───────────────── */}
      {outletFlowing
        ? <AnimatedPipe d="M 637 270 H 710" state={storageOk ? 'COLD_STORAGE' : 'HOT_TEMP'} flowRate={800} />
        : <line x1={637} y1={270} x2={710} y2={270} stroke={C.deadLeg} strokeWidth={4} strokeLinecap="round" strokeDasharray="3 9" />
      }
      <polygon points="710,266 722,270 710,274" fill={outletFlowing ? (storageOk ? C.coldStorage : C.red) : C.deadLeg} />
      <text x={727} y={267} fontSize={9} fill={outletFlowing ? (storageOk ? C.coldStorage : C.red) : C.deadLeg} fontFamily="'Share Tech Mono', monospace">TO STORAGE ≤45°F</text>
      {outletFlowing && (
        <text x={727} y={279} fontSize={9} fill={storageOk ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">
          {finalCoolF}°F {storageOk ? '✓' : '⚠ TOO WARM'}
        </text>
      )}

      {/* ── PMO NOTE ─────────────────────────────── */}
      <text x={480} y={445} textAnchor="middle" fontSize={8} fill={C.border} fontFamily="'Share Tech Mono', monospace">
        VAT PASTEURIZER — PMO §16p(A) — Batch Process, No FDD Required
      </text>
    </svg>
  );
}

// ════════════════════════════════════════════════
// HTST SIMPLE DIAGRAM (no regenerator)
// ════════════════════════════════════════════════
function HTSTSimpleDiagram({ params, fddState, req, calcHoldSec }) {
  const { flowGPH, holdTemp, finalCoolF } = params;
  const storageOk = finalCoolF <= PMO.maxStorageTemp_F;
  const holdOk    = calcHoldSec >= req.holdSec;
  const tempOk    = holdTemp >= req.tempF;

  const fwdState  = fddState === 'forward' ? 'PASTEURIZED' : 'DEAD_LEG';
  const divState  = fddState === 'divert'  ? 'DIVERTED'    : 'DEAD_LEG';
  const stgState  = fddState === 'forward' ? (storageOk ? 'COLD_STORAGE' : 'HOT_TEMP') : 'DEAD_LEG';

  const FDD = { cx: 592, cy: 210 };
  const CLR = { x1: 682, y1: 173, w: 72, h: 60 };

  return (
    <svg viewBox="0 0 960 480" width="100%" style={{ background: '#f8fafc', display: 'block' }}>
      <defs>
        <pattern id="grid-htst-simple" width="40" height="40" patternUnits="userSpaceOnUse">
          <path d="M 40 0 L 0 0 0 40" fill="none" stroke="#e2e8f0" strokeWidth="0.5"/>
        </pattern>
      </defs>
      <rect width="960" height="480" fill="#f8fafc" rx="8" />
      <rect width="960" height="480" fill="url(#grid-htst-simple)" />

      {/* No-regen notice */}
      <text x={480} y={30} textAnchor="middle" fontSize={10} fill={C.yellow} fontFamily="'Share Tech Mono', monospace">
        ⚠ NO REGENERATOR — Raw milk enters heater directly (no heat recovery)
      </text>

      {/* ── BALANCE TANK ─────────────────────────── */}
      <polyline points="15,148 15,238 78,238 78,148" fill="none" stroke={C.border} strokeWidth={2.5} />
      <line x1="78" y1="158" x2="78" y2="170" stroke={C.bg} strokeWidth={5} />
      <line x1="78" y1="164" x2="96" y2="164" stroke={C.border} strokeWidth={2} />
      <line x1="96" y1="148" x2="96" y2="164" stroke={C.border} strokeWidth={2} />
      <rect x="16" y="188" width="61" height="49" fill={C.rawCold} fillOpacity={0.13} />
      <text x="46" y="252" textAnchor="middle" fontSize={8} fill={C.blue} fontFamily="'Share Tech Mono', monospace">BALANCE TANK</text>
      {/* Divert return entry */}
      <line x1="46" y1="148" x2="46" y2="188"
        stroke={divState === 'DIVERTED' ? C.diverted : C.deadLeg} strokeWidth={3}
        strokeDasharray={divState === 'DIVERTED' ? '8 4' : '2 8'} />

      {/* ── PIPE 1: BT → Timing Pump ─────────────── */}
      <AnimatedPipe d="M 78 214 H 118" state="RAW_COLD" flowRate={flowGPH} />

      {/* ── TIMING PUMP (SEALED) ──────────────────── */}
      <circle cx={136} cy={214} r={18} fill={C.panel} stroke={C.yellow} strokeWidth={2} />
      {[0,60,120,180,240,300].map(deg => {
        const r = (deg * Math.PI) / 180;
        return <line key={deg} x1={136} y1={214} x2={136 + 13*Math.cos(r)} y2={214 + 13*Math.sin(r)} stroke={C.yellow} strokeWidth={2} strokeLinecap="round" />;
      })}
      <circle cx={136} cy={214} r={4} fill={C.yellow} />
      <text x={136} y={238} textAnchor="middle" fontSize={7} fill={C.yellow} fontFamily="'Share Tech Mono', monospace">TIMING PUMP</text>
      {/* SEALED badge */}
      <rect x={108} y={243} width={56} height={13} fill={C.red + '22'} stroke={C.red} strokeWidth={1} rx={2} />
      <text x={136} y={253} textAnchor="middle" fontSize={8} fill={C.red} fontWeight="bold" fontFamily="'Share Tech Mono', monospace">⚿ SEALED</text>

      {/* ── PIPE 2: Pump → Heater (raw cold, no preheat) ── */}
      <AnimatedPipe d="M 154 214 H 258" state="RAW_COLD" flowRate={flowGPH} />
      <text x={206} y={232} textAnchor="middle" fontSize={7} fill={C.rawCold} fontFamily="'Share Tech Mono', monospace">RAW (no preheat)</text>

      {/* ── HEATER PHE ───────────────────────────── */}
      <rect x={258} y={173} width={80} height={60} fill={C.panel} stroke={C.orange} strokeWidth={2} rx={3} />
      {[0,1,2,3].map(i => (
        <polyline key={i}
          points={`${268+i*16},173 ${276+i*16},203 ${268+i*16},233`}
          fill="none" stroke={C.orange} strokeWidth={1.5} opacity={0.5}
        />
      ))}
      <text x={298} y={198} textAnchor="middle" fontSize={10} fill={C.orange} fontWeight="bold" fontFamily="'Share Tech Mono', monospace">HEATER</text>
      <text x={298} y={210} textAnchor="middle" fontSize={8} fill={C.orange} fontFamily="'Share Tech Mono', monospace">PHE</text>
      <text x={298} y={246} textAnchor="middle" fontSize={7} fill={C.orange} fontFamily="'Share Tech Mono', monospace">STEAM / HOT WATER</text>

      {/* ── PIPE 3: Heater → Holding Tube ────────── */}
      <AnimatedPipe d="M 338 203 L 358 203 L 358 190" state="HEATING" flowRate={flowGPH} />

      {/* ── HOLDING TUBE (slightly longer, no regen preheat) ── */}
      <rect x={353} y={178} width={168} height={52} fill={C.hotTemp} fillOpacity={0.04} rx={4}
        stroke={C.hotTemp} strokeWidth={0.5} strokeOpacity={0.2} />
      <AnimatedPipe d="M 358 190 H 510" state="HOT_TEMP" flowRate={flowGPH} />
      <AnimatedPipe d="M 510 190 V 207" state="HOT_TEMP" flowRate={flowGPH} />
      <AnimatedPipe d="M 510 207 H 362" state="HOT_TEMP" flowRate={flowGPH} reverse />
      <AnimatedPipe d="M 362 207 V 224" state="HOT_TEMP" flowRate={flowGPH} />
      <AnimatedPipe d="M 362 224 H 510" state="HOT_TEMP" flowRate={flowGPH} />
      <text x={434} y={248} textAnchor="middle" fontSize={8} fill={C.hotTemp} fontFamily="'Share Tech Mono', monospace">HOLDING TUBE</text>
      <text x={434} y={259} textAnchor="middle" fontSize={8} fill={holdOk ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">
        {`calc: ${calcHoldSec.toFixed(3)}s — min: ${req.holdSec}s ${holdOk ? '✓' : '✗'}`}
      </text>

      {/* ── PIPE: HT → TLC ───────────────────────── */}
      <AnimatedPipe d="M 510 224 L 528 210" state="HOT_TEMP" flowRate={flowGPH} />

      {/* ── TLC SENSOR ───────────────────────────── */}
      <polygon points="542,188 564,210 542,232 520,210" fill={C.panel} stroke={tempOk ? C.hotTemp : C.red} strokeWidth={2} />
      <text x={542} y={205} textAnchor="middle" fontSize={8} fill="#0f172a" fontWeight="bold" fontFamily="'Share Tech Mono', monospace">TLC</text>
      <text x={542} y={216} textAnchor="middle" fontSize={8} fill={tempOk ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">{holdTemp.toFixed(1)}°F</text>
      <text x={542} y={248} textAnchor="middle" fontSize={7} fill={tempOk ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">{tempOk ? 'TEMP ✓' : '⚠ BELOW MIN'}</text>

      {/* ── PIPE: TLC → FDD ──────────────────────── */}
      <AnimatedPipe d={`M 564 210 H ${FDD.cx - 22}`} state="HOT_TEMP" flowRate={flowGPH} />

      {/* ── FDD ──────────────────────────────────── */}
      <FDDValve x={FDD.cx} y={FDD.cy} state={fddState} />

      {/* ── PIPE: FDD Forward → Cooler ───────────── */}
      <AnimatedPipe d={`M ${FDD.cx + 22} ${FDD.cy} H ${CLR.x1}`} state={fwdState} flowRate={flowGPH} />

      {/* ── COOLER ───────────────────────────────── */}
      <rect x={CLR.x1} y={CLR.y1} width={CLR.w} height={CLR.h} fill={C.panel}
        stroke={fddState === 'forward' ? C.cooling : C.deadLeg}
        strokeWidth={fddState === 'forward' ? 2 : 1} rx={3} opacity={fddState === 'forward' ? 1 : 0.35} />
      {[0,1,2].map(i => (
        <polyline key={i}
          points={`${CLR.x1+8+i*18},${CLR.y1} ${CLR.x1+14+i*18},${CLR.y1+CLR.h/2} ${CLR.x1+8+i*18},${CLR.y1+CLR.h}`}
          fill="none" stroke={fddState === 'forward' ? C.cooling : C.deadLeg}
          strokeWidth={1.5} opacity={fddState === 'forward' ? 0.55 : 0.15}
        />
      ))}
      <text x={CLR.x1+CLR.w/2} y={CLR.y1+24} textAnchor="middle" fontSize={9} fill={fddState === 'forward' ? C.cooling : C.deadLeg} fontWeight="bold" fontFamily="'Share Tech Mono', monospace">COOLER</text>
      <text x={CLR.x1+CLR.w/2} y={CLR.y1+37} textAnchor="middle" fontSize={8} fill={fddState === 'forward' ? C.cooling : C.deadLeg} fontFamily="'Share Tech Mono', monospace">PHE</text>
      <text x={CLR.x1+CLR.w/2} y={CLR.y1+76} textAnchor="middle" fontSize={7} fill={fddState === 'forward' ? C.cooling : C.deadLeg} fontFamily="'Share Tech Mono', monospace">ICE WATER/GLYCOL</text>

      {/* ── PIPE: Cooler → Storage ───────────────── */}
      <AnimatedPipe d={`M ${CLR.x1+CLR.w} 203 H 875`} state={stgState} flowRate={flowGPH} />
      <polygon points="875,199 887,203 875,207" fill={fddState === 'forward' ? (storageOk ? C.coldStorage : C.red) : C.deadLeg} />
      <text x={893} y={197} fontSize={8} fill={fddState === 'forward' ? (storageOk ? C.coldStorage : C.red) : C.deadLeg} fontFamily="'Share Tech Mono', monospace">TO STORAGE</text>
      <text x={893} y={207} fontSize={8} fill={fddState === 'forward' ? (storageOk ? C.coldStorage : C.red) : C.deadLeg} fontFamily="'Share Tech Mono', monospace">≤45°F</text>

      {/* ── DIVERT RETURN PATH ───────────────────── */}
      <AnimatedPipe d={`M ${FDD.cx} ${FDD.cy+22} V 375 H 46 V 148`} state={divState} flowRate={flowGPH} />
      <text x={330} y={390} textAnchor="middle" fontSize={8} fill={fddState === 'divert' ? C.diverted : C.deadLeg} fontFamily="'Share Tech Mono', monospace">
        {fddState === 'divert' ? '← DIVERT RETURN → BALANCE TANK' : '─── DIVERT PATH (inactive) ───'}
      </text>

      <text x={480} y={445} textAnchor="middle" fontSize={8} fill={C.border} fontFamily="'Share Tech Mono', monospace">
        HTST SIMPLE — NO REGENERATIVE HEAT RECOVERY
      </text>
    </svg>
  );
}

// ════════════════════════════════════════════════
// HOLDING TIME CALCULATOR DISPLAY
// ════════════════════════════════════════════════
function HoldingTimeCalculatorDisplay({ params, calcHoldSec, req }) {
  const { tubeLengthFt, flowGPH } = params;
  const tubeDiamIn = 1.5;
  const tubeVolGal  = tubeLengthFt * Math.PI * Math.pow(tubeDiamIn / 24, 2) * 7.48;
  const avgHoldSec  = (tubeVolGal / flowGPH) * 3600;
  const margin      = calcHoldSec - req.holdSec;
  const progressPct = Math.min(1, Math.max(0, calcHoldSec / (req.holdSec || 0.001)));
  const ok          = margin >= 0;

  const Row = ({ label, val, color = '#475569' }) => (
    <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 3 }}>
      <span style={{ fontSize: 9, color: '#475569', fontFamily: "'Share Tech Mono', monospace" }}>{label}</span>
      <span style={{ fontSize: 9, color, fontFamily: "'Share Tech Mono', monospace", fontWeight: 600 }}>{val}</span>
    </div>
  );

  return (
    <div style={{ marginTop: 12, padding: '8px 10px', background: C.bg, borderRadius: 4, border: `1px solid ${ok ? C.border : C.red}` }}>
      <div style={{ fontSize: 9, color: C.blue, fontFamily: "'Share Tech Mono', monospace", letterSpacing: 1, marginBottom: 6 }}>
        HOLD TIME CALCULATOR
      </div>
      <Row label="Tube Length:" val={`${tubeLengthFt.toFixed(1)} ft`} color={C.orange} />
      <Row label="Tube Volume:" val={`${tubeVolGal.toFixed(4)} gal`} />
      <Row label="Flow Rate:" val={`${Math.round(flowGPH)} GPH`} color={C.rawCold} />
      <Row label="Avg Hold Time:" val={`${avgHoldSec.toFixed(3)} sec`} />
      <Row label="Fastest Particle:" val={`${calcHoldSec.toFixed(3)} sec`} color={C.hotTemp} />
      <Row label="PMO Minimum:" val={`${req.holdSec} sec`} color={C.border} />
      <div style={{ height: 1, background: C.border, margin: '5px 0' }} />
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 5 }}>
        <span style={{ fontSize: 9, color: '#475569', fontFamily: "'Share Tech Mono', monospace" }}>Margin:</span>
        <span style={{ fontSize: 10, color: ok ? C.green : C.red, fontFamily: "'Share Tech Mono', monospace", fontWeight: 700 }}>
          {ok ? `+${margin.toFixed(3)}s` : `SHORT ${margin.toFixed(3)}s`}
        </span>
      </div>
      <div style={{ height: 6, background: C.border, borderRadius: 3, overflow: 'hidden' }}>
        <div style={{
          height: '100%', width: `${(progressPct * 100).toFixed(1)}%`,
          background: ok ? C.green : C.red, borderRadius: 3,
          transition: 'width 0.3s ease, background 0.3s ease',
        }} />
      </div>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 2 }}>
        <span style={{ fontSize: 7, color: C.border, fontFamily: "'Share Tech Mono', monospace" }}>0</span>
        <span style={{ fontSize: 7, color: ok ? C.green : C.red, fontFamily: "'Share Tech Mono', monospace" }}>
          {ok ? '✓ LEGAL HOLD' : '✗ TOO SHORT'}
        </span>
        <span style={{ fontSize: 7, color: C.border, fontFamily: "'Share Tech Mono', monospace" }}>PMO min</span>
      </div>
    </div>
  );
}

// ════════════════════════════════════════════════
// HHST DIAGRAM
// ════════════════════════════════════════════════
function HHSTDiagram({ params, fddState, req, calcHoldSec }) {
  const { flowGPH, holdTemp, finalCoolF, fddPlacement, regenRawPSI, regenPastPSI } = params;
  const correctPlacement = fddPlacement === 'downstream-of-cooler';
  const storageOk  = finalCoolF <= PMO.maxStorageTemp_F;
  const holdOk     = calcHoldSec >= req.holdSec;
  const tempOk     = holdTemp >= req.tempF;
  const deltaP     = regenPastPSI - regenRawPSI;
  const deltaPOk   = deltaP >= 1.0;

  // Pipe state derivations
  const fwdState   = fddState === 'forward' ? 'PASTEURIZED' : 'DEAD_LEG';
  const divState   = fddState === 'divert'  ? 'DIVERTED'    : 'DEAD_LEG';
  const stgState   = fddState === 'forward' ? (storageOk ? 'COLD_STORAGE' : 'HOT_TEMP') : 'DEAD_LEG';

  // Coordinates — shift based on FDD placement
  const FDD   = correctPlacement ? { cx: 656, cy: 207 } : { cx: 502, cy: 207 };
  const CLR   = correctPlacement
    ? { x1: 510, y1: 171, w: 72, h: 58 }
    : { x1: 572, y1: 171, w: 72, h: 58 };
  const STO_X = correctPlacement ? 738 : 730;

  return (
    <svg viewBox="0 0 960 480" width="100%" style={{ background: '#f8fafc', display: 'block' }}>
      <defs>
        <pattern id="grid-hhst" width="40" height="40" patternUnits="userSpaceOnUse">
          <path d="M 40 0 L 0 0 0 40" fill="none" stroke="#e2e8f0" strokeWidth="0.5"/>
        </pattern>
      </defs>
      <rect width="960" height="480" fill="#f8fafc" rx="8" />
      <rect width="960" height="480" fill="url(#grid-hhst)" />

      {/* ── HHST header notice ──────────────────── */}
      <text x={480} y={28} textAnchor="middle" fontSize={10} fill={C.yellow} fontFamily="'Share Tech Mono', monospace">
        ⚠  HHST: Sub-second hold times — FDD must be DOWNSTREAM of cooler per PMO §16p(B)
      </text>

      {/* ── BALANCE TANK ─────────────────────────── */}
      <polyline points="15,148 15,238 78,238 78,148" fill="none" stroke={C.border} strokeWidth={2.5} />
      <line x1="78" y1="158" x2="78" y2="170" stroke={C.bg} strokeWidth={5} />
      <line x1="78" y1="164" x2="96" y2="164" stroke={C.border} strokeWidth={2} />
      <line x1="96" y1="148" x2="96" y2="164" stroke={C.border} strokeWidth={2} />
      <rect x="16" y="188" width="61" height="49" fill={C.rawCold} fillOpacity={0.13} />
      <text x="46" y="252" textAnchor="middle" fontSize={8} fill={C.blue} fontFamily="'Share Tech Mono', monospace">BALANCE TANK</text>
      {/* Divert return entry */}
      <line x1="46" y1="148" x2="46" y2="188"
        stroke={divState === 'DIVERTED' ? C.diverted : C.deadLeg} strokeWidth={3}
        strokeDasharray={divState === 'DIVERTED' ? '8 4' : '2 8'} />

      {/* ── PIPE 1: BT → Booster ─────────────────── */}
      <AnimatedPipe d="M 78 214 H 102" state="RAW_COLD" flowRate={flowGPH} />

      {/* ── BOOSTER PUMP ─────────────────────────── */}
      <circle cx={120} cy={214} r={16} fill={C.panel} stroke={C.border} strokeWidth={2} />
      {[0,60,120,180,240,300].map(deg => {
        const r = (deg * Math.PI) / 180;
        return <line key={deg} x1={120} y1={214} x2={120 + 12*Math.cos(r)} y2={214 + 12*Math.sin(r)} stroke={C.blue} strokeWidth={2} strokeLinecap="round" />;
      })}
      <circle cx={120} cy={214} r={3} fill={C.blue} />
      <text x={120} y={236} textAnchor="middle" fontSize={8} fill={C.blue} fontFamily="'Share Tech Mono', monospace">BOOSTER</text>

      {/* ── PIPE 2: Pump → Regen ─────────────────── */}
      <AnimatedPipe d="M 136 214 H 155" state="RAW_COLD" flowRate={flowGPH} />

      {/* ── REGENERATOR PHE ──────────────────────── */}
      <rect x={155} y={153} width={135} height={78} fill={C.panel} stroke={C.border} strokeWidth={2} rx={3} />
      <rect x={156} y={154} width={66} height={76} fill={C.rawCold} fillOpacity={0.07} rx={2} />
      <rect x={223} y={154} width={66} height={76} fill={C.pasteurized} fillOpacity={0.07} rx={2} />
      <line x1={223} y1={153} x2={223} y2={231} stroke={C.border} strokeWidth={1.5} strokeDasharray="5 3" />
      <text x={190} y={194} textAnchor="middle" fontSize={8} fill={C.rawCold} fontFamily="'Share Tech Mono', monospace">→ RAW →</text>
      <text x={256} y={194} textAnchor="middle" fontSize={8} fill={C.pasteurized} fontFamily="'Share Tech Mono', monospace">← PST ←</text>
      <text x={223} y={170} textAnchor="middle" fontSize={9} fill="#0f172a" fontWeight="bold" fontFamily="'Share Tech Mono', monospace">REGEN PHE</text>
      {/* ΔP readout */}
      <text x={223} y={108} textAnchor="middle" fontSize={9} fill={deltaPOk ? C.green : C.red} fontWeight="bold" fontFamily="'Share Tech Mono', monospace">
        {`ΔP=${deltaP.toFixed(1)} PSI ${deltaPOk ? '✓' : '✗'}`}
      </text>
      <circle cx={185} cy={140} r={11} fill={C.panel} stroke={C.border} strokeWidth={1.5} />
      <text x={185} y={144} textAnchor="middle" fontSize={9} fill={C.rawCold} fontFamily="'Share Tech Mono', monospace">{regenRawPSI}</text>
      <circle cx={262} cy={140} r={11} fill={C.panel} stroke={C.border} strokeWidth={1.5} />
      <text x={262} y={144} textAnchor="middle" fontSize={9} fill={C.pasteurized} fontFamily="'Share Tech Mono', monospace">{regenPastPSI}</text>

      {/* ── PIPE 3: Regen → HHST Heater ─────────── */}
      <AnimatedPipe d="M 290 214 H 310" state="PREHEATING" flowRate={flowGPH} />

      {/* ── HHST HIGH-TEMP HEATER ────────────────── */}
      <rect x={310} y={171} width={80} height={58} fill={C.hotTemp} fillOpacity={0.08} stroke={C.red} strokeWidth={2} rx={3} />
      {[0,1,2,3].map(i => (
        <polyline key={i}
          points={`${320+i*16},171 ${328+i*16},200 ${320+i*16},229`}
          fill="none" stroke={C.red} strokeWidth={1.5} opacity={0.6}
        />
      ))}
      <text x={350} y={194} textAnchor="middle" fontSize={9} fill={C.red} fontWeight="bold" fontFamily="'Share Tech Mono', monospace">HIGH-TEMP</text>
      <text x={350} y={206} textAnchor="middle" fontSize={9} fill={C.red} fontFamily="'Share Tech Mono', monospace">HEATER</text>
      <text x={350} y={218} textAnchor="middle" fontSize={8} fill={C.hotTemp} fontFamily="'Share Tech Mono', monospace">{holdTemp.toFixed(0)}°F</text>
      <text x={350} y={243} textAnchor="middle" fontSize={7} fill={C.red} fontFamily="'Share Tech Mono', monospace">191–212°F range</text>

      {/* ── PIPE 4: Heater → Short Holding Tube ─── */}
      <AnimatedPipe d="M 390 200 L 410 200 L 410 190" state="HOT_TEMP" flowRate={flowGPH} />

      {/* ── HOLDING TUBE (short, 2-run serpentine) ── */}
      <rect x={405} y={178} width={90} height={38} fill={C.hotTemp} fillOpacity={0.04} rx={3}
        stroke={C.hotTemp} strokeWidth={0.5} strokeOpacity={0.25} />
      <AnimatedPipe d="M 410 190 H 488" state="HOT_TEMP" flowRate={flowGPH} />
      <AnimatedPipe d="M 488 190 V 207" state="HOT_TEMP" flowRate={flowGPH} />
      <AnimatedPipe d="M 488 207 H 413" state="HOT_TEMP" flowRate={flowGPH} reverse />
      <text x={447} y={227} textAnchor="middle" fontSize={7} fill={C.hotTemp} fontFamily="'Share Tech Mono', monospace">HOLDING TUBE</text>
      <text x={447} y={237} textAnchor="middle" fontSize={7} fill={holdOk ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">
        {`${calcHoldSec.toFixed(3)}s (min ${req.holdSec}s) ${holdOk ? '✓' : '✗'}`}
      </text>

      {/* ── PIPE: HT exit → TLC ──────────────────── */}
      <AnimatedPipe d="M 413 207 L 430 214" state="HOT_TEMP" flowRate={flowGPH} />

      {/* ── TLC SENSOR ───────────────────────────── */}
      <polygon points="442,194 462,214 442,234 422,214"
        fill={C.panel} stroke={tempOk ? C.hotTemp : C.red} strokeWidth={2} />
      <text x={442} y={210} textAnchor="middle" fontSize={7} fill="#0f172a" fontWeight="bold" fontFamily="'Share Tech Mono', monospace">TLC</text>
      <text x={442} y={220} textAnchor="middle" fontSize={7} fill={tempOk ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">{holdTemp.toFixed(0)}°F</text>
      <text x={442} y={248} textAnchor="middle" fontSize={7} fill={tempOk ? C.green : C.red} fontFamily="'Share Tech Mono', monospace">{tempOk ? '✓' : '⚠'}</text>

      {/* ── PIPE: TLC → FDD or Cooler ────────────── */}
      {/* When wrong placement: FDD is before cooler */}
      {!correctPlacement && (
        <>
          {/* TLC → FDD (wrong position) */}
          <AnimatedPipe d={`M 462 214 H ${FDD.cx - 22}`} state="HOT_TEMP" flowRate={flowGPH} />
          {/* FDD (wrong position — flashing red border) */}
          <g style={{ animation: 'pulse 0.8s ease-in-out infinite' }}>
            <circle cx={FDD.cx} cy={FDD.cy} r={26} fill="none" stroke={C.red} strokeWidth={3} />
          </g>
          <FDDValve x={FDD.cx} y={FDD.cy} state={fddState} />
          {/* Wrong position label */}
          <text x={FDD.cx} y={FDD.cy - 52} textAnchor="middle" fontSize={9} fill={C.red} fontWeight="bold"
            fontFamily="'Share Tech Mono', monospace" style={{ animation: 'pulse 1s ease-in-out infinite' }}>
            ⚠ WRONG POSITION!
          </text>
          {/* FDD fwd → Cooler */}
          <AnimatedPipe d={`M ${FDD.cx + 22} ${FDD.cy} H ${CLR.x1}`} state={fwdState} flowRate={flowGPH} />
        </>
      )}
      {correctPlacement && (
        <>
          {/* TLC → Cooler (FDD is downstream) */}
          <AnimatedPipe d={`M 462 214 H ${CLR.x1}`} state="HOT_TEMP" flowRate={flowGPH} />
        </>
      )}

      {/* ── COOLER PHE ───────────────────────────── */}
      <rect x={CLR.x1} y={CLR.y1} width={CLR.w} height={CLR.h} fill={C.panel}
        stroke={fddState === 'forward' ? C.cooling : (correctPlacement ? C.deadLeg : C.cooling)}
        strokeWidth={2} rx={3}
      />
      {[0,1,2].map(i => (
        <polyline key={i}
          points={`${CLR.x1+8+i*18},${CLR.y1} ${CLR.x1+14+i*18},${CLR.y1+CLR.h/2} ${CLR.x1+8+i*18},${CLR.y1+CLR.h}`}
          fill="none" stroke={C.cooling} strokeWidth={1.5} opacity={0.5}
        />
      ))}
      <text x={CLR.x1+CLR.w/2} y={CLR.y1+22} textAnchor="middle" fontSize={9} fill={C.cooling} fontWeight="bold" fontFamily="'Share Tech Mono', monospace">COOLER</text>
      <text x={CLR.x1+CLR.w/2} y={CLR.y1+35} textAnchor="middle" fontSize={8} fill={C.cooling} fontFamily="'Share Tech Mono', monospace">PHE</text>
      <text x={CLR.x1+CLR.w/2} y={CLR.y1+75} textAnchor="middle" fontSize={7} fill={C.cooling} fontFamily="'Share Tech Mono', monospace">ICE WATER/GLYCOL</text>

      {/* ── After cooler ─────────────────────────── */}
      {correctPlacement && (
        <>
          {/* Cooler → FDD (correct downstream position) */}
          <AnimatedPipe d={`M ${CLR.x1+CLR.w} ${FDD.cy} H ${FDD.cx - 22}`} state="COOLING" flowRate={flowGPH} />
          {/* FDD */}
          <FDDValve x={FDD.cx} y={FDD.cy} state={fddState} />
          {/* FDD → Storage */}
          <AnimatedPipe d={`M ${FDD.cx+22} ${FDD.cy} H ${STO_X}`} state={fwdState} flowRate={flowGPH} />
          {/* PMO callout annotation (green — correct position) */}
          <rect x={FDD.cx - 70} y={FDD.cy - 95} width={140} height={38} fill="#052e12" stroke={C.green} strokeWidth={1.5} rx={3} />
          <text x={FDD.cx} y={FDD.cy - 79} textAnchor="middle" fontSize={8} fill={C.green} fontWeight="bold" fontFamily="'Share Tech Mono', monospace">PMO §16p(B) — HHST</text>
          <text x={FDD.cx} y={FDD.cy - 67} textAnchor="middle" fontSize={7} fill={C.green} fontFamily="'Share Tech Mono', monospace">FDD DOWNSTREAM of cooler ✓</text>
          <line x1={FDD.cx} y1={FDD.cy - 57} x2={FDD.cx} y2={FDD.cy - 26} stroke={C.green} strokeWidth={1} strokeDasharray="3 2" />
        </>
      )}
      {!correctPlacement && (
        <>
          {/* Cooler → Storage (no FDD downstream) */}
          <AnimatedPipe d={`M ${CLR.x1+CLR.w} ${FDD.cy} H ${STO_X}`} state={fwdState} flowRate={flowGPH} />
          {/* Red callout — FDD in wrong position */}
          <rect x={FDD.cx - 80} y={FDD.cy - 100} width={160} height={45} fill="#2e0a0a" stroke={C.red} strokeWidth={1.5} rx={3}
            style={{ animation: 'pulse 1.2s ease-in-out infinite' }} />
          <text x={FDD.cx} y={FDD.cy - 84} textAnchor="middle" fontSize={8} fill={C.red} fontWeight="bold" fontFamily="'Share Tech Mono', monospace">⚠ PMO VIOLATION</text>
          <text x={FDD.cx} y={FDD.cy - 72} textAnchor="middle" fontSize={7} fill={C.red} fontFamily="'Share Tech Mono', monospace">HHST FDD must be AFTER cooler</text>
          <text x={FDD.cx} y={FDD.cy - 62} textAnchor="middle" fontSize={7} fill={C.red} fontFamily="'Share Tech Mono', monospace">PMO §16p(B) — see HHST_FDD_POS</text>
          <line x1={FDD.cx} y1={FDD.cy - 57} x2={FDD.cx} y2={FDD.cy - 26} stroke={C.red} strokeWidth={1} strokeDasharray="3 2" />
        </>
      )}

      {/* ── ASEPTIC STORAGE ──────────────────────── */}
      <rect x={STO_X} y={183} width={120} height={46} fill={fddState === 'forward' ? C.pasteurized + '18' : C.deadLeg + '18'}
        stroke={fddState === 'forward' ? C.pasteurized : C.deadLeg} strokeWidth={1.5} rx={4} />
      <text x={STO_X+60} y={202} textAnchor="middle" fontSize={8} fill={fddState === 'forward' ? C.pasteurized : C.deadLeg} fontWeight="bold" fontFamily="'Share Tech Mono', monospace">ASEPTIC</text>
      <text x={STO_X+60} y={213} textAnchor="middle" fontSize={8} fill={fddState === 'forward' ? C.pasteurized : C.deadLeg} fontFamily="'Share Tech Mono', monospace">ULTRA-PAST.</text>
      <text x={STO_X+60} y={224} textAnchor="middle" fontSize={8} fill={fddState === 'forward' ? C.pasteurized : C.deadLeg} fontFamily="'Share Tech Mono', monospace">STORAGE</text>

      {/* ── DIVERT RETURN ────────────────────────── */}
      <AnimatedPipe d={`M ${FDD.cx} ${FDD.cy+22} V 375 H 46 V 148`} state={divState} flowRate={flowGPH} />
      <text x={350} y={390} textAnchor="middle" fontSize={8} fill={fddState === 'divert' ? C.diverted : C.deadLeg} fontFamily="'Share Tech Mono', monospace">
        {fddState === 'divert' ? '← DIVERT RETURN → BALANCE TANK' : '─── DIVERT PATH (inactive) ───'}
      </text>

      <text x={480} y={445} textAnchor="middle" fontSize={8} fill={C.border} fontFamily="'Share Tech Mono', monospace">
        HHST — HIGH-HEAT-SHORT-TIME PASTEURIZER / ULTRA-PASTEURIZATION
      </text>
    </svg>
  );
}

// ════════════════════════════════════════════════
// PMO REFERENCE STRIP
// ════════════════════════════════════════════════
const PMO_HTST_TABLE = [
  { id: 'standard', tempF: 161, tempC: 72,  hold: '15 sec',   notes: 'Standard milk' },
  { id: 'highFat',  tempF: 166, tempC: 74,  hold: '15 sec',   notes: '≥10% fat / ≥18% solids / sweetened' },
  { id: 'eggnog',   tempF: 175, tempC: 80,  hold: '25 sec',   notes: 'Eggnog' },
  { id: 'alt1',     tempF: 191, tempC: 89,  hold: '1.0 sec',  notes: '' },
  { id: 'alt2',     tempF: 194, tempC: 90,  hold: '0.5 sec',  notes: '' },
  { id: 'alt3',     tempF: 201, tempC: 94,  hold: '0.1 sec',  notes: '' },
  { id: 'alt4',     tempF: 204, tempC: 96,  hold: '0.05 sec', notes: '' },
  { id: 'alt5',     tempF: 212, tempC: 100, hold: '0.01 sec', notes: '' },
];

const PMO_VAT_TABLE = [
  { id: 'standard', tempF: 145, tempC: 63, hold: '30 min', notes: 'Standard milk' },
  { id: 'highFat',  tempF: 150, tempC: 66, hold: '30 min', notes: '≥10% fat / ≥18% solids / sweetened' },
  { id: 'eggnog',   tempF: 155, tempC: 69, hold: '30 min', notes: 'Eggnog' },
];

const th = (w) => ({ width: w, padding: '2px 6px', fontSize: 8, color: C.blue, fontFamily: "'Share Tech Mono', monospace", borderRight: `1px solid ${C.border}`, flexShrink: 0 });
const td = (w, color = '#475569') => ({ width: w, padding: '2px 6px', fontSize: 9, color, fontFamily: "'Share Tech Mono', monospace", borderRight: `1px solid ${C.border}`, flexShrink: 0 });

function PMORefStrip({ tab, product, params }) {
  const isVat  = tab === 'vat';
  const table  = isVat ? PMO_VAT_TABLE : PMO_HTST_TABLE;
  const currTempF = isVat ? params.vatTemp : params.holdTemp;

  return (
    <div style={{
      background: C.panel, borderTop: `2px solid ${C.border}`,
      padding: '8px 16px', flexShrink: 0, overflowX: 'auto',
    }}>
      <div style={{ fontSize: 9, color: C.blue, fontFamily: "'Share Tech Mono', monospace", letterSpacing: 1, marginBottom: 5 }}>
        {isVat
          ? 'PMO TABLE 3a — VAT BATCH PASTEURIZATION TIME/TEMP MINIMUMS'
          : 'PMO TABLE 3b — CONTINUOUS FLOW (HTST/HHST) PASTEURIZATION TIME/TEMP MINIMUMS'}
      </div>
      {/* Header row */}
      <div style={{ display: 'flex', background: C.border, borderRadius: '3px 3px 0 0', width: 'fit-content' }}>
        <div style={th(92)}>Temp (°F)</div>
        <div style={th(72)}>Temp (°C)</div>
        <div style={th(88)}>Hold Time</div>
        <div style={th(230)}>Product Notes</div>
        <div style={th(110)}>Margin to curr</div>
      </div>
      {/* Data rows */}
      {table.map(row => {
        const isCurr = row.id === product;
        const margin = currTempF - row.tempF;
        return (
          <div key={row.id} style={{
            display: 'flex', width: 'fit-content',
            background: isCurr ? C.blue + '1e' : 'transparent',
            borderBottom: `1px solid ${C.border}`,
            outline: isCurr ? `1px solid ${C.blue + '44'}` : 'none',
          }}>
            <div style={td(92, isCurr ? C.blue : '#64748b')}>
              {row.tempF}°F{isCurr ? ' ◄CURR' : ''}
            </div>
            <div style={td(72, '#475569')}>{row.tempC}°C</div>
            <div style={td(88, isCurr ? C.blue : '#475569')}>{row.hold}</div>
            <div style={td(230, '#475569')}>{row.notes || '—'}</div>
            <div style={td(110, isCurr ? (margin >= 0 ? C.green : C.red) : C.border)}>
              {isCurr ? (margin >= 0 ? `+${margin.toFixed(1)}°F above min` : `${margin.toFixed(1)}°F BELOW MIN`) : ''}
            </div>
          </div>
        );
      })}
      <div style={{ marginTop: 4, fontSize: 8, color: '#475569', fontFamily: "'Share Tech Mono', monospace" }}>
        {isVat
          ? '* VAT pasteurizer — batch process. Hold timer resets if temperature drops below minimum during hold period.'
          : '* High fat/solids/sweetened products add 5°F (3°C) to minimum. Timing pump sealed at max speed by Regulatory Authority.'}
      </div>
    </div>
  );
}

// ════════════════════════════════════════════════
// MAIN COMPONENT
// ════════════════════════════════════════════════
const DEFAULT_PARAMS = {
  holdTemp:        163,
  flowGPH:         3000,
  tubeLengthFt:    18,
  regenPastPSI:    18,
  regenRawPSI:     14,
  finalCoolF:      38,
  sealedMaxGPH:    5000,
  overflowMarginIn:14,
  systemState:     'running',
  powerState:      'normal',
  recorderState:   'ok',
  fddPlacement:    'downstream-of-cooler',
  vatTemp:         147,
  vatHoldElapsed:  0,
  vatHoldRequired: 30,
  vatOutletOpen:   false,
  vatPhase:        'holding',
};

const TABS = [
  { id: 'htst-regen', label: 'HTST w/ Regen' },
  { id: 'htst-simple', label: 'HTST Simple' },
  { id: 'hhst', label: 'HHST' },
  { id: 'vat', label: 'VAT' },
];

const PRODUCTS = Object.entries(PMO.htst).map(([id, v]) => ({ id, label: v.label }));

function PasteurizerSim() {
  const [tab,       setTab]      = useState('htst-regen');
  const [product,   setProduct]  = useState('standard');
  const [unitF,     setUnitF]    = useState(true);
  const [params,    setParams]   = useState(DEFAULT_PARAMS);
  const [overrides, setOverrides]= useState({});
  const [rightPanel, setRightPanel]= useState('conditions');
  const [tooltip,     setTooltip]    = useState(null);   // { title, body, pmoRef, currentValue, x, y }
  const [divertPopup, setDivertPopup]= useState(false);
  const [historyLog,  setHistoryLog] = useState([]);     // [{ ts, event, detail }]
  const prevFddRef = useRef('forward');

  // ── Computed values ──
  const req        = PMO.htst[product];
  const tubeDiamIn = 1.5;
  const tubeVolGal = params.tubeLengthFt * Math.PI * Math.pow(tubeDiamIn / 24, 2) * 7.48;
  const avgHoldSec = (tubeVolGal / params.flowGPH) * 3600;
  const calcHoldSec = avgHoldSec * 0.5;
  const allParams  = { ...params, calcHoldSec };

  const conditionResults = DIVERT_CONDITIONS.map(c => {
    const applicable = !((c.vatOnly && tab !== 'vat') || (c.hhstOnly && tab !== 'hhst'));
    const passing    = applicable ? (overrides[c.id] ? false : c.check(allParams, req)) : true;
    return {
      ...c, passing, applicable,
      displayVal: c.display ? c.display(allParams, req) : '—',
    };
  });

  const violations = conditionResults.filter(c => !c.passing && c.applicable);
  const fddState   = violations.length === 0 ? 'forward' : 'divert';

  // Track fddState changes → update history log and show divert popup
  useEffect(() => {
    if (prevFddRef.current !== fddState) {
      const ts     = new Date().toLocaleTimeString('en-US', { hour12: false });
      const event  = fddState === 'divert' ? 'DIVERT' : 'FORWARD';
      const detail = fddState === 'divert'
        ? conditionResults.filter(c => !c.passing && c.applicable).map(v => `${v.label}: ${v.displayVal}`).join(' / ')
        : 'All conditions satisfied';
      setHistoryLog(log => [{ ts, event, detail }, ...log].slice(0, 10));
      if (fddState === 'divert') setDivertPopup(true);
      prevFddRef.current = fddState;
    }
  }, [fddState]);

  const setParam = (key, val) => setParams(p => ({ ...p, [key]: val }));
  const toggleOverride = (id) => setOverrides(o => ({ ...o, [id]: !o[id] }));

  // ── Scenario buttons ──
  const scenarios = [
    { label: 'Drop Temp 5°F',     action: () => setParam('holdTemp', Math.max(140, params.holdTemp - 5)) },
    { label: 'Kill Power',        action: () => setParam('powerState', params.powerState === 'normal' ? 'lost' : 'normal') },
    { label: 'Simulate Startup',  action: () => setParam('systemState', params.systemState !== 'startup' ? 'startup' : 'running') },
    { label: 'Increase Flow 30%', action: () => setParam('flowGPH', Math.min(10000, params.flowGPH * 1.3)) },
    { label: 'Drop Regen ΔP',    action: () => setParam('regenPastPSI', params.regenRawPSI + 0.5) },
    { label: '✅ Reset All Legal', action: () => { setParams(DEFAULT_PARAMS); setOverrides({}); } },
  ];

  const bannerOk   = fddState === 'forward';

  // Live margins for enhanced forward banner
  const tempMargin  = params.holdTemp - req.tempF;
  const holdMargin  = calcHoldSec - req.holdSec;
  const regenDP     = params.regenPastPSI - params.regenRawPSI;
  const regenMargin = regenDP - PMO.regenMinDeltaP_psi;
  const coolerMargin= PMO.maxStorageTemp_F - params.finalCoolF;
  const tight = (margin, min) => margin < Math.abs(min) * 0.10;
  const marginColor = (margin, min) => tight(margin, min) ? C.yellow : C.green;


  return (
    <div style={{ background: C.bg, minHeight: '100vh', display: 'flex', flexDirection: 'column' }}>
      {/* ── Google Fonts + CSS Animations ── */}
      <style>{`
        @import url('https://fonts.googleapis.com/css2?family=Share+Tech+Mono&family=Rajdhani:wght@400;500;600;700&display=swap');
        @keyframes pipFlowFwd { from { stroke-dashoffset: 30; } to { stroke-dashoffset: 0; } }
        @keyframes pipFlowRev { from { stroke-dashoffset: 0; } to { stroke-dashoffset: 30; } }
        @keyframes pulse { 0%,100% { opacity:1; } 50% { opacity:0.4; } }
        @keyframes agitatorSpin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
        @keyframes divertPulse { 0%,100% { box-shadow: 0 0 12px #ef444466; } 50% { box-shadow: 0 0 28px #ef4444cc; } }
        * { box-sizing: border-box; margin: 0; padding: 0; }
        @media print {
          .no-print { display: none !important; }
          body { background: white !important; color: black !important; }
          svg text { fill: #111 !important; }
          .print-header { display: block !important; }
        }
        input[type=range] { -webkit-appearance: none; height: 4px; background: #e2e8f0; border-radius: 2px; outline: none; }
        input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; width: 14px; height: 14px; border-radius: 50%; cursor: pointer; }
        ::-webkit-scrollbar { width: 5px; } ::-webkit-scrollbar-track { background: #f8fafc; } ::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 3px; }
      `}</style>

      {/* ── HEADER ── */}
      <div style={{
        padding: '10px 20px', background: C.panel, borderBottom: `2px solid ${C.blue}`,
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
      }}>
        <div>
          <div style={{ fontSize: 16, fontWeight: 700, color: C.blue, fontFamily: "'Rajdhani', sans-serif", letterSpacing: 2 }}>
            HTST PASTEURIZER COMPLIANCE SIMULATOR
          </div>
          <div style={{ fontSize: 10, color: '#475569', fontFamily: "'Share Tech Mono', monospace" }}>
            PMO Grade A Pasteurized Milk Ordinance — Interactive FDD Logic Trainer
          </div>
        </div>
        <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
          {/* Unit toggle */}
          <button
            onClick={() => setUnitF(u => !u)}
            style={{ padding: '4px 10px', background: C.border, border: `1px solid ${C.blue}`, color: C.blue, borderRadius: 4, cursor: 'pointer', fontSize: 11, fontFamily: "'Share Tech Mono', monospace" }}
          >
            {unitF ? '°F' : '°C'}
          </button>
          {/* Product selector */}
          <select
            value={product} onChange={e => setProduct(e.target.value)}
            style={{ padding: '4px 8px', background: C.panel, border: `1px solid ${C.border}`, color: '#0f172a', borderRadius: 4, fontSize: 11, fontFamily: "'Share Tech Mono', monospace" }}
          >
            {PRODUCTS.map(p => <option key={p.id} value={p.id}>{p.label}</option>)}
          </select>
          {/* Print Report button */}
          <button
            className="no-print"
            onClick={() => {
              document.body.classList.add('print-mode');
              window.print();
              document.body.classList.remove('print-mode');
            }}
            style={{ padding: '4px 10px', background: C.bg, border: `1px solid ${C.border}`, color: '#64748b', borderRadius: 4, cursor: 'pointer', fontSize: 11, fontFamily: "'Share Tech Mono', monospace" }}
            onMouseEnter={e => { e.currentTarget.style.borderColor = C.blue; e.currentTarget.style.color = C.blue; }}
            onMouseLeave={e => { e.currentTarget.style.borderColor = C.border; e.currentTarget.style.color = '#64748b'; }}
          >
            Print Report
          </button>
        </div>
      </div>

      {/* ── TAB BAR ── */}
      <div style={{ display: 'flex', background: C.panel, borderBottom: `1px solid ${C.border}` }}>
        {TABS.map(t => (
          <button
            key={t.id}
            onClick={() => setTab(t.id)}
            style={{
              padding: '8px 18px', border: 'none', cursor: 'pointer',
              background: tab === t.id ? C.bg : 'transparent',
              color: tab === t.id ? C.blue : '#475569',
              borderBottom: tab === t.id ? `2px solid ${C.blue}` : '2px solid transparent',
              fontSize: 11, fontFamily: "'Rajdhani', sans-serif", fontWeight: 600, letterSpacing: 1,
              transition: 'color 0.15s',
            }}
          >
            {t.label}
          </button>
        ))}
      </div>

      {/* ── COMPLIANCE BANNER ── */}
      <div style={{
        padding: '8px 20px',
        background: bannerOk ? '#dcfce7' : '#fee2e2',
        borderBottom: `2px solid ${bannerOk ? C.greenBorder : C.redBorder}`,
        animation: !bannerOk ? 'pulse 1.5s ease-in-out infinite' : 'none',
      }}>
        {bannerOk ? (
          <div>
            <div style={{ fontSize: 13, fontWeight: 700, color: C.green, fontFamily: "'Rajdhani', sans-serif", letterSpacing: 1, marginBottom: 4 }}>
              ✅ FORWARD FLOW — ALL CONDITIONS SATISFIED
            </div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: '6px 20px' }}>
              {tab !== 'vat' && <>
                <span style={{ fontSize: 10, fontFamily: "'Share Tech Mono', monospace", color: marginColor(tempMargin, req.tempF) }}>
                  Temp: {params.holdTemp.toFixed(1)}°F ▲ +{tempMargin.toFixed(1)}°F above {req.tempF}°F min
                </span>
                <span style={{ fontSize: 10, fontFamily: "'Share Tech Mono', monospace", color: marginColor(holdMargin, req.holdSec) }}>
                  Hold: {calcHoldSec.toFixed(2)}s ▲ +{holdMargin.toFixed(2)}s above {req.holdSec}s min
                </span>
                {tab === 'htst-regen' && <span style={{ fontSize: 10, fontFamily: "'Share Tech Mono', monospace", color: marginColor(regenMargin, 1.0) }}>
                  Regen: ΔP={regenDP.toFixed(1)} PSI ▲ +{regenMargin.toFixed(1)} PSI above 1.0 min
                </span>}
                <span style={{ fontSize: 10, fontFamily: "'Share Tech Mono', monospace", color: marginColor(coolerMargin, 10) }}>
                  Cooler: {params.finalCoolF.toFixed(1)}°F ✓ below 45°F max
                </span>
                <span style={{ fontSize: 10, fontFamily: "'Share Tech Mono', monospace", color: C.green }}>
                  FDD: ENERGIZED — FORWARD POSITION
                </span>
              </>}
              {tab === 'vat' && <>
                <span style={{ fontSize: 10, fontFamily: "'Share Tech Mono', monospace", color: C.green }}>
                  Vat Temp: {params.vatTemp}°F ▲ +{(params.vatTemp - req.tempF).toFixed(1)}°F above {req.tempF}°F min
                </span>
                <span style={{ fontSize: 10, fontFamily: "'Share Tech Mono', monospace", color: C.green }}>
                  Hold: {params.vatHoldElapsed}/{params.vatHoldRequired} min — All conditions satisfied
                </span>
              </>}
            </div>
          </div>
        ) : (
          <span style={{ fontSize: 13, fontWeight: 700, color: C.red, fontFamily: "'Rajdhani', sans-serif", letterSpacing: 1 }}>
            {tab === 'vat'
              ? `⚠ HOLD VIOLATION — ${violations.length} condition(s) failed: ${violations.map(v => v.label).join(' · ')}`
              : `⚠ DIVERT — ${violations.length} condition(s) failed: ${violations.map(v => v.label).join(' · ')}`}
          </span>
        )}
      </div>

      {/* ── MAIN CONTENT ── */}
      <div style={{ display: 'flex', flex: 1, overflow: 'hidden', minHeight: 0 }}>

        {/* ── LEFT: SLIDERS ── */}
        <div style={{
          width: 210, background: C.panel, borderRight: `1px solid ${C.border}`,
          padding: '14px 12px', overflowY: 'auto', flexShrink: 0,
        }}>
          <div style={{ fontSize: 10, color: C.blue, fontFamily: "'Share Tech Mono', monospace", letterSpacing: 1, marginBottom: 12 }}>
            PROCESS PARAMETERS
          </div>

          {/* ── HTST / HHST SLIDERS ── */}
          {tab !== 'vat' && (
            <>
              <Slider label="Hold Temp" min={150} max={220} step={0.5} value={params.holdTemp} onChange={v => setParam('holdTemp', v)} unit="°F" color={C.hotTemp} />
              <Slider label="Flow Rate" min={500} max={10000} step={50} value={params.flowGPH} onChange={v => setParam('flowGPH', v)} unit=" GPH" color={C.rawCold} />
              <Slider label="Tube Length" min={5} max={50} step={0.5} value={params.tubeLengthFt} onChange={v => setParam('tubeLengthFt', v)} unit=" ft" color={C.orange} />
              {tab === 'htst-regen' && (
                <>
                  <Slider label="Regen Past PSI" min={5} max={30} step={0.5} value={params.regenPastPSI} onChange={v => setParam('regenPastPSI', v)} unit=" psi" color={C.pasteurized} />
                  <Slider label="Regen Raw PSI" min={5} max={30} step={0.5} value={params.regenRawPSI} onChange={v => setParam('regenRawPSI', v)} unit=" psi" color={C.rawCold} />
                  <Slider label="Overflow Margin" min={0} max={30} step={0.5} value={params.overflowMarginIn} onChange={v => setParam('overflowMarginIn', v)} unit='"' color={C.yellow} />
                </>
              )}
              <Slider label="Final Cool Temp" min={33} max={55} step={0.5} value={params.finalCoolF} onChange={v => setParam('finalCoolF', v)} unit="°F" color={C.cooling} />

              {/* HHST: FDD placement toggle */}
              {tab === 'hhst' && (
                <div style={{ marginBottom: 12 }}>
                  <div style={{ fontSize: 10, color: '#64748b', fontFamily: "'Rajdhani', sans-serif", marginBottom: 4 }}>FDD Placement Demo</div>
                  <button
                    onClick={() => setParam('fddPlacement',
                      params.fddPlacement === 'downstream-of-cooler' ? 'upstream-of-cooler' : 'downstream-of-cooler')}
                    style={{
                      width: '100%', padding: '6px', borderRadius: 4, cursor: 'pointer', fontSize: 9,
                      fontFamily: "'Share Tech Mono', monospace", fontWeight: 600, lineHeight: 1.4,
                      background: params.fddPlacement === 'downstream-of-cooler' ? C.green + '18' : C.red + '22',
                      border: `1px solid ${params.fddPlacement === 'downstream-of-cooler' ? C.green : C.red}`,
                      color: params.fddPlacement === 'downstream-of-cooler' ? C.green : C.red,
                    }}
                  >
                    {params.fddPlacement === 'downstream-of-cooler'
                      ? '✓ FDD downstream (correct)\nClick → move upstream (violation)'
                      : '⚠ FDD upstream (VIOLATION)\nClick → restore correct position'}
                  </button>
                </div>
              )}

              {/* Hold time calculator (HTST/HHST only) */}
              {(tab === 'htst-regen' || tab === 'htst-simple' || tab === 'hhst') && (
                <HoldingTimeCalculatorDisplay params={params} calcHoldSec={calcHoldSec} req={req} />
              )}
            </>
          )}

          {/* ── VAT SLIDERS ── */}
          {tab === 'vat' && (
            <>
              <div style={{ fontSize: 8, color: '#475569', fontFamily: "'Share Tech Mono', monospace", marginBottom: 8 }}>
                VAT PMO: {req.tempF}°F / {req.holdSec}s (use Standard Milk product = 145°F PMO basis)
              </div>
              <Slider label="Vat Temperature" min={130} max={220} step={0.5} value={params.vatTemp} onChange={v => setParam('vatTemp', v)} unit="°F" color={C.orange} />
              <Slider label="Hold Elapsed" min={0} max={35} step={0.25} value={params.vatHoldElapsed} onChange={v => setParam('vatHoldElapsed', v)} unit=" min" color={C.yellow} />
              <Slider label="Hold Required" min={10} max={60} step={1} value={params.vatHoldRequired} onChange={v => setParam('vatHoldRequired', v)} unit=" min" color={C.border} />
              <Slider label="Final Cool Temp" min={33} max={55} step={0.5} value={params.finalCoolF} onChange={v => setParam('finalCoolF', v)} unit="°F" color={C.cooling} />
              {/* Outlet valve toggle */}
              <div style={{ marginBottom: 12 }}>
                <div style={{ fontSize: 10, color: '#64748b', fontFamily: "'Rajdhani', sans-serif", marginBottom: 4 }}>Outlet Valve</div>
                <button
                  onClick={() => setParam('vatOutletOpen', !params.vatOutletOpen)}
                  style={{
                    width: '100%', padding: '6px', borderRadius: 4, cursor: 'pointer', fontSize: 10,
                    fontFamily: "'Share Tech Mono', monospace", fontWeight: 600,
                    background: params.vatOutletOpen ? (params.vatHoldElapsed < params.vatHoldRequired ? C.red + '33' : C.green + '22') : C.bg,
                    border: `1px solid ${params.vatOutletOpen ? (params.vatHoldElapsed < params.vatHoldRequired ? C.red : C.green) : C.border}`,
                    color: params.vatOutletOpen ? (params.vatHoldElapsed < params.vatHoldRequired ? C.red : C.green) : '#64748b',
                  }}
                >
                  {params.vatOutletOpen ? '🔓 OUTLET OPEN' : '🔒 OUTLET CLOSED'}
                </button>
              </div>
              {/* Vat phase toggle */}
              <div style={{ marginBottom: 12 }}>
                <div style={{ fontSize: 10, color: '#64748b', fontFamily: "'Rajdhani', sans-serif", marginBottom: 4 }}>Vat Phase</div>
                {['heating','holding','cooling'].map(phase => (
                  <button key={phase} onClick={() => setParam('vatPhase', phase)} style={{
                    marginRight: 4, marginBottom: 4, padding: '3px 7px', borderRadius: 3, cursor: 'pointer',
                    fontSize: 9, fontFamily: "'Share Tech Mono', monospace",
                    background: params.vatPhase === phase ? C.blue + '33' : C.bg,
                    border: `1px solid ${params.vatPhase === phase ? C.blue : C.border}`,
                    color: params.vatPhase === phase ? C.blue : '#64748b',
                  }}>{phase}</button>
                ))}
              </div>
            </>
          )}

          {/* ── SET FORWARD FLOW button ── */}
          <div style={{ marginTop: 14 }}>
            <button
              onClick={() => {
                // tubeLengthFt=50 + flowGPH=500 → calcHoldSec≈16.5s ≥ 15s (standard milk min)
                setProduct('standard');
                setParams({ holdTemp:163, flowGPH:500, tubeLengthFt:50, regenPastPSI:18, regenRawPSI:14, finalCoolF:38, sealedMaxGPH:5000, overflowMarginIn:14, systemState:'running', powerState:'normal', recorderState:'ok', fddPlacement:'downstream-of-cooler', vatTemp:147, vatHoldElapsed:25, vatHoldRequired:30, vatOutletOpen:false, vatPhase:'holding' });
                setOverrides({});
              }}
              style={{
                display: 'block', width: '100%', padding: '9px 10px', textAlign: 'center',
                background: '#16a34a', border: '1px solid #15803d',
                color: '#ffffff', fontFamily: "'Rajdhani', sans-serif",
                fontWeight: 700, fontSize: 13, borderRadius: 4, cursor: 'pointer',
                boxShadow: '0 0 10px #16a34a55', letterSpacing: 0.5,
              }}
            >
              ✅ SET FORWARD FLOW — Show Legal Operation
            </button>
          </div>

          {/* Violation demos divider */}
          <div style={{ margin: '12px 0 6px', display: 'flex', alignItems: 'center', gap: 6 }}>
            <div style={{ flex: 1, height: 1, background: C.border }} />
            <span style={{ fontSize: 9, color: C.textMuted, fontFamily: "'Share Tech Mono', monospace", whiteSpace: 'nowrap' }}>── VIOLATION DEMOS ──</span>
            <div style={{ flex: 1, height: 1, background: C.border }} />
          </div>

          {scenarios.map((s, i) => (
            <button
              key={i}
              onClick={s.action}
              style={{
                display: 'block', width: '100%', marginBottom: 5,
                padding: '5px 8px', textAlign: 'left',
                background: C.bg, border: `1px solid ${C.border}`,
                color: i === scenarios.length - 1 ? C.green : '#64748b',
                borderRadius: 4, cursor: 'pointer', fontSize: 10,
                fontFamily: "'Share Tech Mono', monospace",
                transition: 'border-color 0.15s, color 0.15s',
              }}
              onMouseEnter={e => { e.currentTarget.style.borderColor = C.blue; e.currentTarget.style.color = 'white'; }}
              onMouseLeave={e => { e.currentTarget.style.borderColor = C.border; e.currentTarget.style.color = i === scenarios.length - 1 ? C.green : '#64748b'; }}
            >
              {s.label}
            </button>
          ))}

          {/* ── EVENT LOG ── */}
          <div style={{ marginTop: 14 }}>
            <div style={{ fontSize: 10, color: C.blue, fontFamily: "'Share Tech Mono', monospace", letterSpacing: 1, marginBottom: 6 }}>
              EVENT LOG
            </div>
            <div style={{ maxHeight: 130, overflowY: 'auto', background: C.bg, borderRadius: 4, border: `1px solid ${C.border}`, padding: '5px 7px' }}>
              {historyLog.length === 0 ? (
                <div style={{ fontSize: 9, color: '#475569', fontFamily: "'Share Tech Mono', monospace" }}>No events yet</div>
              ) : historyLog.map((e, i) => (
                <div key={i} style={{ marginBottom: 5 }}>
                  <span style={{ fontSize: 8, color: '#475569', fontFamily: "'Share Tech Mono', monospace" }}>{e.ts} </span>
                  <span style={{ fontSize: 9, fontWeight: 700, color: e.event === 'DIVERT' ? C.red : C.green, fontFamily: "'Share Tech Mono', monospace" }}>{e.event} </span>
                  <div style={{ fontSize: 8, color: '#64748b', fontFamily: "'Share Tech Mono', monospace", marginTop: 1, lineHeight: 1.4 }}>{e.detail}</div>
                </div>
              ))}
            </div>
          </div>
        </div>

        {/* ── CENTER: DIAGRAM ── */}
        <div style={{ flex: 1, overflow: 'auto', padding: '16px' }}>

          {/* ── PROCESS STATE BOX ── */}
          <div style={{
            marginBottom: 12, padding: '8px 14px',
            background: bannerOk ? C.greenBg : C.redBg,
            border: `1px solid ${bannerOk ? C.greenBorder : C.redBorder}`,
            borderRadius: 5, fontFamily: "'Share Tech Mono', monospace",
          }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', flexWrap: 'wrap', gap: '4px 20px' }}>
              <span style={{ fontSize: 10, color: bannerOk ? C.green : C.red, fontWeight: 700 }}>
                Mode: {bannerOk ? 'NORMAL PRODUCTION' : `⚠ DIVERTED`}
              </span>
              <span style={{ fontSize: 10, color: bannerOk ? C.green : C.red, fontWeight: 700 }}>
                FDD: {bannerOk ? 'FORWARD ✅' : 'DIVERT ❌'}
              </span>
              {bannerOk ? <>
                <span style={{ fontSize: 10, color: C.textMuted }}>
                  Product: {(PRODUCTS.find(p => p.id === product) || {}).label || product}
                </span>
                <span style={{ fontSize: 10, color: C.textMuted }}>
                  System: {params.systemState.toUpperCase()}
                </span>
                {tab !== 'vat' && <>
                  <span style={{ fontSize: 10, color: marginColor(tempMargin, req.tempF) }}>
                    Hold Temp: {params.holdTemp.toFixed(1)}°F (+{tempMargin.toFixed(1)}°F margin)
                  </span>
                  <span style={{ fontSize: 10, color: marginColor(holdMargin, req.holdSec) }}>
                    Hold Time: {calcHoldSec.toFixed(2)}s (+{holdMargin.toFixed(2)}s)
                  </span>
                </>}
              </> : <>
                <span style={{ fontSize: 10, color: C.red }}>
                  Reason: {violations[0]?.label || '—'}
                </span>
                <span style={{ fontSize: 10, color: C.red }}>
                  Conditions Failed: {violations.length}
                </span>
              </>}
            </div>
          </div>

          {tab === 'htst-regen' && (
            <HTSTRegenDiagram params={params} fddState={fddState} req={req} calcHoldSec={calcHoldSec} />
          )}
          {tab === 'htst-simple' && (
            <HTSTSimpleDiagram params={params} fddState={fddState} req={req} calcHoldSec={calcHoldSec} />
          )}
          {tab === 'vat' && (
            <VATDiagram params={params} req={req} />
          )}
          {tab === 'hhst' && (
            <HHSTDiagram params={params} fddState={fddState} req={req} calcHoldSec={calcHoldSec} />
          )}
        </div>

        {/* ── RIGHT: CONDITIONS / SOP PANEL ── */}
        <div style={{
          width: 300, background: C.panel, borderLeft: `1px solid ${C.border}`,
          display: 'flex', flexDirection: 'column', flexShrink: 0, overflow: 'hidden',
        }}>
          {/* Tab toggle */}
          <div style={{ display: 'flex', borderBottom: `1px solid ${C.border}`, flexShrink: 0 }}>
            {[['conditions', 'DIVERT CONDITIONS'], ['sop', 'OPERATOR SOPs']].map(([id, label]) => (
              <button key={id} onClick={() => setRightPanel(id)} style={{
                flex: 1, padding: '7px 4px', border: 'none', cursor: 'pointer',
                fontSize: 9, fontFamily: "'Share Tech Mono', monospace", letterSpacing: 0.5,
                background: rightPanel === id ? C.bg : 'transparent',
                color: rightPanel === id ? (id === 'sop' ? C.orange : C.blue) : '#4a6a8a',
                borderBottom: rightPanel === id
                  ? `2px solid ${id === 'sop' ? C.orange : C.blue}`
                  : '2px solid transparent',
                transition: 'color 0.15s',
              }}>
                {label}
              </button>
            ))}
          </div>
          {rightPanel === 'conditions'
            ? <DivertConditionsPanel conditionResults={conditionResults} tab={tab} onToggleOverride={toggleOverride} />
            : <OperatorSOPPanel />
          }
        </div>
      </div>

      {/* ── PMO REFERENCE STRIP ── */}
      <PMORefStrip tab={tab} product={product} params={params} />

      {/* ── DIVERT POPUP ── */}
      {divertPopup && violations.length > 0 && (
        <div className="no-print" style={{
          position: 'fixed', top: 80, right: 320, width: 330, zIndex: 500,
          background: '#1a0606', border: `2px solid ${C.red}`, borderRadius: 6,
          padding: 14, animation: 'divertPulse 1.5s ease-in-out infinite',
        }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
            <span style={{ fontSize: 13, fontWeight: 700, color: C.red, fontFamily: "'Rajdhani', sans-serif", letterSpacing: 1 }}>
              ⚠ DIVERT TRIGGERED
            </span>
            <button
              onClick={() => setDivertPopup(false)}
              style={{ background: 'none', border: 'none', color: '#64748b', cursor: 'pointer', fontSize: 16, lineHeight: 1 }}
            >✕</button>
          </div>
          <div style={{ maxHeight: 360, overflowY: 'auto' }}>
            {violations.map((v, i) => (
              <div key={v.id} style={{ marginBottom: 10, paddingBottom: 8, borderBottom: i < violations.length - 1 ? `1px solid ${C.border}` : 'none' }}>
                <div style={{ fontSize: 11, fontWeight: 700, color: C.red, fontFamily: "'Rajdhani', sans-serif", marginBottom: 3 }}>{v.label}</div>
                <div style={{ fontSize: 10, color: C.yellow, fontFamily: "'Share Tech Mono', monospace", marginBottom: 4 }}>{v.displayVal}</div>
                <div style={{ fontSize: 9, color: '#9ab0c8', fontFamily: "'Share Tech Mono', monospace", lineHeight: 1.55, marginBottom: 3 }}>{v.explanation}</div>
                <div style={{ fontSize: 9, color: '#475569', fontFamily: "'Share Tech Mono', monospace" }}>{v.pmoRef}</div>
              </div>
            ))}
          </div>
        </div>
      )}

      {/* ── SVG TOOLTIP ── */}
      <Tooltip tip={tooltip} />
    </div>
  );
}

// Mount when loaded via CDN (index.html)
if (typeof ReactDOM !== 'undefined' && document.getElementById('root')) {
  ReactDOM.createRoot(document.getElementById('root')).render(
    React.createElement(PasteurizerSim)
  );
}
