/* Practice figures, part two — connected and core-platform practices.
   Same rules as part one: instrument detail, CSS keyframes only, mobile drops
   panels rather than shrinking type. Shared helpers come from part one. */
/* Helpers are resolved at render time, not at load: with a dozen Babel scripts on
   one page the execution order of src modules is not guaranteed. */
const PFG = (props) => window.Fig(props);
const GP = (props) => window.Panel(props);
const GM = (...a) => window.MONO(...a);
const cA = "var(--sx-accent)", cF = "var(--sx-field)", cS = "var(--sx-signal)", cAM = "var(--sx-amber)";
const cL = "var(--border-default)", cL2 = "var(--border-strong)";
const cQ = "var(--text-quiet)", cI = "var(--text-strong)", cB = "var(--text-body)";

/* ── Energy-tech ──────────────────────────────────────────────────────────
   The hierarchy a distribution utility actually has, reads climbing it, and
   the command coming back down with an acknowledgement that is checked. */
function FigEnergy({ mobile }) {
  const meters = mobile ? 5 : 9;
  const h = mobile ? 200 : 250;
  const sy = 24, fy = 84, my = mobile ? 140 : 148;
  const mx = (i) => 18 + i * ((mobile ? 330 : 250) / (meters - 1));
  const feeders = [0, 1];
  return (
    <PFG h={h} title="Reads up, command down" subtitle="company → circle → feeder → transformer → meter"
      note="Counts are representative of a distribution utility of this size. A command is confirmed by the device or reported as failed — the acknowledgement window is contractual, not best-effort."
      legend={[{ label: "interval read", color: cF }, { label: "command", color: cAM }]}>
      <rect x="128" y={sy - 13} width="144" height="26" rx="3" fill="var(--surface-raised)" stroke={cA} />
      <text x="200" y={sy - 1} textAnchor="middle" fill={cI} style={GM(10)}>circle · lahore east</text>
      <text x="200" y={sy + 9} textAnchor="middle" fill={cQ} style={GM(7)}>3 IT centres kept in sync</text>
      {feeders.map((f) => {
        const fx = f === 0 ? 84 : 232;
        return (
          <g key={f}>
            <path d={`M${fx} ${fy - 10} V${sy + 22} H200`} fill="none" stroke={cL2} strokeWidth="1" />
            <rect x={fx - 40} y={fy - 10} width="80" height="22" rx="3" fill="var(--surface-card)" stroke={cL2} />
            <text x={fx} y={fy + 4} textAnchor="middle" fill={cB} style={GM(8)}>feeder F-{118 + f * 4}</text>
            <text x={fx} y={fy - 16} textAnchor="middle" fill={cQ} style={GM(7)}>{f === 0 ? "12 transformers" : "9 transformers"}</text>
          </g>
        );
      })}
      {Array.from({ length: meters }).map((_, i) => {
        const x = mx(i), tgt = x < 200 ? 84 : 232;
        return (
          <g key={i}>
            <path d={`M${x} ${my - 8} V${fy + 26} H${tgt} V${fy + 12}`} fill="none" stroke={cL} strokeWidth="0.7" />
            <rect x={x - 7} y={my - 8} width="14" height="14" rx="2" fill="var(--surface-card)" stroke={i === 3 ? cAM : cL2} />
            <circle className="pf-load" style={{ animationDelay: `${i * 0.32}s` }} cx={x} cy={my - 8} r="2.4" fill={cF} />
            {!mobile && <text x={x} y={my + 18} textAnchor="middle" fill={cQ} style={GM(6)}>{4471 + i * 3}</text>}
          </g>
        );
      })}
      <circle className="pf-command" cx="200" cy={sy + 14} r="3.2" fill={cAM} />
      {!mobile && (
        <>
          <GP x={286} y={fy - 26} w={110} h={100} label="command status">
            {[["queued", "3", cQ], ["acknowledged", "3", cF], ["failed", "0", cF], ["window", "15 min", cQ]].map((r, i) => (
              <g key={r[0]} className="pf-field" style={{ animationDelay: `${0.6 + i * 0.3}s` }}>
                <text x="294" y={fy + 6 + i * 18} fill={cQ} style={GM(7)}>{r[0]}</text>
                <text x="388" y={fy + 6 + i * 18} textAnchor="end" fill={r[2]} style={GM(9)}>{r[1]}</text>
              </g>
            ))}
          </GP>
          <text x="18" y={my + 40} fill={cQ} style={GM(7)}>validation before billing</text>
          {[["spike", cF], ["zero", cF], ["rollover", cF], ["gap 07:45", cAM], ["clock drift", cF], ["phase", cF]].map((r, i) => (
            <g key={r[0]} className="pf-field" style={{ animationDelay: `${i * 0.22}s` }}>
              <rect x={18 + i * 62} y={my + 48} width="56" height="15" rx="2" fill="none" stroke={r[1]} opacity="0.8" />
              <text x={46 + i * 62} y={my + 58} textAnchor="middle" fill={r[1]} style={GM(7)}>{r[0]}</text>
            </g>
          ))}
          <text x="18" y={my + 78} fill={cQ} style={GM(7)}>1 of 96 intervals estimated, flagged on the record — never silently filled</text>
        </>
      )}
      {mobile && <text x="18" y={my + 34} fill={cQ} style={GM(7)}>6 validation rules before a read reaches a bill</text>}
    </PFG>
  );
}

