(function(){"use strict";try{if(typeof document<"u"){var r=document.createElement("style");r.appendChild(document.createTextNode("._wrapper_h2w9g_1{--gc-bg: var(--color-bg, #0d1117);--gc-bg-secondary: var(--color-bg-secondary, #182237);--gc-text: var(--color-text, #f1f4ef);--gc-text-muted: var(--color-text-muted, #b6c0d4);--gc-primary: var(--color-primary, #45c4b0);--gc-accent: var(--color-accent, #ff6b6b);--gc-border: var(--color-border, #34516f);width:100%}._frame_h2w9g_12{position:relative;min-height:100dvh;padding:10px;color:var(--gc-text);font-family:Space Mono,IBM Plex Mono,Courier New,monospace;background:radial-gradient(circle at 12% 8%,rgb(69 196 176 / 24%),transparent 42%),radial-gradient(circle at 86% 14%,rgb(255 107 107 / 20%),transparent 38%),linear-gradient(156deg,var(--gc-bg),var(--gc-bg-secondary));border:1px solid color-mix(in srgb,var(--gc-border) 70%,transparent)}._frameSucceeded_h2w9g_25{background:radial-gradient(circle at 18% 12%,rgb(86 255 148 / 26%),transparent 42%),radial-gradient(circle at 82% 16%,rgb(42 210 104 / 22%),transparent 38%),linear-gradient(156deg,#0f2f1f,#1b5234);border-color:color-mix(in srgb,#4be38f 56%,var(--gc-border))}._header_h2w9g_33{margin-bottom:8px}._title_h2w9g_37{margin:0;font-size:clamp(20px,6.4vw,32px);letter-spacing:.05em;text-transform:uppercase}._subtitle_h2w9g_44{margin:4px 0 0;color:var(--gc-text-muted);font-size:clamp(11px,3.3vw,14px)}._statsLine_h2w9g_50{margin:5px 0 0;padding:5px 6px;border:1px solid color-mix(in srgb,var(--gc-border) 70%,transparent);background:#0913209e;font-size:clamp(11px,3.1vw,13px)}._boardPanel_h2w9g_58{margin-bottom:8px}._board_h2w9g_58{position:relative;overflow:hidden;width:min(88vw,340px);aspect-ratio:1 / 1;display:grid;grid-template-columns:repeat(8,1fr);grid-template-rows:repeat(8,1fr);border:2px solid color-mix(in srgb,var(--gc-primary) 45%,var(--gc-border));box-shadow:0 0 0 1px #00000059,0 14px 26px #00000061}._trailOverlay_h2w9g_76{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;pointer-events:none;z-index:1}._trailPath_h2w9g_85{fill:none;stroke:#ff2828e5;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;filter:drop-shadow(0 0 5px rgb(255 30 30 / 65%))}._trailHead_h2w9g_94{fill:#ff3c3cf5;filter:drop-shadow(0 0 6px rgb(255 45 45 / 70%))}._cell_h2w9g_99{position:relative;display:grid;place-items:center}._lightCell_h2w9g_105{background:#f4ecd8}._darkCell_h2w9g_109{background:#c08c61}._knight_h2w9g_113{position:absolute;z-index:3;display:grid;place-items:center;width:100%;height:100%;font-family:Times New Roman,Georgia,serif;font-size:clamp(28px,15vw,56px);line-height:1;color:#111827;text-shadow:0 1px 0 rgb(255 255 255 / 55%),0 3px 8px rgb(0 0 0 / 25%);transform:translateY(-1px)}._target_h2w9g_130{position:absolute;z-index:2;font-size:clamp(12px,8.5vw,33px);color:#e21c29;text-shadow:0 0 8px rgb(236 37 58 / 60%)}._readout_h2w9g_138{margin-bottom:8px;padding:7px;border:1px solid color-mix(in srgb,var(--gc-border) 72%,transparent);background:#040a1173}._readoutLine_h2w9g_145{margin:0;font-size:clamp(11px,3.2vw,14px)}._readoutLine_h2w9g_145+._readoutLine_h2w9g_145{margin-top:3px}._programPanel_h2w9g_154{display:flex;flex-direction:column;gap:6px}._programTrack_h2w9g_160{min-height:42px;display:flex;flex-wrap:wrap;align-items:center;gap:5px;border:1px solid color-mix(in srgb,var(--gc-border) 70%,transparent);background:#07111d85;padding:7px}._placeholder_h2w9g_171{color:var(--gc-text-muted);font-size:12px}._step_h2w9g_176{width:24px;height:24px;display:grid;place-items:center;border:1px solid color-mix(in srgb,var(--gc-primary) 45%,var(--gc-border));background:#45c4b024;font-weight:600;font-size:13px}._stepExecuted_h2w9g_187{background:#ff6b6b40;border-color:#ff6b6b99}._programButtons_h2w9g_192,._controlRow_h2w9g_193{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}._button_h2w9g_199,._buttonPrimary_h2w9g_200{border:1px solid color-mix(in srgb,var(--gc-border) 70%,transparent);padding:7px 6px;font:inherit;font-size:20px;text-transform:uppercase;letter-spacing:.05em;cursor:pointer;transition:transform .12s ease,background-color .12s ease}._button_h2w9g_199{background:#09132099;color:var(--gc-text)}._buttonPrimary_h2w9g_200{background:color-mix(in srgb,var(--gc-primary) 35%,#12252f);color:#f2fff8;border-color:color-mix(in srgb,var(--gc-primary) 65%,transparent)}._button_h2w9g_199:disabled,._buttonPrimary_h2w9g_200:disabled{opacity:.48;cursor:not-allowed}._button_h2w9g_199:active,._buttonPrimary_h2w9g_200:active{transform:scale(.98)}._legend_h2w9g_233{margin:0;color:var(--gc-text-muted);font-size:11px}._promptOverlay_h2w9g_239{position:absolute;top:0;right:0;bottom:0;left:0;display:grid;place-content:center;gap:8px;padding:16px;background:#02080ddb;border:1px solid color-mix(in srgb,var(--gc-accent) 40%,var(--gc-border))}._promptTitle_h2w9g_250{margin:0;text-align:center;text-transform:uppercase;letter-spacing:.08em;font-size:clamp(20px,6vw,32px)}._promptText_h2w9g_258{margin:0;text-align:center;color:var(--gc-text-muted)}._promptOptions_h2w9g_264{display:flex;justify-content:center;gap:10px}._promptOption_h2w9g_264{min-width:110px;border:1px solid color-mix(in srgb,var(--gc-border) 70%,transparent);background:#09132099;color:var(--gc-text);padding:8px 10px;font:inherit;font-size:14px;text-align:left;cursor:pointer}._promptSelected_h2w9g_282{border-color:color-mix(in srgb,var(--gc-accent) 70%,transparent);background:#ff6b6b33}._promptHint_h2w9g_287{margin:0;text-align:center;color:var(--gc-text-muted);font-size:11px}@media (max-width: 560px){._programButtons_h2w9g_192,._controlRow_h2w9g_193{grid-template-columns:1fr 1fr 1fr 1fr}}@media (min-width: 780px){._frame_h2w9g_12{max-width:540px;margin:0 auto;border-radius:14px;min-height:auto}}")),document.head.appendChild(r)}}catch(e){console.error("vite-plugin-css-injected-by-js",e)}})(); import { jsx as a, jsxs as l } from "react/jsx-runtime"; import { useMemo as ne, useState as g, useRef as me, useEffect as oe, useCallback as x } from "react"; const Oe = "_wrapper_h2w9g_1", Ae = "_frame_h2w9g_12", Ee = "_frameSucceeded_h2w9g_25", Le = "_header_h2w9g_33", Re = "_title_h2w9g_37", Ie = "_statsLine_h2w9g_50", Me = "_boardPanel_h2w9g_58", De = "_board_h2w9g_58", He = "_trailOverlay_h2w9g_76", Ge = "_trailPath_h2w9g_85", Be = "_trailHead_h2w9g_94", Ue = "_cell_h2w9g_99", Fe = "_lightCell_h2w9g_105", Ye = "_darkCell_h2w9g_109", Ve = "_knight_h2w9g_113", je = "_target_h2w9g_130", Xe = "_readout_h2w9g_138", Ke = "_readoutLine_h2w9g_145", Ze = "_programPanel_h2w9g_154", ze = "_programTrack_h2w9g_160", We = "_placeholder_h2w9g_171", qe = "_step_h2w9g_176", Je = "_stepExecuted_h2w9g_187", Qe = "_programButtons_h2w9g_192", et = "_controlRow_h2w9g_193", tt = "_button_h2w9g_199", rt = "_buttonPrimary_h2w9g_200", nt = "_legend_h2w9g_233", ot = "_promptOverlay_h2w9g_239", at = "_promptTitle_h2w9g_250", st = "_promptText_h2w9g_258", ct = "_promptOptions_h2w9g_264", lt = "_promptOption_h2w9g_264", it = "_promptSelected_h2w9g_282", dt = "_promptHint_h2w9g_287", e = { wrapper: Oe, frame: Ae, frameSucceeded: Ee, header: Le, title: Re, statsLine: Ie, boardPanel: Me, board: De, trailOverlay: He, trailPath: Ge, trailHead: Be, cell: Ue, lightCell: Fe, darkCell: Ye, knight: Ve, target: je, readout: Xe, readoutLine: Ke, programPanel: Ze, programTrack: ze, placeholder: We, step: qe, stepExecuted: Je, programButtons: Qe, controlRow: et, button: tt, buttonPrimary: rt, legend: nt, promptOverlay: ot, promptTitle: at, promptText: st, promptOptions: ct, promptOption: lt, promptSelected: it, promptHint: dt }, C = 8, h = { x: 0, y: C - 1 }, pt = 220, ut = 64, mt = 3, G = 100, ht = 5, gt = { up: { dx: 0, dy: -1 }, down: { dx: 0, dy: 1 }, left: { dx: -1, dy: 0 }, right: { dx: 1, dy: 0 } }, _t = { up: "↑", down: "↓", left: "←", right: "→" }, ge = [ { dx: 0, dy: 1 }, { dx: 1, dy: 1 }, { dx: 1, dy: 2 }, { dx: 1, dy: 3 }, { dx: 2, dy: 3 }, { dx: 1, dy: 5 }, { dx: 1, dy: 6 } ], Z = (r, o, d) => Math.min(d, Math.max(o, r)), _e = (r) => r.x >= 0 && r.x < C && r.y >= 0 && r.y < C, yt = (r, o) => r.x === o.x && r.y === o.y, ce = (r, o) => o === 0 ? r : ce(o, r % o), ft = (r, o) => { const d = Math.abs(o.x - r.x), p = Math.abs(o.y - r.y); if (d === 0 && p === 0) return 0; if (d === 0 || p === 0) return d + p; const _ = ce(d, p); return d / _ + p / _; }, wt = (r) => new Promise((o) => { window.setTimeout(o, r); }), he = (r) => r === "Enter" || r === "NumpadEnter" || r === " " || r === "Space" || r === "Spacebar", bt = (r) => `${(r.x + 0.5) * G},${(r.y + 0.5) * G}`, z = (r) => Z(r, 0, ge.length - 1), ye = (r) => ge[z(r)], ae = (r) => { const o = ye(r); return o.dx + o.dy; }, se = (r) => { const o = ye(r), d = []; for (let _ = 1; _ < C; _ += 1) { const u = { x: h.x + o.dx * _, y: h.y - o.dy * _ }; if (!_e(u)) break; Math.abs(u.x - h.x) + Math.abs(u.y - h.y) > ht && d.push(u); } if (d.length === 0) return { x: h.x + o.dx, y: h.y - o.dy }; const p = Math.floor(Math.random() * d.length); return d[p]; }; function Nt({ config: r, onComplete: o, onProgress: d, theme: p, className: _ }) { const u = ne(() => { const n = r.params.goalCaptures; return typeof n != "number" ? mt : Z(Math.round(n), 1, 10); }, [r.params.goalCaptures]), [v, le] = g(0), [N, W] = g(h), [$, ie] = g(() => se(0)), [y, q] = g([]), [B, U] = g([h]), [f, k] = g("idle"), [fe, O] = g(-1), [w, de] = g(0), [pe, L] = g(""), [R, F] = g("yes"), [I, Y] = g("continue"), [b, we] = g(!1), S = me(0), V = me(!1), i = f === "running", m = f === "gameOverPrompt" || f === "successPrompt" || f === "finished", J = ae(v), be = ne(() => p ? { "--gc-primary": p.primary, "--gc-accent": p.accent, "--gc-bg": p.bg, "--gc-bg-secondary": p.bgSecondary, "--gc-text": p.text, "--gc-text-muted": p.textMuted, "--gc-border": p.border } : {}, [p]); oe(() => { const n = w / u; d == null || d(Math.round(Z(n * 100, 0, 100))); }, [w, u, d]); const j = x((n, t, s = "") => { S.current += 1, k("idle"), le(z(n)), W(h), ie(se(n)), U([h]), O(-1), de(t), F("yes"), Y("continue"), L(s); }, []), Q = x(() => { j(v, 0, `Looking for a ${J}-step move set.`); }, [v, J, j]), X = x((n = 0) => { const t = z(v + 1), s = ae(t); j(t, n, `Looking for a ${s}-step move set.`); }, [v, j]), ee = x(() => { V.current || (V.current = !0, S.current += 1, k("finished"), o({ success: !1, error: "Player chose no after game over.", data: { captures: w, goalCaptures: u, configId: r.id, completedAt: (/* @__PURE__ */ new Date()).toISOString(), hasEverSucceeded: b } })); }, [w, r.id, u, b, o]), D = x(() => { V.current || (V.current = !0, S.current += 1, k("finished"), o({ success: !0, score: 100, data: { captures: w, goalCaptures: u, configId: r.id, completedAt: (/* @__PURE__ */ new Date()).toISOString(), hasEverSucceeded: b } })); }, [w, r.id, u, b, o]), M = x((n) => { q((t) => i || m || t.length >= ut ? t : [...t, n]); }, [m, i]), xe = x(() => { i || m || q((n) => n.slice(0, -1)); }, [m, i]), Ce = x(() => { i || m || q([]); }, [m, i]), Ne = x(() => { S.current += 1, k("idle"), O(-1), L("Program stopped."); }, []), Se = x(async () => { if (i || m || y.length === 0) return; const n = S.current + 1; S.current = n; let t = N, s = $, c = w, T = 0; for (k("running"), O(-1), U([N]), L(""); S.current === n; ) for (let P = 0; P < y.length; P += 1) { if (await wt(pt), S.current !== n) return; const H = y[P], K = gt[H], A = { x: t.x + K.dx, y: t.y + K.dy }; if (!_e(A)) { k("gameOverPrompt"), F("yes"), O(-1), L(`Game over after ${T} step(s). Try again?`); return; } if (T += 1, t = A, W(A), U((E) => [...E, A]), O(P), yt(A, s)) { if (c += 1, de(c), we(!0), c >= u) { k("successPrompt"), Y("continue"), O(-1), L(`Success. ${c} challenge(s) complete.`); return; } const E = z(v + 1), re = se(E), Te = ae(E); t = h, s = re, k("idle"), le(E), W(h), ie(re), U([h]), O(-1), L( `Challenge ${c}/${u} complete. Looking for a ${Te}-step move set.` ); return; } } }, [w, v, u, m, N, y, i, $]); oe(() => { const n = (t) => { const s = { ArrowUp: "up", ArrowDown: "down", ArrowLeft: "left", ArrowRight: "right" }; if (f === "gameOverPrompt") { if (t.key === "ArrowLeft" || t.key === "ArrowUp") { t.preventDefault(), F("yes"); return; } if (t.key === "ArrowRight" || t.key === "ArrowDown") { t.preventDefault(), F("no"); return; } he(t.key) && (t.preventDefault(), R === "yes" ? Q() : b ? D() : ee()); return; } if (f === "successPrompt") { if (t.key === "ArrowLeft" || t.key === "ArrowUp") { t.preventDefault(), Y("continue"); return; } if (t.key === "ArrowRight" || t.key === "ArrowDown") { t.preventDefault(), Y("done"); return; } he(t.key) && (t.preventDefault(), I === "continue" ? X() : D()); return; } if (f !== "idle") return; const c = s[t.key]; c && (t.preventDefault(), M(c)); }; return window.addEventListener("keydown", n), () => { window.removeEventListener("keydown", n); }; }, [ M, ee, D, R, b, f, Q, X, I ]), oe( () => () => { S.current += 1; }, [] ); const Pe = ne(() => { const n = $.x - N.x, t = N.y - $.y, s = Math.abs(n), c = Math.abs(t), T = ft(N, $); if (s === 0 && c === 0) return { angle: 0, motifLength: T, motif: "On target" }; if (s === 0 || c === 0) return { angle: s === 0 ? 90 : 0, motifLength: T, motif: s === 0 ? `${t >= 0 ? "U" : "D"} x ${c}` : `${n >= 0 ? "R" : "L"} x ${s}` }; const P = ce(s, c), H = s / P, K = c / P, A = `${n >= 0 ? "R" : "L"} x ${H}`, E = `${t >= 0 ? "U" : "D"} x ${K}`; return { angle: Math.atan2(c, s) * (180 / Math.PI), motifLength: T, motif: `${A}, ${E}` }; }, [N, $]), ve = Math.round(Z(w / u * 100, 0, 100)), $e = _ ? `${e.wrapper} ${_}` : e.wrapper, ue = C * G, ke = B.map(bt).join(" "), te = B[B.length - 1]; return /* @__PURE__ */ a("div", { className: $e, style: be, children: /* @__PURE__ */ l( "section", { className: `${e.frame} ${b ? e.frameSucceeded : ""}`, "aria-label": "Chess move set trainer", children: [ /* @__PURE__ */ l("header", { className: e.header, children: [ /* @__PURE__ */ a("h2", { className: e.title, children: "The Chess Analogy" }), /* @__PURE__ */ l("p", { className: e.statsLine, children: [ "Captures ", w, "/", u, " • Progress ", ve, "% • Program ", y.length, " • Target ", J ] }) ] }), /* @__PURE__ */ a("div", { className: e.boardPanel, children: /* @__PURE__ */ l("div", { className: e.board, role: "grid", "aria-label": "8 by 8 checkerboard", children: [ /* @__PURE__ */ l( "svg", { className: e.trailOverlay, viewBox: `0 0 ${ue} ${ue}`, preserveAspectRatio: "none", "aria-hidden": "true", children: [ B.length > 1 && /* @__PURE__ */ a("polyline", { className: e.trailPath, points: ke }), te && /* @__PURE__ */ a( "circle", { className: e.trailHead, cx: (te.x + 0.5) * G, cy: (te.y + 0.5) * G, r: 6 } ) ] } ), Array.from({ length: C * C }).map((n, t) => { const s = t % C, c = Math.floor(t / C), T = (s + c) % 2 === 1, P = N.x === s && N.y === c, H = $.x === s && $.y === c; return /* @__PURE__ */ l( "div", { className: `${e.cell} ${T ? e.darkCell : e.lightCell}`, role: "gridcell", "aria-label": `x ${s + 1}, y ${C - c}`, children: [ H && /* @__PURE__ */ a("span", { className: e.target, "aria-hidden": "true", children: "●" }), P && /* @__PURE__ */ a("span", { className: e.knight, "aria-hidden": "true", children: "♞" }) ] }, `${s}-${c}` ); }) ] }) }), /* @__PURE__ */ l("div", { className: e.readout, children: [ /* @__PURE__ */ l("p", { className: e.readoutLine, children: [ "Angle: ", /* @__PURE__ */ l("strong", { children: [ Pe.angle.toFixed(1), "°" ] }) ] }), !1 ] }), /* @__PURE__ */ l("div", { className: e.programPanel, children: [ /* @__PURE__ */ l("div", { className: e.programTrack, "aria-live": "polite", children: [ y.length === 0 && /* @__PURE__ */ a("span", { className: e.placeholder, children: "Empty move set" }), y.map((n, t) => /* @__PURE__ */ a( "span", { className: `${e.step} ${i && t === fe ? e.stepExecuted : ""}`, children: _t[n] }, `${n}-${t}` )) ] }), /* @__PURE__ */ l("div", { className: e.programButtons, children: [ /* @__PURE__ */ a("button", { type: "button", className: e.button, onClick: () => M("up"), disabled: i || m, children: "↑" }), /* @__PURE__ */ a("button", { type: "button", className: e.button, onClick: () => M("left"), disabled: i || m, children: "←" }), /* @__PURE__ */ a("button", { type: "button", className: e.button, onClick: () => M("down"), disabled: i || m, children: "↓" }), /* @__PURE__ */ a("button", { type: "button", className: e.button, onClick: () => M("right"), disabled: i || m, children: "→" }) ] }), /* @__PURE__ */ l("div", { className: e.controlRow, children: [ /* @__PURE__ */ a("button", { type: "button", className: e.button, onClick: xe, disabled: i || m || y.length === 0, children: "Undo" }), /* @__PURE__ */ a("button", { type: "button", className: e.button, onClick: Ce, disabled: i || m || y.length === 0, children: "Clear" }), /* @__PURE__ */ a("button", { type: "button", className: e.buttonPrimary, onClick: i ? Ne : Se, disabled: m || y.length === 0, children: i ? "Stop" : "Run" }), /* @__PURE__ */ a("button", { type: "button", className: e.button, onClick: () => X(), disabled: i, children: "Reset" }) ] }), pe && /* @__PURE__ */ a("p", { className: e.legend, children: pe }) ] }), f === "gameOverPrompt" && /* @__PURE__ */ l("div", { className: e.promptOverlay, role: "dialog", "aria-modal": "true", "aria-label": "Game over prompt", children: [ /* @__PURE__ */ a("p", { className: e.promptTitle, children: "Game over" }), /* @__PURE__ */ a("p", { className: e.promptText, children: b ? "Try again or stop?" : "Try again?" }), /* @__PURE__ */ l("div", { className: e.promptOptions, children: [ /* @__PURE__ */ l( "button", { type: "button", className: `${e.promptOption} ${R === "yes" ? e.promptSelected : ""}`, onClick: Q, children: [ R === "yes" ? "▶ " : "", "Yes" ] } ), /* @__PURE__ */ l( "button", { type: "button", className: `${e.promptOption} ${R === "no" ? e.promptSelected : ""}`, onClick: b ? D : ee, children: [ R === "no" ? "▶ " : "", b ? "I'm done" : "No" ] } ) ] }), /* @__PURE__ */ a("p", { className: e.promptHint, children: "Use arrows + Enter." }) ] }), f === "successPrompt" && /* @__PURE__ */ l("div", { className: e.promptOverlay, role: "dialog", "aria-modal": "true", "aria-label": "Success prompt", children: [ /* @__PURE__ */ a("p", { className: e.promptTitle, children: "Success" }), /* @__PURE__ */ a("p", { className: e.promptText, children: "Continue?" }), /* @__PURE__ */ l("div", { className: e.promptOptions, children: [ /* @__PURE__ */ l( "button", { type: "button", className: `${e.promptOption} ${I === "continue" ? e.promptSelected : ""}`, onClick: () => X(), children: [ I === "continue" ? "▶ " : "", "Yes" ] } ), /* @__PURE__ */ l( "button", { type: "button", className: `${e.promptOption} ${I === "done" ? e.promptSelected : ""}`, onClick: D, children: [ I === "done" ? "▶ " : "", "I'm done" ] } ) ] }), /* @__PURE__ */ a("p", { className: e.promptHint, children: "Use arrows + Enter." }) ] }) ] } ) }); } const St = { name: "chess_analogy", displayName: "Chess Move Set Lab", version: "1.0.0", paramSchema: { goalCaptures: { type: "range", label: "Targets To Capture", description: "How many red targets must be captured before completion.", default: 3, min: 1, max: 10, step: 1 } }, defaultParams: { goalCaptures: 3 } }; export { Nt as default, St as metadata }; //# sourceMappingURL=chess_analogy.js.map