/* 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 (
circle · lahore east
3 IT centres kept in sync
{feeders.map((f) => {
const fx = f === 0 ? 84 : 232;
return (
feeder F-{118 + f * 4}
{f === 0 ? "12 transformers" : "9 transformers"}
);
})}
{Array.from({ length: meters }).map((_, i) => {
const x = mx(i), tgt = x < 200 ? 84 : 232;
return (
{!mobile && {4471 + i * 3}}
);
})}
{!mobile && (
<>
{[["queued", "3", cQ], ["acknowledged", "3", cF], ["failed", "0", cF], ["window", "15 min", cQ]].map((r, i) => (
{r[0]}
{r[1]}
))}
validation before billing
{[["spike", cF], ["zero", cF], ["rollover", cF], ["gap 07:45", cAM], ["clock drift", cF], ["phase", cF]].map((r, i) => (
{r[0]}
))}
1 of 96 intervals estimated, flagged on the record — never silently filled
>
)}
{mobile && 6 validation rules before a read reaches a bill}
);
}
/* ── 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 (
{[0, 0.25, 0.5, 0.75, 1].map((t) => (
{Math.round(10 + t * 24)}%
))}
refill point
{depths.slice(0, mobile ? 2 : 3).map(([label, col, amp], i) => (
))}
{[0, 1, 2].slice(0, mobile ? 2 : 3).map((k) => {
const x = X(k * 24 + 17);
return (
valve · 9 mm
);
})}
{!mobile && (
<>
verify 90 min
{[["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) => (
{r[0]}
{r[1]}
))}
profile moved further than predicted, so next cycle drops the setpoint 0.4 mm
>
)}
{mobile && applied 9.1 mm · profile answered 24.7% vs 24.1% expected}
);
}
/* ── 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 (
stage
count
{rows.map((r, i) => {
const y = top + i * rowH;
return (
{r[0]}
{!mobile && {r[2]}}
{mobile && r[2] && {r[2]}}
{r[1]}
);
})}
{!mobile && (
arrears ageing, by circle
{[["0–30", 0.62, cF], ["31–60", 0.28, cF], ["61–90", 0.14, cAM], ["90+", 0.08, cS]].map((b, i) => (
{b[0]}
))}
recovery reported per circle, division and tariff class
90.6% collected
)}
);
}
/* ── 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 (
{lanes.map(([name, cadence, per, col], i) => {
const y = top + i * gap;
return (
{name}
{cadence}
{[0, 1, 2, 3].map((k) => (
))}
{i === 2 && !mobile && }
);
})}
window
{["account", "site", "asset", "period"].map((k, i) => (
{k}
))}
{!mobile && (
{[["rows / day", "41.2k"], ["reconciled", "nightly"], ["retention", "rolling"], ["late window", "72 h"]].map((r, i) => (
{r[0]}
{r[1]}
))}
master-file synchronisation keeps regional centres consistent
)}
);
}
/* ── 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 (
uptime · trailing 90 days
{Array.from({ length: mobile ? 30 : 45 }).map((_, i) => {
const bad = i === (mobile ? 19 : 29);
return ;
})}
99.94%
one incident · 34 min · postmortem published
{stages.map(([s, dur], i) => {
const x = 4 + i * gapx;
return (
{i > 0 && }
{s}
{dur}
);
})}
gate failed, rolled back in 40s, no traffic served
{!mobile && (
{[["dev", "ephemeral", cF], ["staging", "prod-shaped", cF], ["prod", "in-country", cA], ["dr", "tested quarterly", cQ]].map((e, i) => (
{e[0]}
{e[1]}
))}
)}
);
}
const PRACTICE_FIGURES = {
"ai-agents": (m) => ,
"document-intelligence": (m) => ,
"applied-ml": (m) => window.PF_LONG.forecast(m),
"computer-vision": (m) => ,
"industrial-iot": (m) => ,
"energy-tech": (m) => ,
"agri-tech": (m) => window.PF_LONG.agri(m),
"erp-billing": (m) => window.PF_LONG.ledger(m),
"data-platforms": (m) => ,
"cloud-devops": (m) => window.PF_LONG.devops(m),
};
Object.assign(window, { PRACTICE_FIGURES, FigEnergy, FigAgri, FigLedger, FigData, FigDevops });