/* ── Agri-tech ────────────────────────────────────────────────────────────
   Three probe depths, the water balance that reads them, and the verification
   step that corrects the next cycle. */
function FigAgri({ mobile }) {
  const h = mobile ? 200 : 252, x0 = 30, x1 = 392, base = h - (mobile ? 44 : 74), top = 40;
  const N = 72;
  const X = (i) => x0 + (i / N) * (x1 - x0);
  const depths = [["20 cm", cF, 0.0], ["40 cm", cA, 0.14], ["60 cm", cQ, 0.26]];
  const curve = (ph, amp) => {
    const d = [];
    for (let i = 0; i <= N; i++) {
      const c = i % 24;
      const v = (c < 17 ? 0.74 - c * 0.026 : 0.3 + (c - 17) * 0.066) * (1 - amp) + amp * 0.55 + ph * 0.1;
      d.push((i ? "L" : "M") + X(i).toFixed(1) + " " + (base - v * (base - top)).toFixed(1));
    }
    return d.join(" ");
  };
  const thr = base - 0.42 * (base - top);
  return (
    <PFG h={h} title="Sense, decide, verify" subtitle="three probe depths, one irrigation decision, then the check"
      note="Readings are representative of a mid-cycle house at midday. The grower's bounds are hard limits in the deployed system; every override is logged with who set it."
      legend={[{ label: "20 cm", color: cF }, { label: "40 cm", color: cA }, { label: "60 cm", color: cQ }]}>
      {[0, 0.25, 0.5, 0.75, 1].map((t) => (
        <g key={t}>
          <line x1={x0} y1={base - t * (base - top)} x2={x1} y2={base - t * (base - top)} stroke={cL} strokeWidth="0.6" />
          <text x={x0 - 5} y={base - t * (base - top) + 3} textAnchor="end" fill={cQ} style={GM(7)}>{Math.round(10 + t * 24)}%</text>
        </g>
      ))}
      <line x1={x0} y1={thr} x2={x1} y2={thr} stroke={cAM} strokeDasharray="4 3" strokeWidth="1" />
      <text x={x1} y={thr - 5} textAnchor="end" fill={cAM} style={GM(7)}>refill point</text>
      {depths.slice(0, mobile ? 2 : 3).map(([label, col, amp], i) => (
        <path key={label} className="pf-draw-slow" style={{ animationDelay: `${i * 0.4}s`, opacity: i === 0 ? 1 : 0.65 }} d={curve(i * 0.02, amp)} fill="none" stroke={col} strokeWidth={i === 0 ? 1.7 : 1.1} />
      ))}
      {[0, 1, 2].slice(0, mobile ? 2 : 3).map((k) => {
        const x = X(k * 24 + 17);
        return (
          <g key={k} className="pf-valve" style={{ animationDelay: `${k * 2.4 + 1}s` }}>
            <line x1={x} y1={top - 16} x2={x} y2={base} stroke={cA} strokeWidth="1" strokeDasharray="2 3" />
            <rect x={x - 30} y={top - 30} width="60" height="16" rx="3" fill="var(--surface-raised)" stroke={cA} />
            <text x={x} y={top - 19} textAnchor="middle" fill={cA} style={GM(7)}>valve · 9 mm</text>
          </g>
        );
      })}
      {!mobile && (
        <>
          <path d={`M${X(17)} ${top - 6} H${X(23)}`} stroke={cF} strokeWidth="1" />
          <path d={`M${X(17)} ${top - 9} v6 M${X(23)} ${top - 9} v6`} stroke={cF} strokeWidth="1" />
          <text x={X(20)} y={top - 11} textAnchor="middle" fill={cF} style={GM(7)}>verify 90 min</text>
          <line x1={x0} y1={base + 22} x2={x1} y2={base + 22} stroke={cL} />
          {[["et₀", "5.6 mm/day"], ["crop kc", "1.05 mid"], ["rain 48h", "2 mm · low conf"], ["applied", "9.1 mm"], ["expected", "24.1% · got 24.7%"]].map((r, i) => (
            <g key={r[0]} className="pf-field" style={{ animationDelay: `${i * 0.26}s` }}>
              <text x={x0 - 24 + i * 76} y={base + 36} fill={cQ} style={GM(7)}>{r[0]}</text>
              <text x={x0 - 24 + i * 76} y={base + 48} fill={i === 4 ? cF : cI} style={GM(8)}>{r[1]}</text>
            </g>
          ))}
          <text x={x0 - 24} y={base + 64} fill={cQ} style={GM(7)}>profile moved further than predicted, so next cycle drops the setpoint 0.4 mm</text>
        </>
      )}
      {mobile && <text x={x0 - 24} y={base + 28} fill={cQ} style={GM(7)}>applied 9.1 mm · profile answered 24.7% vs 24.1% expected</text>}
    </PFG>
  );
}

