/* visuals6.jsx — The Transistor.
   A small "control" stream operates a big "main" valve. Bigger base flow →
   wider main valve opening. Tiny input controls big output. */

/* ─── TransistorWaterScene ───────────────────────────────────────────────
   Two barrels:
     • LEFT-TOP: small "control" barrel feeding a tiny pipe (base)
     • LEFT-BOTTOM: big "supply" barrel feeding a wide pipe (collector)
   The base flow operates a gate in the main pipe.
   ───────────────────────────────────────────────────────────────────────── */
function TransistorWaterScene({ vCC = 10, vBase = 0, beta = 50, height = 380, showLabels = true, kids = false }) {
  const W = 820, H = 460;

  // Normalize: vBase 0-2 V drives gain. Saturate at ~1.5V.
  const baseFraction = Math.max(0, Math.min(1, (vBase - 0.6) / 1.2));
  const iBase = baseFraction * 0.04;       // small current
  const iCollector = Math.min(vCC / 1.0, iBase * beta);  // amplified
  const periodBase = flowPeriod(Math.max(0.05, iBase * 10));
  const periodMain = flowPeriod(Math.max(0.05, iCollector));

  // Layout: small barrel top-left, big barrel bottom-left
  const baseBarrelCx = 90, baseBarrelTop = 50, baseBarrelBot = 130;
  const baseRimRx = 28, baseMidRx = 38;
  const ccBarrelCx = 90, ccBarrelTop = 200, ccBarrelBot = 380;
  const ccRimRx = 50, ccMidRx = 64;

  // Pipes
  const basePipeY = 90;
  const basePipeStart = baseBarrelCx + 36;
  const basePipeBaseH = 8;

  const mainPipeY = 300;
  const mainPipeStart = ccBarrelCx + 50;
  const mainPipeEnd = W - 60;
  const mainBaseH = 28;

  // The gate sits in the main pipe at the same X as where the base pipe arrives
  const gateCx = 500;
  const gateOpen = baseFraction;    // 0..1
  const gateHalfH = mainBaseH * (0.08 + 0.92 * gateOpen);
  // Lock-gate geometry: a sliding plate (like a canal-lock paddle) that the
  // base trickle PULLS UP. Plate has a fixed length; its bottom edge sets the
  // opening. Fully open → plate retracted into the housing above the pipe.
  const pipeTopY = mainPipeY - mainBaseH;
  const pipeBotY = mainPipeY + mainBaseH;
  const openingTopY = pipeBotY - 2 * gateHalfH;   // bottom of the plate
  const plateLen = 2 * mainBaseH;
  const plateTopY = openingTopY - plateLen;
  const housingTopY = pipeTopY - plateLen - 14;   // tall enough to swallow the plate
  // water downstream of the gate: level matches the opening; dry when off
  const postFrac = iCollector > 0.02 ? gateHalfH / mainBaseH : 0;

  // Base pipe routes: from base barrel right, then down to gate
  const basePipeEnd = gateCx;

  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={height}
         preserveAspectRatio="xMidYMid meet" style={{ display: "block", maxHeight: height }}>
      {/* Small control barrel */}
      {renderBarrel({ cx: baseBarrelCx, top: baseBarrelTop, bot: baseBarrelBot,
                      rimRx: baseRimRx, midRx: baseMidRx,
                      fill: Math.max(0, Math.min(1, vBase / 2)), idSuffix: "trb" })}
      {/* Big supply barrel */}
      {renderBarrel({ cx: ccBarrelCx, top: ccBarrelTop, bot: ccBarrelBot,
                      rimRx: ccRimRx, midRx: ccMidRx,
                      fill: fillRatio(vCC), idSuffix: "trcc" })}

      {/* Tiny base pipe: horizontal then turns down into the lock housing */}
      <path d={`M ${basePipeStart} ${basePipeY - basePipeBaseH}
                L ${basePipeEnd - 18} ${basePipeY - basePipeBaseH}
                Q ${basePipeEnd - 4} ${basePipeY - basePipeBaseH}, ${basePipeEnd + 6} ${basePipeY + 16}
                L ${basePipeEnd + 6} ${housingTopY - 2}`}
            fill="none" stroke="var(--ink)" strokeWidth="1.5" />
      <path d={`M ${basePipeStart} ${basePipeY + basePipeBaseH}
                L ${basePipeEnd - 6} ${basePipeY + basePipeBaseH}
                Q ${basePipeEnd + 6} ${basePipeY + basePipeBaseH}, ${basePipeEnd + 18} ${basePipeY + 22}
                L ${basePipeEnd + 18} ${housingTopY - 2}`}
            fill="none" stroke="var(--ink)" strokeWidth="1.5" />

      {/* Tiny base flow */}
      {iBase > 0.001 && (
        <path d={`M ${basePipeStart + 4} ${basePipeY}
                  L ${basePipeEnd + 12} ${basePipeY}
                  L ${basePipeEnd + 12} ${housingTopY - 2}`}
              fill="none" stroke="var(--current-soft)" strokeWidth="2"
              strokeDasharray="4 12" strokeLinecap="round"
              className="flow-anim" style={{ "--flow-period": periodBase }} />
      )}

      {/* Main pipe (split around gate). Downstream runs at the gate's level —
          and runs DRY when the gate is shut. */}
      {renderPipe({ pipeStart: mainPipeStart, pipeEnd: gateCx - 26, pipeY: mainPipeY,
                    baseH: mainBaseH, constrictions: [],
                    current: iCollector, period: periodMain,
                    idSuffix: "trm-pre", showOutletCap: false })}
      {renderPipe({ pipeStart: gateCx + 26, pipeEnd: mainPipeEnd, pipeY: mainPipeY,
                    baseH: mainBaseH, constrictions: [],
                    current: iCollector, period: periodMain, idSuffix: "trm-post",
                    levels: [{ fromX: gateCx + 26, toX: mainPipeEnd, frac: postFrac }] })}

      {/* ── The LOCK GATE (the "transistor") ────────────────────────
          A canal-lock paddle: a ribbed plate sliding in a housing, hauled
          up by the base trickle, falling shut without it. ───────────── */}
      {/* housing above the pipe that the plate retracts into */}
      <rect x={gateCx - 26} y={housingTopY} width={52} height={pipeTopY - housingTopY + 4}
            fill="var(--bg-card)" stroke="var(--ink)" strokeWidth="2.5" rx="4" />
      {/* frame around the pipe section */}
      <rect x={gateCx - 26} y={pipeTopY - 8} width={52} height={mainBaseH * 2 + 16}
            fill="none" stroke="var(--ink)" strokeWidth="2.5" rx="4" />
      {/* guide slots */}
      <line x1={gateCx - 20} y1={housingTopY + 6} x2={gateCx - 20} y2={pipeBotY + 4}
            stroke="var(--ink-faint)" strokeWidth="1" strokeDasharray="2 4" />
      <line x1={gateCx + 20} y1={housingTopY + 6} x2={gateCx + 20} y2={pipeBotY + 4}
            stroke="var(--ink-faint)" strokeWidth="1" strokeDasharray="2 4" />
      {/* the sliding plate — ribbed, metal, bottom edge = the opening */}
      <g style={{ transition: "transform 160ms ease-out" }}>
        <rect x={gateCx - 17} y={plateTopY} width={34} height={plateLen}
              fill={`oklch(0.62 ${0.05 + baseFraction * 0.09} ${30 + baseFraction * 25})`}
              stroke="var(--ink)" strokeWidth="2" rx="2" />
        {[0.25, 0.5, 0.75].map(f => (
          <line key={f} x1={gateCx - 13} y1={plateTopY + plateLen * f}
                x2={gateCx + 13} y2={plateTopY + plateLen * f}
                stroke="var(--ink)" strokeWidth="1.2" opacity="0.45" />
        ))}
        {/* lifting rod from plate top up into the housing cap */}
        <line x1={gateCx} y1={plateTopY} x2={gateCx} y2={housingTopY + 6}
              stroke="var(--ink)" strokeWidth="3" strokeLinecap="round" />
        {/* crossbar handle on the rod */}
        <rect x={gateCx - 10} y={housingTopY + 4} width={20} height={5} rx="2.5" fill="var(--ink)" />
      </g>
      {/* motion chevrons — which way the plate is being pulled right now */}
      <g fill={gateOpen > 0.04 ? "var(--current)" : "var(--ink-faint)"}>
        {gateOpen > 0.04 ? (
          <>
            <path d={`M ${gateCx + 34} ${pipeTopY - 26} l 6 8 l -12 0 Z`} />
            <path d={`M ${gateCx + 34} ${pipeTopY - 14} l 6 8 l -12 0 Z`} opacity="0.55" />
          </>
        ) : (
          <>
            <path d={`M ${gateCx + 34} ${pipeTopY - 30} l 6 -8 l -12 0 Z`} />
            <path d={`M ${gateCx + 34} ${pipeTopY - 18} l 6 -8 l -12 0 Z`} opacity="0.55" />
          </>
        )}
      </g>

      {/* Outlet droplets */}
      {iCollector > 0.1 && renderOutletDroplets({ pipeEnd: mainPipeEnd, pipeY: mainPipeY,
                                                  current: iCollector, period: periodMain })}

      {showLabels && (
        <g fontFamily="IBM Plex Mono, monospace" letterSpacing="0.14em">
          <text x={baseBarrelCx} y={baseBarrelTop - 12} textAnchor="middle"
                fontSize="17.5" fill="var(--current)">
            {kids ? <>Handle · {vBase.toFixed(2)}V</> : <>V<tspan fontSize="12">base</tspan> · {vBase.toFixed(2)}V</>}
          </text>
          <text x={ccBarrelCx} y={ccBarrelTop - 14} textAnchor="middle"
                fontSize="20.5" fill="var(--water)">
            {kids ? <>Supply · {vCC.toFixed(1)}V</> : <>V<tspan fontSize="13.5">CC</tspan> · {vCC.toFixed(1)}V</>}
          </text>
          <text x={gateCx} y={mainPipeY + mainBaseH + 36} textAnchor="middle"
                fontSize="17.5" fill="var(--ink-faint)">
            {kids ? "SLIDING GATE" : "LOCK GATE"} · {(baseFraction * 100).toFixed(0)}% OPEN
          </text>
          <text x={gateCx + 50} y={housingTopY + 16} fontSize="14"
                fill={iBase > 0.001 ? "var(--current)" : "var(--ink-faint)"}>
            {iBase > 0.001
              ? (kids ? "← trickle pulls the gate UP" : "← base flow hauls the plate up")
              : (kids ? "← no trickle — gate falls shut" : "← no base flow — plate sits shut")}
          </text>
          <text x={mainPipeEnd - 110} y={mainPipeY - mainBaseH - 14}
                fontSize="19" fill={iCollector > 0.05 ? "var(--current)" : "var(--ink-faint)"}>
            {kids ? <>Out · {iCollector.toFixed(2)}A</> : <>I<tspan fontSize="12">out</tspan> · {iCollector.toFixed(2)}A</>}
          </text>
          <text x={baseBarrelCx + 50} y={basePipeY - 14}
                fontSize="15" fill={iBase > 0.001 ? "var(--current)" : "var(--ink-faint)"}>
            {kids ? "tiny trickle" : <>tiny I<tspan fontSize="11">b</tspan> · {(iBase * 1000).toFixed(1)}mA</>}
          </text>
        </g>
      )}
    </svg>
  );
}

