From b4ed440aedb5b32708de1b794d1a43ed5d22310e Mon Sep 17 00:00:00 2001 From: jenstandstad Date: Wed, 10 Jun 2026 11:48:44 +0200 Subject: [PATCH] Initial commit --- .gitignore | 7 + README.md | 23 + component-contract.md | 92 ++ dist/bloodsugar.js | 8 + dist/bloodsugar.js.map | 1 + glitch.manifest.json | 15 + glitchcomponent.md | 14 + index.html | 12 + package-lock.json | 2919 ++++++++++++++++++++++++++++++++++++++++ package.json | 49 + sound-bridge.md | 34 + src/Component.tsx | 842 ++++++++++++ src/dev-theme.css | 53 + src/dev.tsx | 74 + src/index.tsx | 80 ++ src/styles.module.css | 878 ++++++++++++ src/types.ts | 59 + src/vite-env.d.ts | 1 + tsconfig.json | 30 + vite.config.ts | 36 + 20 files changed, 5227 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 component-contract.md create mode 100644 dist/bloodsugar.js create mode 100644 dist/bloodsugar.js.map create mode 100644 glitch.manifest.json create mode 100644 glitchcomponent.md create mode 100644 index.html create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 sound-bridge.md create mode 100644 src/Component.tsx create mode 100644 src/dev-theme.css create mode 100644 src/dev.tsx create mode 100644 src/index.tsx create mode 100644 src/styles.module.css create mode 100644 src/types.ts create mode 100644 src/vite-env.d.ts create mode 100644 tsconfig.json create mode 100644 vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..68405ce --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +node_modules/ +.DS_Store +.env +.env.local +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/README.md b/README.md new file mode 100644 index 0000000..04b1f9d --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# Blood Sugar Delay Lab + +Standalone Glitch University component that visualizes type 2 diabetes as a delayed feedback problem. The graph shows blood sugar, insulin level, and insulin response moving out of phase so learners can see how delay destabilizes a system that is trying to return to equilibrium. + +## Commands + +- `npm install` +- `npm run dev` +- `npm run build` +- `npm run preview` + +From the workspace root, the standard wrappers also work: + +- `npm run glitch:validate` +- `npm run glitch:build` +- `npm run glitch:release` + +## Notes + +- The packaged entrypoint is `src/index.tsx` +- Dev-only styling lives in `src/dev-theme.css` +- Host integration metadata lives in `glitch.manifest.json` +- CDN release path: `/components/bloodsugar.js` diff --git a/component-contract.md b/component-contract.md new file mode 100644 index 0000000..6e38491 --- /dev/null +++ b/component-contract.md @@ -0,0 +1,92 @@ +# GlitchComponent Contract (Canonical Shape) + +Use the local `lightlane` project as the canonical source when available: + +- `../lightlane/src/types.ts` +- `../lightlane/src/index.tsx` + +This reference captures the current shape observed in `lightlane` so the skill can scaffold quickly. + +## Required Exports + +`src/index.tsx` should export: + +- `default` component +- `metadata` object (`GlitchComponentMetadata`) +- relevant types re-exported from `src/types.ts` + +## Core Types (Current Lightlane-Compatible Shape) + +```ts +export interface GlitchComponentConfig { + id: string; + name: string; + version: string; + params: Record; +} + +export interface GlitchTheme { + primary: string; + accent: string; + bg: string; + bgSecondary: string; + text: string; + textMuted: string; + border: string; +} + +export interface GlitchComponentResult { + success: boolean; + score?: number; + data?: unknown; + error?: string; +} + +export interface GlitchComponentProps { + config: GlitchComponentConfig; + onComplete: (result: GlitchComponentResult) => void; + onProgress?: (percent: number) => void; + theme?: GlitchTheme; + className?: string; +} + +export interface ParamSchema { + [key: string]: { + type: 'number' | 'string' | 'boolean' | 'color' | 'select' | 'range'; + label?: string; + description?: string; + default: unknown; + options?: { value: string | number; label: string }[]; + min?: number; + max?: number; + step?: number; + }; +} + +export interface GlitchComponentMetadata { + name: string; + displayName: string; + version: string; + paramSchema: ParamSchema; + defaultParams: Record; +} +``` + +## Metadata Expectations + +- `name`: kebab-case slug used by host registration +- `displayName`: human-friendly title +- `version`: semantic version string +- `paramSchema`: controls/settings schema for host and dev harness +- `defaultParams`: values that produce a working component without additional configuration + +## Behavioral Expectations + +- Call `onComplete(...)` when the experience completes or fails definitively. +- Call `onProgress(percent)` for multi-step flows when progress is meaningful. +- Use `config.params` as the single source of runtime config. +- Respect `theme` if provided, but keep fallbacks for standalone mode. + +## Validation Tip + +Before finalizing a scaffold, compare generated `src/types.ts` and `src/index.tsx` against the current `../lightlane/src/types.ts` and `../lightlane/src/index.tsx` to catch drift. diff --git a/dist/bloodsugar.js b/dist/bloodsugar.js new file mode 100644 index 0000000..cd30632 --- /dev/null +++ b/dist/bloodsugar.js @@ -0,0 +1,8 @@ +(function(){"use strict";try{if(typeof document<"u"){var e=document.createElement("style");e.appendChild(document.createTextNode('._root_1vqqu_1{--component-bg: var(--color-bg, #0a0a0f);--component-bg-secondary: var(--color-bg-secondary, #12121a);--component-text: var(--color-text, #e8e8ec);--component-text-muted: var(--color-text-muted, #9999a8);--component-primary: var(--color-primary, #6366f1);--component-accent: var(--color-accent, #22d3ee);--component-border: var(--color-border, #2a2a3a);box-sizing:border-box!important;width:min(100%,1500px);margin:0 auto;color:var(--component-text);font-family:var(--font-main, system-ui, sans-serif);line-height:1.5}._root_1vqqu_1,._root_1vqqu_1 *,._root_1vqqu_1 *:before,._root_1vqqu_1 *:after{box-sizing:border-box!important}._board_1vqqu_24{display:grid;grid-template-columns:10.4fr 5.6fr;grid-template-rows:1fr;gap:0;width:100%;aspect-ratio:16 / 9;min-height:0}._chartPanel_1vqqu_34,._controlPanel_1vqqu_35{min-width:0;min-height:0;border:1px solid var(--component-border);border-radius:var(--border-radius, 12px);overflow:hidden;background:linear-gradient(135deg,color-mix(in srgb,var(--component-primary) 12%,transparent),transparent 35%),linear-gradient(180deg,var(--component-bg-secondary),var(--component-bg))}._chartPanel_1vqqu_34{position:relative;width:100%;height:100%;padding:1rem 1rem .95rem 4.15rem;background:linear-gradient(90deg,rgba(255,255,255,.05) 1px,transparent 1px),linear-gradient(180deg,rgba(255,255,255,.04) 1px,transparent 1px),color-mix(in srgb,var(--component-bg) 76%,black);background-size:10% 100%,100% 20%,auto}._controlPanel_1vqqu_35{width:100%;height:100%;display:grid;grid-template-rows:auto minmax(0,1.35fr) auto auto auto;gap:.72rem;padding:1.05rem}._chartHeader_1vqqu_67,._controlHeader_1vqqu_68{min-width:0}._chartHeader_1vqqu_67{position:absolute;top:1rem;right:1rem;left:4.15rem;z-index:1;display:flex;justify-content:space-between;gap:1rem;pointer-events:none}._chartHeader_1vqqu_67 strong{color:var(--component-text-muted);font-family:var(--font-mono, monospace);font-size:.86rem;font-weight:500;text-transform:uppercase}._happyChartBadge_1vqqu_92,._hangryChartBadge_1vqqu_93{position:absolute;top:50%;left:50%;z-index:2;border-radius:var(--border-radius-sm, 8px);padding:.35rem 1rem;font-family:var(--font-display, var(--font-main, system-ui, sans-serif));font-size:6.4rem;font-style:italic;letter-spacing:0;line-height:1;pointer-events:none;text-align:center;text-transform:uppercase;text-shadow:0 0 28px rgba(34,211,238,.28);transform:translate(-50%,-50%);white-space:nowrap}._chartEmoji_1vqqu_113,._hangryChartEmoji_1vqqu_114{position:absolute;top:3.15rem;right:1.35rem;z-index:3;display:grid;place-items:center;width:10.4rem;height:10.4rem;border-radius:999px;background:color-mix(in srgb,var(--component-primary) 20%,rgba(10,10,15,.84));box-shadow:0 0 0 1px color-mix(in srgb,var(--component-primary) 42%,transparent),0 0 24px color-mix(in srgb,var(--component-primary) 24%,transparent);font-size:6.1rem;line-height:1;pointer-events:none}._hangryChartEmoji_1vqqu_114{animation:_hangryShake_1vqqu_1 .24s linear infinite,_hangryBreath_1vqqu_1 1.1s ease-in-out infinite;background:radial-gradient(circle,#f871719e,#f871712e 56%,#0a0a0fdb 72%);box-shadow:0 0 #f871716b,0 0 22px #f8717175}._happyChartBadge_1vqqu_92{color:color-mix(in srgb,var(--component-accent) 74%,white);opacity:.46}._hangryChartBadge_1vqqu_93{animation:_hangryBadgeShake_1vqqu_1 .26s linear infinite,_hangryPulse_1vqqu_1 1.35s ease-in-out infinite;background:#f8717124;box-shadow:0 0 0 1px #f8717161,0 0 22px #f871716b;color:#fecaca;text-shadow:0 0 18px rgba(248,113,113,.7),0 0 42px rgba(248,113,113,.42)}._eyebrow_1vqqu_163{margin:0 0 .45rem;color:var(--component-accent);font-family:var(--font-mono, monospace);font-size:.92rem;letter-spacing:0;text-transform:uppercase}._title_1vqqu_172{margin:0;color:var(--component-text);font-family:var(--font-display, var(--font-main, system-ui, sans-serif));font-size:1.9rem;font-weight:700;line-height:1.16}._mood_1vqqu_181,._hangryMood_1vqqu_182{display:flex;flex-direction:column;justify-content:center;gap:.85rem;min-height:0;padding:1.15rem;border:1px solid color-mix(in srgb,var(--component-border) 84%,white);border-radius:var(--border-radius-sm, 8px);background:color-mix(in srgb,var(--component-bg-secondary) 82%,black);text-align:center}._hangryMood_1vqqu_182{animation:_hangryPanelPulse_1vqqu_1 1.4s ease-in-out infinite;border-color:#f87171a3;background:radial-gradient(circle at 50% 32%,rgba(248,113,113,.34),transparent 38%),color-mix(in srgb,var(--component-bg-secondary) 78%,black)}._emoji_1vqqu_203,._hangryEmoji_1vqqu_204{display:grid;place-items:center;width:5.4rem;height:5.4rem;margin:0 auto;border-radius:999px;background:color-mix(in srgb,var(--component-primary) 18%,transparent);font-size:3.15rem}._hangryEmoji_1vqqu_204{animation:_hangryShake_1vqqu_1 .24s linear infinite,_hangryBreath_1vqqu_1 1.1s ease-in-out infinite;background:radial-gradient(circle,rgba(248,113,113,.62),rgba(248,113,113,.16) 56%,transparent 72%);box-shadow:0 0 #f871716b,0 0 22px #f8717175}._mood_1vqqu_181 strong,._mood_1vqqu_181 small,._hangryMood_1vqqu_182 strong,._hangryMood_1vqqu_182 small{display:block}._mood_1vqqu_181 small,._hangryMood_1vqqu_182 small{max-width:32rem;margin:.48rem auto 0;color:var(--component-text-muted);font-size:1.28rem;line-height:1.38}._mood_1vqqu_181 strong,._hangryMood_1vqqu_182 strong{font-family:var(--font-display, var(--font-main, system-ui, sans-serif));font-size:1.8rem;line-height:1.05}._hangryMood_1vqqu_182 strong{color:#fecaca}._zoneLabels_1vqqu_253{position:absolute;top:4.2rem;bottom:3.2rem;left:.9rem;display:flex;flex-direction:column;justify-content:space-between;width:2.65rem;color:var(--component-text-muted);font-family:var(--font-mono, monospace);font-size:.72rem;line-height:1.25;text-align:center;text-transform:uppercase}._chart_1vqqu_34{display:block;width:100%;height:100%;padding-top:2.65rem;overflow:visible}._gridLine_1vqqu_278{stroke:#ffffff17;stroke-width:.35}._targetLine_1vqqu_283{stroke:#ffffff6b;stroke-dasharray:1.4 1.4;stroke-width:.45}._glucoseLine_1vqqu_289,._insulinLine_1vqqu_290,._responseLine_1vqqu_291{fill:none;vector-effect:non-scaling-stroke}._glucoseLine_1vqqu_289{stroke:var(--component-primary);stroke-width:2.85}._insulinLine_1vqqu_290{stroke:var(--component-accent);stroke-width:2.3}._responseLine_1vqqu_291{stroke:#fbbf24;stroke-dasharray:3 2;stroke-width:1.85}._cursorLine_1vqqu_312{stroke:#ffffff52;stroke-width:.55}._delayLine_1vqqu_317{stroke:#fbbf24;stroke-linecap:round;stroke-width:1.75}._delayCallout_1vqqu_323{filter:drop-shadow(0 0 5px rgba(251,191,36,.42))}._delayText_1vqqu_327{fill:#fef3c7;font-family:var(--font-mono, monospace);font-size:3px;font-weight:600;letter-spacing:0;paint-order:stroke;stroke:#0a0a0fdb;stroke-width:.8px;text-transform:uppercase}._foodLine_1vqqu_339{stroke:#ffffff4d;stroke-dasharray:1.6 1.6;stroke-width:.6}._mealWindow_1vqqu_345{fill:#fb71851a;stroke:#fb71853d;stroke-width:.3}._snackWindow_1vqqu_351{fill:#fbbf241f;stroke:#fbbf2452;stroke-width:.3}._snackLine_1vqqu_357{stroke:#fbbf248a;stroke-dasharray:1.6 1.6;stroke-width:.55}._foodMarker_1vqqu_363{dominant-baseline:middle;font-size:7.5px}._glucoseDot_1vqqu_368,._insulinDot_1vqqu_369,._responseDot_1vqqu_370{vector-effect:non-scaling-stroke;stroke:var(--component-bg);stroke-width:1.2}._glucoseDot_1vqqu_368{fill:var(--component-primary)}._insulinDot_1vqqu_369{fill:var(--component-accent)}._responseDot_1vqqu_370{fill:#fbbf24}._legend_1vqqu_388{position:absolute;right:1rem;bottom:.95rem;left:4.15rem;display:flex;flex-wrap:wrap;gap:.55rem .8rem;align-items:center;color:var(--component-text-muted);font-family:var(--font-mono, monospace);font-size:.86rem}._legend_1vqqu_388 span{display:inline-flex;gap:.38rem;align-items:center}._legend_1vqqu_388 i{display:inline-block;width:1.35rem;height:.28rem;border-radius:999px}._glucoseKey_1vqqu_415{background:var(--component-primary)}._insulinKey_1vqqu_419{background:var(--component-accent)}._responseKey_1vqqu_423{background:#fbbf24}._foodKey_1vqqu_427{background:#fb7185}._snackKey_1vqqu_431{background:#fbbf24}._sidePanel_1vqqu_435{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.55rem;min-height:0;overflow:hidden}._metric_1vqqu_443,._delayCard_1vqqu_444{min-width:0;padding:.78rem;border:1px solid var(--component-border);border-radius:var(--border-radius-sm, 8px);background:color-mix(in srgb,var(--component-bg-secondary) 84%,black)}._metric_1vqqu_443 span,._delayCard_1vqqu_444 span{display:block;color:var(--component-text-muted);font-family:var(--font-mono, monospace);font-size:.72rem;line-height:1.2;text-transform:uppercase}._metric_1vqqu_443 strong,._delayCard_1vqqu_444 strong{display:block;margin-top:.15rem;color:var(--component-text);font-size:1.52rem;line-height:1.1}._metric_1vqqu_443 small{color:var(--component-text-muted);font-size:.72rem;font-weight:400}._delayCard_1vqqu_444{border-color:color-mix(in srgb,#fbbf24 42%,var(--component-border))}._delayCard_1vqqu_444 p{display:none;margin:.55rem 0 0;color:var(--component-text-muted);font-size:clamp(.72rem,1vw,.92rem);line-height:1.38}._causalChain_1vqqu_489{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:.38rem;min-height:0}._causalStep_1vqqu_496,._activeCausalStep_1vqqu_497{position:relative;min-width:0;padding:.55rem .42rem;border:1px solid var(--component-border);border-radius:var(--border-radius-sm, 8px);background:color-mix(in srgb,var(--component-bg-secondary) 86%,black)}._causalStep_1vqqu_496:not(:last-child):after,._activeCausalStep_1vqqu_497:not(:last-child):after{position:absolute;top:50%;right:-.36rem;z-index:1;color:var(--component-text-muted);content:">";font-family:var(--font-mono, monospace);font-size:.7rem;transform:translateY(-50%)}._activeCausalStep_1vqqu_497{border-color:color-mix(in srgb,var(--component-accent) 72%,white);background:color-mix(in srgb,var(--component-accent) 18%,var(--component-bg-secondary))}._causalStep_1vqqu_496 span,._activeCausalStep_1vqqu_497 span{display:block;overflow:hidden;color:var(--component-text-muted);font-family:var(--font-mono, monospace);font-size:.64rem;line-height:1;text-overflow:ellipsis;text-transform:uppercase;white-space:nowrap}._causalStep_1vqqu_496 strong,._activeCausalStep_1vqqu_497 strong{display:block;margin-top:.2rem;overflow:hidden;color:var(--component-text);font-size:1rem;line-height:1;text-overflow:ellipsis;white-space:nowrap}._controls_1vqqu_549{display:grid;grid-template-columns:.8fr .9fr 1fr;gap:.5rem}._button_1vqqu_555,._buttonPrimary_1vqqu_556{min-width:0;border-radius:var(--border-radius-sm, 8px);padding:.78rem .7rem;cursor:pointer;font:inherit;font-size:1rem;transition:transform var(--transition, .2s ease),opacity var(--transition, .2s ease),border-color var(--transition, .2s ease)}._button_1vqqu_555{border:1px solid var(--component-border);background:var(--component-bg-secondary);color:var(--component-text)}._buttonPrimary_1vqqu_556{border:1px solid color-mix(in srgb,var(--component-primary) 68%,white);background:var(--component-primary);color:#fff}._button_1vqqu_555:hover,._buttonPrimary_1vqqu_556:hover{opacity:.95;transform:translateY(-1px)}._button_1vqqu_555:disabled,._buttonPrimary_1vqqu_556:disabled{cursor:not-allowed;opacity:.45;transform:none}@keyframes _hangryShake_1vqqu_1{0%,to{transform:translate(0)}25%{transform:translate(-1px) rotate(-1deg)}50%{transform:translate(1px) rotate(1deg)}75%{transform:translate(-.5px) rotate(-.5deg)}}@keyframes _hangryBadgeShake_1vqqu_1{0%,to{transform:translate(-50%,-50%)}25%{transform:translate(calc(-50% - 2px),-50%) rotate(-1deg)}50%{transform:translate(calc(-50% + 2px),-50%) rotate(1deg)}75%{transform:translate(calc(-50% - 1px),-50%) rotate(-.5deg)}}@keyframes _hangryBreath_1vqqu_1{0%,to{box-shadow:0 0 #f8717157,0 0 18px #f8717157}50%{box-shadow:0 0 0 .75rem #f8717100,0 0 30px #f87171a3}}@keyframes _hangryPulse_1vqqu_1{0%,to{opacity:.76}50%{opacity:1}}@keyframes _hangryPanelPulse_1vqqu_1{0%,to{box-shadow:0 0 #f8717100}50%{box-shadow:0 0 20px #f8717138}}@media(orientation:portrait),(max-width:820px){._root_1vqqu_1{width:min(100%,760px)}._board_1vqqu_24{grid-template-columns:1fr;grid-template-rows:auto auto;gap:clamp(.7rem,2vw,1rem);aspect-ratio:auto}._chartPanel_1vqqu_34,._controlPanel_1vqqu_35{width:100%;height:auto;aspect-ratio:1 / 1}._controlPanel_1vqqu_35{grid-template-rows:auto minmax(0,1.25fr) auto auto auto;gap:.58rem;padding:.85rem}._chartPanel_1vqqu_34{padding:.85rem .85rem .78rem 3.35rem}._chartHeader_1vqqu_67,._legend_1vqqu_388{left:3.35rem}._chartEmoji_1vqqu_113,._hangryChartEmoji_1vqqu_114{top:2.75rem;right:1rem;width:8.7rem;height:8.7rem;font-size:5rem}._chartHeader_1vqqu_67 strong,._legend_1vqqu_388{font-size:.72rem}._eyebrow_1vqqu_163{font-size:.78rem}._title_1vqqu_172{font-size:1.55rem}._sidePanel_1vqqu_435{grid-template-columns:repeat(3,minmax(0,1fr));gap:.45rem}._mood_1vqqu_181,._hangryMood_1vqqu_182{gap:.55rem;padding:.72rem}._mood_1vqqu_181 strong,._hangryMood_1vqqu_182 strong{font-size:1.42rem}._mood_1vqqu_181 small,._hangryMood_1vqqu_182 small{font-size:1.02rem;line-height:1.32}._happyChartBadge_1vqqu_92,._hangryChartBadge_1vqqu_93{font-size:4.2rem}._metric_1vqqu_443,._delayCard_1vqqu_444{padding:.55rem}._metric_1vqqu_443 strong,._delayCard_1vqqu_444 strong{font-size:1.18rem}._causalChain_1vqqu_489{gap:.28rem}._causalStep_1vqqu_496,._activeCausalStep_1vqqu_497{padding:.38rem .3rem}}@media(max-width:520px){._chartPanel_1vqqu_34{padding:.72rem .68rem .7rem 2.7rem}._chartHeader_1vqqu_67,._legend_1vqqu_388{left:2.7rem}._chartEmoji_1vqqu_113,._hangryChartEmoji_1vqqu_114{top:2.28rem;right:.78rem;width:6.5rem;height:6.5rem;font-size:3.8rem}._chartHeader_1vqqu_67{top:.72rem;right:.68rem}._chartHeader_1vqqu_67 strong,._legend_1vqqu_388{font-size:.58rem}._legend_1vqqu_388{right:.68rem;bottom:.68rem;gap:.32rem .48rem}._zoneLabels_1vqqu_253{left:.55rem;width:1.85rem;font-size:.54rem}._title_1vqqu_172{font-size:1.18rem}._eyebrow_1vqqu_163{margin-bottom:.25rem;font-size:.68rem}._happyChartBadge_1vqqu_92,._hangryChartBadge_1vqqu_93{font-size:3rem}._mood_1vqqu_181,._hangryMood_1vqqu_182{gap:.38rem;padding:.55rem}._mood_1vqqu_181 strong,._hangryMood_1vqqu_182 strong{font-size:1.18rem}._mood_1vqqu_181 small,._hangryMood_1vqqu_182 small{font-size:1rem;line-height:1.28}._sidePanel_1vqqu_435{grid-template-columns:repeat(2,minmax(0,1fr));gap:.35rem}._metric_1vqqu_443,._delayCard_1vqqu_444{padding:.42rem}._metric_1vqqu_443 span,._delayCard_1vqqu_444 span{font-size:.56rem}._metric_1vqqu_443 strong,._delayCard_1vqqu_444 strong{font-size:.92rem}._causalChain_1vqqu_489{display:none}._controls_1vqqu_549{grid-template-columns:.8fr .9fr 1fr;gap:.35rem}._button_1vqqu_555,._buttonPrimary_1vqqu_556{padding:.52rem .4rem;font-size:.8rem}}')),document.head.appendChild(e)}}catch(r){console.error("vite-plugin-css-injected-by-js",r)}})(); +var GlitchComponent=(function(V,M){"use strict";var Z={exports:{}},K={};var he;function _e(){if(he)return K;he=1;var o=Symbol.for("react.transitional.element"),i=Symbol.for("react.fragment");function d(l,c,r){var p=null;if(r!==void 0&&(p=""+r),c.key!==void 0&&(p=""+c.key),"key"in c){r={};for(var u in c)u!=="key"&&(r[u]=c[u])}else r=c;return c=r.ref,{$$typeof:o,type:l,key:p,ref:c!==void 0?c:null,props:r}}return K.Fragment=i,K.jsx=d,K.jsxs=d,K}var B={};var pe;function xe(){return pe||(pe=1,process.env.NODE_ENV!=="production"&&(function(){function o(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===se?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case _:return"Fragment";case w:return"Profiler";case D:return"StrictMode";case ce:return"Suspense";case ee:return"SuspenseList";case v:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case x:return"Portal";case P:return e.displayName||"Context";case Q:return(e._context.displayName||"Context")+".Consumer";case ie:var n=e.render;return e=e.displayName,e||(e=n.displayName||n.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case ue:return n=e.displayName||null,n!==null?n:o(e.type)||"Memo";case O:n=e._payload,e=e._init;try{return o(e(n))}catch{}}return null}function i(e){return""+e}function d(e){try{i(e);var n=!1}catch{n=!0}if(n){n=console;var h=n.error,y=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return h.call(n,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",y),i(e)}}function l(e){if(e===_)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===O)return"<...>";try{var n=o(e);return n?"<"+n+">":"<...>"}catch{return"<...>"}}function c(){var e=F.A;return e===null?null:e.getOwner()}function r(){return Error("react-stack-top-frame")}function p(e){if(T.call(e,"key")){var n=Object.getOwnPropertyDescriptor(e,"key").get;if(n&&n.isReactWarning)return!1}return e.key!==void 0}function u(e,n){function h(){te||(te=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",n))}h.isReactWarning=!0,Object.defineProperty(e,"key",{get:h,configurable:!0})}function g(){var e=o(this.type);return z[e]||(z[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function q(e,n,h,y,G,Y){var m=h.ref;return e={$$typeof:a,type:e,key:n,props:h,_owner:y},(m!==void 0?m:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:g}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:G}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:Y}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function k(e,n,h,y,G,Y){var m=n.children;if(m!==void 0)if(y)if(de(m)){for(y=0;y +React keys must be passed directly to JSX without using spread: + let props = %s; + <%s key={someKey} {...props} />`,y,m,I,m),U[m+y]=!0)}if(m=null,h!==void 0&&(d(h),m=""+h),p(n)&&(d(n.key),m=""+n.key),"key"in n){h={};for(var X in n)X!=="key"&&(h[X]=n[X])}else h=n;return m&&u(h,typeof e=="function"?e.displayName||e.name||"Unknown":e),q(e,m,h,c(),G,Y)}function C(e){b(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===O&&(e._payload.status==="fulfilled"?b(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function b(e){return typeof e=="object"&&e!==null&&e.$$typeof===a}var E=M,a=Symbol.for("react.transitional.element"),x=Symbol.for("react.portal"),_=Symbol.for("react.fragment"),D=Symbol.for("react.strict_mode"),w=Symbol.for("react.profiler"),Q=Symbol.for("react.consumer"),P=Symbol.for("react.context"),ie=Symbol.for("react.forward_ref"),ce=Symbol.for("react.suspense"),ee=Symbol.for("react.suspense_list"),ue=Symbol.for("react.memo"),O=Symbol.for("react.lazy"),v=Symbol.for("react.activity"),se=Symbol.for("react.client.reference"),F=E.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,T=Object.prototype.hasOwnProperty,de=Array.isArray,L=console.createTask?console.createTask:function(){return null};E={react_stack_bottom_frame:function(e){return e()}};var te,z={},ne=E.react_stack_bottom_frame.bind(E,r)(),oe=L(l(r)),U={};B.Fragment=_,B.jsx=function(e,n,h){var y=1e4>F.recentlyCreatedOwnerStacks++;return k(e,n,h,!1,y?Error("react-stack-top-frame"):ne,y?L(l(e)):oe)},B.jsxs=function(e,n,h){var y=1e4>F.recentlyCreatedOwnerStacks++;return k(e,n,h,!0,y?Error("react-stack-top-frame"):ne,y?L(l(e)):oe)}})()),B}var ye;function ve(){return ye||(ye=1,process.env.NODE_ENV==="production"?Z.exports=_e():Z.exports=xe()),Z.exports}var s=ve();const t={root:"_root_1vqqu_1",board:"_board_1vqqu_24",chartPanel:"_chartPanel_1vqqu_34",controlPanel:"_controlPanel_1vqqu_35",chartHeader:"_chartHeader_1vqqu_67",controlHeader:"_controlHeader_1vqqu_68",happyChartBadge:"_happyChartBadge_1vqqu_92",hangryChartBadge:"_hangryChartBadge_1vqqu_93",chartEmoji:"_chartEmoji_1vqqu_113",hangryChartEmoji:"_hangryChartEmoji_1vqqu_114",eyebrow:"_eyebrow_1vqqu_163",title:"_title_1vqqu_172",mood:"_mood_1vqqu_181",hangryMood:"_hangryMood_1vqqu_182",zoneLabels:"_zoneLabels_1vqqu_253",chart:"_chart_1vqqu_34",gridLine:"_gridLine_1vqqu_278",targetLine:"_targetLine_1vqqu_283",glucoseLine:"_glucoseLine_1vqqu_289",insulinLine:"_insulinLine_1vqqu_290",responseLine:"_responseLine_1vqqu_291",cursorLine:"_cursorLine_1vqqu_312",delayLine:"_delayLine_1vqqu_317",delayCallout:"_delayCallout_1vqqu_323",delayText:"_delayText_1vqqu_327",foodLine:"_foodLine_1vqqu_339",mealWindow:"_mealWindow_1vqqu_345",snackWindow:"_snackWindow_1vqqu_351",snackLine:"_snackLine_1vqqu_357",foodMarker:"_foodMarker_1vqqu_363",glucoseDot:"_glucoseDot_1vqqu_368",insulinDot:"_insulinDot_1vqqu_369",responseDot:"_responseDot_1vqqu_370",legend:"_legend_1vqqu_388",glucoseKey:"_glucoseKey_1vqqu_415",insulinKey:"_insulinKey_1vqqu_419",responseKey:"_responseKey_1vqqu_423",foodKey:"_foodKey_1vqqu_427",snackKey:"_snackKey_1vqqu_431",sidePanel:"_sidePanel_1vqqu_435",metric:"_metric_1vqqu_443",causalChain:"_causalChain_1vqqu_489",causalStep:"_causalStep_1vqqu_496",activeCausalStep:"_activeCausalStep_1vqqu_497",controls:"_controls_1vqqu_549",button:"_button_1vqqu_555",buttonPrimary:"_buttonPrimary_1vqqu_556"},W={click:"ui.button_click",hover:"ui.button_hover"},N=520,R=700,je=54,Se=84,me=102,ke=348,Ee=368,Le=388,fe=72,j=96,Te=145,A=[{id:"baseline",eyebrow:"Stage 1",title:"Blood sugar is a control loop.",copy:"No meal, no drama. The system stays near its set point.",chartLabel:"Blood sugar only",showFood:!1,showInsulin:!1,showResponse:!1,showDelay:!1,destabilized:!1,startMinute:0,stopMinute:44},{id:"meal-start",eyebrow:"Stage 2",title:"Food pushes glucose up.",copy:"The meal starts first. Blood sugar keeps rising while food is absorbed.",chartLabel:"Meal starts before the peak",showFood:!0,showInsulin:!1,showResponse:!1,showDelay:!1,destabilized:!1,startMinute:0,stopMinute:92},{id:"glucose-peak",eyebrow:"Stage 3",title:"Sugar rises first.",copy:"Insulin is not the cause of this peak. It is the answer to it.",chartLabel:"Glucose rises first",showFood:!0,showInsulin:!1,showResponse:!1,showDelay:!1,destabilized:!1,startMinute:92,stopMinute:126},{id:"insulin-rise",eyebrow:"Stage 4",title:"Insulin answers the rise.",copy:"The pancreas responds to glucose that was already high.",chartLabel:"Glucose causes insulin",showFood:!0,showInsulin:!0,showResponse:!1,showDelay:!1,destabilized:!1,startMinute:126,stopMinute:156},{id:"glucose-fall",eyebrow:"Stage 5",title:"Then action lands in tissue.",copy:"Insulin action pulls glucose out of blood. The curve bends down.",chartLabel:"Insulin causes glucose uptake",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!1,destabilized:!1,startMinute:156,stopMinute:206},{id:"insulin-fall",eyebrow:"Stage 6",title:"Lower sugar quiets insulin.",copy:"When glucose falls, the signal fades. The loop starts settling.",chartLabel:"Lower glucose lowers insulin",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!1,destabilized:!1,startMinute:206,stopMinute:252},{id:"return-baseline",eyebrow:"Stage 7",title:"Good timing stabilizes.",copy:"The response arrives while it is still useful, so the loop returns to baseline.",chartLabel:"Back toward equilibrium",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!1,destabilized:!1,startMinute:252,stopMinute:320},{id:"loop-summary",eyebrow:"Stage 8",title:"The loop is simple.",copy:"Glucose calls. Insulin answers. Tissue acts. Timing decides whether this stabilizes.",chartLabel:"A stabilizing feedback loop",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!1,destabilized:!1,startMinute:0,stopMinute:320},{id:"lag-setup",eyebrow:"Stage 9",title:"Now add only delay.",copy:"Same meal. Same loop. The answer just arrives late.",chartLabel:"Same loop, more lag",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!0,destabilized:!0,startMinute:0,stopMinute:92},{id:"lag-high",eyebrow:"Stage 10",title:"This is the “resistance” moment.",copy:"It looks like glucose is not being handled. But in this model, the response is late.",chartLabel:"Lag lets glucose run high",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!0,destabilized:!0,startMinute:92,stopMinute:132},{id:"lag-insulin",eyebrow:"Stage 11",title:"The answer points backward.",copy:"Insulin is reacting to old glucose information. The system is chasing the past.",chartLabel:"The answer arrives late",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!0,destabilized:!0,startMinute:132,stopMinute:186},{id:"late-action",eyebrow:"Stage 12",title:"Late correction finally hits.",copy:"Now uptake is strong, but the original glucose problem has already moved on.",chartLabel:"Correction after the moment passed",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!0,destabilized:!0,startMinute:186,stopMinute:236},{id:"crash",eyebrow:"Stage 13",title:"Late becomes too much.",copy:"A correction that would have helped earlier now overshoots. That is the crash.",chartLabel:"The crash",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!0,destabilized:!0,startMinute:236,stopMinute:306},{id:"recovery",eyebrow:"Stage 14",title:"The loop remembers.",copy:"Insulin action fades slowly. The body is still carrying the late response.",chartLabel:"Memory in the loop",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!0,destabilized:!0,startMinute:306,stopMinute:440},{id:"whiplash-summary",eyebrow:"Stage 15",title:"Timing made the whiplash.",copy:"High, then low, from the same loop. The problem is not just level. It is delay.",chartLabel:"Recovery without snacking",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!0,destabilized:!0,startMinute:440,stopMinute:650},{id:"snack-setup",eyebrow:"Stage 16",title:"The crash recruits behavior.",copy:"The low feels urgent. Snacking becomes the easiest way to push glucose back up.",chartLabel:"Snack added during the low",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!0,destabilized:!0,showSnack:!0,snacking:!0,startMinute:306,stopMinute:368},{id:"snack-bump",eyebrow:"Stage 17",title:"The snack works short term.",copy:"Glucose rises. The feeling improves. But the loop has not learned timing.",chartLabel:"Short-term relief",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!0,destabilized:!0,showSnack:!0,snacking:!0,startMinute:368,stopMinute:414},{id:"snack-insulin",eyebrow:"Stage 18",title:"Now the loop is triggered again.",copy:"The snack is another glucose input, so the delayed response starts chasing again.",chartLabel:"Another response is triggered",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!0,destabilized:!0,showSnack:!0,snacking:!0,startMinute:414,stopMinute:464},{id:"calorie-cost",eyebrow:"Stage 19",title:"Relief has a calorie cost.",copy:"The snack solves the low by adding energy. Repeat that pattern and intake rises.",chartLabel:"Relief has a calorie cost",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!0,destabilized:!0,showSnack:!0,snacking:!0,startMinute:464,stopMinute:560},{id:"snack-summary",eyebrow:"Stage 20",title:"Aha: the villain is delay.",copy:"What gets called resistance can be seen here as timing failure: late response, overshoot, crash, snack.",chartLabel:"Whiplash plus snacking",showFood:!0,showInsulin:!0,showResponse:!0,showDelay:!0,destabilized:!0,showSnack:!0,snacking:!0,startMinute:0,stopMinute:650}];function H(o,i,d){try{o?.playSound?.(i,d)}catch{}}function S(o,i,d){return Math.min(d,Math.max(i,o))}function $(o,i){return typeof o=="number"&&Number.isFinite(o)?o:i}function Me(o,i){return i.reduce((d,l)=>{const c=l.width??24,r=o-l.center;return d+l.load*Math.exp(-(r*r)/(2*c*c))},0)}function ge(o,i){const d=[];let l=j,c=12,r=0;const p=R/N,u=Math.max(1,Math.round(o.sensorDelay/p)),g=Array(u+2).fill(j);for(let q=0;q({t:i/(N-1)*R,glucose:j,insulin:12,response:0,food:0,sensedGlucose:j,uptake:0}))}function ae(o,i,d,l,c){return o.slice(0,c+1).map((r,p)=>{const u=p/(N-1)*100,g=100-(r[i]-d)/(l-d)*100;return`${u.toFixed(2)},${S(g,4,96).toFixed(2)}`}).join(" ")}function re(o,i,d,l,c){const r=i/(N-1)*100,p=100-(o[c]-d)/(l-d)*100;return{x:r,y:S(p,4,96)}}function be(o){return S(Math.round(o/R*(N-1)),0,N-1)}function Re(o){return o>=Te?{emoji:"🥴",label:"High zone",copy:"Sugar is lingering above the healthy range while insulin is still catching up."}:o<=fe?{emoji:"😠",label:"Low zone",copy:"The delayed response overcorrected. Energy dips, mood gets sharp."}:{emoji:"🙂",label:"Target zone",copy:"The system is near equilibrium, with fuel and response mostly in sync."}}function qe(o,i){return i.showFood?o.food>10?"food":i.showInsulin&&o.sensedGlucose>j+4&&o.insulin<24?"sense":i.showInsulin&&o.insulin>24&&(!i.showResponse||o.response<12)?"insulin":i.showResponse&&o.response>12?"action":"baseline":"baseline"}function we({config:o,onComplete:i,onProgress:d,theme:l,className:c,host:r}){const p=o.params??{},u={responseDelay:$(p.responseDelay,34),mealLoad:$(p.mealLoad,44),pancreasStrength:$(p.pancreasStrength,1),playbackSpeed:$(p.playbackSpeed,1),primaryColor:p.primaryColor??l?.primary??"#6366f1",accentColor:p.accentColor??l?.accent??"#22d3ee"},[g,q]=M.useState(0),[k,C]=M.useState(!1),[b,E]=M.useState(0),a=A[b],x=M.useMemo(()=>{if(a.id==="baseline")return Ne();const f=a.snacking?[{center:Le,load:u.mealLoad*.7,width:20}]:[];return a.destabilized?ge({sensorDelay:u.responseDelay+4,actionDelay:u.responseDelay*1.5+15,betaGain:u.pancreasStrength*1.55,insulinClearance:32,insulinEffect:1.18},[{center:me,load:u.mealLoad*1.23,width:24},...f]):ge({sensorDelay:7,actionDelay:18,betaGain:.82,insulinClearance:22,insulinEffect:1.08},[{center:me,load:30,width:24}])},[u.responseDelay,u.mealLoad,u.pancreasStrength,a.destabilized,a.id,a.snacking]),_=be(a.startMinute),D=be(a.stopMinute),w=x[g]??x[0],Q=Re(w.glucose),P=w.glucose<=fe,ie=P?"Hangry":"Happy",ce=Math.round(w.glucose),ee=Math.round(w.insulin),ue=S(Math.round(u.responseDelay/80*100),0,100),O=S(Math.round((Math.max(...x.map(f=>f.glucose))-Math.min(...x.map(f=>f.glucose)))*.9),0,100),v=re(w,g,50,200,"glucose"),se=re(w,g,0,125,"insulin"),F=re(w,g,0,125,"response"),T=je/R*100,de=Se/R*100,L=ke/R*100,te=Ee/R*100,z=v.x>=T,ne=v.x>=L,oe=u.responseDelay/R*100,U=S(v.x-oe,0,100),e=(U+v.x)/2,n=qe(w,a),h=Math.round(w.sensedGlucose),y=w.uptake.toFixed(1);M.useEffect(()=>{if(k)return;const f=window.setInterval(()=>{q(J=>J>=D?J:J+1)},42/u.playbackSpeed);return()=>window.clearInterval(f)},[u.playbackSpeed,k,D]),M.useEffect(()=>{const f=Math.max(1,D-_),J=(b+S((g-_)/f,0,1))/A.length;d?.(Math.min(95,Math.round(J*95)))},[g,b,d,_,D]),M.useEffect(()=>{q(_),C(!1)},[b,_]);const G={"--component-bg":l?.bg,"--component-bg-secondary":l?.bgSecondary,"--component-text":l?.text,"--component-text-muted":l?.textMuted,"--component-primary":u.primaryColor,"--component-accent":u.accentColor,"--component-border":l?.border};function Y(){H(r,W.click,{target:"pause",paused:!k}),C(f=>!f)}function m(){H(r,W.click,{target:"previous-stage",lessonIndex:b}),E(f=>Math.max(0,f-1))}function I(){if(H(r,W.click,{target:"next-stage",lessonIndex:b}),b>=A.length-1){X();return}E(f=>Math.min(A.length-1,f+1))}function X(){H(r,W.click,{target:"complete"}),d?.(100),i({success:!0,score:Math.max(1,100-Math.round((ue+O)/4)),data:{completedAt:new Date().toISOString(),responseDelay:u.responseDelay,instabilityScore:O,lesson:"Delay can turn a stabilizing feedback loop into an oscillating hysteresis loop."}})}return s.jsx("div",{className:[t.root,c].filter(Boolean).join(" "),style:G,children:s.jsxs("div",{className:t.board,children:[s.jsxs("div",{className:t.chartPanel,children:[s.jsx("div",{className:P?t.hangryChartEmoji:t.chartEmoji,"aria-hidden":"true",children:a.showFood&&!z?"🍽️":Q.emoji}),s.jsx("div",{className:P?t.hangryChartBadge:t.happyChartBadge,"aria-live":"polite",children:ie}),s.jsxs("div",{className:t.chartHeader,children:[s.jsx("p",{className:t.eyebrow,children:a.eyebrow}),s.jsx("strong",{children:a.chartLabel})]}),s.jsxs("div",{className:t.zoneLabels,"aria-hidden":"true",children:[s.jsx("span",{children:"unhealthy high"}),s.jsx("span",{children:"target"}),s.jsx("span",{children:"cranky low"})]}),s.jsxs("svg",{className:t.chart,viewBox:"0 0 100 100",role:"img","aria-label":"Animated graph of blood sugar, insulin level, and insulin response",children:[s.jsxs("defs",{children:[s.jsxs("linearGradient",{id:"bloodsugarHighZone",x1:"0",x2:"0",y1:"0",y2:"1",children:[s.jsx("stop",{offset:"0%",stopColor:"rgba(248, 113, 113, 0.28)"}),s.jsx("stop",{offset:"100%",stopColor:"rgba(248, 113, 113, 0.06)"})]}),s.jsxs("linearGradient",{id:"bloodsugarLowZone",x1:"0",x2:"0",y1:"0",y2:"1",children:[s.jsx("stop",{offset:"0%",stopColor:"rgba(34, 211, 238, 0.05)"}),s.jsx("stop",{offset:"100%",stopColor:"rgba(34, 211, 238, 0.26)"})]}),s.jsx("marker",{id:"bloodsugarDelayArrow",markerHeight:"4",markerWidth:"5",orient:"auto",refX:"4.4",refY:"2",children:s.jsx("path",{d:"M0,0 L5,2 L0,4 Z",fill:"#fbbf24"})})]}),s.jsx("rect",{x:"0",y:"0",width:"100",height:"37",fill:"url(#bloodsugarHighZone)"}),s.jsx("rect",{x:"0",y:"83",width:"100",height:"17",fill:"url(#bloodsugarLowZone)"}),[20,40,60,80].map(f=>s.jsx("line",{className:t.gridLine,x1:"0",x2:"100",y1:f,y2:f},f)),s.jsx("line",{className:t.targetLine,x1:"0",x2:"100",y1:"69.33",y2:"69.33"}),a.showFood?s.jsxs(s.Fragment,{children:[s.jsx("rect",{className:t.mealWindow,x:T,y:"5",width:de-T,height:"91"}),s.jsx("line",{className:t.foodLine,x1:T,x2:T,y1:"5",y2:"96"}),s.jsx("text",{className:t.foodMarker,x:T,y:"12",textAnchor:"middle",children:"🍽️"}),a.showSnack?s.jsxs(s.Fragment,{children:[s.jsx("rect",{className:t.snackWindow,x:L,y:"5",width:te-L,height:"91"}),s.jsx("line",{className:t.snackLine,x1:L,x2:L,y1:"5",y2:"96"}),s.jsx("text",{className:t.foodMarker,x:L,y:"12",textAnchor:"middle",children:"🍬"})]}):null]}):null,s.jsx("polyline",{className:t.glucoseLine,points:ae(x,"glucose",50,200,g)}),a.showInsulin?s.jsx("polyline",{className:t.insulinLine,points:ae(x,"insulin",0,125,g)}):null,a.showResponse?s.jsx("polyline",{className:t.responseLine,points:ae(x,"response",0,125,g)}):null,s.jsx("line",{className:t.cursorLine,x1:v.x,x2:v.x,y1:"0",y2:"100"}),a.showDelay?s.jsxs("g",{className:t.delayCallout,children:[s.jsx("line",{className:t.delayLine,markerEnd:"url(#bloodsugarDelayArrow)",x1:U,x2:v.x,y1:"18",y2:"18"}),s.jsx("text",{className:t.delayText,x:e,y:"16",textAnchor:"middle",children:"late response"})]}):null,s.jsx("circle",{className:t.glucoseDot,cx:v.x,cy:v.y,r:"2.2"}),a.showInsulin?s.jsx("circle",{className:t.insulinDot,cx:se.x,cy:se.y,r:"1.9"}):null,a.showResponse?s.jsx("circle",{className:t.responseDot,cx:F.x,cy:F.y,r:"1.6"}):null]}),s.jsxs("div",{className:t.legend,children:[s.jsxs("span",{children:[s.jsx("i",{className:t.glucoseKey})," Blood sugar"]}),a.showFood?s.jsxs("span",{children:[s.jsx("i",{className:t.foodKey})," Food event"]}):null,a.showSnack?s.jsxs("span",{children:[s.jsx("i",{className:t.snackKey})," Snack"]}):null,a.showInsulin?s.jsxs("span",{children:[s.jsx("i",{className:t.insulinKey})," Insulin level"]}):null,a.showResponse?s.jsxs("span",{children:[s.jsx("i",{className:t.responseKey})," Insulin action in tissue"]}):null]})]}),s.jsxs("section",{className:t.controlPanel,children:[s.jsxs("div",{className:t.controlHeader,children:[s.jsxs("p",{className:t.eyebrow,children:[a.eyebrow," of ",A.length]}),s.jsx("h2",{className:t.title,children:a.title})]}),s.jsx("div",{className:P?t.hangryMood:t.mood,"aria-live":"polite",children:s.jsxs("span",{children:[s.jsx("strong",{children:a.showFood&&!z?"Food is coming":Q.label}),s.jsx("small",{children:a.copy})]})}),s.jsxs("div",{className:t.sidePanel,children:[s.jsxs("div",{className:t.metric,children:[s.jsx("span",{children:"Blood sugar"}),s.jsxs("strong",{children:[ce,s.jsx("small",{children:" mg/dL"})]})]}),a.showFood?s.jsxs("div",{className:t.metric,children:[s.jsx("span",{children:a.showSnack?"Snack":"Food event"}),s.jsx("strong",{children:a.showSnack?ne?"added":"craving":z?"absorbing":"up next"})]}):s.jsxs("div",{className:t.metric,children:[s.jsx("span",{children:"Baseline"}),s.jsxs("strong",{children:[j,s.jsx("small",{children:" mg/dL"})]})]}),a.showInsulin?s.jsxs("div",{className:t.metric,children:[s.jsx("span",{children:"Insulin"}),s.jsxs("strong",{children:[ee,s.jsx("small",{children:" signal"})]})]}):null,a.showDelay?s.jsxs("div",{className:t.metric,children:[s.jsx("span",{children:"Delay"}),s.jsxs("strong",{children:[Math.round(u.responseDelay),s.jsx("small",{children:" min"})]})]}):null]}),s.jsxs("div",{className:t.causalChain,"aria-label":"Causal chain",children:[s.jsxs("div",{className:n==="food"?t.activeCausalStep:t.causalStep,children:[s.jsx("span",{children:"Food"}),s.jsx("strong",{children:Math.round(w.food)})]}),s.jsxs("div",{className:n==="sense"?t.activeCausalStep:t.causalStep,children:[s.jsx("span",{children:"Old sugar"}),s.jsx("strong",{children:h})]}),s.jsxs("div",{className:n==="insulin"?t.activeCausalStep:t.causalStep,children:[s.jsx("span",{children:"Insulin"}),s.jsx("strong",{children:ee})]}),s.jsxs("div",{className:n==="action"?t.activeCausalStep:t.causalStep,children:[s.jsx("span",{children:"Action"}),s.jsx("strong",{children:y})]})]}),s.jsxs("footer",{className:t.controls,children:[s.jsx("button",{className:t.button,disabled:b===0,onClick:m,type:"button",children:"Back"}),s.jsx("button",{className:t.button,onClick:Y,onMouseEnter:()=>H(r,W.hover),type:"button",children:k?"Resume":"Pause"}),s.jsx("button",{className:t.buttonPrimary,onClick:I,type:"button",children:b===A.length-1?"Complete":"Next"})]})]})]})})}const le={name:"bloodsugar",displayName:"Blood Sugar Delay Lab",version:"1.0.0",paramSchema:{responseDelay:{type:"range",label:"Feedback Lag",description:"Minutes of delay between glucose rising, insulin being secreted, and insulin action arriving.",default:34,min:0,max:80,step:1},mealLoad:{type:"range",label:"Meal Size",default:44,min:20,max:80,step:1},pancreasStrength:{type:"range",label:"Compensation Strength",default:1,min:.45,max:1.6,step:.01},playbackSpeed:{type:"range",label:"Playback Speed",default:1,min:.25,max:3,step:.05},primaryColor:{type:"color",label:"Glucose Color",default:"#6366f1"},accentColor:{type:"color",label:"Insulin Color",default:"#22d3ee"}},defaultParams:{responseDelay:34,mealLoad:44,pancreasStrength:1,playbackSpeed:1,primaryColor:"#6366f1",accentColor:"#22d3ee"}};return typeof window<"u"&&(window.GlitchComponents??={},window.GlitchComponents[le.name]={default:we,metadata:le}),V.default=we,V.metadata=le,Object.defineProperties(V,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}}),V})({},React); +//# sourceMappingURL=bloodsugar.js.map diff --git a/dist/bloodsugar.js.map b/dist/bloodsugar.js.map new file mode 100644 index 0000000..ca0e9a2 --- /dev/null +++ b/dist/bloodsugar.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bloodsugar.js","sources":["../node_modules/react/cjs/react-jsx-runtime.production.js","../node_modules/react/cjs/react-jsx-runtime.development.js","../node_modules/react/jsx-runtime.js","../src/Component.tsx","../src/index.tsx"],"sourcesContent":["/**\n * @license React\n * react-jsx-runtime.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\");\nfunction jsxProd(type, config, maybeKey) {\n var key = null;\n void 0 !== maybeKey && (key = \"\" + maybeKey);\n void 0 !== config.key && (key = \"\" + config.key);\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n config = maybeKey.ref;\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n ref: void 0 !== config ? config : null,\n props: maybeKey\n };\n}\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsxProd;\nexports.jsxs = jsxProd;\n","/**\n * @license React\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\n\"production\" !== process.env.NODE_ENV &&\n (function () {\n function getComponentNameFromType(type) {\n if (null == type) return null;\n if (\"function\" === typeof type)\n return type.$$typeof === REACT_CLIENT_REFERENCE\n ? null\n : type.displayName || type.name || null;\n if (\"string\" === typeof type) return type;\n switch (type) {\n case REACT_FRAGMENT_TYPE:\n return \"Fragment\";\n case REACT_PROFILER_TYPE:\n return \"Profiler\";\n case REACT_STRICT_MODE_TYPE:\n return \"StrictMode\";\n case REACT_SUSPENSE_TYPE:\n return \"Suspense\";\n case REACT_SUSPENSE_LIST_TYPE:\n return \"SuspenseList\";\n case REACT_ACTIVITY_TYPE:\n return \"Activity\";\n }\n if (\"object\" === typeof type)\n switch (\n (\"number\" === typeof type.tag &&\n console.error(\n \"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue.\"\n ),\n type.$$typeof)\n ) {\n case REACT_PORTAL_TYPE:\n return \"Portal\";\n case REACT_CONTEXT_TYPE:\n return type.displayName || \"Context\";\n case REACT_CONSUMER_TYPE:\n return (type._context.displayName || \"Context\") + \".Consumer\";\n case REACT_FORWARD_REF_TYPE:\n var innerType = type.render;\n type = type.displayName;\n type ||\n ((type = innerType.displayName || innerType.name || \"\"),\n (type = \"\" !== type ? \"ForwardRef(\" + type + \")\" : \"ForwardRef\"));\n return type;\n case REACT_MEMO_TYPE:\n return (\n (innerType = type.displayName || null),\n null !== innerType\n ? innerType\n : getComponentNameFromType(type.type) || \"Memo\"\n );\n case REACT_LAZY_TYPE:\n innerType = type._payload;\n type = type._init;\n try {\n return getComponentNameFromType(type(innerType));\n } catch (x) {}\n }\n return null;\n }\n function testStringCoercion(value) {\n return \"\" + value;\n }\n function checkKeyStringCoercion(value) {\n try {\n testStringCoercion(value);\n var JSCompiler_inline_result = !1;\n } catch (e) {\n JSCompiler_inline_result = !0;\n }\n if (JSCompiler_inline_result) {\n JSCompiler_inline_result = console;\n var JSCompiler_temp_const = JSCompiler_inline_result.error;\n var JSCompiler_inline_result$jscomp$0 =\n (\"function\" === typeof Symbol &&\n Symbol.toStringTag &&\n value[Symbol.toStringTag]) ||\n value.constructor.name ||\n \"Object\";\n JSCompiler_temp_const.call(\n JSCompiler_inline_result,\n \"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.\",\n JSCompiler_inline_result$jscomp$0\n );\n return testStringCoercion(value);\n }\n }\n function getTaskName(type) {\n if (type === REACT_FRAGMENT_TYPE) return \"<>\";\n if (\n \"object\" === typeof type &&\n null !== type &&\n type.$$typeof === REACT_LAZY_TYPE\n )\n return \"<...>\";\n try {\n var name = getComponentNameFromType(type);\n return name ? \"<\" + name + \">\" : \"<...>\";\n } catch (x) {\n return \"<...>\";\n }\n }\n function getOwner() {\n var dispatcher = ReactSharedInternals.A;\n return null === dispatcher ? null : dispatcher.getOwner();\n }\n function UnknownOwner() {\n return Error(\"react-stack-top-frame\");\n }\n function hasValidKey(config) {\n if (hasOwnProperty.call(config, \"key\")) {\n var getter = Object.getOwnPropertyDescriptor(config, \"key\").get;\n if (getter && getter.isReactWarning) return !1;\n }\n return void 0 !== config.key;\n }\n function defineKeyPropWarningGetter(props, displayName) {\n function warnAboutAccessingKey() {\n specialPropKeyWarningShown ||\n ((specialPropKeyWarningShown = !0),\n console.error(\n \"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)\",\n displayName\n ));\n }\n warnAboutAccessingKey.isReactWarning = !0;\n Object.defineProperty(props, \"key\", {\n get: warnAboutAccessingKey,\n configurable: !0\n });\n }\n function elementRefGetterWithDeprecationWarning() {\n var componentName = getComponentNameFromType(this.type);\n didWarnAboutElementRef[componentName] ||\n ((didWarnAboutElementRef[componentName] = !0),\n console.error(\n \"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.\"\n ));\n componentName = this.props.ref;\n return void 0 !== componentName ? componentName : null;\n }\n function ReactElement(type, key, props, owner, debugStack, debugTask) {\n var refProp = props.ref;\n type = {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n props: props,\n _owner: owner\n };\n null !== (void 0 !== refProp ? refProp : null)\n ? Object.defineProperty(type, \"ref\", {\n enumerable: !1,\n get: elementRefGetterWithDeprecationWarning\n })\n : Object.defineProperty(type, \"ref\", { enumerable: !1, value: null });\n type._store = {};\n Object.defineProperty(type._store, \"validated\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: 0\n });\n Object.defineProperty(type, \"_debugInfo\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: null\n });\n Object.defineProperty(type, \"_debugStack\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugStack\n });\n Object.defineProperty(type, \"_debugTask\", {\n configurable: !1,\n enumerable: !1,\n writable: !0,\n value: debugTask\n });\n Object.freeze && (Object.freeze(type.props), Object.freeze(type));\n return type;\n }\n function jsxDEVImpl(\n type,\n config,\n maybeKey,\n isStaticChildren,\n debugStack,\n debugTask\n ) {\n var children = config.children;\n if (void 0 !== children)\n if (isStaticChildren)\n if (isArrayImpl(children)) {\n for (\n isStaticChildren = 0;\n isStaticChildren < children.length;\n isStaticChildren++\n )\n validateChildKeys(children[isStaticChildren]);\n Object.freeze && Object.freeze(children);\n } else\n console.error(\n \"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.\"\n );\n else validateChildKeys(children);\n if (hasOwnProperty.call(config, \"key\")) {\n children = getComponentNameFromType(type);\n var keys = Object.keys(config).filter(function (k) {\n return \"key\" !== k;\n });\n isStaticChildren =\n 0 < keys.length\n ? \"{key: someKey, \" + keys.join(\": ..., \") + \": ...}\"\n : \"{key: someKey}\";\n didWarnAboutKeySpread[children + isStaticChildren] ||\n ((keys =\n 0 < keys.length ? \"{\" + keys.join(\": ..., \") + \": ...}\" : \"{}\"),\n console.error(\n 'A props object containing a \"key\" prop is being spread into JSX:\\n let props = %s;\\n <%s {...props} />\\nReact keys must be passed directly to JSX without using spread:\\n let props = %s;\\n <%s key={someKey} {...props} />',\n isStaticChildren,\n children,\n keys,\n children\n ),\n (didWarnAboutKeySpread[children + isStaticChildren] = !0));\n }\n children = null;\n void 0 !== maybeKey &&\n (checkKeyStringCoercion(maybeKey), (children = \"\" + maybeKey));\n hasValidKey(config) &&\n (checkKeyStringCoercion(config.key), (children = \"\" + config.key));\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n children &&\n defineKeyPropWarningGetter(\n maybeKey,\n \"function\" === typeof type\n ? type.displayName || type.name || \"Unknown\"\n : type\n );\n return ReactElement(\n type,\n children,\n maybeKey,\n getOwner(),\n debugStack,\n debugTask\n );\n }\n function validateChildKeys(node) {\n isValidElement(node)\n ? node._store && (node._store.validated = 1)\n : \"object\" === typeof node &&\n null !== node &&\n node.$$typeof === REACT_LAZY_TYPE &&\n (\"fulfilled\" === node._payload.status\n ? isValidElement(node._payload.value) &&\n node._payload.value._store &&\n (node._payload.value._store.validated = 1)\n : node._store && (node._store.validated = 1));\n }\n function isValidElement(object) {\n return (\n \"object\" === typeof object &&\n null !== object &&\n object.$$typeof === REACT_ELEMENT_TYPE\n );\n }\n var React = require(\"react\"),\n REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\"),\n REACT_STRICT_MODE_TYPE = Symbol.for(\"react.strict_mode\"),\n REACT_PROFILER_TYPE = Symbol.for(\"react.profiler\"),\n REACT_CONSUMER_TYPE = Symbol.for(\"react.consumer\"),\n REACT_CONTEXT_TYPE = Symbol.for(\"react.context\"),\n REACT_FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\"),\n REACT_SUSPENSE_TYPE = Symbol.for(\"react.suspense\"),\n REACT_SUSPENSE_LIST_TYPE = Symbol.for(\"react.suspense_list\"),\n REACT_MEMO_TYPE = Symbol.for(\"react.memo\"),\n REACT_LAZY_TYPE = Symbol.for(\"react.lazy\"),\n REACT_ACTIVITY_TYPE = Symbol.for(\"react.activity\"),\n REACT_CLIENT_REFERENCE = Symbol.for(\"react.client.reference\"),\n ReactSharedInternals =\n React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n hasOwnProperty = Object.prototype.hasOwnProperty,\n isArrayImpl = Array.isArray,\n createTask = console.createTask\n ? console.createTask\n : function () {\n return null;\n };\n React = {\n react_stack_bottom_frame: function (callStackForError) {\n return callStackForError();\n }\n };\n var specialPropKeyWarningShown;\n var didWarnAboutElementRef = {};\n var unknownOwnerDebugStack = React.react_stack_bottom_frame.bind(\n React,\n UnknownOwner\n )();\n var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));\n var didWarnAboutKeySpread = {};\n exports.Fragment = REACT_FRAGMENT_TYPE;\n exports.jsx = function (type, config, maybeKey) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !1,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n exports.jsxs = function (type, config, maybeKey) {\n var trackActualOwner =\n 1e4 > ReactSharedInternals.recentlyCreatedOwnerStacks++;\n return jsxDEVImpl(\n type,\n config,\n maybeKey,\n !0,\n trackActualOwner\n ? Error(\"react-stack-top-frame\")\n : unknownOwnerDebugStack,\n trackActualOwner ? createTask(getTaskName(type)) : unknownOwnerDebugTask\n );\n };\n })();\n","'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","import { useEffect, useMemo, useState, type CSSProperties } from 'react'\nimport styles from './styles.module.css'\nimport type { GlitchComponentProps, GlitchHostBridge } from './types'\n\ninterface BloodSugarParams {\n responseDelay?: number\n mealLoad?: number\n pancreasStrength?: number\n playbackSpeed?: number\n primaryColor?: string\n accentColor?: string\n}\n\ninterface Sample {\n t: number\n glucose: number\n insulin: number\n response: number\n food: number\n sensedGlucose: number\n uptake: number\n}\n\ntype LessonStageId =\n | 'baseline'\n | 'meal-start'\n | 'glucose-peak'\n | 'insulin-rise'\n | 'glucose-fall'\n | 'insulin-fall'\n | 'return-baseline'\n | 'loop-summary'\n | 'lag-setup'\n | 'lag-high'\n | 'lag-insulin'\n | 'late-action'\n | 'crash'\n | 'recovery'\n | 'whiplash-summary'\n | 'snack-setup'\n | 'snack-bump'\n | 'snack-insulin'\n | 'calorie-cost'\n | 'snack-summary'\n\ninterface LessonStage {\n id: LessonStageId\n eyebrow: string\n title: string\n copy: string\n chartLabel: string\n showFood: boolean\n showInsulin: boolean\n showResponse: boolean\n showDelay: boolean\n destabilized: boolean\n showSnack?: boolean\n snacking?: boolean\n startMinute: number\n stopMinute: number\n}\n\nconst SOUND_IDS = {\n click: 'ui.button_click',\n hover: 'ui.button_hover'\n}\n\nconst SAMPLE_COUNT = 520\nconst CYCLE_MINUTES = 700\nconst MEAL_START_MINUTE = 54\nconst MEAL_END_MINUTE = 84\nconst FOOD_ABSORPTION_PEAK_MINUTE = 102\nconst SNACK_START_MINUTE = 348\nconst SNACK_END_MINUTE = 368\nconst SNACK_ABSORPTION_PEAK_MINUTE = 388\nconst LOW_GLUCOSE = 72\nconst TARGET_GLUCOSE = 96\nconst HIGH_GLUCOSE = 145\n\nconst LESSON_STAGES: LessonStage[] = [\n {\n id: 'baseline',\n eyebrow: 'Stage 1',\n title: 'Blood sugar is a control loop.',\n copy: 'No meal, no drama. The system stays near its set point.',\n chartLabel: 'Blood sugar only',\n showFood: false,\n showInsulin: false,\n showResponse: false,\n showDelay: false,\n destabilized: false,\n startMinute: 0,\n stopMinute: 44\n },\n {\n id: 'meal-start',\n eyebrow: 'Stage 2',\n title: 'Food pushes glucose up.',\n copy: 'The meal starts first. Blood sugar keeps rising while food is absorbed.',\n chartLabel: 'Meal starts before the peak',\n showFood: true,\n showInsulin: false,\n showResponse: false,\n showDelay: false,\n destabilized: false,\n startMinute: 0,\n stopMinute: 92\n },\n {\n id: 'glucose-peak',\n eyebrow: 'Stage 3',\n title: 'Sugar rises first.',\n copy: 'Insulin is not the cause of this peak. It is the answer to it.',\n chartLabel: 'Glucose rises first',\n showFood: true,\n showInsulin: false,\n showResponse: false,\n showDelay: false,\n destabilized: false,\n startMinute: 92,\n stopMinute: 126\n },\n {\n id: 'insulin-rise',\n eyebrow: 'Stage 4',\n title: 'Insulin answers the rise.',\n copy: 'The pancreas responds to glucose that was already high.',\n chartLabel: 'Glucose causes insulin',\n showFood: true,\n showInsulin: true,\n showResponse: false,\n showDelay: false,\n destabilized: false,\n startMinute: 126,\n stopMinute: 156\n },\n {\n id: 'glucose-fall',\n eyebrow: 'Stage 5',\n title: 'Then action lands in tissue.',\n copy: 'Insulin action pulls glucose out of blood. The curve bends down.',\n chartLabel: 'Insulin causes glucose uptake',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: false,\n destabilized: false,\n startMinute: 156,\n stopMinute: 206\n },\n {\n id: 'insulin-fall',\n eyebrow: 'Stage 6',\n title: 'Lower sugar quiets insulin.',\n copy: 'When glucose falls, the signal fades. The loop starts settling.',\n chartLabel: 'Lower glucose lowers insulin',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: false,\n destabilized: false,\n startMinute: 206,\n stopMinute: 252\n },\n {\n id: 'return-baseline',\n eyebrow: 'Stage 7',\n title: 'Good timing stabilizes.',\n copy: 'The response arrives while it is still useful, so the loop returns to baseline.',\n chartLabel: 'Back toward equilibrium',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: false,\n destabilized: false,\n startMinute: 252,\n stopMinute: 320\n },\n {\n id: 'loop-summary',\n eyebrow: 'Stage 8',\n title: 'The loop is simple.',\n copy: 'Glucose calls. Insulin answers. Tissue acts. Timing decides whether this stabilizes.',\n chartLabel: 'A stabilizing feedback loop',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: false,\n destabilized: false,\n startMinute: 0,\n stopMinute: 320\n },\n {\n id: 'lag-setup',\n eyebrow: 'Stage 9',\n title: 'Now add only delay.',\n copy: 'Same meal. Same loop. The answer just arrives late.',\n chartLabel: 'Same loop, more lag',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: true,\n destabilized: true,\n startMinute: 0,\n stopMinute: 92\n },\n {\n id: 'lag-high',\n eyebrow: 'Stage 10',\n title: 'This is the “resistance” moment.',\n copy: 'It looks like glucose is not being handled. But in this model, the response is late.',\n chartLabel: 'Lag lets glucose run high',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: true,\n destabilized: true,\n startMinute: 92,\n stopMinute: 132\n },\n {\n id: 'lag-insulin',\n eyebrow: 'Stage 11',\n title: 'The answer points backward.',\n copy: 'Insulin is reacting to old glucose information. The system is chasing the past.',\n chartLabel: 'The answer arrives late',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: true,\n destabilized: true,\n startMinute: 132,\n stopMinute: 186\n },\n {\n id: 'late-action',\n eyebrow: 'Stage 12',\n title: 'Late correction finally hits.',\n copy: 'Now uptake is strong, but the original glucose problem has already moved on.',\n chartLabel: 'Correction after the moment passed',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: true,\n destabilized: true,\n startMinute: 186,\n stopMinute: 236\n },\n {\n id: 'crash',\n eyebrow: 'Stage 13',\n title: 'Late becomes too much.',\n copy: 'A correction that would have helped earlier now overshoots. That is the crash.',\n chartLabel: 'The crash',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: true,\n destabilized: true,\n startMinute: 236,\n stopMinute: 306\n },\n {\n id: 'recovery',\n eyebrow: 'Stage 14',\n title: 'The loop remembers.',\n copy: 'Insulin action fades slowly. The body is still carrying the late response.',\n chartLabel: 'Memory in the loop',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: true,\n destabilized: true,\n startMinute: 306,\n stopMinute: 440\n },\n {\n id: 'whiplash-summary',\n eyebrow: 'Stage 15',\n title: 'Timing made the whiplash.',\n copy: 'High, then low, from the same loop. The problem is not just level. It is delay.',\n chartLabel: 'Recovery without snacking',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: true,\n destabilized: true,\n startMinute: 440,\n stopMinute: 650\n },\n {\n id: 'snack-setup',\n eyebrow: 'Stage 16',\n title: 'The crash recruits behavior.',\n copy: 'The low feels urgent. Snacking becomes the easiest way to push glucose back up.',\n chartLabel: 'Snack added during the low',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: true,\n destabilized: true,\n showSnack: true,\n snacking: true,\n startMinute: 306,\n stopMinute: 368\n },\n {\n id: 'snack-bump',\n eyebrow: 'Stage 17',\n title: 'The snack works short term.',\n copy: 'Glucose rises. The feeling improves. But the loop has not learned timing.',\n chartLabel: 'Short-term relief',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: true,\n destabilized: true,\n showSnack: true,\n snacking: true,\n startMinute: 368,\n stopMinute: 414\n },\n {\n id: 'snack-insulin',\n eyebrow: 'Stage 18',\n title: 'Now the loop is triggered again.',\n copy: 'The snack is another glucose input, so the delayed response starts chasing again.',\n chartLabel: 'Another response is triggered',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: true,\n destabilized: true,\n showSnack: true,\n snacking: true,\n startMinute: 414,\n stopMinute: 464\n },\n {\n id: 'calorie-cost',\n eyebrow: 'Stage 19',\n title: 'Relief has a calorie cost.',\n copy: 'The snack solves the low by adding energy. Repeat that pattern and intake rises.',\n chartLabel: 'Relief has a calorie cost',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: true,\n destabilized: true,\n showSnack: true,\n snacking: true,\n startMinute: 464,\n stopMinute: 560\n },\n {\n id: 'snack-summary',\n eyebrow: 'Stage 20',\n title: 'Aha: the villain is delay.',\n copy: 'What gets called resistance can be seen here as timing failure: late response, overshoot, crash, snack.',\n chartLabel: 'Whiplash plus snacking',\n showFood: true,\n showInsulin: true,\n showResponse: true,\n showDelay: true,\n destabilized: true,\n showSnack: true,\n snacking: true,\n startMinute: 0,\n stopMinute: 650\n }\n]\n\nfunction safePlaySound(host: GlitchHostBridge | undefined, id: string, payload?: Record) {\n try {\n host?.playSound?.(id, payload)\n } catch {\n // Host sound should never break standalone learning.\n }\n}\n\nfunction clamp(value: number, min: number, max: number) {\n return Math.min(max, Math.max(min, value))\n}\n\nfunction readNumber(value: unknown, fallback: number) {\n return typeof value === 'number' && Number.isFinite(value) ? value : fallback\n}\n\ninterface MechanisticParams {\n mealLoad: number\n sensorDelay: number\n actionDelay: number\n betaGain: number\n insulinClearance: number\n insulinEffect: number\n}\n\ninterface FoodEvent {\n center: number\n load: number\n width?: number\n}\n\nfunction mealAbsorption(minute: number, events: FoodEvent[]) {\n return events.reduce((total, event) => {\n const width = event.width ?? 24\n const distance = minute - event.center\n return total + event.load * Math.exp(-(distance * distance) / (2 * width * width))\n }, 0)\n}\n\nfunction simulate(params: MechanisticParams, events: FoodEvent[]) {\n const samples: Sample[] = []\n let glucose = TARGET_GLUCOSE\n let insulin = 12\n let insulinAction = 0\n const dt = CYCLE_MINUTES / SAMPLE_COUNT\n const delaySamples = Math.max(1, Math.round(params.sensorDelay / dt))\n const glucoseHistory: number[] = Array(delaySamples + 2).fill(TARGET_GLUCOSE)\n\n for (let index = 0; index < SAMPLE_COUNT; index += 1) {\n const minute = index * dt\n const delayedGlucose = glucoseHistory[0] ?? TARGET_GLUCOSE\n const secretionTarget = 12 + Math.max(0, delayedGlucose - TARGET_GLUCOSE) * params.betaGain\n const food = mealAbsorption(minute, events)\n const intake = food * 0.032\n\n insulin += (secretionTarget - insulin) * (dt / params.insulinClearance)\n insulin = clamp(insulin, 2, 140)\n\n const actionTarget = Math.max(0, insulin - 12)\n insulinAction += (actionTarget - insulinAction) * (dt / params.actionDelay)\n insulinAction = clamp(insulinAction, 0, 130)\n\n const insulinDrivenUptake = insulinAction * params.insulinEffect * (glucose / TARGET_GLUCOSE) * 0.018\n const homeostaticReturn = (TARGET_GLUCOSE - glucose) * 0.012\n glucose += intake + homeostaticReturn - insulinDrivenUptake\n glucose = clamp(glucose, 50, 205)\n\n samples.push({ t: minute, glucose, insulin, response: insulinAction, food, sensedGlucose: delayedGlucose, uptake: insulinDrivenUptake })\n glucoseHistory.push(glucose)\n glucoseHistory.shift()\n }\n\n return samples\n}\n\nfunction baselineSamples() {\n return Array.from({ length: SAMPLE_COUNT }, (_, index) => {\n const t = (index / (SAMPLE_COUNT - 1)) * CYCLE_MINUTES\n return {\n t,\n glucose: TARGET_GLUCOSE,\n insulin: 12,\n response: 0,\n food: 0,\n sensedGlucose: TARGET_GLUCOSE,\n uptake: 0\n }\n })\n}\n\nfunction pointsFor(\n samples: Sample[],\n key: keyof Pick,\n min: number,\n max: number,\n endIndex: number\n) {\n return samples\n .slice(0, endIndex + 1)\n .map((sample, index) => {\n const x = (index / (SAMPLE_COUNT - 1)) * 100\n const y = 100 - ((sample[key] - min) / (max - min)) * 100\n return `${x.toFixed(2)},${clamp(y, 4, 96).toFixed(2)}`\n })\n .join(' ')\n}\n\nfunction xyFor(sample: Sample, index: number, min: number, max: number, key: keyof Pick) {\n const x = (index / (SAMPLE_COUNT - 1)) * 100\n const y = 100 - ((sample[key] - min) / (max - min)) * 100\n return { x, y: clamp(y, 4, 96) }\n}\n\nfunction indexFromMinute(minute: number) {\n return clamp(Math.round((minute / CYCLE_MINUTES) * (SAMPLE_COUNT - 1)), 0, SAMPLE_COUNT - 1)\n}\n\nfunction getMood(glucose: number) {\n if (glucose >= HIGH_GLUCOSE) {\n return {\n emoji: '🥴',\n label: 'High zone',\n copy: 'Sugar is lingering above the healthy range while insulin is still catching up.'\n }\n }\n\n if (glucose <= LOW_GLUCOSE) {\n return {\n emoji: '😠',\n label: 'Low zone',\n copy: 'The delayed response overcorrected. Energy dips, mood gets sharp.'\n }\n }\n\n return {\n emoji: '🙂',\n label: 'Target zone',\n copy: 'The system is near equilibrium, with fuel and response mostly in sync.'\n }\n}\n\nfunction getActiveStep(sample: Sample, stage: LessonStage) {\n if (!stage.showFood) return 'baseline'\n if (sample.food > 10) return 'food'\n if (stage.showInsulin && sample.sensedGlucose > TARGET_GLUCOSE + 4 && sample.insulin < 24) return 'sense'\n if (stage.showInsulin && sample.insulin > 24 && (!stage.showResponse || sample.response < 12)) return 'insulin'\n if (stage.showResponse && sample.response > 12) return 'action'\n return 'baseline'\n}\n\nexport default function GlitchComponent({\n config,\n onComplete,\n onProgress,\n theme,\n className,\n host\n}: GlitchComponentProps) {\n const rawParams = (config.params ?? {}) as BloodSugarParams\n const params = {\n responseDelay: readNumber(rawParams.responseDelay, 34),\n mealLoad: readNumber(rawParams.mealLoad, 44),\n pancreasStrength: readNumber(rawParams.pancreasStrength, 1),\n playbackSpeed: readNumber(rawParams.playbackSpeed, 1),\n primaryColor: rawParams.primaryColor ?? theme?.primary ?? '#6366f1',\n accentColor: rawParams.accentColor ?? theme?.accent ?? '#22d3ee'\n }\n\n const [cursor, setCursor] = useState(0)\n const [paused, setPaused] = useState(false)\n const [lessonIndex, setLessonIndex] = useState(0)\n const stage = LESSON_STAGES[lessonIndex]\n\n const samples = useMemo(() => {\n if (stage.id === 'baseline') return baselineSamples()\n\n const snackEvents: FoodEvent[] = stage.snacking\n ? [{ center: SNACK_ABSORPTION_PEAK_MINUTE, load: params.mealLoad * 0.7, width: 20 }]\n : []\n\n if (stage.destabilized) {\n return simulate(\n {\n mealLoad: params.mealLoad * 1.23,\n sensorDelay: params.responseDelay + 4,\n actionDelay: params.responseDelay * 1.5 + 15,\n betaGain: params.pancreasStrength * 1.55,\n insulinClearance: 32,\n insulinEffect: 1.18\n },\n [{ center: FOOD_ABSORPTION_PEAK_MINUTE, load: params.mealLoad * 1.23, width: 24 }, ...snackEvents]\n )\n }\n\n return simulate(\n {\n mealLoad: 30,\n sensorDelay: 7,\n actionDelay: 18,\n betaGain: 0.82,\n insulinClearance: 22,\n insulinEffect: 1.08\n },\n [{ center: FOOD_ABSORPTION_PEAK_MINUTE, load: 30, width: 24 }]\n )\n }, [params.responseDelay, params.mealLoad, params.pancreasStrength, stage.destabilized, stage.id, stage.snacking])\n\n const startIndex = indexFromMinute(stage.startMinute)\n const stopIndex = indexFromMinute(stage.stopMinute)\n const sample = samples[cursor] ?? samples[0]\n const mood = getMood(sample.glucose)\n const isHangry = sample.glucose <= LOW_GLUCOSE\n const moodWord = isHangry ? 'Hangry' : 'Happy'\n const glucoseNow = Math.round(sample.glucose)\n const insulinNow = Math.round(sample.insulin)\n const lagScore = clamp(Math.round((params.responseDelay / 80) * 100), 0, 100)\n const instabilityScore = clamp(\n Math.round((Math.max(...samples.map((entry) => entry.glucose)) - Math.min(...samples.map((entry) => entry.glucose))) * 0.9),\n 0,\n 100\n )\n const currentGlucose = xyFor(sample, cursor, 50, 200, 'glucose')\n const currentInsulin = xyFor(sample, cursor, 0, 125, 'insulin')\n const currentResponse = xyFor(sample, cursor, 0, 125, 'response')\n const mealStartX = (MEAL_START_MINUTE / CYCLE_MINUTES) * 100\n const mealEndX = (MEAL_END_MINUTE / CYCLE_MINUTES) * 100\n const snackStartX = (SNACK_START_MINUTE / CYCLE_MINUTES) * 100\n const snackEndX = (SNACK_END_MINUTE / CYCLE_MINUTES) * 100\n const hasReachedFood = currentGlucose.x >= mealStartX\n const hasReachedSnack = currentGlucose.x >= snackStartX\n const delayOffset = (params.responseDelay / CYCLE_MINUTES) * 100\n const delayedResponseX = clamp(currentGlucose.x - delayOffset, 0, 100)\n const delayMidpointX = (delayedResponseX + currentGlucose.x) / 2\n const activeStep = getActiveStep(sample, stage)\n const sensedNow = Math.round(sample.sensedGlucose)\n const uptakeNow = sample.uptake.toFixed(1)\n\n useEffect(() => {\n if (paused) return\n\n const interval = window.setInterval(() => {\n setCursor((value) => (value >= stopIndex ? value : value + 1))\n }, 42 / params.playbackSpeed)\n\n return () => window.clearInterval(interval)\n }, [params.playbackSpeed, paused, stopIndex])\n\n useEffect(() => {\n const stageSpan = Math.max(1, stopIndex - startIndex)\n const stageProgress = (lessonIndex + clamp((cursor - startIndex) / stageSpan, 0, 1)) / LESSON_STAGES.length\n onProgress?.(Math.min(95, Math.round(stageProgress * 95)))\n }, [cursor, lessonIndex, onProgress, startIndex, stopIndex])\n\n useEffect(() => {\n setCursor(startIndex)\n setPaused(false)\n }, [lessonIndex, startIndex])\n\n const componentTheme = {\n '--component-bg': theme?.bg,\n '--component-bg-secondary': theme?.bgSecondary,\n '--component-text': theme?.text,\n '--component-text-muted': theme?.textMuted,\n '--component-primary': params.primaryColor,\n '--component-accent': params.accentColor,\n '--component-border': theme?.border\n } as CSSProperties\n\n function togglePaused() {\n safePlaySound(host, SOUND_IDS.click, { target: 'pause', paused: !paused })\n setPaused((value) => !value)\n }\n\n function previousStage() {\n safePlaySound(host, SOUND_IDS.click, { target: 'previous-stage', lessonIndex })\n setLessonIndex((value) => Math.max(0, value - 1))\n }\n\n function nextStage() {\n safePlaySound(host, SOUND_IDS.click, { target: 'next-stage', lessonIndex })\n if (lessonIndex >= LESSON_STAGES.length - 1) {\n completeLesson()\n return\n }\n\n setLessonIndex((value) => Math.min(LESSON_STAGES.length - 1, value + 1))\n }\n\n function completeLesson() {\n safePlaySound(host, SOUND_IDS.click, { target: 'complete' })\n onProgress?.(100)\n onComplete({\n success: true,\n score: Math.max(1, 100 - Math.round((lagScore + instabilityScore) / 4)),\n data: {\n completedAt: new Date().toISOString(),\n responseDelay: params.responseDelay,\n instabilityScore,\n lesson: 'Delay can turn a stabilizing feedback loop into an oscillating hysteresis loop.'\n }\n })\n }\n\n return (\n
\n
\n
\n
\n {stage.showFood && !hasReachedFood ? '🍽️' : mood.emoji}\n
\n
\n {moodWord}\n
\n
\n