/* ── ERP & billing ────────────────────────────────────────────────────────
   The cycle as a ledger: what came in, what was held, what was posted, and
   what is still owed. */
function FigLedger({ mobile }) {
  const rows = mobile
    ? [["reads_ingested", "6.52M", "", cF], ["exceptions_held", "20,510", "circle desk", cAM], ["bills_generated", "6.50M", "8 circles", cF], ["payments_posted", "5.91M", "bank files", cF]]
    : [["reads_ingested", "6.52M", "field · smart · manual", cF], ["exceptions_held", "20,510", "to circle desk, before billing", cAM], ["tariff_applied", "6.50M", "protected · unprotected · TOU", cF], ["bill_run", "6.50M", "batch, restartable checkpoints", cF], ["dispatch", "6.50M", "print · portal · sms", cF], ["payments_posted", "5.91M", "machine-readable bank returns", cF], ["rejected", "1,340", "re-presented next file", cAM]];
  const rowH = 24, top = 26;
  const h = top + rows.length * rowH + (mobile ? 40 : 74);
  return (
    <PFG h={h} title="One cycle, posted and reconciled" subtitle="reads in, bill out, payment matched"
      note="Representative magnitudes for a cycle of this size. No implausible read reaches a bill — held reads are worked at the circle desk before the run continues."
      legend={[{ label: "posted", color: cF }, { label: "held", color: cAM }]}>
      <text x="10" y="14" fill={cQ} style={GM(7)}>stage</text>
      <text x="392" y="14" textAnchor="end" fill={cQ} style={GM(7)}>count</text>
      <line x1="6" y1="18" x2="394" y2="18" stroke={cL2} />
      {rows.map((r, i) => {
        const y = top + i * rowH;
        return (
          <g key={r[0]} className="pf-row" style={{ animationDelay: `${i * 0.4}s` }}>
            <rect x="6" y={y - 9} width="388" height={rowH - 3} rx="2" fill={i % 2 ? "var(--surface-card)" : "transparent"} />
            <rect x="6" y={y - 9} width="2.5" height={rowH - 3} fill={r[3]} />
            <text x="18" y={y + 4} fill={cI} style={GM(9)}>{r[0]}</text>
            {!mobile && <text x="170" y={y + 4} fill={cQ} style={GM(7)}>{r[2]}</text>}
            {mobile && r[2] && <text x="250" y={y + 4} textAnchor="end" fill={cQ} style={GM(7)}>{r[2]}</text>}
            <text x="388" y={y + 4} textAnchor="end" fill={r[3] === cAM ? cAM : cI} style={GM(9)}>{r[1]}</text>
          </g>
        );
      })}
      {!mobile && (
        <g className="pf-field" style={{ animationDelay: "1.8s" }}>
          <line x1="6" y1={h - 56} x2="394" y2={h - 56} stroke={cL2} />
          <text x="6" y={h - 42} fill={cQ} style={GM(7)}>arrears ageing, by circle</text>
          {[["0–30", 0.62, cF], ["31–60", 0.28, cF], ["61–90", 0.14, cAM], ["90+", 0.08, cS]].map((b, i) => (
            <g key={b[0]}>
              <rect x={6 + i * 62} y={h - 34} width="52" height="8" rx="1.5" fill={cL2} opacity="0.5" />
              <rect x={6 + i * 62} y={h - 34} width={52 * b[1]} height="8" rx="1.5" fill={b[2]} />
              <text x={6 + i * 62} y={h - 12} fill={cQ} style={GM(7)}>{b[0]}</text>
            </g>
          ))}
          <text x="392" y={h - 34} textAnchor="end" fill={cQ} style={GM(7)}>recovery reported per circle, division and tariff class</text>
          <text x="392" y={h - 12} textAnchor="end" fill={cF} style={GM(9)}>90.6% collected</text>
        </g>
      )}
    </PFG>
  );
}

