/* ============================================================================
PRSM SOLAR — TAB VIEWS
========================================================================== */
const { useState: useStateT } = React;
const FLAG_LABEL = {
pass: "Verified",
price_corrected: "Price corrected",
unverifiable: "Unverifiable",
out_of_stock: "Out of stock",
open_quote: "Open quote",
owned: "Owned ($0)",
estimate: "Estimate only",
};
function SectionHead({ n, kicker, title, sub }) {
return (
<div className="sec-head">
<div className="sec-num mono">{n}</div>
<div>
{kicker && <div className="eyebrow" style={{ marginBottom: 4 }}>{kicker}</div>}
<h2 className="sec-title">{title}</h2>
{sub && <p className="sec-sub">{sub}</p>}
</div>
</div>
);
}
const Flag = ({ s }) => (
<span className={"flag " + s} title={FLAG_LABEL[s]}><i />{FLAG_LABEL[s]}</span>
);
/* ----------------------------- OVERVIEW ------------------------------- */
function PhaseCard({ d, tone }) {
const stats = [
["PV active", d.pvActive, d.pvActiveNote],
["Battery", d.battery, d.batteryNote],
["Inverter", d.inverter, d.inverterNote],
["Production", d.production, d.productionNote],
];
return (
<div className={"phase-card " + tone}>
<div className="phase-card-top">
<span className={"stamp " + (tone === "p1" ? "estimate" : "computed")}>{d.tag}</span>
<span className="phase-landed mono">{d.landed}<em>{d.landedNote}</em></span>
</div>
<h3 className="phase-name">{d.name}</h3>
<p className="phase-blurb">{d.blurb}</p>
<div className="stat-grid">
{stats.map(([k, v, n]) => (
<div className="stat" key={k}>
<div className="stat-k tag">{k}</div>
<div className="stat-v">{v}</div>
<div className="stat-n mono">{n}</div>
</div>
))}
</div>
</div>
);
}
function Overview() {
const P = window.PRSM;
return (
<div className="tab-wrap">
<div className="ov-hero">
<div>
<div className="eyebrow">Build concept</div>
<h2 className="ov-title">Two phases, one island.<br />Shore-assisted today, fully off-grid tomorrow.</h2>
<p className="ov-lede">
Phase 1 stands up an 8 kW array, a 6 kW inverter and a 16 kWh pack — with shore power topping the
battery through a UL-listed DC charger during the build-out. Phase 2 drops the grid: the array doubles,
a second inverter parallels in (N+1), and a second pack lands on a ≥350 A DC bank.
</p>
</div>
<div className="ov-combined sheet">
<div className="eyebrow">Both phases · landed</div>
<div className="ov-big mono">{P.summary.combined.landed}</div>
<div className="ov-combined-rows">
<div><span className="tag">Goods</span><b className="mono">{P.summary.combined.goods}</b></div>
<div><span className="tag">Shipping</span><b className="mono">{P.summary.combined.shipping}</b></div>
</div>
<p className="ov-combined-foot mono">incl. ~6% VT use tax unless S-3E filed</p>
</div>
</div>
<div className="phase-flow">
<PhaseCard d={P.summary.phase1} tone="p1" />
<div className="flow-arrow"><span className="mono">drop grid</span><div className="arrow-line" /><span className="arrow-head">▶</span></div>
<PhaseCard d={P.summary.phase2} tone="p2" />
</div>
<div className="ov-cols">
<div className="sheet pad">
<SectionHead n="01" title="System specs" sub="Script-validated electrical quantities (NREL-grade Python)." />
<div className="spec-grid">
{P.specs.map((s) => (
<div className="spec" key={s.label}>
<div className="spec-top"><span className="spec-label">{s.label}</span><span className="spec-code mono">{s.code}</span></div>
<div className="spec-val mono">{s.value}</div>
<div className="spec-note">{s.note}</div>
</div>
))}
</div>
<div className="legend"><span className="stamp computed">Computed</span><span className="legend-txt">specs are script-traced; dollar figures elsewhere are dated estimates.</span></div>
</div>
<div className="ov-side">
<div className="sheet pad">
<SectionHead n="02" title="Locked decisions" />
<ul className="dec-list">
{P.decisions.map((d) => (
<li key={d.k}><span className="dec-k mono">{d.k}</span><span className="dec-v">{d.v}</span></li>
))}
</ul>
</div>
<div className="sheet pad oos">
<SectionHead n="03" title="Out of scope" sub="Separate budgets — not in the BOM totals." />
<ul className="oos-list">
{P.outOfScope.map((o, i) => <li key={i}><span className="mono oos-x">×</span>{o}</li>)}
</ul>
</div>
</div>
</div>
</div>
);
}
/* ------------------------------- BOM ---------------------------------- */
function BomTable({ phase }) {
const data = window.PRSM.bom[phase];
return (
<div>
<p className="basis-note">{data.basis}</p>
{data.groups.map((g) => (
<div className="bom-group" key={g.name}>
<div className="bom-group-head"><span className="mono">{g.name}</span><span className="hairline-grow" /></div>
<div className="bom-rows">
<div className="bom-row bom-head">
<div>Item</div><div>Spec</div><div>Qty</div><div>Vendor · SKU</div><div className="r">Goods</div><div className="r">Ship</div><div>Status</div>
</div>
{g.items.map((it, i) => (
<div className="bom-row" key={i}>
<div className="bom-item">{it.item}</div>
<div className="bom-spec">{it.spec}</div>
<div className="bom-qty mono">{it.qty}</div>
<div className="bom-vendor">{it.vendor}{it.sku && it.sku !== "—" && <span className="bom-sku mono">{it.sku}</span>}</div>
<div className="bom-goods mono r">{it.goods}</div>
<div className="bom-ship mono r">{it.ship}</div>
<div className="bom-status"><Flag s={it.status} />{it.note && <span className="bom-note">{it.note}</span>}</div>
</div>
))}
</div>
</div>
))}
</div>
);
}
function BOM() {
const [phase, setPhase] = useStateT("phase1");
return (
<div className="tab-wrap">
<div className="tab-toolbar">
<SectionHead n="04" kicker="Bill of materials" title={window.PRSM.bom[phase].title} />
<div className="seg">
<button className={phase === "phase1" ? "on" : ""} onClick={() => setPhase("phase1")}>Phase 1</button>
<button className={phase === "phase2" ? "on" : ""} onClick={() => setPhase("phase2")}>Phase 2</button>
</div>
</div>
<div className="flag-legend">
{Object.keys(FLAG_LABEL).map((k) => <Flag key={k} s={k} />)}
</div>
<BomTable phase={phase} />
<p className="fine mono">Quantities & specs are computed/script-traced. Dollar, freight & tax figures are dated 2026-06-03 web-researched estimates — confirm at checkout or via RFQ before ordering.</p>
</div>
);
}
/* ------------------------------ COSTS --------------------------------- */
function RollList({ rows }) {
return (
<div className="roll">
{rows.map((r, i) => (
<div className={"roll-row" + (r.strong ? " strong" : "")} key={i}>
<span className="roll-k">{r.k}{r.flag && <span className="stamp shore" style={{ marginLeft: 8 }}>{r.flag}</span>}</span>
<span className="roll-v mono">{r.v}</span>
</div>
))}
</div>
);
}
function Costs() {
const P = window.PRSM;
const t = P.transition;
return (
<div className="tab-wrap">
<div className="est-banner">
<span className="stamp estimate">Estimate</span>
<p>Every dollar here is a <b>dated 2026-06-03 web-researched estimate</b> — prices move with copper, tariffs and shipping. Quantities and electrical specs are computed; the money is not. Confirm at checkout / via RFQ before ordering.</p>
</div>
<div className="cost-cols">
<div className="sheet pad">
<div className="cost-head"><span className="stamp estimate">Phase 1</span><span className="cost-total mono">$7,800–8,500</span></div>
<h3 className="cost-sub">Goods roll-up</h3>
<RollList rows={P.bom.phase1.rollup} />
<hr className="dotrule" style={{ margin: "16px 0" }} />
<h3 className="cost-sub">Landed</h3>
<RollList rows={P.bom.phase1.landed} />
</div>
<div className="sheet pad">
<div className="cost-head"><span className="stamp computed">Phase 2</span><span className="cost-total mono">$6,300–6,700</span></div>
<h3 className="cost-sub">Goods roll-up (Δ)</h3>
<RollList rows={P.bom.phase2.rollup} />
<hr className="dotrule" style={{ margin: "16px 0" }} />
<h3 className="cost-sub">Landed delta</h3>
<RollList rows={P.bom.phase2.landed} />
</div>
</div>
<div className="sheet pad two-phase">
<SectionHead n="05" title="Two-phase total + racking" sub="Electrical landed (computed BoS, dated estimates) with the Phase-1 wood-rack materials folded in." />
<div className="tp-grid">
<div className="tp-row tp-head"><div>Stage</div><div className="r">Goods</div><div className="r">Shipping</div><div className="r">Landed</div></div>
<div className="tp-row"><div>Phase 1 · electrical</div><div className="r mono">$6,745–6,955</div><div className="r mono">$590–1,040</div><div className="r mono">$7,800–8,500</div></div>
<div className="tp-row"><div>Phase 2 (Δ) · electrical</div><div className="r mono">$5,650–5,850</div><div className="r mono">$320–470</div><div className="r mono">$6,300–6,700</div></div>
<div className="tp-row"><div>Both phases · electrical</div><div className="r mono">{P.summary.combined.goods}</div><div className="r mono">{P.summary.combined.shipping}</div><div className="r mono">{P.summary.combined.landed}</div></div>
<div className="tp-row"><div>+ Racking · Ph-1 wood rack <span className="stamp estimate" style={{ marginLeft: 6 }}>materials est</span></div><div className="r mono">$1,400–2,800</div><div className="r mono">local</div><div className="r mono">$1,500–2,950</div></div>
<div className="tp-row tp-total"><div>Both phases + racking</div><div className="r mono">$13,800–15,600</div><div className="r mono">$910–1,510</div><div className="r mono">$15,600–18,150</div></div>
</div>
<p className="fine mono">Racking is the Phase-1 wood-rack materials band from the structural handoff (landed = +6% VT use tax) — refine it live in the <b>Racking</b> tab calculator (default ≈ $2,508). Phase 2's added bank uses the identical design; structural labor, foundations & trenching remain owner-fabricated (out of scope).</p>
</div>
<div className="sheet pad trans">
<div className="trans-head">
<div>
<span className="stamp shore">Optional</span>
<h3 className="cost-sub" style={{ marginTop: 8 }}>{t.title}</h3>
<p className="trans-sub mono">{t.subtitle}</p>
</div>
<span className="cost-total mono">{t.total}</span>
</div>
<p className="trans-blurb">{t.blurb}</p>
<div className="trans-items">
{t.items.map((it, i) => (
<div className="trans-item" key={i}>
<div className="trans-item-top"><span>{it.item}</span><b className="mono">{it.goods}</b></div>
<div className="trans-item-spec mono">{it.spec}</div>
</div>
))}
</div>
<p className="trans-rule"><span className="mono">RULE</span>{t.rule}</p>
</div>
</div>
);
}
/* --------------------------- SCHEMATICS ------------------------------- */
function Schematics() {
const [phase, setPhase] = useStateT("phase1");
const [idx, setIdx] = useStateT(0);
const list = window.SCHEMATICS[phase];
const cur = list[Math.min(idx, list.length - 1)];
const Comp = cur.Comp;
const setP = (p) => { setPhase(p); setIdx(0); };
return (
<div className="tab-wrap">
<div className="tab-toolbar">
<SectionHead n="06" kicker="Schematics" title={phase === "phase1" ? "Phase 1 — Hybrid" : "Phase 2 — Off-Grid"} sub="Redrawn from the validated SLD topology & computed values. Drag to pan, scroll to zoom." />
<div className="seg">
<button className={phase === "phase1" ? "on" : ""} onClick={() => setP("phase1")}>Phase 1</button>
<button className={phase === "phase2" ? "on" : ""} onClick={() => setP("phase2")}>Phase 2</button>
</div>
</div>
<div className="seg seg-line">
{list.map((s, i) => (
<button key={s.id} className={i === idx ? "on" : ""} onClick={() => setIdx(i)}>{s.label}</button>
))}
</div>
<Comp key={cur.id} />
<div className="sch-notes">
<div className="stamp computed">Computed</div>
<p className="mono">Topology, gauges (8 AWG PV · 2/0 Cu battery), OCPD (175 A Class-T · ≥350 A bank), cold Voc 430.1 V and string sizing are script-traced. Symbols are schematic, not to scale; confirm trench/run lengths before buying wire.</p>
</div>
</div>
);
}
/* ----------------------------- FLYOVER -------------------------------- */
function Flyover() {
return (
<div className="tab-wrap">
<SectionHead n="07" kicker="3D rendering" title="Site flyover" sub="Placeholder slot — drop a rendered video or stills of the installed ground-mount here." />
<div className="fly-slot">
<div className="fly-inner">
<div className="fly-play">▶</div>
<div className="fly-title mono">3D RENDER / FLYOVER</div>
<div className="fly-sub">Drop a video file or render sequence of the installed array, inverter wall & battery bank.</div>
<div className="fly-specs">
<span className="tag">15-acre ground-mount</span>
<span className="tag">55° tilt (as-built)</span>
<span className="tag">4×7S array</span>
<span className="tag">battery shed (Ph 2)</span>
</div>
</div>
<div className="fly-corner tl" /><div className="fly-corner tr" /><div className="fly-corner bl" /><div className="fly-corner br" />
</div>
<p className="fine mono">When you have a render, hand me the file and I'll wire it in here with playback controls.</p>
</div>
);
}
Object.assign(window, { Overview, BOM, Costs, Schematics, Flyover, SectionHead, Flag });