{stage.eyebrow}

\n {stage.chartLabel}\n
\n
\n unhealthy high\n target\n cranky low\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n {[20, 40, 60, 80].map((line) => (\n \n ))}\n \n {stage.showFood ? (\n <>\n \n \n \n 🍽️\n \n {stage.showSnack ? (\n <>\n \n \n \n 🍬\n \n \n ) : null}\n \n ) : null}\n \n {stage.showInsulin ? : null}\n {stage.showResponse ? : null}\n \n {stage.showDelay ? (\n \n \n \n late response\n \n \n ) : null}\n \n {stage.showInsulin ? : null}\n {stage.showResponse ? : null}\n \n
\n Blood sugar\n {stage.showFood ? Food event : null}\n {stage.showSnack ? Snack : null}\n {stage.showInsulin ? Insulin level : null}\n {stage.showResponse ? Insulin action in tissue : null}\n
\n
\n\n
\n
\n

{stage.eyebrow} of {LESSON_STAGES.length}

\n

{stage.title}

\n
\n\n
\n \n {stage.showFood && !hasReachedFood ? 'Food is coming' : mood.label}\n {stage.copy}\n \n
\n\n
\n
\n Blood sugar\n {glucoseNow} mg/dL\n
\n {stage.showFood ? (\n
\n {stage.showSnack ? 'Snack' : 'Food event'}\n {stage.showSnack ? (hasReachedSnack ? 'added' : 'craving') : hasReachedFood ? 'absorbing' : 'up next'}\n
\n ) : (\n
\n Baseline\n {TARGET_GLUCOSE} mg/dL\n
\n )}\n {stage.showInsulin ? (\n
\n Insulin\n {insulinNow} signal\n
\n ) : null}\n {stage.showDelay ? (\n
\n Delay\n {Math.round(params.responseDelay)} min\n
\n ) : null}\n
\n\n
\n
\n Food\n {Math.round(sample.food)}\n
\n
\n Old sugar\n {sensedNow}\n
\n
\n Insulin\n {insulinNow}\n
\n
\n Action\n {uptakeNow}\n
\n
\n\n
\n \n \n \n
\n
\n
\n
\n )\n}\n","import Component from './Component'\nimport type { GlitchComponentMetadata } from './types'\n\nexport default Component\n\nexport const metadata: GlitchComponentMetadata = {\n\n name: 'bloodsugar',\n displayName: 'Blood Sugar Delay Lab',\n version: '1.0.0',\n paramSchema: {\n responseDelay: {\n type: 'range',\n label: 'Feedback Lag',\n description: 'Minutes of delay between glucose rising, insulin being secreted, and insulin action arriving.',\n default: 34,\n min: 0,\n max: 80,\n step: 1\n },\n mealLoad: {\n type: 'range',\n label: 'Meal Size',\n default: 44,\n min: 20,\n max: 80,\n step: 1\n },\n pancreasStrength: {\n type: 'range',\n label: 'Compensation Strength',\n default: 1,\n min: 0.45,\n max: 1.6,\n step: 0.01\n },\n playbackSpeed: {\n type: 'range',\n label: 'Playback Speed',\n default: 1,\n min: 0.25,\n max: 3,\n step: 0.05\n },\n primaryColor: {\n type: 'color',\n label: 'Glucose Color',\n default: '#6366f1'\n },\n accentColor: {\n type: 'color',\n label: 'Insulin Color',\n default: '#22d3ee'\n }\n },\n defaultParams: {\n responseDelay: 34,\n mealLoad: 44,\n pancreasStrength: 1,\n playbackSpeed: 1,\n primaryColor: '#6366f1',\n accentColor: '#22d3ee'\n }\n}\n\nexport type {\n GlitchComponentProps,\n GlitchComponentConfig,\n GlitchComponentResult,\n GlitchTheme,\n GlitchHostBridge\n} from './types'\n\n// CDN self-registration: when loaded as an IIFE script from the CDN, this registers\n// the component in window.GlitchComponents so the host loader can retrieve it by id.\nif (typeof window !== 'undefined') {\n type GCRegistry = Record\n ;(window as unknown as { GlitchComponents: GCRegistry }).GlitchComponents ??= {}\n ;(window as unknown as { GlitchComponents: GCRegistry }).GlitchComponents[metadata.name] = { default: Component, metadata }\n}\n"],"names":["REACT_ELEMENT_TYPE","REACT_FRAGMENT_TYPE","jsxProd","type","config","maybeKey","key","propName","reactJsxRuntime_production","getComponentNameFromType","REACT_CLIENT_REFERENCE","REACT_PROFILER_TYPE","REACT_STRICT_MODE_TYPE","REACT_SUSPENSE_TYPE","REACT_SUSPENSE_LIST_TYPE","REACT_ACTIVITY_TYPE","REACT_PORTAL_TYPE","REACT_CONTEXT_TYPE","REACT_CONSUMER_TYPE","REACT_FORWARD_REF_TYPE","innerType","REACT_MEMO_TYPE","REACT_LAZY_TYPE","testStringCoercion","value","checkKeyStringCoercion","JSCompiler_inline_result","JSCompiler_temp_const","JSCompiler_inline_result$jscomp$0","getTaskName","name","getOwner","dispatcher","ReactSharedInternals","UnknownOwner","hasValidKey","hasOwnProperty","getter","defineKeyPropWarningGetter","props","displayName","warnAboutAccessingKey","specialPropKeyWarningShown","elementRefGetterWithDeprecationWarning","componentName","didWarnAboutElementRef","ReactElement","owner","debugStack","debugTask","refProp","jsxDEVImpl","isStaticChildren","children","isArrayImpl","validateChildKeys","keys","k","didWarnAboutKeySpread","node","isValidElement","object","React","require$$0","createTask","callStackForError","unknownOwnerDebugStack","unknownOwnerDebugTask","reactJsxRuntime_development","trackActualOwner","jsxRuntimeModule","require$$1","SOUND_IDS","SAMPLE_COUNT","CYCLE_MINUTES","MEAL_START_MINUTE","MEAL_END_MINUTE","FOOD_ABSORPTION_PEAK_MINUTE","SNACK_START_MINUTE","SNACK_END_MINUTE","SNACK_ABSORPTION_PEAK_MINUTE","LOW_GLUCOSE","TARGET_GLUCOSE","HIGH_GLUCOSE","LESSON_STAGES","safePlaySound","host","id","payload","clamp","min","max","readNumber","fallback","mealAbsorption","minute","events","total","event","width","distance","simulate","params","samples","glucose","insulin","insulinAction","dt","delaySamples","glucoseHistory","index","delayedGlucose","secretionTarget","food","intake","actionTarget","insulinDrivenUptake","homeostaticReturn","baselineSamples","_","pointsFor","endIndex","sample","x","y","xyFor","indexFromMinute","getMood","getActiveStep","stage","GlitchComponent","onComplete","onProgress","theme","className","rawParams","cursor","setCursor","useState","paused","setPaused","lessonIndex","setLessonIndex","useMemo","snackEvents","startIndex","stopIndex","mood","isHangry","moodWord","glucoseNow","insulinNow","lagScore","instabilityScore","entry","currentGlucose","currentInsulin","currentResponse","mealStartX","mealEndX","snackStartX","snackEndX","hasReachedFood","hasReachedSnack","delayOffset","delayedResponseX","delayMidpointX","activeStep","sensedNow","uptakeNow","useEffect","interval","stageSpan","stageProgress","componentTheme","togglePaused","previousStage","nextStage","completeLesson","jsx","styles","jsxs","line","Fragment","metadata","Component"],"mappings":"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","x_google_ignoreList":[0,1,2]} \ No newline at end of file diff --git a/glitch.manifest.json b/glitch.manifest.json new file mode 100644 index 0000000..4fc107d --- /dev/null +++ b/glitch.manifest.json @@ -0,0 +1,15 @@ +{ + "componentId": "bloodsugar", + "displayName": "Blood Sugar Delay Lab", + "version": "1.0.0", + "folderName": "glitch_bloodsugar", + "packageName": "@glitch-components/bloodsugar", + "entry": "dist/bloodsugar.js", + "source": "src/index.tsx", + "tags": [ + "glitch-component", + "biology", + "systems", + "feedback" + ] +} diff --git a/glitchcomponent.md b/glitchcomponent.md new file mode 100644 index 0000000..6c3da02 --- /dev/null +++ b/glitchcomponent.md @@ -0,0 +1,14 @@ +# Create GlitchComponent + +The canonical Glitch University component workflow now lives at the workspace root: + +- `/Users/jenstandstad/Projects/glitch-components/GLITCH_COMPONENT_STANDARD.md` +- `/Users/jenstandstad/Projects/glitch-components/templates/react-vite-glitch-component/` +- `/Users/jenstandstad/Projects/glitch-components/scripts/new-glitch-component.mjs` + +Use the root scaffold instead of copying this folder or reusing older component boilerplate. + +For special features suchas 3D, Sound bridge etc consider the referenes in + +/Users/jenstandstad/Projects/glitch-components/skills/references + diff --git a/index.html b/index.html new file mode 100644 index 0000000..d22a55d --- /dev/null +++ b/index.html @@ -0,0 +1,12 @@ + + + + + + Blood Sugar Delay Lab + + +
+ + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..60b3c96 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2919 @@ +{ + "name": "@glitch-components/bloodsugar", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@glitch-components/bloodsugar", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@types/react": "^19.2.0", + "@types/react-dom": "^19.2.0", + "@vitejs/plugin-react": "^5.1.1", + "leva": "^0.10.1", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "typescript": "^5.9.3", + "vite": "^7.2.4", + "vite-plugin-css-injected-by-js": "^3.5.2" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz", + "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", + "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz", + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.6" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", + "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", + "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.10.tgz", + "integrity": "sha512-4kY9IVa6+9nJPsYmngK5Uk2kUmZnv7ChhHAFeQ5oaj8jrR1bIi3xww8nH71pz1/Ve4d/cXO3YxT8eikt1B0a8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.4", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", + "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz", + "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz", + "integrity": "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.4.tgz", + "integrity": "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.4.tgz", + "integrity": "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.4.tgz", + "integrity": "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.4.tgz", + "integrity": "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.4.tgz", + "integrity": "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.4.tgz", + "integrity": "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.4.tgz", + "integrity": "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.4.tgz", + "integrity": "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.4.tgz", + "integrity": "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.4.tgz", + "integrity": "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.4.tgz", + "integrity": "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.4.tgz", + "integrity": "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.4.tgz", + "integrity": "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.4.tgz", + "integrity": "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.4.tgz", + "integrity": "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.4.tgz", + "integrity": "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.4.tgz", + "integrity": "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.4.tgz", + "integrity": "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.4.tgz", + "integrity": "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.4.tgz", + "integrity": "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.4.tgz", + "integrity": "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.4.tgz", + "integrity": "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.4.tgz", + "integrity": "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.4.tgz", + "integrity": "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@stitches/react": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@stitches/react/-/react-1.2.8.tgz", + "integrity": "sha512-9g9dWI4gsSVe8bNLlb+lMkBYsnIKCZTmvqvDG+Avnn69XfmHZKiaMrx7cgTaddq7aTPPmXiTsbFcUy0xgI4+wA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "react": ">= 16.3.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.15", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.15.tgz", + "integrity": "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@use-gesture/core": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.3.1.tgz", + "integrity": "sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@use-gesture/react": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@use-gesture/react/-/react-10.3.1.tgz", + "integrity": "sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@use-gesture/core": "10.3.1" + }, + "peerDependencies": { + "react": ">= 16.8.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.2.0.tgz", + "integrity": "sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/attr-accept": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz", + "integrity": "sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.31", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.31.tgz", + "integrity": "sha512-MujYO3eP72uvmSE0i4wltsodRfIpZATP3jvzRNRGGxgzId7aVocVJJV3nf01qnzzKFGxQVC9bpWxl5cjxTr/7Q==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001793", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz", + "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.360", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.360.tgz", + "integrity": "sha512-GkcBt6YYAw9SxFWn+xVar4cLVGlXVuswwtRLBozi2zp0GjXs4ZnOrqV4zbXzg35n7w81hCkyJNYicgXlVHAmBA==", + "dev": true, + "license": "ISC" + }, + "node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend-shallow/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-selector": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-0.5.0.tgz", + "integrity": "sha512-s8KNnmIDTBoD0p9uJ9uD0XY38SCeBOtj0UMXyQSLg1Ypfrfj8+dAvwsLjYQkQ2GjhVtp2HrnF5cJzMhBjfD8HA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/leva": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/leva/-/leva-0.10.1.tgz", + "integrity": "sha512-BcjnfUX8jpmwZUz2L7AfBtF9vn4ggTH33hmeufDULbP3YgNZ/C+ss/oO3stbrqRQyaOmRwy70y7BGTGO81S3rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@radix-ui/react-portal": "^1.1.4", + "@radix-ui/react-tooltip": "^1.1.8", + "@stitches/react": "^1.2.8", + "@use-gesture/react": "^10.2.5", + "colord": "^2.9.2", + "dequal": "^2.0.2", + "merge-value": "^1.0.0", + "react-colorful": "^5.5.1", + "react-dropzone": "^12.0.0", + "v8n": "^1.3.3", + "zustand": "^3.6.9" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/merge-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/merge-value/-/merge-value-1.0.0.tgz", + "integrity": "sha512-fJMmvat4NeKz63Uv9iHWcPDjCWcCkoiRoajRTEO8hlhUC6rwaHg0QCF9hBOTjZmm4JuglPckPSTtcuJL5kp0TQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-value": "^2.0.6", + "is-extendable": "^1.0.0", + "mixin-deep": "^1.2.0", + "set-value": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.44", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz", + "integrity": "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/react": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.6.tgz", + "integrity": "sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-colorful": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.7.0.tgz", + "integrity": "sha512-fuesYIemttah97XmsIHmz4OORDHiSFzyc9HMAIrCHJou2jaRQmL8cFJ76K4zQhhj8jzwOBlOi4BaGTjjOZCfTg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.6", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.6.tgz", + "integrity": "sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.6" + } + }, + "node_modules/react-dropzone": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-12.1.0.tgz", + "integrity": "sha512-iBYHA1rbopIvtzokEX4QubO6qk5IF/x3BtKGu74rF2JkQDXnwC4uO/lHKpaw4PJIV6iIAYOlwLv2FpiGyqHNog==", + "dev": true, + "license": "MIT", + "dependencies": { + "attr-accept": "^2.2.2", + "file-selector": "^0.5.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">= 10.13" + }, + "peerDependencies": { + "react": ">= 16.8" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.4.tgz", + "integrity": "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.4", + "@rollup/rollup-android-arm64": "4.60.4", + "@rollup/rollup-darwin-arm64": "4.60.4", + "@rollup/rollup-darwin-x64": "4.60.4", + "@rollup/rollup-freebsd-arm64": "4.60.4", + "@rollup/rollup-freebsd-x64": "4.60.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.4", + "@rollup/rollup-linux-arm-musleabihf": "4.60.4", + "@rollup/rollup-linux-arm64-gnu": "4.60.4", + "@rollup/rollup-linux-arm64-musl": "4.60.4", + "@rollup/rollup-linux-loong64-gnu": "4.60.4", + "@rollup/rollup-linux-loong64-musl": "4.60.4", + "@rollup/rollup-linux-ppc64-gnu": "4.60.4", + "@rollup/rollup-linux-ppc64-musl": "4.60.4", + "@rollup/rollup-linux-riscv64-gnu": "4.60.4", + "@rollup/rollup-linux-riscv64-musl": "4.60.4", + "@rollup/rollup-linux-s390x-gnu": "4.60.4", + "@rollup/rollup-linux-x64-gnu": "4.60.4", + "@rollup/rollup-linux-x64-musl": "4.60.4", + "@rollup/rollup-openbsd-x64": "4.60.4", + "@rollup/rollup-openharmony-arm64": "4.60.4", + "@rollup/rollup-win32-arm64-msvc": "4.60.4", + "@rollup/rollup-win32-ia32-msvc": "4.60.4", + "@rollup/rollup-win32-x64-gnu": "4.60.4", + "@rollup/rollup-win32-x64-msvc": "4.60.4", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/set-value/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/v8n": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/v8n/-/v8n-1.5.1.tgz", + "integrity": "sha512-LdabyT4OffkyXFCe9UT+uMkxNBs5rcTVuZClvxQr08D5TUgo1OFKkoT65qYRCsiKBl/usHjpXvP4hHMzzDRj3A==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.3.tgz", + "integrity": "sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-plugin-css-injected-by-js": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/vite-plugin-css-injected-by-js/-/vite-plugin-css-injected-by-js-3.5.2.tgz", + "integrity": "sha512-2MpU/Y+SCZyWUB6ua3HbJCrgnF0KACAsmzOQt1UvRVJCGF6S8xdA3ZUhWcWdM9ivG4I5az8PnQmwwrkC2CAQrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "vite": ">2.0.0-0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/zustand": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz", + "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..4632282 --- /dev/null +++ b/package.json @@ -0,0 +1,49 @@ +{ + "name": "@glitch-components/bloodsugar", + "version": "1.0.0", + "description": "Blood Sugar Delay Lab glitch component for Glitch University", + "type": "module", + "main": "./dist/bloodsugar.js", + "module": "./dist/bloodsugar.js", + "types": "./src/types.ts", + "exports": { + ".": { + "import": "./dist/bloodsugar.js", + "types": "./src/types.ts" + } + }, + "files": [ + "dist", + "src/types.ts", + "glitch.manifest.json" + ], + "scripts": { + "dev": "vite", + "build": "tsc --noEmit && vite build", + "preview": "vite preview", + "typecheck": "tsc --noEmit" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "devDependencies": { + "@types/react": "^19.2.0", + "@types/react-dom": "^19.2.0", + "@vitejs/plugin-react": "^5.1.1", + "leva": "^0.10.1", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "typescript": "^5.9.3", + "vite": "^7.2.4", + "vite-plugin-css-injected-by-js": "^3.5.2" + }, + "keywords": [ + "glitch", + "mini-game", + "react", + "component" + ], + "author": "Glitch.university", + "license": "MIT" +} diff --git a/sound-bridge.md b/sound-bridge.md new file mode 100644 index 0000000..0a43443 --- /dev/null +++ b/sound-bridge.md @@ -0,0 +1,34 @@ +# Sound Bridge Notes + +Glitch University uses a host-managed sound system (Howler-based) with string sound keys, for example: + +- `playSound('ui.button_click')` +- `playSound('ui.button_hover')` + +## Recommendation + +Treat sound as an optional host integration: + +- Use a small wrapper function in the component (`safePlaySound`) that checks whether a host sound function exists. +- No-op when unavailable (standalone dev should still run). +- Keep sound identifiers as strings/constants so they match host definitions. + +## Example Pattern + +```ts +type PlaySound = (id: string) => void; + +export function safePlaySound(playSound: PlaySound | undefined, id: string) { + try { + playSound?.(id); + } catch { + // Ignore host sound errors in standalone/local mode + } +} +``` + +## Unknowns to Confirm Later + +- How the host exposes `playSound` to glitch-components (prop, context, global import, event bus) +- Which sound keys are safe/standardized across experiences +- Whether completion/reward sounds are triggered by host or component diff --git a/src/Component.tsx b/src/Component.tsx new file mode 100644 index 0000000..d662e42 --- /dev/null +++ b/src/Component.tsx @@ -0,0 +1,842 @@ +import { useEffect, useMemo, useState, type CSSProperties } from 'react' +import styles from './styles.module.css' +import type { GlitchComponentProps, GlitchHostBridge } from './types' + +interface BloodSugarParams { + responseDelay?: number + mealLoad?: number + pancreasStrength?: number + playbackSpeed?: number + primaryColor?: string + accentColor?: string +} + +interface Sample { + t: number + glucose: number + insulin: number + response: number + food: number + sensedGlucose: number + uptake: number +} + +type LessonStageId = + | 'baseline' + | 'meal-start' + | 'glucose-peak' + | 'insulin-rise' + | 'glucose-fall' + | 'insulin-fall' + | 'return-baseline' + | 'loop-summary' + | 'lag-setup' + | 'lag-high' + | 'lag-insulin' + | 'late-action' + | 'crash' + | 'recovery' + | 'whiplash-summary' + | 'snack-setup' + | 'snack-bump' + | 'snack-insulin' + | 'calorie-cost' + | 'snack-summary' + +interface LessonStage { + id: LessonStageId + eyebrow: string + title: string + copy: string + chartLabel: string + showFood: boolean + showInsulin: boolean + showResponse: boolean + showDelay: boolean + destabilized: boolean + showSnack?: boolean + snacking?: boolean + startMinute: number + stopMinute: number +} + +const SOUND_IDS = { + click: 'ui.button_click', + hover: 'ui.button_hover' +} + +const SAMPLE_COUNT = 520 +const CYCLE_MINUTES = 700 +const MEAL_START_MINUTE = 54 +const MEAL_END_MINUTE = 84 +const FOOD_ABSORPTION_PEAK_MINUTE = 102 +const SNACK_START_MINUTE = 348 +const SNACK_END_MINUTE = 368 +const SNACK_ABSORPTION_PEAK_MINUTE = 388 +const LOW_GLUCOSE = 72 +const TARGET_GLUCOSE = 96 +const HIGH_GLUCOSE = 145 + +const LESSON_STAGES: LessonStage[] = [ + { + id: 'baseline', + eyebrow: 'Stage 1', + title: 'Blood sugar is a control loop.', + copy: 'No meal, no drama. The system stays near its set point.', + chartLabel: 'Blood sugar only', + showFood: false, + showInsulin: false, + showResponse: false, + showDelay: false, + destabilized: false, + startMinute: 0, + stopMinute: 44 + }, + { + id: 'meal-start', + eyebrow: 'Stage 2', + title: 'Food pushes glucose up.', + copy: 'The meal starts first. Blood sugar keeps rising while food is absorbed.', + chartLabel: 'Meal starts before the peak', + showFood: true, + showInsulin: false, + showResponse: false, + showDelay: false, + destabilized: false, + startMinute: 0, + stopMinute: 92 + }, + { + id: 'glucose-peak', + eyebrow: 'Stage 3', + title: 'Sugar rises first.', + copy: 'Insulin is not the cause of this peak. It is the answer to it.', + chartLabel: 'Glucose rises first', + showFood: true, + showInsulin: false, + showResponse: false, + showDelay: false, + destabilized: false, + startMinute: 92, + stopMinute: 126 + }, + { + id: 'insulin-rise', + eyebrow: 'Stage 4', + title: 'Insulin answers the rise.', + copy: 'The pancreas responds to glucose that was already high.', + chartLabel: 'Glucose causes insulin', + showFood: true, + showInsulin: true, + showResponse: false, + showDelay: false, + destabilized: false, + startMinute: 126, + stopMinute: 156 + }, + { + id: 'glucose-fall', + eyebrow: 'Stage 5', + title: 'Then action lands in tissue.', + copy: 'Insulin action pulls glucose out of blood. The curve bends down.', + chartLabel: 'Insulin causes glucose uptake', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: false, + destabilized: false, + startMinute: 156, + stopMinute: 206 + }, + { + id: 'insulin-fall', + eyebrow: 'Stage 6', + title: 'Lower sugar quiets insulin.', + copy: 'When glucose falls, the signal fades. The loop starts settling.', + chartLabel: 'Lower glucose lowers insulin', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: false, + destabilized: false, + startMinute: 206, + stopMinute: 252 + }, + { + id: 'return-baseline', + eyebrow: 'Stage 7', + title: 'Good timing stabilizes.', + copy: 'The response arrives while it is still useful, so the loop returns to baseline.', + chartLabel: 'Back toward equilibrium', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: false, + destabilized: false, + startMinute: 252, + stopMinute: 320 + }, + { + id: 'loop-summary', + eyebrow: 'Stage 8', + title: 'The loop is simple.', + copy: 'Glucose calls. Insulin answers. Tissue acts. Timing decides whether this stabilizes.', + chartLabel: 'A stabilizing feedback loop', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: false, + destabilized: false, + startMinute: 0, + stopMinute: 320 + }, + { + id: 'lag-setup', + eyebrow: 'Stage 9', + title: 'Now add only delay.', + copy: 'Same meal. Same loop. The answer just arrives late.', + chartLabel: 'Same loop, more lag', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: true, + destabilized: true, + startMinute: 0, + stopMinute: 92 + }, + { + id: 'lag-high', + eyebrow: 'Stage 10', + title: 'This is the “resistance” moment.', + copy: 'It looks like glucose is not being handled. But in this model, the response is late.', + chartLabel: 'Lag lets glucose run high', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: true, + destabilized: true, + startMinute: 92, + stopMinute: 132 + }, + { + id: 'lag-insulin', + eyebrow: 'Stage 11', + title: 'The answer points backward.', + copy: 'Insulin is reacting to old glucose information. The system is chasing the past.', + chartLabel: 'The answer arrives late', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: true, + destabilized: true, + startMinute: 132, + stopMinute: 186 + }, + { + id: 'late-action', + eyebrow: 'Stage 12', + title: 'Late correction finally hits.', + copy: 'Now uptake is strong, but the original glucose problem has already moved on.', + chartLabel: 'Correction after the moment passed', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: true, + destabilized: true, + startMinute: 186, + stopMinute: 236 + }, + { + id: 'crash', + eyebrow: 'Stage 13', + title: 'Late becomes too much.', + copy: 'A correction that would have helped earlier now overshoots. That is the crash.', + chartLabel: 'The crash', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: true, + destabilized: true, + startMinute: 236, + stopMinute: 306 + }, + { + id: 'recovery', + eyebrow: 'Stage 14', + title: 'The loop remembers.', + copy: 'Insulin action fades slowly. The body is still carrying the late response.', + chartLabel: 'Memory in the loop', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: true, + destabilized: true, + startMinute: 306, + stopMinute: 440 + }, + { + id: 'whiplash-summary', + eyebrow: 'Stage 15', + title: 'Timing made the whiplash.', + copy: 'High, then low, from the same loop. The problem is not just level. It is delay.', + chartLabel: 'Recovery without snacking', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: true, + destabilized: true, + startMinute: 440, + stopMinute: 650 + }, + { + id: 'snack-setup', + eyebrow: 'Stage 16', + title: 'The crash recruits behavior.', + copy: 'The low feels urgent. Snacking becomes the easiest way to push glucose back up.', + chartLabel: 'Snack added during the low', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: true, + destabilized: true, + showSnack: true, + snacking: true, + startMinute: 306, + stopMinute: 368 + }, + { + id: 'snack-bump', + eyebrow: 'Stage 17', + title: 'The snack works short term.', + copy: 'Glucose rises. The feeling improves. But the loop has not learned timing.', + chartLabel: 'Short-term relief', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: true, + destabilized: true, + showSnack: true, + snacking: true, + startMinute: 368, + stopMinute: 414 + }, + { + id: 'snack-insulin', + eyebrow: 'Stage 18', + title: 'Now the loop is triggered again.', + copy: 'The snack is another glucose input, so the delayed response starts chasing again.', + chartLabel: 'Another response is triggered', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: true, + destabilized: true, + showSnack: true, + snacking: true, + startMinute: 414, + stopMinute: 464 + }, + { + id: 'calorie-cost', + eyebrow: 'Stage 19', + title: 'Relief has a calorie cost.', + copy: 'The snack solves the low by adding energy. Repeat that pattern and intake rises.', + chartLabel: 'Relief has a calorie cost', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: true, + destabilized: true, + showSnack: true, + snacking: true, + startMinute: 464, + stopMinute: 560 + }, + { + id: 'snack-summary', + eyebrow: 'Stage 20', + title: 'Aha: the villain is delay.', + copy: 'What gets called resistance can be seen here as timing failure: late response, overshoot, crash, snack.', + chartLabel: 'Whiplash plus snacking', + showFood: true, + showInsulin: true, + showResponse: true, + showDelay: true, + destabilized: true, + showSnack: true, + snacking: true, + startMinute: 0, + stopMinute: 650 + } +] + +function safePlaySound(host: GlitchHostBridge | undefined, id: string, payload?: Record) { + try { + host?.playSound?.(id, payload) + } catch { + // Host sound should never break standalone learning. + } +} + +function clamp(value: number, min: number, max: number) { + return Math.min(max, Math.max(min, value)) +} + +function readNumber(value: unknown, fallback: number) { + return typeof value === 'number' && Number.isFinite(value) ? value : fallback +} + +interface MechanisticParams { + mealLoad: number + sensorDelay: number + actionDelay: number + betaGain: number + insulinClearance: number + insulinEffect: number +} + +interface FoodEvent { + center: number + load: number + width?: number +} + +function mealAbsorption(minute: number, events: FoodEvent[]) { + return events.reduce((total, event) => { + const width = event.width ?? 24 + const distance = minute - event.center + return total + event.load * Math.exp(-(distance * distance) / (2 * width * width)) + }, 0) +} + +function simulate(params: MechanisticParams, events: FoodEvent[]) { + const samples: Sample[] = [] + let glucose = TARGET_GLUCOSE + let insulin = 12 + let insulinAction = 0 + const dt = CYCLE_MINUTES / SAMPLE_COUNT + const delaySamples = Math.max(1, Math.round(params.sensorDelay / dt)) + const glucoseHistory: number[] = Array(delaySamples + 2).fill(TARGET_GLUCOSE) + + for (let index = 0; index < SAMPLE_COUNT; index += 1) { + const minute = index * dt + const delayedGlucose = glucoseHistory[0] ?? TARGET_GLUCOSE + const secretionTarget = 12 + Math.max(0, delayedGlucose - TARGET_GLUCOSE) * params.betaGain + const food = mealAbsorption(minute, events) + const intake = food * 0.032 + + insulin += (secretionTarget - insulin) * (dt / params.insulinClearance) + insulin = clamp(insulin, 2, 140) + + const actionTarget = Math.max(0, insulin - 12) + insulinAction += (actionTarget - insulinAction) * (dt / params.actionDelay) + insulinAction = clamp(insulinAction, 0, 130) + + const insulinDrivenUptake = insulinAction * params.insulinEffect * (glucose / TARGET_GLUCOSE) * 0.018 + const homeostaticReturn = (TARGET_GLUCOSE - glucose) * 0.012 + glucose += intake + homeostaticReturn - insulinDrivenUptake + glucose = clamp(glucose, 50, 205) + + samples.push({ t: minute, glucose, insulin, response: insulinAction, food, sensedGlucose: delayedGlucose, uptake: insulinDrivenUptake }) + glucoseHistory.push(glucose) + glucoseHistory.shift() + } + + return samples +} + +function baselineSamples() { + return Array.from({ length: SAMPLE_COUNT }, (_, index) => { + const t = (index / (SAMPLE_COUNT - 1)) * CYCLE_MINUTES + return { + t, + glucose: TARGET_GLUCOSE, + insulin: 12, + response: 0, + food: 0, + sensedGlucose: TARGET_GLUCOSE, + uptake: 0 + } + }) +} + +function pointsFor( + samples: Sample[], + key: keyof Pick, + min: number, + max: number, + endIndex: number +) { + return samples + .slice(0, endIndex + 1) + .map((sample, index) => { + const x = (index / (SAMPLE_COUNT - 1)) * 100 + const y = 100 - ((sample[key] - min) / (max - min)) * 100 + return `${x.toFixed(2)},${clamp(y, 4, 96).toFixed(2)}` + }) + .join(' ') +} + +function xyFor(sample: Sample, index: number, min: number, max: number, key: keyof Pick) { + const x = (index / (SAMPLE_COUNT - 1)) * 100 + const y = 100 - ((sample[key] - min) / (max - min)) * 100 + return { x, y: clamp(y, 4, 96) } +} + +function indexFromMinute(minute: number) { + return clamp(Math.round((minute / CYCLE_MINUTES) * (SAMPLE_COUNT - 1)), 0, SAMPLE_COUNT - 1) +} + +function getMood(glucose: number) { + if (glucose >= HIGH_GLUCOSE) { + return { + emoji: '🥴', + label: 'High zone', + copy: 'Sugar is lingering above the healthy range while insulin is still catching up.' + } + } + + if (glucose <= LOW_GLUCOSE) { + return { + emoji: '😠', + label: 'Low zone', + copy: 'The delayed response overcorrected. Energy dips, mood gets sharp.' + } + } + + return { + emoji: '🙂', + label: 'Target zone', + copy: 'The system is near equilibrium, with fuel and response mostly in sync.' + } +} + +function getActiveStep(sample: Sample, stage: LessonStage) { + if (!stage.showFood) return 'baseline' + if (sample.food > 10) return 'food' + if (stage.showInsulin && sample.sensedGlucose > TARGET_GLUCOSE + 4 && sample.insulin < 24) return 'sense' + if (stage.showInsulin && sample.insulin > 24 && (!stage.showResponse || sample.response < 12)) return 'insulin' + if (stage.showResponse && sample.response > 12) return 'action' + return 'baseline' +} + +export default function GlitchComponent({ + config, + onComplete, + onProgress, + theme, + className, + host +}: GlitchComponentProps) { + const rawParams = (config.params ?? {}) as BloodSugarParams + const params = { + responseDelay: readNumber(rawParams.responseDelay, 34), + mealLoad: readNumber(rawParams.mealLoad, 44), + pancreasStrength: readNumber(rawParams.pancreasStrength, 1), + playbackSpeed: readNumber(rawParams.playbackSpeed, 1), + primaryColor: rawParams.primaryColor ?? theme?.primary ?? '#6366f1', + accentColor: rawParams.accentColor ?? theme?.accent ?? '#22d3ee' + } + + const [cursor, setCursor] = useState(0) + const [paused, setPaused] = useState(false) + const [lessonIndex, setLessonIndex] = useState(0) + const stage = LESSON_STAGES[lessonIndex] + + const samples = useMemo(() => { + if (stage.id === 'baseline') return baselineSamples() + + const snackEvents: FoodEvent[] = stage.snacking + ? [{ center: SNACK_ABSORPTION_PEAK_MINUTE, load: params.mealLoad * 0.7, width: 20 }] + : [] + + if (stage.destabilized) { + return simulate( + { + mealLoad: params.mealLoad * 1.23, + sensorDelay: params.responseDelay + 4, + actionDelay: params.responseDelay * 1.5 + 15, + betaGain: params.pancreasStrength * 1.55, + insulinClearance: 32, + insulinEffect: 1.18 + }, + [{ center: FOOD_ABSORPTION_PEAK_MINUTE, load: params.mealLoad * 1.23, width: 24 }, ...snackEvents] + ) + } + + return simulate( + { + mealLoad: 30, + sensorDelay: 7, + actionDelay: 18, + betaGain: 0.82, + insulinClearance: 22, + insulinEffect: 1.08 + }, + [{ center: FOOD_ABSORPTION_PEAK_MINUTE, load: 30, width: 24 }] + ) + }, [params.responseDelay, params.mealLoad, params.pancreasStrength, stage.destabilized, stage.id, stage.snacking]) + + const startIndex = indexFromMinute(stage.startMinute) + const stopIndex = indexFromMinute(stage.stopMinute) + const sample = samples[cursor] ?? samples[0] + const mood = getMood(sample.glucose) + const isHangry = sample.glucose <= LOW_GLUCOSE + const moodWord = isHangry ? 'Hangry' : 'Happy' + const glucoseNow = Math.round(sample.glucose) + const insulinNow = Math.round(sample.insulin) + const lagScore = clamp(Math.round((params.responseDelay / 80) * 100), 0, 100) + const instabilityScore = clamp( + Math.round((Math.max(...samples.map((entry) => entry.glucose)) - Math.min(...samples.map((entry) => entry.glucose))) * 0.9), + 0, + 100 + ) + const currentGlucose = xyFor(sample, cursor, 50, 200, 'glucose') + const currentInsulin = xyFor(sample, cursor, 0, 125, 'insulin') + const currentResponse = xyFor(sample, cursor, 0, 125, 'response') + const mealStartX = (MEAL_START_MINUTE / CYCLE_MINUTES) * 100 + const mealEndX = (MEAL_END_MINUTE / CYCLE_MINUTES) * 100 + const snackStartX = (SNACK_START_MINUTE / CYCLE_MINUTES) * 100 + const snackEndX = (SNACK_END_MINUTE / CYCLE_MINUTES) * 100 + const hasReachedFood = currentGlucose.x >= mealStartX + const hasReachedSnack = currentGlucose.x >= snackStartX + const delayOffset = (params.responseDelay / CYCLE_MINUTES) * 100 + const delayedResponseX = clamp(currentGlucose.x - delayOffset, 0, 100) + const delayMidpointX = (delayedResponseX + currentGlucose.x) / 2 + const activeStep = getActiveStep(sample, stage) + const sensedNow = Math.round(sample.sensedGlucose) + const uptakeNow = sample.uptake.toFixed(1) + + useEffect(() => { + if (paused) return + + const interval = window.setInterval(() => { + setCursor((value) => (value >= stopIndex ? value : value + 1)) + }, 42 / params.playbackSpeed) + + return () => window.clearInterval(interval) + }, [params.playbackSpeed, paused, stopIndex]) + + useEffect(() => { + const stageSpan = Math.max(1, stopIndex - startIndex) + const stageProgress = (lessonIndex + clamp((cursor - startIndex) / stageSpan, 0, 1)) / LESSON_STAGES.length + onProgress?.(Math.min(95, Math.round(stageProgress * 95))) + }, [cursor, lessonIndex, onProgress, startIndex, stopIndex]) + + useEffect(() => { + setCursor(startIndex) + setPaused(false) + }, [lessonIndex, startIndex]) + + const componentTheme = { + '--component-bg': theme?.bg, + '--component-bg-secondary': theme?.bgSecondary, + '--component-text': theme?.text, + '--component-text-muted': theme?.textMuted, + '--component-primary': params.primaryColor, + '--component-accent': params.accentColor, + '--component-border': theme?.border + } as CSSProperties + + function togglePaused() { + safePlaySound(host, SOUND_IDS.click, { target: 'pause', paused: !paused }) + setPaused((value) => !value) + } + + function previousStage() { + safePlaySound(host, SOUND_IDS.click, { target: 'previous-stage', lessonIndex }) + setLessonIndex((value) => Math.max(0, value - 1)) + } + + function nextStage() { + safePlaySound(host, SOUND_IDS.click, { target: 'next-stage', lessonIndex }) + if (lessonIndex >= LESSON_STAGES.length - 1) { + completeLesson() + return + } + + setLessonIndex((value) => Math.min(LESSON_STAGES.length - 1, value + 1)) + } + + function completeLesson() { + safePlaySound(host, SOUND_IDS.click, { target: 'complete' }) + onProgress?.(100) + onComplete({ + success: true, + score: Math.max(1, 100 - Math.round((lagScore + instabilityScore) / 4)), + data: { + completedAt: new Date().toISOString(), + responseDelay: params.responseDelay, + instabilityScore, + lesson: 'Delay can turn a stabilizing feedback loop into an oscillating hysteresis loop.' + } + }) + } + + return ( +
+
+
+ +
+ {moodWord} +
+
+

{stage.eyebrow}

+ {stage.chartLabel} +
+ + + + + + + + + + + + + + + + + + {[20, 40, 60, 80].map((line) => ( + + ))} + + {stage.showFood ? ( + <> + + + + 🍽️ + + {stage.showSnack ? ( + <> + + + + 🍬 + + + ) : null} + + ) : null} + + {stage.showInsulin ? : null} + {stage.showResponse ? : null} + + {stage.showDelay ? ( + + + + late response + + + ) : null} + + {stage.showInsulin ? : null} + {stage.showResponse ? : null} + +
+ Blood sugar + {stage.showFood ? Food event : null} + {stage.showSnack ? Snack : null} + {stage.showInsulin ? Insulin level : null} + {stage.showResponse ? Insulin action in tissue : null} +
+
+ +
+
+

{stage.eyebrow} of {LESSON_STAGES.length}

+

{stage.title}

+
+ +
+ + {stage.showFood && !hasReachedFood ? 'Food is coming' : mood.label} + {stage.copy} + +
+ +
+
+ Blood sugar + {glucoseNow} mg/dL +
+ {stage.showFood ? ( +
+ {stage.showSnack ? 'Snack' : 'Food event'} + {stage.showSnack ? (hasReachedSnack ? 'added' : 'craving') : hasReachedFood ? 'absorbing' : 'up next'} +
+ ) : ( +
+ Baseline + {TARGET_GLUCOSE} mg/dL +
+ )} + {stage.showInsulin ? ( +
+ Insulin + {insulinNow} signal +
+ ) : null} + {stage.showDelay ? ( +
+ Delay + {Math.round(params.responseDelay)} min +
+ ) : null} +
+ +
+
+ Food + {Math.round(sample.food)} +
+
+ Old sugar + {sensedNow} +
+
+ Insulin + {insulinNow} +
+
+ Action + {uptakeNow} +
+
+ +
+ + + +
+
+
+
+ ) +} diff --git a/src/dev-theme.css b/src/dev-theme.css new file mode 100644 index 0000000..e81590c --- /dev/null +++ b/src/dev-theme.css @@ -0,0 +1,53 @@ +@import url("https://fonts.googleapis.com/css2?family=Iceland&family=JetBrains+Mono:wght@400;600&family=Russo+One&display=swap"); + +:root { + --color-bg: #0a0a0f; + --color-bg-secondary: #12121a; + --color-text: #e8e8ec; + --color-text-muted: #9999a8; + --color-primary: #6366f1; + --color-primary-hover: #818cf8; + --color-accent: #22d3ee; + --color-accent-secondary: #a855f7; + --color-border: #2a2a3a; + --font-main: "Iceland", -apple-system, BlinkMacSystemFont, sans-serif; + --font-display: "Russo One", -apple-system, BlinkMacSystemFont, sans-serif; + --font-mono: "JetBrains Mono", "Iceland", monospace; + --small-font: 1.875rem; + --spacing-xs: 0.5rem; + --spacing-sm: 1rem; + --spacing-md: 2rem; + --spacing-lg: 4rem; + --spacing-xl: 6rem; + --max-width: 1200px; + --border-radius: 12px; + --border-radius-sm: 8px; + --transition: 0.2s ease; +} + +html, +body, +#root { + width: 100%; + min-height: 100%; +} + +body { + margin: 0; + background: + radial-gradient(circle at top, rgb(99 102 241 / 18%), transparent 36%), + linear-gradient(180deg, #080810, #0d1018); + color: var(--color-text); + font-family: var(--font-main); +} + +.dev-shell { + min-height: 100vh; + padding: 1rem; +} + +@media (max-width: 980px) { + .dev-shell { + padding: 1rem; + } +} diff --git a/src/dev.tsx b/src/dev.tsx new file mode 100644 index 0000000..96519af --- /dev/null +++ b/src/dev.tsx @@ -0,0 +1,74 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import { Leva, useControls } from 'leva' +import Component from './Component' +import './dev-theme.css' +import { metadata } from './index' + +function buildLevaSchema() { + return Object.entries(metadata.paramSchema).reduce((acc, [key, schema]) => { + if (schema.type === 'range' || schema.type === 'number') { + acc[key] = { + value: schema.default as number, + min: schema.min, + max: schema.max, + step: schema.step + } + return acc + } + + if (schema.type === 'select') { + acc[key] = { + value: schema.default, + options: + schema.options?.reduce>((map, option) => { + map[option.label] = option.value + return map + }, {}) ?? {} + } + return acc + } + + acc[key] = schema.default + return acc + }, {} as Record) +} + +function DevHarness() { + const params = useControls('Simulation', buildLevaSchema() as Parameters[1]) as Record + + return ( +
+
+ ) +} + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + +) diff --git a/src/index.tsx b/src/index.tsx new file mode 100644 index 0000000..a8794e2 --- /dev/null +++ b/src/index.tsx @@ -0,0 +1,80 @@ +import Component from './Component' +import type { GlitchComponentMetadata } from './types' + +export default Component + +export const metadata: GlitchComponentMetadata = { + + name: 'bloodsugar', + displayName: 'Blood Sugar Delay Lab', + version: '1.0.0', + paramSchema: { + responseDelay: { + type: 'range', + label: 'Feedback Lag', + description: 'Minutes of delay between glucose rising, insulin being secreted, and insulin action arriving.', + default: 34, + min: 0, + max: 80, + step: 1 + }, + mealLoad: { + type: 'range', + label: 'Meal Size', + default: 44, + min: 20, + max: 80, + step: 1 + }, + pancreasStrength: { + type: 'range', + label: 'Compensation Strength', + default: 1, + min: 0.45, + max: 1.6, + step: 0.01 + }, + playbackSpeed: { + type: 'range', + label: 'Playback Speed', + default: 1, + min: 0.25, + max: 3, + step: 0.05 + }, + primaryColor: { + type: 'color', + label: 'Glucose Color', + default: '#6366f1' + }, + accentColor: { + type: 'color', + label: 'Insulin Color', + default: '#22d3ee' + } + }, + defaultParams: { + responseDelay: 34, + mealLoad: 44, + pancreasStrength: 1, + playbackSpeed: 1, + primaryColor: '#6366f1', + accentColor: '#22d3ee' + } +} + +export type { + GlitchComponentProps, + GlitchComponentConfig, + GlitchComponentResult, + GlitchTheme, + GlitchHostBridge +} from './types' + +// CDN self-registration: when loaded as an IIFE script from the CDN, this registers +// the component in window.GlitchComponents so the host loader can retrieve it by id. +if (typeof window !== 'undefined') { + type GCRegistry = Record + ;(window as unknown as { GlitchComponents: GCRegistry }).GlitchComponents ??= {} + ;(window as unknown as { GlitchComponents: GCRegistry }).GlitchComponents[metadata.name] = { default: Component, metadata } +} diff --git a/src/styles.module.css b/src/styles.module.css new file mode 100644 index 0000000..fc03935 --- /dev/null +++ b/src/styles.module.css @@ -0,0 +1,878 @@ +.root { + --component-bg: var(--color-bg, #0a0a0f); + --component-bg-secondary: var(--color-bg-secondary, #12121a); + --component-text: var(--color-text, #e8e8ec); + --component-text-muted: var(--color-text-muted, #9999a8); + --component-primary: var(--color-primary, #6366f1); + --component-accent: var(--color-accent, #22d3ee); + --component-border: var(--color-border, #2a2a3a); + box-sizing: border-box !important; + width: min(100%, 1500px); + margin: 0 auto; + color: var(--component-text); + font-family: var(--font-main, system-ui, sans-serif); + line-height: 1.5; +} + +.root, +.root *, +.root *::before, +.root *::after { + box-sizing: border-box !important; +} + +.board { + display: grid; + grid-template-columns: 10.4fr 5.6fr; + grid-template-rows: 1fr; + gap: 0; + width: 100%; + aspect-ratio: 16 / 9; + min-height: 0; +} + +.chartPanel, +.controlPanel { + min-width: 0; + min-height: 0; + border: 1px solid var(--component-border); + border-radius: var(--border-radius, 12px); + overflow: hidden; + background: + linear-gradient(135deg, color-mix(in srgb, var(--component-primary) 12%, transparent), transparent 35%), + linear-gradient(180deg, var(--component-bg-secondary), var(--component-bg)); +} + +.chartPanel { + position: relative; + width: 100%; + height: 100%; + padding: 1rem 1rem 0.95rem 4.15rem; + background: + linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px), + linear-gradient(180deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px), + color-mix(in srgb, var(--component-bg) 76%, black); + background-size: 10% 100%, 100% 20%, auto; +} + +.controlPanel { + width: 100%; + height: 100%; + display: grid; + grid-template-rows: auto minmax(0, 1.35fr) auto auto auto; + gap: 0.72rem; + padding: 1.05rem; +} + +.chartHeader, +.controlHeader { + min-width: 0; +} + +.chartHeader { + position: absolute; + top: 1rem; + right: 1rem; + left: 4.15rem; + z-index: 1; + display: flex; + justify-content: space-between; + gap: 1rem; + pointer-events: none; +} + +.chartHeader strong { + color: var(--component-text-muted); + font-family: var(--font-mono, monospace); + font-size: 0.86rem; + font-weight: 500; + text-transform: uppercase; +} + +.happyChartBadge, +.hangryChartBadge { + position: absolute; + top: 50%; + left: 50%; + z-index: 2; + border-radius: var(--border-radius-sm, 8px); + padding: 0.35rem 1rem; + font-family: var(--font-display, var(--font-main, system-ui, sans-serif)); + font-size: 6.4rem; + font-style: italic; + letter-spacing: 0; + line-height: 1; + pointer-events: none; + text-align: center; + text-transform: uppercase; + text-shadow: 0 0 28px rgba(34, 211, 238, 0.28); + transform: translate(-50%, -50%); + white-space: nowrap; +} + +.chartEmoji, +.hangryChartEmoji { + position: absolute; + top: 3.15rem; + right: 1.35rem; + z-index: 3; + display: grid; + place-items: center; + width: 10.4rem; + height: 10.4rem; + border-radius: 999px; + background: color-mix(in srgb, var(--component-primary) 20%, rgba(10, 10, 15, 0.84)); + box-shadow: + 0 0 0 1px color-mix(in srgb, var(--component-primary) 42%, transparent), + 0 0 24px color-mix(in srgb, var(--component-primary) 24%, transparent); + font-size: 6.1rem; + line-height: 1; + pointer-events: none; +} + +.hangryChartEmoji { + animation: + hangryShake 0.24s linear infinite, + hangryBreath 1.1s ease-in-out infinite; + background: + radial-gradient(circle, rgba(248, 113, 113, 0.62), rgba(248, 113, 113, 0.18) 56%, rgba(10, 10, 15, 0.86) 72%); + box-shadow: + 0 0 0 0 rgba(248, 113, 113, 0.42), + 0 0 22px rgba(248, 113, 113, 0.46); +} + +.happyChartBadge { + color: color-mix(in srgb, var(--component-accent) 74%, white); + opacity: 0.46; +} + +.hangryChartBadge { + animation: + hangryBadgeShake 0.26s linear infinite, + hangryPulse 1.35s ease-in-out infinite; + background: rgba(248, 113, 113, 0.14); + box-shadow: + 0 0 0 1px rgba(248, 113, 113, 0.38), + 0 0 22px rgba(248, 113, 113, 0.42); + color: #fecaca; + text-shadow: + 0 0 18px rgba(248, 113, 113, 0.7), + 0 0 42px rgba(248, 113, 113, 0.42); +} + +.eyebrow { + margin: 0 0 0.45rem; + color: var(--component-accent); + font-family: var(--font-mono, monospace); + font-size: 0.92rem; + letter-spacing: 0; + text-transform: uppercase; +} + +.title { + margin: 0; + color: var(--component-text); + font-family: var(--font-display, var(--font-main, system-ui, sans-serif)); + font-size: 1.9rem; + font-weight: 700; + line-height: 1.16; +} + +.mood, +.hangryMood { + display: flex; + flex-direction: column; + justify-content: center; + gap: 0.85rem; + min-height: 0; + padding: 1.15rem; + border: 1px solid color-mix(in srgb, var(--component-border) 84%, white); + border-radius: var(--border-radius-sm, 8px); + background: color-mix(in srgb, var(--component-bg-secondary) 82%, black); + text-align: center; +} + +.hangryMood { + animation: hangryPanelPulse 1.4s ease-in-out infinite; + border-color: rgba(248, 113, 113, 0.64); + background: + radial-gradient(circle at 50% 32%, rgba(248, 113, 113, 0.34), transparent 38%), + color-mix(in srgb, var(--component-bg-secondary) 78%, black); +} + +.emoji, +.hangryEmoji { + display: grid; + place-items: center; + width: 5.4rem; + height: 5.4rem; + margin: 0 auto; + border-radius: 999px; + background: color-mix(in srgb, var(--component-primary) 18%, transparent); + font-size: 3.15rem; +} + +.hangryEmoji { + animation: + hangryShake 0.24s linear infinite, + hangryBreath 1.1s ease-in-out infinite; + background: + radial-gradient(circle, rgba(248, 113, 113, 0.62), rgba(248, 113, 113, 0.16) 56%, transparent 72%); + box-shadow: + 0 0 0 0 rgba(248, 113, 113, 0.42), + 0 0 22px rgba(248, 113, 113, 0.46); +} + +.mood strong, +.mood small, +.hangryMood strong, +.hangryMood small { + display: block; +} + +.mood small, +.hangryMood small { + max-width: 32rem; + margin: 0.48rem auto 0; + color: var(--component-text-muted); + font-size: 1.28rem; + line-height: 1.38; +} + +.mood strong, +.hangryMood strong { + font-family: var(--font-display, var(--font-main, system-ui, sans-serif)); + font-size: 1.8rem; + line-height: 1.05; +} + +.hangryMood strong { + color: #fecaca; +} + +.zoneLabels { + position: absolute; + top: 4.2rem; + bottom: 3.2rem; + left: 0.9rem; + display: flex; + flex-direction: column; + justify-content: space-between; + width: 2.65rem; + color: var(--component-text-muted); + font-family: var(--font-mono, monospace); + font-size: 0.72rem; + line-height: 1.25; + text-align: center; + text-transform: uppercase; +} + +.chart { + display: block; + width: 100%; + height: 100%; + padding-top: 2.65rem; + overflow: visible; +} + +.gridLine { + stroke: rgba(255, 255, 255, 0.09); + stroke-width: 0.35; +} + +.targetLine { + stroke: rgba(255, 255, 255, 0.42); + stroke-dasharray: 1.4 1.4; + stroke-width: 0.45; +} + +.glucoseLine, +.insulinLine, +.responseLine { + fill: none; + vector-effect: non-scaling-stroke; +} + +.glucoseLine { + stroke: var(--component-primary); + stroke-width: 2.85; +} + +.insulinLine { + stroke: var(--component-accent); + stroke-width: 2.3; +} + +.responseLine { + stroke: #fbbf24; + stroke-dasharray: 3 2; + stroke-width: 1.85; +} + +.cursorLine { + stroke: rgba(255, 255, 255, 0.32); + stroke-width: 0.55; +} + +.delayLine { + stroke: #fbbf24; + stroke-linecap: round; + stroke-width: 1.75; +} + +.delayCallout { + filter: drop-shadow(0 0 5px rgba(251, 191, 36, 0.42)); +} + +.delayText { + fill: #fef3c7; + font-family: var(--font-mono, monospace); + font-size: 3px; + font-weight: 600; + letter-spacing: 0; + paint-order: stroke; + stroke: rgba(10, 10, 15, 0.86); + stroke-width: 0.8px; + text-transform: uppercase; +} + +.foodLine { + stroke: rgba(255, 255, 255, 0.3); + stroke-dasharray: 1.6 1.6; + stroke-width: 0.6; +} + +.mealWindow { + fill: rgba(251, 113, 133, 0.1); + stroke: rgba(251, 113, 133, 0.24); + stroke-width: 0.3; +} + +.snackWindow { + fill: rgba(251, 191, 36, 0.12); + stroke: rgba(251, 191, 36, 0.32); + stroke-width: 0.3; +} + +.snackLine { + stroke: rgba(251, 191, 36, 0.54); + stroke-dasharray: 1.6 1.6; + stroke-width: 0.55; +} + +.foodMarker { + dominant-baseline: middle; + font-size: 7.5px; +} + +.glucoseDot, +.insulinDot, +.responseDot { + vector-effect: non-scaling-stroke; + stroke: var(--component-bg); + stroke-width: 1.2; +} + +.glucoseDot { + fill: var(--component-primary); +} + +.insulinDot { + fill: var(--component-accent); +} + +.responseDot { + fill: #fbbf24; +} + +.legend { + position: absolute; + right: 1rem; + bottom: 0.95rem; + left: 4.15rem; + display: flex; + flex-wrap: wrap; + gap: 0.55rem 0.8rem; + align-items: center; + color: var(--component-text-muted); + font-family: var(--font-mono, monospace); + font-size: 0.86rem; +} + +.legend span { + display: inline-flex; + gap: 0.38rem; + align-items: center; +} + +.legend i { + display: inline-block; + width: 1.35rem; + height: 0.28rem; + border-radius: 999px; +} + +.glucoseKey { + background: var(--component-primary); +} + +.insulinKey { + background: var(--component-accent); +} + +.responseKey { + background: #fbbf24; +} + +.foodKey { + background: #fb7185; +} + +.snackKey { + background: #fbbf24; +} + +.sidePanel { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 0.55rem; + min-height: 0; + overflow: hidden; +} + +.metric, +.delayCard { + min-width: 0; + padding: 0.78rem; + border: 1px solid var(--component-border); + border-radius: var(--border-radius-sm, 8px); + background: color-mix(in srgb, var(--component-bg-secondary) 84%, black); +} + +.metric span, +.delayCard span { + display: block; + color: var(--component-text-muted); + font-family: var(--font-mono, monospace); + font-size: 0.72rem; + line-height: 1.2; + text-transform: uppercase; +} + +.metric strong, +.delayCard strong { + display: block; + margin-top: 0.15rem; + color: var(--component-text); + font-size: 1.52rem; + line-height: 1.1; +} + +.metric small { + color: var(--component-text-muted); + font-size: 0.72rem; + font-weight: 400; +} + +.delayCard { + border-color: color-mix(in srgb, #fbbf24 42%, var(--component-border)); +} + +.delayCard p { + display: none; + margin: 0.55rem 0 0; + color: var(--component-text-muted); + font-size: clamp(0.72rem, 1vw, 0.92rem); + line-height: 1.38; +} + +.causalChain { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 0.38rem; + min-height: 0; +} + +.causalStep, +.activeCausalStep { + position: relative; + min-width: 0; + padding: 0.55rem 0.42rem; + border: 1px solid var(--component-border); + border-radius: var(--border-radius-sm, 8px); + background: color-mix(in srgb, var(--component-bg-secondary) 86%, black); +} + +.causalStep:not(:last-child)::after, +.activeCausalStep:not(:last-child)::after { + position: absolute; + top: 50%; + right: -0.36rem; + z-index: 1; + color: var(--component-text-muted); + content: '>'; + font-family: var(--font-mono, monospace); + font-size: 0.7rem; + transform: translateY(-50%); +} + +.activeCausalStep { + border-color: color-mix(in srgb, var(--component-accent) 72%, white); + background: color-mix(in srgb, var(--component-accent) 18%, var(--component-bg-secondary)); +} + +.causalStep span, +.activeCausalStep span { + display: block; + overflow: hidden; + color: var(--component-text-muted); + font-family: var(--font-mono, monospace); + font-size: 0.64rem; + line-height: 1; + text-overflow: ellipsis; + text-transform: uppercase; + white-space: nowrap; +} + +.causalStep strong, +.activeCausalStep strong { + display: block; + margin-top: 0.2rem; + overflow: hidden; + color: var(--component-text); + font-size: 1rem; + line-height: 1; + text-overflow: ellipsis; + white-space: nowrap; +} + +.controls { + display: grid; + grid-template-columns: 0.8fr 0.9fr 1fr; + gap: 0.5rem; +} + +.button, +.buttonPrimary { + min-width: 0; + border-radius: var(--border-radius-sm, 8px); + padding: 0.78rem 0.7rem; + cursor: pointer; + font: inherit; + font-size: 1rem; + transition: + transform var(--transition, 0.2s ease), + opacity var(--transition, 0.2s ease), + border-color var(--transition, 0.2s ease); +} + +.button { + border: 1px solid var(--component-border); + background: var(--component-bg-secondary); + color: var(--component-text); +} + +.buttonPrimary { + border: 1px solid color-mix(in srgb, var(--component-primary) 68%, white); + background: var(--component-primary); + color: white; +} + +.button:hover, +.buttonPrimary:hover { + opacity: 0.95; + transform: translateY(-1px); +} + +.button:disabled, +.buttonPrimary:disabled { + cursor: not-allowed; + opacity: 0.45; + transform: none; +} + +@keyframes hangryShake { + 0%, + 100% { + transform: translateX(0); + } + + 25% { + transform: translateX(-1px) rotate(-1deg); + } + + 50% { + transform: translateX(1px) rotate(1deg); + } + + 75% { + transform: translateX(-0.5px) rotate(-0.5deg); + } +} + +@keyframes hangryBadgeShake { + 0%, + 100% { + transform: translate(-50%, -50%); + } + + 25% { + transform: translate(calc(-50% - 2px), -50%) rotate(-1deg); + } + + 50% { + transform: translate(calc(-50% + 2px), -50%) rotate(1deg); + } + + 75% { + transform: translate(calc(-50% - 1px), -50%) rotate(-0.5deg); + } +} + +@keyframes hangryBreath { + 0%, + 100% { + box-shadow: + 0 0 0 0 rgba(248, 113, 113, 0.34), + 0 0 18px rgba(248, 113, 113, 0.34); + } + + 50% { + box-shadow: + 0 0 0 0.75rem rgba(248, 113, 113, 0), + 0 0 30px rgba(248, 113, 113, 0.64); + } +} + +@keyframes hangryPulse { + 0%, + 100% { + opacity: 0.76; + } + + 50% { + opacity: 1; + } +} + +@keyframes hangryPanelPulse { + 0%, + 100% { + box-shadow: 0 0 0 rgba(248, 113, 113, 0); + } + + 50% { + box-shadow: 0 0 20px rgba(248, 113, 113, 0.22); + } +} + +@media (orientation: portrait), (max-width: 820px) { + .root { + width: min(100%, 760px); + } + + .board { + grid-template-columns: 1fr; + grid-template-rows: auto auto; + gap: clamp(0.7rem, 2vw, 1rem); + aspect-ratio: auto; + } + + .chartPanel, + .controlPanel { + width: 100%; + height: auto; + aspect-ratio: 1 / 1; + } + + .controlPanel { + grid-template-rows: auto minmax(0, 1.25fr) auto auto auto; + gap: 0.58rem; + padding: 0.85rem; + } + + .chartPanel { + padding: 0.85rem 0.85rem 0.78rem 3.35rem; + } + + .chartHeader, + .legend { + left: 3.35rem; + } + + .chartEmoji, + .hangryChartEmoji { + top: 2.75rem; + right: 1rem; + width: 8.7rem; + height: 8.7rem; + font-size: 5rem; + } + + .chartHeader strong, + .legend { + font-size: 0.72rem; + } + + .eyebrow { + font-size: 0.78rem; + } + + .title { + font-size: 1.55rem; + } + + .sidePanel { + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 0.45rem; + } + + .mood, + .hangryMood { + gap: 0.55rem; + padding: 0.72rem; + } + + .mood strong, + .hangryMood strong { + font-size: 1.42rem; + } + + .mood small, + .hangryMood small { + font-size: 1.02rem; + line-height: 1.32; + } + + .happyChartBadge, + .hangryChartBadge { + font-size: 4.2rem; + } + + .metric, + .delayCard { + padding: 0.55rem; + } + + .metric strong, + .delayCard strong { + font-size: 1.18rem; + } + + .causalChain { + gap: 0.28rem; + } + + .causalStep, + .activeCausalStep { + padding: 0.38rem 0.3rem; + } +} + +@media (max-width: 520px) { + .chartPanel { + padding: 0.72rem 0.68rem 0.7rem 2.7rem; + } + + .chartHeader, + .legend { + left: 2.7rem; + } + + .chartEmoji, + .hangryChartEmoji { + top: 2.28rem; + right: 0.78rem; + width: 6.5rem; + height: 6.5rem; + font-size: 3.8rem; + } + + .chartHeader { + top: 0.72rem; + right: 0.68rem; + } + + .chartHeader strong, + .legend { + font-size: 0.58rem; + } + + .legend { + right: 0.68rem; + bottom: 0.68rem; + gap: 0.32rem 0.48rem; + } + + .zoneLabels { + left: 0.55rem; + width: 1.85rem; + font-size: 0.54rem; + } + + .title { + font-size: 1.18rem; + } + + .eyebrow { + margin-bottom: 0.25rem; + font-size: 0.68rem; + } + + .happyChartBadge, + .hangryChartBadge { + font-size: 3rem; + } + + .mood, + .hangryMood { + gap: 0.38rem; + padding: 0.55rem; + } + + .mood strong, + .hangryMood strong { + font-size: 1.18rem; + } + + .mood small, + .hangryMood small { + font-size: 1rem; + line-height: 1.28; + } + + .sidePanel { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 0.35rem; + } + + .metric, + .delayCard { + padding: 0.42rem; + } + + .metric span, + .delayCard span { + font-size: 0.56rem; + } + + .metric strong, + .delayCard strong { + font-size: 0.92rem; + } + + .causalChain { + display: none; + } + + .controls { + grid-template-columns: 0.8fr 0.9fr 1fr; + gap: 0.35rem; + } + + .button, + .buttonPrimary { + padding: 0.52rem 0.4rem; + font-size: 0.8rem; + } +} diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..f8f83b8 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,59 @@ +export interface GlitchComponentConfig { + id: string + name: string + version: string + params: Record +} + +export interface GlitchHostBridge { + playSound?: (id: string, payload?: Record) => void + stopSound?: (id: string, payload?: Record) => void + emit?: (type: string, payload?: unknown) => void +} + +export interface GlitchTheme { + primary: string + accent: string + bg: string + bgSecondary: string + text: string + textMuted: string + border: string +} + +export interface GlitchComponentResult { + success: boolean + score?: number + data?: unknown + error?: string +} + +export interface GlitchComponentProps { + config: GlitchComponentConfig + onComplete: (result: GlitchComponentResult) => void + onProgress?: (percent: number) => void + theme?: GlitchTheme + className?: string + host?: GlitchHostBridge +} + +export interface ParamSchema { + [key: string]: { + type: 'number' | 'string' | 'boolean' | 'color' | 'select' | 'range' + label?: string + description?: string + default: unknown + options?: { value: string | number; label: string }[] + min?: number + max?: number + step?: number + } +} + +export interface GlitchComponentMetadata { + name: string + displayName: string + version: string + paramSchema: ParamSchema + defaultParams: Record +} diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..e65dca4 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "lib": [ + "ES2022", + "DOM", + "DOM.Iterable" + ], + "module": "ESNext", + "types": [ + "vite/client" + ], + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": [ + "src" + ] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..7b32f27 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,36 @@ +import { resolve } from 'path' +import react from '@vitejs/plugin-react' +import { defineConfig } from 'vite' +import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js' + +// IIFE format: component registers itself in window.GlitchComponents at load time. +// react/jsx-runtime is intentionally NOT external — it gets bundled and reads from window.React. +// Host apps must expose window.React and window.ReactDOM before loading any component script. +export default defineConfig(({ mode }) => ({ + plugins: [react(), cssInjectedByJsPlugin()], + build: { + lib: { + entry: resolve(__dirname, 'src/index.tsx'), + name: 'GlitchComponent', + fileName: () => 'bloodsugar.js', + formats: ['iife'] + }, + rollupOptions: { + external: ['react', 'react-dom'], + output: { + globals: { + react: 'React', + 'react-dom': 'ReactDOM', + }, + assetFileNames: 'assets/[name][extname]', + exports: 'named' + } + }, + sourcemap: true, + minify: mode === 'production' + }, + server: { + port: 3001, + open: true + } +}))