/* ── Data platforms ───────────────────────────────────────────────────────
   Four cadences, a late arrival that still lands in the right window, and the
   four keys everything is written against. */
function FigData({ mobile }) {
  const lanes = mobile
    ? [["telemetry", "40–80/day", 0.6, cA], ["meter reads", "15-min", 1.0, cF], ["documents", "on arrival", 1.7, cS]]
    : [["device telemetry", "40–80 msg / meter / day", 0.6, cA], ["meter reads", "15-minute interval", 1.0, cF], ["enterprise records", "nightly batch", 1.5, cQ], ["documents", "on arrival", 2.0, cS]];
  const top = 30, gap = 30;
  const h = top + lanes.length * gap + (mobile ? 46 : 84);
  const lx = mobile ? 92 : 132, rx = 268;
  const outY = top + (lanes.length - 1) * gap / 2 + 8;
  return (
    <PFG h={h} title="Four cadences, one schema" subtitle="whatever the source, one shape at rest"
      note="Every source lands in the same account, site, asset and period schema. A late record is written into the window it belongs to, not the window it arrived in."
      legend={[{ label: "on time", color: cF }, { label: "late arrival", color: cAM }]}>
      {lanes.map(([name, cadence, per, col], i) => {
        const y = top + i * gap;
        return (
          <g key={name}>
            <text x="6" y={y - 2} fill={cI} style={GM(9)}>{name}</text>
            <text x="6" y={y + 9} fill={cQ} style={GM(7)}>{cadence}</text>
            <line x1={lx} y1={y} x2={rx} y2={y} stroke={cL} />
            {[0, 1, 2, 3].map((k) => (
              <circle key={k} className="pf-flow" style={{ animationDuration: `${per * 2.6}s`, animationDelay: `${k * per * 0.65}s`, "--span": `${rx - lx}px` }} cx={lx} cy={y} r="3" fill={col} />
            ))}
            {i === 2 && !mobile && <circle className="pf-flow" style={{ animationDuration: "3.4s", animationDelay: "1.2s", "--span": `${rx - lx}px` }} cx={lx} cy={y} r="3.4" fill={cAM} />}
            <path d={`M${rx} ${y} Q${rx + 22} ${y} ${rx + 22} ${outY}`} fill="none" stroke={cL} />
          </g>
        );
      })}
      <g className="pf-sweep">
        <rect x={lx + 20} y={top - 16} width="54" height={(lanes.length - 1) * gap + 32} rx="2" fill="none" stroke={cA} strokeDasharray="3 3" />
        <text x={lx + 47} y={top - 20} textAnchor="middle" fill={cA} style={GM(7)}>window</text>
      </g>
      <GP x={rx + 22} y={outY - 26} w={400 - rx - 26} h="54" label="one schema" tone={cA}>
        {["account", "site", "asset", "period"].map((k, i) => (
          <text key={k} x={rx + 30 + (i % 2) * 52} y={outY - 4 + Math.floor(i / 2) * 15} fill={cB} style={GM(8)}>{k}</text>
        ))}
      </GP>
      {!mobile && (
        <g className="pf-field" style={{ animationDelay: "1.4s" }}>
          <line x1="6" y1={h - 58} x2="394" y2={h - 58} stroke={cL} />
          {[["rows / day", "41.2k"], ["reconciled", "nightly"], ["retention", "rolling"], ["late window", "72 h"]].map((r, i) => (
            <g key={r[0]}>
              <text x={6 + i * 100} y={h - 44} fill={cQ} style={GM(7)}>{r[0]}</text>
              <text x={6 + i * 100} y={h - 31} fill={cI} style={GM(9)}>{r[1]}</text>
            </g>
          ))}
          <text x="6" y={h - 10} fill={cQ} style={GM(7)}>master-file synchronisation keeps regional centres consistent</text>
        </g>
      )}
    </PFG>
  );
}

/* ── Cloud & DevOps ───────────────────────────────────────────────────────
   The pipeline with its gate, the environments it promotes through, and the
   uptime that is a number rather than an opinion. */