/* ─── TransistorCircuitScene ────────────────────────────────────────────
   NPN BJT symbol: collector top, emitter bottom, base on the left.
   Base current controls collector current; gain = beta.
   ───────────────────────────────────────────────────────────────────────── */
function TransistorCircuitScene({ vCC = 10, vBase = 0, beta = 50, height = 380, showLabels = true, kids = false }) {
  const W = 820, H = 460;
  const baseFraction = Math.max(0, Math.min(1, (vBase - 0.6) / 1.2));
  const iBase = baseFraction * 0.04;
  const iCollector = Math.min(vCC / 1.0, iBase * beta);
  const periodBase = flowPeriod(Math.max(0.05, iBase * 10));
  const periodMain = flowPeriod(Math.max(0.05, iCollector));

  // Layout
  const Lbat = 130, batCy = 230, batHalfH = 30;
  const ccTop = 80;
  const txCx = 480, txCy = 230;       // transistor center
  const bulbCx = 680, bulbCy = ccTop + 50, bulbR = 30;
  const ground = 380;

  // Wires
  // Battery (V_CC) + → up to ccTop → right to bulb → down through bulb → down to collector
  // Bulb is "load" hanging on the collector
  // Emitter → ground rail → battery −
  // Base input on lower left → into base

  const wirePathMain = `
    M ${Lbat} ${batCy - batHalfH}
    L ${Lbat} ${ccTop}
    L ${bulbCx} ${ccTop}
    L ${bulbCx} ${bulbCy - bulbR}
    M ${bulbCx} ${bulbCy + bulbR}
    L ${bulbCx} ${txCy - 50}
    L ${txCx + 28} ${txCy - 50}
    L ${txCx + 28} ${txCy - 16}
    M ${txCx + 28} ${txCy + 16}
    L ${txCx + 28} ${ground}
    L ${Lbat} ${ground}
    L ${Lbat} ${batCy + batHalfH}
  `;

  // Base input wire
  const baseWirePath = `M 100 ${ground - 60} L 100 ${txCy + 20} L ${txCx - 30} ${txCy + 20} L ${txCx - 30} ${txCy + 4}`;

  // Loop for main electrons
  const loopMain = `
    M ${Lbat} ${batCy - batHalfH}
    L ${Lbat} ${ccTop} L ${bulbCx} ${ccTop}
    L ${bulbCx} ${txCy - 16}
    L ${txCx + 28} ${txCy - 16} L ${txCx + 28} ${ground}
    L ${Lbat} ${ground} L ${Lbat} ${batCy + batHalfH}
    L ${Lbat} ${batCy - batHalfH} Z
  `;
  const loopBase = `M 100 ${ground - 60} L 100 ${txCy + 20} L ${txCx - 30} ${txCy + 20} L ${txCx + 28} ${ground} L 100 ${ground} L 100 ${ground - 60} Z`;

  const flowingMain = iCollector > 0.05;
  const flowingBase = iBase > 0.001;
  const power = vCC * iCollector;
  const glowOpacity = Math.max(0, Math.min(1, power / 14));

  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={height}
         preserveAspectRatio="xMidYMid meet" style={{ display: "block", maxHeight: height }}>
      <path d={wirePathMain} fill="none" stroke="var(--current-faint)"
            strokeWidth="9" strokeLinecap="round"
            opacity={flowingMain ? 0.5 : 0} style={{ transition: "opacity 200ms ease" }} />
      <path d={wirePathMain} fill="none" stroke="var(--ink)" strokeWidth="2.5" strokeLinecap="round" />
      <path d={baseWirePath} fill="none" stroke="var(--ink)" strokeWidth="2" strokeLinecap="round" />

      {flowingMain && renderElectrons({ path: loopMain, period: periodMain,
                                        flowing: true, count: 6 })}
      {flowingBase && renderElectrons({ path: loopBase, period: periodBase,
                                        flowing: true, count: 3,
                                        color: "var(--current-soft)" })}

      {/* V_CC battery */}
      {renderBatterySymbol({ cx: Lbat, cy: batCy, halfH: batHalfH, voltage: vCC, showLabel: showLabels })}

      {/* V_base source — drawn small */}
      <g>
        <line x1={94} y1={ground - 60 - 10} x2={106} y2={ground - 60 - 10}
              stroke="var(--ink)" strokeWidth="2.5" />
        <line x1={97} y1={ground - 60 + 4} x2={103} y2={ground - 60 + 4}
              stroke="var(--ink)" strokeWidth="2.5" />
        {showLabels && (
          <text x={75} y={ground - 60 + 2} textAnchor="end"
                fontFamily="IBM Plex Mono, monospace" fontSize="17.5"
                fill="var(--current)" letterSpacing="0.12em">
            {kids ? <>Handle·{vBase.toFixed(2)}V</> : <>V<tspan fontSize="12">base</tspan>·{vBase.toFixed(2)}V</>}
          </text>
        )}
      </g>

      {/* Bulb (load) */}
      {renderBulbSymbol({ cx: bulbCx, cy: bulbCy, r: bulbR, glowOpacity, flowing: flowingMain,
                          label: showLabels && "LOAD" })}

      {/* Transistor symbol (NPN BJT) */}
      <g>
        <circle cx={txCx + 28} cy={txCy} r={26} fill="var(--bg-card)" stroke="var(--ink)" strokeWidth="2" />
        {/* base line */}
        <line x1={txCx + 8} y1={txCy - 12} x2={txCx + 8} y2={txCy + 12}
              stroke="var(--ink)" strokeWidth="3" />
        {/* collector diagonal */}
        <line x1={txCx + 8} y1={txCy - 6} x2={txCx + 24} y2={txCy - 18}
              stroke="var(--ink)" strokeWidth="2" />
        {/* emitter diagonal with arrowhead */}
        <line x1={txCx + 8} y1={txCy + 6} x2={txCx + 24} y2={txCy + 18}
              stroke="var(--ink)" strokeWidth="2" />
        <polygon points={`${txCx + 24},${txCy + 18} ${txCx + 18},${txCy + 16} ${txCx + 20},${txCy + 12}`}
                 fill="var(--ink)" />
        {/* leads — base extends left to wire, collector up, emitter down */}
        <line x1={txCx - 30} y1={txCy} x2={txCx + 8} y2={txCy}
              stroke="var(--ink)" strokeWidth="2" />
        <line x1={txCx + 24} y1={txCy - 18} x2={txCx + 28} y2={txCy - 16}
              stroke="var(--ink)" strokeWidth="2" />
        <line x1={txCx + 24} y1={txCy + 18} x2={txCx + 28} y2={txCy + 16}
              stroke="var(--ink)" strokeWidth="2" />

        {showLabels && (
          <>
            {!kids && <text x={txCx - 36} y={txCy + 4} textAnchor="end"
                  fontFamily="IBM Plex Mono, monospace" fontSize="15"
                  fill="var(--ink-faint)" letterSpacing="0.14em">B</text>}
            {!kids && <text x={txCx + 60} y={txCy - 30} textAnchor="start"
                  fontFamily="IBM Plex Mono, monospace" fontSize="15"
                  fill="var(--ink-faint)" letterSpacing="0.14em">C</text>}
            {!kids && <text x={txCx + 60} y={txCy + 36} textAnchor="start"
                  fontFamily="IBM Plex Mono, monospace" fontSize="15"
                  fill="var(--ink-faint)" letterSpacing="0.14em">E</text>}
            <text x={txCx + 28} y={txCy + 56} textAnchor="middle"
                  fontFamily="IBM Plex Mono, monospace" fontSize="15"
                  fill="var(--ink-faint)" letterSpacing="0.14em">{kids ? "the valve" : `NPN · β=${beta}`}</text>
          </>
        )}
      </g>

      {/* ground symbol */}
      <g>
        <line x1={Lbat - 14} y1={ground} x2={Lbat + 14} y2={ground} stroke="var(--ink)" strokeWidth="2" />
        <line x1={Lbat - 10} y1={ground + 4} x2={Lbat + 10} y2={ground + 4} stroke="var(--ink)" strokeWidth="2" />
        <line x1={Lbat - 6} y1={ground + 8} x2={Lbat + 6} y2={ground + 8} stroke="var(--ink)" strokeWidth="2" />
      </g>

      {showLabels && (
        <g fontFamily="IBM Plex Mono, monospace" letterSpacing="0.14em">
          <text x={W / 2} y={H - 10} textAnchor="middle" fontSize="17.5"
                fill={flowingMain ? "var(--current)" : "var(--ink-faint)"}>
            {kids ? (
              <>tiny in · {(iBase * 1000).toFixed(1)}mA{"  →  "}big out · {iCollector.toFixed(2)}A{"  (×"}{beta}{")"}</>
            ) : (
              <>I<tspan fontSize="12">B</tspan>·{(iBase * 1000).toFixed(1)}mA{"  →  "}I<tspan fontSize="12">C</tspan>·{iCollector.toFixed(2)}A{"  (×"}{beta}{")"}</>
            )}
          </text>
        </g>
      )}
    </svg>
  );
}

Object.assign(window, { TransistorWaterScene, TransistorCircuitScene });