function FigDevops({ mobile }) {
  const stages = mobile
    ? [["build", "2m10"], ["test", "4m02"], ["deploy", "1m18"]]
    : [["commit", "—"], ["build", "2m10"], ["test", "4m02"], ["canary 5%", "10m"], ["deploy", "1m18"]];
  const h = mobile ? 196 : 240, y = mobile ? 74 : 86;
  const bw = mobile ? 108 : 70, gapx = (392 - bw) / (stages.length - 1);
  return (
    <PFG h={h} title="Delivery pipeline" subtitle="with the gate that stops a bad build"
      note="Provisioning, delivery and monitoring are one system. Rollback is a path we exercise on a schedule, not a paragraph in a document."
      legend={[{ label: "passed", color: cF }, { label: "gate held", color: cAM }]}>
      <text x="4" y="14" fill={cQ} style={GM(7)}>uptime · trailing 90 days</text>
      {Array.from({ length: mobile ? 30 : 45 }).map((_, i) => {
        const bad = i === (mobile ? 19 : 29);
        return <rect key={i} className="pf-tick" style={{ animationDelay: `${i * 0.06}s` }} x={4 + i * (392 / (mobile ? 30 : 45))} y="20" width={392 / (mobile ? 30 : 45) - 2.5} height="14" rx="1" fill={bad ? cAM : cF} opacity="0.8" />;
      })}
      <text x="392" y="14" textAnchor="end" fill={cI} style={GM(9)}>99.94%</text>
      <text x="4" y="48" fill={cQ} style={GM(7)}>one incident · 34 min · postmortem published</text>

      {stages.map(([s, dur], i) => {
        const x = 4 + i * gapx;
        return (
          <g key={s}>
            {i > 0 && <path d={`M${x - gapx + bw} ${y + 15} H${x}`} stroke={cL2} strokeWidth="1" />}
            <rect className="pf-stage" style={{ animationDelay: `${i * 0.55}s` }} x={x} y={y} width={bw} height="30" rx="3" fill="var(--surface-card)" stroke={cL2} />
            <text x={x + bw / 2} y={y + 14} textAnchor="middle" fill={cI} style={GM(9)}>{s}</text>
            <text x={x + bw / 2} y={y + 25} textAnchor="middle" fill={cQ} style={GM(7)}>{dur}</text>
          </g>
        );
      })}
      <g className="pf-rollback">
        <path d={`M${4 + (stages.length - 2) * gapx + bw / 2} ${y + 36} V${y + 54} H${4 + bw / 2} V${y + 36}`} fill="none" stroke={cAM} strokeWidth="1.2" strokeDasharray="4 3" />
        <path d={`M${4 + bw / 2 - 4} ${y + 42} l4 -7 l4 7 z`} fill={cAM} />
        <text x="200" y={y + 68} textAnchor="middle" fill={cAM} style={GM(8)}>gate failed, rolled back in 40s, no traffic served</text>
      </g>
      {!mobile && (
        <g className="pf-field" style={{ animationDelay: "1.2s" }}>
          <line x1="4" y1={h - 52} x2="396" y2={h - 52} stroke={cL} />
          {[["dev", "ephemeral", cF], ["staging", "prod-shaped", cF], ["prod", "in-country", cA], ["dr", "tested quarterly", cQ]].map((e, i) => (
            <g key={e[0]}>
              <rect x={4 + i * 100} y={h - 42} width="88" height="30" rx="3" fill="none" stroke={e[2]} opacity="0.7" />
              <text x={12 + i * 100} y={h - 28} fill={cI} style={GM(9)}>{e[0]}</text>
              <text x={12 + i * 100} y={h - 17} fill={cQ} style={GM(7)}>{e[1]}</text>
            </g>
          ))}
        </g>
      )}
    </PFG>
  );
}

const PRACTICE_FIGURES = {
  "ai-agents": (m) => <FigAgents mobile={m} />,
  "document-intelligence": (m) => <FigDocs mobile={m} />,
  "applied-ml": (m) => window.PF_LONG.forecast(m),
  "computer-vision": (m) => <FigVision mobile={m} />,
  "industrial-iot": (m) => <FigEdge mobile={m} />,
  "energy-tech": (m) => <FigEnergy mobile={m} />,
  "agri-tech": (m) => window.PF_LONG.agri(m),
  "erp-billing": (m) => window.PF_LONG.ledger(m),
  "data-platforms": (m) => <FigData mobile={m} />,
  "cloud-devops": (m) => window.PF_LONG.devops(m),
};

Object.assign(window, { PRACTICE_FIGURES, FigEnergy, FigAgri, FigLedger, FigData, FigDevops });
