Zeetay commited on
Commit
5456422
·
1 Parent(s): 5bb23c3

feat: Next.js frontend for hosted demo + README live-demo section

Browse files
README.md CHANGED
@@ -9,11 +9,31 @@ retrieve → generate → evaluate → log → improve → repeat
9
  ```
10
 
11
  Every good output becomes future few-shot fuel and a regression baseline; every
12
- bad output gets flagged for review. The system gets better the more it runs
13
  without any human editing prompts in the hot path.
14
 
15
  ---
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  ## What it does (and why it's architecturally interesting)
18
 
19
  Most "LLM app" demos are a single prompt with no memory and no notion of
@@ -23,7 +43,7 @@ quality. This project is built around three ideas that make it a genuine
23
  1. **It judges itself on multiple axes.** Each output is scored 1–5 on four
24
  independent dimensions (hook strength, brand alignment, clarity, conversion
25
  intent) by a separate judge model. Dimension scores are first-class and
26
- stored separately there is no single "vibe" score driving decisions.
27
 
28
  2. **It remembers what worked.** High-scoring outputs are embedded by their
29
  brand brief and stored in a local vector store. On every new run, the agent
@@ -91,7 +111,7 @@ cp .env.example .env # Windows: copy .env.example .env
91
  ```
92
 
93
  Only `GROQ_API_KEY` is required. Everything else (SQLite at `./agent.db`,
94
- ChromaDB at `./chroma_db`) is local no other external services.
95
 
96
  ### First run
97
 
@@ -166,7 +186,7 @@ flagged).
166
  *"below quality threshold."*
167
 
168
  Because winners re-enter memory, the pool of few-shot exemplars improves run
169
- over run that is the "self-improving" part.
170
 
171
  ---
172
 
@@ -182,7 +202,7 @@ Four dimensions, each 1–5:
182
  | `clarity` | Is the message immediately understandable? | 0.25 |
183
  | `conversion_intent`| Does it drive toward the stated goal? | 0.20 |
184
 
185
- The weighted average is **internal only** used for thresholds and ranking.
186
  All four raw dimensions are always stored separately.
187
 
188
  ### Golden dataset (`evals/golden.py`)
@@ -214,7 +234,7 @@ spuriously) when `GROQ_API_KEY` is unset or the golden dataset is still empty.
214
 
215
  ## Prompt versioning & how to swap versions safely
216
 
217
- All prompt text lives in `agent/prompts.py` nothing is hardcoded anywhere
218
  else. Each prompt is a named, versioned constant (`GENERATION_PROMPT_V1`,
219
  `GENERATION_PROMPT_V2`, …). A single constant selects which is live:
220
 
@@ -246,8 +266,8 @@ is used in a real run" means in practice: the golden dataset is the gate.
246
 
247
  ## Design Decisions
248
 
249
- **Why ChromaDB for memory.** The agent needs *semantic* retrieval "find past
250
- briefs like this one" not exact lookups. ChromaDB gives a persistent local
251
  vector store with cosine similarity and zero external services, and it pairs
252
  cleanly with local sentence-transformers embeddings. SQLite alone can't do
253
  nearest-neighbour search over brief semantics; a hosted vector DB would violate
@@ -257,12 +277,12 @@ the "local only" constraint and add ops overhead for no benefit at this scale.
257
  is unactionable and easy for a judge to anchor on. Scoring four independent
258
  dimensions tells you *why* copy is weak (great hook, poor clarity) and makes the
259
  signal far more stable and debuggable. We do compute a weighted average, but
260
- only for internal thresholds/ranking the four raw dimensions are always
261
  stored, so we never lose information by collapsing too early.
262
 
263
  **Why SQLite for eval storage.** Eval results are structured, relational, and
264
  queryable (runs → outputs → scores; golden; flagged). SQLite gives ACID
265
- guarantees, trivial setup, a single-file database, and real SQL ideal for run
266
  history and a golden dataset. It needs no server and ships with Python. A hosted
267
  DB would add infrastructure with no upside for a local, single-node harness.
268
 
@@ -295,8 +315,8 @@ self-improving-agent/
295
  ```
296
 
297
  ## Constraints honoured
298
- - No LangChain the agent loop is built directly.
299
- - No managed eval platform the judge and runner are custom.
300
- - No external database SQLite + ChromaDB, local only.
301
  - No prompts hardcoded outside `agent/prompts.py`.
302
  - Synchronous throughout, except where FastAPI's interface applies.
 
9
  ```
10
 
11
  Every good output becomes future few-shot fuel and a regression baseline; every
12
+ bad output gets flagged for review. The system gets better the more it runs,
13
  without any human editing prompts in the hot path.
14
 
15
  ---
16
 
17
+ ## Live Demo
18
+
19
+ **🔗 Live demo:** _<add your deployed Vercel URL here>_
20
+
21
+ The hosted demo runs the full loop from the browser: fill the brief (pre-filled
22
+ with a FitFuel example), click **Generate**, and watch the agent retrieve past
23
+ winners, generate three variants, and score each on four dimensions in real time.
24
+
25
+ - **Frontend:** Next.js (App Router) deployed on **Vercel**, in [`web/`](web/).
26
+ - **Backend:** the FastAPI app deployed on **Railway** (see [`Procfile`](Procfile)),
27
+ with CORS, a per-IP rate limit on `/run`, a `/stats` endpoint, and a startup
28
+ seed so a fresh deployment shows non-zero stats and working retrieval on the
29
+ very first visit.
30
+
31
+ > Deployment env vars: the backend needs `GROQ_API_KEY` (and optionally
32
+ > `CORS_ORIGINS` = your Vercel URL); the frontend needs `NEXT_PUBLIC_API_URL` =
33
+ > your Railway backend URL. See the per-app `.env.example` files.
34
+
35
+ ---
36
+
37
  ## What it does (and why it's architecturally interesting)
38
 
39
  Most "LLM app" demos are a single prompt with no memory and no notion of
 
43
  1. **It judges itself on multiple axes.** Each output is scored 1–5 on four
44
  independent dimensions (hook strength, brand alignment, clarity, conversion
45
  intent) by a separate judge model. Dimension scores are first-class and
46
+ stored separately; there is no single "vibe" score driving decisions.
47
 
48
  2. **It remembers what worked.** High-scoring outputs are embedded by their
49
  brand brief and stored in a local vector store. On every new run, the agent
 
111
  ```
112
 
113
  Only `GROQ_API_KEY` is required. Everything else (SQLite at `./agent.db`,
114
+ ChromaDB at `./chroma_db`) is local; no other external services.
115
 
116
  ### First run
117
 
 
186
  *"below quality threshold."*
187
 
188
  Because winners re-enter memory, the pool of few-shot exemplars improves run
189
+ over run; that is the "self-improving" part.
190
 
191
  ---
192
 
 
202
  | `clarity` | Is the message immediately understandable? | 0.25 |
203
  | `conversion_intent`| Does it drive toward the stated goal? | 0.20 |
204
 
205
+ The weighted average is **internal only**, used for thresholds and ranking.
206
  All four raw dimensions are always stored separately.
207
 
208
  ### Golden dataset (`evals/golden.py`)
 
234
 
235
  ## Prompt versioning & how to swap versions safely
236
 
237
+ All prompt text lives in `agent/prompts.py`; nothing is hardcoded anywhere
238
  else. Each prompt is a named, versioned constant (`GENERATION_PROMPT_V1`,
239
  `GENERATION_PROMPT_V2`, …). A single constant selects which is live:
240
 
 
266
 
267
  ## Design Decisions
268
 
269
+ **Why ChromaDB for memory.** The agent needs *semantic* retrieval: "find past
270
+ briefs like this one", not exact lookups. ChromaDB gives a persistent local
271
  vector store with cosine similarity and zero external services, and it pairs
272
  cleanly with local sentence-transformers embeddings. SQLite alone can't do
273
  nearest-neighbour search over brief semantics; a hosted vector DB would violate
 
277
  is unactionable and easy for a judge to anchor on. Scoring four independent
278
  dimensions tells you *why* copy is weak (great hook, poor clarity) and makes the
279
  signal far more stable and debuggable. We do compute a weighted average, but
280
+ only for internal thresholds/ranking; the four raw dimensions are always
281
  stored, so we never lose information by collapsing too early.
282
 
283
  **Why SQLite for eval storage.** Eval results are structured, relational, and
284
  queryable (runs → outputs → scores; golden; flagged). SQLite gives ACID
285
+ guarantees, trivial setup, a single-file database, and real SQL, ideal for run
286
  history and a golden dataset. It needs no server and ships with Python. A hosted
287
  DB would add infrastructure with no upside for a local, single-node harness.
288
 
 
315
  ```
316
 
317
  ## Constraints honoured
318
+ - No LangChain; the agent loop is built directly.
319
+ - No managed eval platform; the judge and runner are custom.
320
+ - No external database; SQLite + ChromaDB, local only.
321
  - No prompts hardcoded outside `agent/prompts.py`.
322
  - Synchronous throughout, except where FastAPI's interface applies.
web/.env.example ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ # URL of the FastAPI backend the frontend calls (/run and /stats).
2
+ # Locally, point this at the running uvicorn server (default port 8000).
3
+ # In production, set it to your Railway backend URL in the Vercel dashboard.
4
+ NEXT_PUBLIC_API_URL=http://localhost:3000
web/.gitignore ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ /node_modules
2
+ /.next
3
+ /out
4
+ .env
5
+ .env*.local
6
+ *.tsbuildinfo
7
+ next-env.d.ts.bak
web/app/globals.css ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ :root {
6
+ color-scheme: dark;
7
+ }
8
+
9
+ html,
10
+ body {
11
+ background-color: #0a0a0b;
12
+ color: #e4e4e7;
13
+ }
14
+
15
+ body {
16
+ -webkit-font-smoothing: antialiased;
17
+ text-rendering: optimizeLegibility;
18
+ }
19
+
20
+ /* Thin, restrained scrollbars to match the dashboard aesthetic. */
21
+ * {
22
+ scrollbar-width: thin;
23
+ scrollbar-color: #26262b transparent;
24
+ }
25
+ *::-webkit-scrollbar {
26
+ width: 8px;
27
+ height: 8px;
28
+ }
29
+ *::-webkit-scrollbar-thumb {
30
+ background: #26262b;
31
+ border-radius: 0;
32
+ }
33
+
34
+ /* Subtle pulse used by the loading status line. */
35
+ @keyframes softPulse {
36
+ 0%,
37
+ 100% {
38
+ opacity: 0.45;
39
+ }
40
+ 50% {
41
+ opacity: 1;
42
+ }
43
+ }
44
+ .animate-soft-pulse {
45
+ animation: softPulse 1.4s ease-in-out infinite;
46
+ }
web/app/layout.tsx ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Metadata } from "next";
2
+ import "./globals.css";
3
+
4
+ export const metadata: Metadata = {
5
+ title: "Self-Improving Ad Copy Agent",
6
+ description:
7
+ "A DTC ad-copy agent that scores its own outputs with an LLM judge, remembers the winners, and improves over time.",
8
+ };
9
+
10
+ export default function RootLayout({
11
+ children,
12
+ }: {
13
+ children: React.ReactNode;
14
+ }) {
15
+ return (
16
+ <html lang="en">
17
+ <body className="font-sans antialiased">{children}</body>
18
+ </html>
19
+ );
20
+ }
web/app/page.tsx ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client";
2
+
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+ import { BriefForm } from "@/components/BriefForm";
5
+ import { HowItWorks } from "@/components/HowItWorks";
6
+ import { ResultCard } from "@/components/ResultCard";
7
+ import { StatsStrip } from "@/components/StatsStrip";
8
+ import { ApiError, getStats, runAgent } from "@/lib/api";
9
+ import type { Brief, RunResponse, Stats } from "@/lib/types";
10
+
11
+ const EXAMPLE_BRIEF: Brief = {
12
+ brand: "FitFuel",
13
+ product: "High-protein meal replacement shake",
14
+ audience: "Busy professionals aged 25-40",
15
+ tone: "Energetic and no-nonsense",
16
+ goal: "Drive trial purchases",
17
+ };
18
+
19
+ // Ordered variant rendering regardless of backend ordering.
20
+ const ORDER: RunResponse["outputs"][number]["variant_type"][] = [
21
+ "headline",
22
+ "body",
23
+ "cta",
24
+ ];
25
+
26
+ const LOADING_PHASES = [
27
+ "Retrieving examples…",
28
+ "Generating variants…",
29
+ "Scoring with the judge…",
30
+ ];
31
+
32
+ export default function Page() {
33
+ const [brief, setBrief] = useState<Brief>(EXAMPLE_BRIEF);
34
+ const [loading, setLoading] = useState(false);
35
+ const [phase, setPhase] = useState(0);
36
+ const [result, setResult] = useState<RunResponse | null>(null);
37
+ const [stats, setStats] = useState<Stats | null>(null);
38
+ const [error, setError] = useState<string | null>(null);
39
+ const phaseTimer = useRef<ReturnType<typeof setInterval> | null>(null);
40
+
41
+ const refreshStats = useCallback(async () => {
42
+ try {
43
+ setStats(await getStats());
44
+ } catch {
45
+ // Stats are non-critical; leave them dashed if unreachable.
46
+ }
47
+ }, []);
48
+
49
+ useEffect(() => {
50
+ refreshStats();
51
+ }, [refreshStats]);
52
+
53
+ // Advance the loading status text while a run is in flight.
54
+ useEffect(() => {
55
+ if (loading) {
56
+ setPhase(0);
57
+ phaseTimer.current = setInterval(() => {
58
+ setPhase((p) => Math.min(p + 1, LOADING_PHASES.length - 1));
59
+ }, 1100);
60
+ } else if (phaseTimer.current) {
61
+ clearInterval(phaseTimer.current);
62
+ phaseTimer.current = null;
63
+ }
64
+ return () => {
65
+ if (phaseTimer.current) clearInterval(phaseTimer.current);
66
+ };
67
+ }, [loading]);
68
+
69
+ const onChange = (key: keyof Brief, value: string) =>
70
+ setBrief((b) => ({ ...b, [key]: value }));
71
+
72
+ const onSubmit = async () => {
73
+ setLoading(true);
74
+ setError(null);
75
+ try {
76
+ const data = await runAgent(brief);
77
+ setResult(data);
78
+ await refreshStats();
79
+ } catch (e) {
80
+ const msg = e instanceof ApiError ? e.message : "Something went wrong.";
81
+ setError(msg);
82
+ } finally {
83
+ setLoading(false);
84
+ }
85
+ };
86
+
87
+ const orderedOutputs = result
88
+ ? ORDER.map((t) => result.outputs.find((o) => o.variant_type === t)).filter(
89
+ (o): o is RunResponse["outputs"][number] => Boolean(o),
90
+ )
91
+ : [];
92
+
93
+ return (
94
+ <main className="mx-auto max-w-5xl px-5 py-10 sm:py-14">
95
+ {/* Header */}
96
+ <header className="mb-10 flex flex-col gap-4 border-b border-ink-700 pb-6 sm:flex-row sm:items-start sm:justify-between">
97
+ <div>
98
+ <h1 className="text-xl font-semibold tracking-tight text-zinc-50 sm:text-2xl">
99
+ Self-Improving Ad Copy Agent
100
+ </h1>
101
+ <p className="mt-1.5 max-w-xl text-sm leading-relaxed text-zinc-500">
102
+ Generates DTC ad copy, scores its own output with an LLM judge,
103
+ remembers the winners, and gets better with every run.
104
+ </p>
105
+ </div>
106
+ <div className="sm:pt-1">
107
+ <StatsStrip stats={stats} />
108
+ </div>
109
+ </header>
110
+
111
+ {/* Brief form */}
112
+ <BriefForm
113
+ brief={brief}
114
+ onChange={onChange}
115
+ onSubmit={onSubmit}
116
+ loading={loading}
117
+ statusText={LOADING_PHASES[phase]}
118
+ />
119
+
120
+ {/* Error */}
121
+ {error && (
122
+ <div className="mt-5 border border-red-500/40 bg-red-500/10 px-4 py-3 text-sm text-red-300">
123
+ {error}
124
+ </div>
125
+ )}
126
+
127
+ {/* Results */}
128
+ {result && (
129
+ <section className="mt-8">
130
+ {result.retrieved_count > 0 && (
131
+ <p className="mb-3 font-mono text-xs text-zinc-500">
132
+ <span className="text-emerald-400">↺</span> Informed by{" "}
133
+ {result.retrieved_count} past high-scoring example
134
+ {result.retrieved_count === 1 ? "" : "s"}.
135
+ </p>
136
+ )}
137
+ <div className="grid grid-cols-1 gap-4 lg:grid-cols-3">
138
+ {orderedOutputs.map((o) => (
139
+ <ResultCard key={o.variant_type} output={o} />
140
+ ))}
141
+ </div>
142
+ <p className="mt-3 font-mono text-[11px] text-zinc-600">
143
+ run #{result.run_id} · prompt {result.prompt_version}
144
+ {result.feedback.promoted_to_golden.length > 0 &&
145
+ ` · promoted: ${result.feedback.promoted_to_golden.join(", ")}`}
146
+ </p>
147
+ </section>
148
+ )}
149
+
150
+ {/* How it works */}
151
+ <div className="mt-12">
152
+ <HowItWorks />
153
+ </div>
154
+
155
+ <footer className="mt-10 border-t border-ink-700 pt-5 font-mono text-[11px] text-zinc-600">
156
+ Backend: FastAPI on Railway · Frontend: Next.js on Vercel · Judge &
157
+ generator: llama-3.3-70b
158
+ </footer>
159
+ </main>
160
+ );
161
+ }
web/components/BriefForm.tsx ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Brief } from "@/lib/types";
2
+
3
+ const FIELDS: { key: keyof Brief; label: string; placeholder: string }[] = [
4
+ { key: "brand", label: "Brand", placeholder: "FitFuel" },
5
+ { key: "product", label: "Product", placeholder: "High-protein meal replacement shake" },
6
+ { key: "audience", label: "Audience", placeholder: "Busy professionals aged 25-40" },
7
+ { key: "tone", label: "Tone", placeholder: "Energetic and no-nonsense" },
8
+ { key: "goal", label: "Goal", placeholder: "Drive trial purchases" },
9
+ ];
10
+
11
+ export function BriefForm({
12
+ brief,
13
+ onChange,
14
+ onSubmit,
15
+ loading,
16
+ statusText,
17
+ }: {
18
+ brief: Brief;
19
+ onChange: (key: keyof Brief, value: string) => void;
20
+ onSubmit: () => void;
21
+ loading: boolean;
22
+ statusText: string;
23
+ }) {
24
+ return (
25
+ <form
26
+ onSubmit={(e) => {
27
+ e.preventDefault();
28
+ onSubmit();
29
+ }}
30
+ className="border border-ink-700 bg-ink-900"
31
+ >
32
+ <div className="border-b border-ink-700 px-5 py-3">
33
+ <h2 className="font-mono text-xs uppercase tracking-wider text-zinc-400">
34
+ Brand Brief
35
+ </h2>
36
+ </div>
37
+
38
+ <div className="grid grid-cols-1 gap-4 px-5 py-5 sm:grid-cols-2">
39
+ {FIELDS.map((f) => (
40
+ <div
41
+ key={f.key}
42
+ className={f.key === "product" ? "sm:col-span-2" : undefined}
43
+ >
44
+ <label
45
+ htmlFor={f.key}
46
+ className="mb-1.5 block font-mono text-[11px] uppercase tracking-wider text-zinc-500"
47
+ >
48
+ {f.label}
49
+ </label>
50
+ <input
51
+ id={f.key}
52
+ type="text"
53
+ value={brief[f.key]}
54
+ placeholder={f.placeholder}
55
+ onChange={(e) => onChange(f.key, e.target.value)}
56
+ disabled={loading}
57
+ className="w-full border border-ink-700 bg-ink-950 px-3 py-2 text-sm text-zinc-100 outline-none transition-colors placeholder:text-zinc-600 focus:border-zinc-500 disabled:opacity-60"
58
+ />
59
+ </div>
60
+ ))}
61
+ </div>
62
+
63
+ <div className="flex items-center justify-between gap-4 border-t border-ink-700 px-5 py-4">
64
+ <p
65
+ className={`font-mono text-xs text-zinc-500 ${
66
+ loading ? "animate-soft-pulse" : ""
67
+ }`}
68
+ >
69
+ {loading ? statusText : "Ready"}
70
+ </p>
71
+ <button
72
+ type="submit"
73
+ disabled={loading}
74
+ className="border border-zinc-300 bg-zinc-100 px-4 py-2 text-sm font-medium text-ink-950 transition-colors hover:bg-white disabled:cursor-not-allowed disabled:border-ink-600 disabled:bg-ink-700 disabled:text-zinc-400"
75
+ >
76
+ {loading ? "Running…" : "Generate Copy"}
77
+ </button>
78
+ </div>
79
+ </form>
80
+ );
81
+ }
web/components/HowItWorks.tsx ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const STEPS = [
2
+ {
3
+ n: "01",
4
+ title: "Generate",
5
+ body: "The agent turns a brand brief into three ad-copy variants: a headline hook, body copy, and a CTA.",
6
+ },
7
+ {
8
+ n: "02",
9
+ title: "Judge",
10
+ body: "A separate LLM-as-judge scores each variant 1–5 on four dimensions: hook strength, brand alignment, clarity, and conversion intent.",
11
+ },
12
+ {
13
+ n: "03",
14
+ title: "Remember",
15
+ body: "Outputs scoring ≥ 4.0 are promoted into a golden dataset and a vector memory; weak ones (< 2.5) get flagged for review.",
16
+ },
17
+ {
18
+ n: "04",
19
+ title: "Improve & guard",
20
+ body: "Future runs retrieve those winners as few-shot examples, so quality compounds, and a regression gate blocks any prompt change that drops golden scores.",
21
+ },
22
+ ];
23
+
24
+ export function HowItWorks() {
25
+ return (
26
+ <section className="border border-ink-700 bg-ink-900">
27
+ <div className="border-b border-ink-700 px-5 py-3">
28
+ <h2 className="font-mono text-xs uppercase tracking-wider text-zinc-400">
29
+ How it works
30
+ </h2>
31
+ </div>
32
+ <div className="grid grid-cols-1 gap-px bg-ink-700 sm:grid-cols-2 lg:grid-cols-4">
33
+ {STEPS.map((s) => (
34
+ <div key={s.n} className="bg-ink-900 px-5 py-5">
35
+ <div className="mb-2 flex items-center gap-2">
36
+ <span className="font-mono text-xs text-zinc-600">{s.n}</span>
37
+ <span className="text-sm font-medium text-zinc-200">{s.title}</span>
38
+ </div>
39
+ <p className="text-[13px] leading-relaxed text-zinc-500">{s.body}</p>
40
+ </div>
41
+ ))}
42
+ </div>
43
+ </section>
44
+ );
45
+ }
web/components/ResultCard.tsx ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Output, Scores } from "@/lib/types";
2
+
3
+ const VARIANT_LABEL: Record<Output["variant_type"], string> = {
4
+ headline: "Headline",
5
+ body: "Body",
6
+ cta: "CTA",
7
+ };
8
+
9
+ // Badge / accent color by weighted average: green >=4.0, amber 2.5-4.0, red <2.5.
10
+ function band(weighted: number) {
11
+ if (weighted >= 4.0) {
12
+ return { text: "text-emerald-400", border: "border-emerald-500/40", bg: "bg-emerald-500/10", bar: "bg-emerald-400/70" };
13
+ }
14
+ if (weighted >= 2.5) {
15
+ return { text: "text-amber-400", border: "border-amber-500/40", bg: "bg-amber-500/10", bar: "bg-amber-400/70" };
16
+ }
17
+ return { text: "text-red-400", border: "border-red-500/40", bg: "bg-red-500/10", bar: "bg-red-400/70" };
18
+ }
19
+
20
+ const DIMS: { key: keyof Scores; label: string }[] = [
21
+ { key: "hook_strength", label: "Hook" },
22
+ { key: "brand_alignment", label: "Brand" },
23
+ { key: "clarity", label: "Clarity" },
24
+ { key: "conversion_intent", label: "Conv" },
25
+ ];
26
+
27
+ function ScoreBar({ label, value, barClass }: { label: string; value: number; barClass: string }) {
28
+ const pct = Math.max(0, Math.min(100, (value / 5) * 100));
29
+ return (
30
+ <div className="flex items-center gap-2">
31
+ <span className="w-14 font-mono text-[10px] uppercase tracking-wider text-zinc-500">
32
+ {label}
33
+ </span>
34
+ <div className="h-1.5 flex-1 bg-ink-800">
35
+ <div className={`h-full ${barClass}`} style={{ width: `${pct}%` }} />
36
+ </div>
37
+ <span className="w-4 text-right font-mono text-[11px] tabular-nums text-zinc-400">
38
+ {value}
39
+ </span>
40
+ </div>
41
+ );
42
+ }
43
+
44
+ export function ResultCard({ output }: { output: Output }) {
45
+ const { scores } = output;
46
+ const c = band(scores.weighted_average);
47
+
48
+ return (
49
+ <div className="flex flex-col border border-ink-700 bg-ink-900">
50
+ <div className="flex items-center justify-between border-b border-ink-700 px-4 py-2.5">
51
+ <span className="font-mono text-xs uppercase tracking-wider text-zinc-400">
52
+ {VARIANT_LABEL[output.variant_type]}
53
+ </span>
54
+ <span
55
+ className={`border ${c.border} ${c.bg} ${c.text} px-2 py-0.5 font-mono text-xs tabular-nums`}
56
+ title="Weighted average score"
57
+ >
58
+ {scores.weighted_average.toFixed(2)}
59
+ </span>
60
+ </div>
61
+
62
+ <div className="flex-1 px-4 py-4">
63
+ <p className="text-sm leading-relaxed text-zinc-100">{output.content}</p>
64
+ </div>
65
+
66
+ <div className="space-y-2 border-t border-ink-700 px-4 py-3">
67
+ {DIMS.map((d) => (
68
+ <ScoreBar
69
+ key={d.key}
70
+ label={d.label}
71
+ value={Number(scores[d.key])}
72
+ barClass={c.bar}
73
+ />
74
+ ))}
75
+ </div>
76
+ </div>
77
+ );
78
+ }
web/components/StatsStrip.tsx ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Stats } from "@/lib/types";
2
+
3
+ export function StatsStrip({ stats }: { stats: Stats | null }) {
4
+ const item = (label: string, value: number | null) => (
5
+ <span className="inline-flex items-baseline gap-1.5">
6
+ <span className="text-zinc-500">{label}</span>
7
+ <span className="font-mono text-zinc-200 tabular-nums">
8
+ {value === null ? "–" : value}
9
+ </span>
10
+ </span>
11
+ );
12
+
13
+ return (
14
+ <div className="flex items-center gap-3 border border-ink-700 bg-ink-850 px-3 py-1.5 text-xs">
15
+ {item("Runs", stats?.runs ?? null)}
16
+ <span className="text-ink-600">·</span>
17
+ {item("Golden", stats?.golden ?? null)}
18
+ <span className="text-ink-600">·</span>
19
+ {item("Flagged", stats?.flagged ?? null)}
20
+ </div>
21
+ );
22
+ }
web/lib/api.ts ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Brief, RunResponse, Stats } from "./types";
2
+
3
+ const API_URL = process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:8000";
4
+
5
+ /** Raised for any non-OK API response, with a user-friendly message. */
6
+ export class ApiError extends Error {
7
+ status: number;
8
+ constructor(message: string, status: number) {
9
+ super(message);
10
+ this.name = "ApiError";
11
+ this.status = status;
12
+ }
13
+ }
14
+
15
+ async function parseError(res: Response): Promise<string> {
16
+ if (res.status === 429) {
17
+ return "Rate limit reached (10 runs/minute). Give it a minute and try again.";
18
+ }
19
+ try {
20
+ const data = await res.json();
21
+ if (data?.detail) return String(data.detail);
22
+ } catch {
23
+ /* fall through to generic */
24
+ }
25
+ return `Request failed (${res.status}).`;
26
+ }
27
+
28
+ export async function getStats(): Promise<Stats> {
29
+ const res = await fetch(`${API_URL}/stats`, { cache: "no-store" });
30
+ if (!res.ok) throw new ApiError(await parseError(res), res.status);
31
+ return res.json();
32
+ }
33
+
34
+ export async function runAgent(brief: Brief): Promise<RunResponse> {
35
+ let res: Response;
36
+ try {
37
+ res = await fetch(`${API_URL}/run`, {
38
+ method: "POST",
39
+ headers: { "Content-Type": "application/json" },
40
+ body: JSON.stringify(brief),
41
+ });
42
+ } catch {
43
+ // Network / CORS / backend down.
44
+ throw new ApiError(
45
+ "Could not reach the backend. Is the API running and NEXT_PUBLIC_API_URL set correctly?",
46
+ 0,
47
+ );
48
+ }
49
+ if (!res.ok) throw new ApiError(await parseError(res), res.status);
50
+ return res.json();
51
+ }
52
+
53
+ export { API_URL };
web/lib/types.ts ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export interface Brief {
2
+ brand: string;
3
+ product: string;
4
+ audience: string;
5
+ tone: string;
6
+ goal: string;
7
+ }
8
+
9
+ export type VariantType = "headline" | "body" | "cta";
10
+
11
+ export interface Scores {
12
+ hook_strength: number;
13
+ brand_alignment: number;
14
+ clarity: number;
15
+ conversion_intent: number;
16
+ weighted_average: number;
17
+ rationale?: string;
18
+ }
19
+
20
+ export interface Output {
21
+ variant_type: VariantType;
22
+ content: string;
23
+ scores: Scores;
24
+ }
25
+
26
+ export interface Feedback {
27
+ promoted_to_golden: string[];
28
+ flagged_for_review: string[];
29
+ golden_threshold: number;
30
+ flag_threshold: number;
31
+ }
32
+
33
+ export interface RunResponse {
34
+ run_id: number;
35
+ brief: Brief;
36
+ prompt_version: string;
37
+ retrieved_count: number;
38
+ retrieved_examples: number;
39
+ outputs: Output[];
40
+ feedback: Feedback;
41
+ }
42
+
43
+ export interface Stats {
44
+ runs: number;
45
+ golden: number;
46
+ flagged: number;
47
+ }
web/next-env.d.ts ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ /// <reference types="next" />
2
+ /// <reference types="next/image-types/global" />
3
+
4
+ // NOTE: This file should not be edited
5
+ // see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
web/next.config.mjs ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ reactStrictMode: true,
4
+ };
5
+
6
+ export default nextConfig;
web/package-lock.json ADDED
@@ -0,0 +1,1664 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "self-improving-agent-web",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "self-improving-agent-web",
9
+ "version": "1.0.0",
10
+ "dependencies": {
11
+ "next": "14.2.35",
12
+ "react": "18.3.1",
13
+ "react-dom": "18.3.1"
14
+ },
15
+ "devDependencies": {
16
+ "@types/node": "20.16.11",
17
+ "@types/react": "18.3.11",
18
+ "@types/react-dom": "18.3.0",
19
+ "autoprefixer": "10.4.20",
20
+ "postcss": "8.5.10",
21
+ "tailwindcss": "3.4.14",
22
+ "typescript": "5.6.3"
23
+ }
24
+ },
25
+ "node_modules/@alloc/quick-lru": {
26
+ "version": "5.2.0",
27
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
28
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
29
+ "dev": true,
30
+ "license": "MIT",
31
+ "engines": {
32
+ "node": ">=10"
33
+ },
34
+ "funding": {
35
+ "url": "https://github.com/sponsors/sindresorhus"
36
+ }
37
+ },
38
+ "node_modules/@jridgewell/gen-mapping": {
39
+ "version": "0.3.13",
40
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
41
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
42
+ "dev": true,
43
+ "license": "MIT",
44
+ "dependencies": {
45
+ "@jridgewell/sourcemap-codec": "^1.5.0",
46
+ "@jridgewell/trace-mapping": "^0.3.24"
47
+ }
48
+ },
49
+ "node_modules/@jridgewell/resolve-uri": {
50
+ "version": "3.1.2",
51
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
52
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
53
+ "dev": true,
54
+ "license": "MIT",
55
+ "engines": {
56
+ "node": ">=6.0.0"
57
+ }
58
+ },
59
+ "node_modules/@jridgewell/sourcemap-codec": {
60
+ "version": "1.5.5",
61
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
62
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
63
+ "dev": true,
64
+ "license": "MIT"
65
+ },
66
+ "node_modules/@jridgewell/trace-mapping": {
67
+ "version": "0.3.31",
68
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
69
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
70
+ "dev": true,
71
+ "license": "MIT",
72
+ "dependencies": {
73
+ "@jridgewell/resolve-uri": "^3.1.0",
74
+ "@jridgewell/sourcemap-codec": "^1.4.14"
75
+ }
76
+ },
77
+ "node_modules/@next/env": {
78
+ "version": "14.2.35",
79
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz",
80
+ "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==",
81
+ "license": "MIT"
82
+ },
83
+ "node_modules/@next/swc-darwin-arm64": {
84
+ "version": "14.2.33",
85
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.33.tgz",
86
+ "integrity": "sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==",
87
+ "cpu": [
88
+ "arm64"
89
+ ],
90
+ "license": "MIT",
91
+ "optional": true,
92
+ "os": [
93
+ "darwin"
94
+ ],
95
+ "engines": {
96
+ "node": ">= 10"
97
+ }
98
+ },
99
+ "node_modules/@next/swc-darwin-x64": {
100
+ "version": "14.2.33",
101
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.33.tgz",
102
+ "integrity": "sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==",
103
+ "cpu": [
104
+ "x64"
105
+ ],
106
+ "license": "MIT",
107
+ "optional": true,
108
+ "os": [
109
+ "darwin"
110
+ ],
111
+ "engines": {
112
+ "node": ">= 10"
113
+ }
114
+ },
115
+ "node_modules/@next/swc-linux-arm64-gnu": {
116
+ "version": "14.2.33",
117
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.33.tgz",
118
+ "integrity": "sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==",
119
+ "cpu": [
120
+ "arm64"
121
+ ],
122
+ "license": "MIT",
123
+ "optional": true,
124
+ "os": [
125
+ "linux"
126
+ ],
127
+ "engines": {
128
+ "node": ">= 10"
129
+ }
130
+ },
131
+ "node_modules/@next/swc-linux-arm64-musl": {
132
+ "version": "14.2.33",
133
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.33.tgz",
134
+ "integrity": "sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==",
135
+ "cpu": [
136
+ "arm64"
137
+ ],
138
+ "license": "MIT",
139
+ "optional": true,
140
+ "os": [
141
+ "linux"
142
+ ],
143
+ "engines": {
144
+ "node": ">= 10"
145
+ }
146
+ },
147
+ "node_modules/@next/swc-linux-x64-gnu": {
148
+ "version": "14.2.33",
149
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.33.tgz",
150
+ "integrity": "sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==",
151
+ "cpu": [
152
+ "x64"
153
+ ],
154
+ "license": "MIT",
155
+ "optional": true,
156
+ "os": [
157
+ "linux"
158
+ ],
159
+ "engines": {
160
+ "node": ">= 10"
161
+ }
162
+ },
163
+ "node_modules/@next/swc-linux-x64-musl": {
164
+ "version": "14.2.33",
165
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.33.tgz",
166
+ "integrity": "sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==",
167
+ "cpu": [
168
+ "x64"
169
+ ],
170
+ "license": "MIT",
171
+ "optional": true,
172
+ "os": [
173
+ "linux"
174
+ ],
175
+ "engines": {
176
+ "node": ">= 10"
177
+ }
178
+ },
179
+ "node_modules/@next/swc-win32-arm64-msvc": {
180
+ "version": "14.2.33",
181
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.33.tgz",
182
+ "integrity": "sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==",
183
+ "cpu": [
184
+ "arm64"
185
+ ],
186
+ "license": "MIT",
187
+ "optional": true,
188
+ "os": [
189
+ "win32"
190
+ ],
191
+ "engines": {
192
+ "node": ">= 10"
193
+ }
194
+ },
195
+ "node_modules/@next/swc-win32-ia32-msvc": {
196
+ "version": "14.2.33",
197
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.33.tgz",
198
+ "integrity": "sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==",
199
+ "cpu": [
200
+ "ia32"
201
+ ],
202
+ "license": "MIT",
203
+ "optional": true,
204
+ "os": [
205
+ "win32"
206
+ ],
207
+ "engines": {
208
+ "node": ">= 10"
209
+ }
210
+ },
211
+ "node_modules/@next/swc-win32-x64-msvc": {
212
+ "version": "14.2.33",
213
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.33.tgz",
214
+ "integrity": "sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==",
215
+ "cpu": [
216
+ "x64"
217
+ ],
218
+ "license": "MIT",
219
+ "optional": true,
220
+ "os": [
221
+ "win32"
222
+ ],
223
+ "engines": {
224
+ "node": ">= 10"
225
+ }
226
+ },
227
+ "node_modules/@nodelib/fs.scandir": {
228
+ "version": "2.1.5",
229
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
230
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
231
+ "dev": true,
232
+ "license": "MIT",
233
+ "dependencies": {
234
+ "@nodelib/fs.stat": "2.0.5",
235
+ "run-parallel": "^1.1.9"
236
+ },
237
+ "engines": {
238
+ "node": ">= 8"
239
+ }
240
+ },
241
+ "node_modules/@nodelib/fs.stat": {
242
+ "version": "2.0.5",
243
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
244
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
245
+ "dev": true,
246
+ "license": "MIT",
247
+ "engines": {
248
+ "node": ">= 8"
249
+ }
250
+ },
251
+ "node_modules/@nodelib/fs.walk": {
252
+ "version": "1.2.8",
253
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
254
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
255
+ "dev": true,
256
+ "license": "MIT",
257
+ "dependencies": {
258
+ "@nodelib/fs.scandir": "2.1.5",
259
+ "fastq": "^1.6.0"
260
+ },
261
+ "engines": {
262
+ "node": ">= 8"
263
+ }
264
+ },
265
+ "node_modules/@swc/counter": {
266
+ "version": "0.1.3",
267
+ "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
268
+ "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
269
+ "license": "Apache-2.0"
270
+ },
271
+ "node_modules/@swc/helpers": {
272
+ "version": "0.5.5",
273
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz",
274
+ "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==",
275
+ "license": "Apache-2.0",
276
+ "dependencies": {
277
+ "@swc/counter": "^0.1.3",
278
+ "tslib": "^2.4.0"
279
+ }
280
+ },
281
+ "node_modules/@types/node": {
282
+ "version": "20.16.11",
283
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.11.tgz",
284
+ "integrity": "sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==",
285
+ "dev": true,
286
+ "license": "MIT",
287
+ "dependencies": {
288
+ "undici-types": "~6.19.2"
289
+ }
290
+ },
291
+ "node_modules/@types/prop-types": {
292
+ "version": "15.7.15",
293
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
294
+ "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==",
295
+ "dev": true,
296
+ "license": "MIT"
297
+ },
298
+ "node_modules/@types/react": {
299
+ "version": "18.3.11",
300
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz",
301
+ "integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==",
302
+ "dev": true,
303
+ "license": "MIT",
304
+ "dependencies": {
305
+ "@types/prop-types": "*",
306
+ "csstype": "^3.0.2"
307
+ }
308
+ },
309
+ "node_modules/@types/react-dom": {
310
+ "version": "18.3.0",
311
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz",
312
+ "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==",
313
+ "dev": true,
314
+ "license": "MIT",
315
+ "dependencies": {
316
+ "@types/react": "*"
317
+ }
318
+ },
319
+ "node_modules/any-promise": {
320
+ "version": "1.3.0",
321
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
322
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
323
+ "dev": true,
324
+ "license": "MIT"
325
+ },
326
+ "node_modules/anymatch": {
327
+ "version": "3.1.3",
328
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
329
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
330
+ "dev": true,
331
+ "license": "ISC",
332
+ "dependencies": {
333
+ "normalize-path": "^3.0.0",
334
+ "picomatch": "^2.0.4"
335
+ },
336
+ "engines": {
337
+ "node": ">= 8"
338
+ }
339
+ },
340
+ "node_modules/arg": {
341
+ "version": "5.0.2",
342
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
343
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
344
+ "dev": true,
345
+ "license": "MIT"
346
+ },
347
+ "node_modules/autoprefixer": {
348
+ "version": "10.4.20",
349
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
350
+ "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==",
351
+ "dev": true,
352
+ "funding": [
353
+ {
354
+ "type": "opencollective",
355
+ "url": "https://opencollective.com/postcss/"
356
+ },
357
+ {
358
+ "type": "tidelift",
359
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
360
+ },
361
+ {
362
+ "type": "github",
363
+ "url": "https://github.com/sponsors/ai"
364
+ }
365
+ ],
366
+ "license": "MIT",
367
+ "dependencies": {
368
+ "browserslist": "^4.23.3",
369
+ "caniuse-lite": "^1.0.30001646",
370
+ "fraction.js": "^4.3.7",
371
+ "normalize-range": "^0.1.2",
372
+ "picocolors": "^1.0.1",
373
+ "postcss-value-parser": "^4.2.0"
374
+ },
375
+ "bin": {
376
+ "autoprefixer": "bin/autoprefixer"
377
+ },
378
+ "engines": {
379
+ "node": "^10 || ^12 || >=14"
380
+ },
381
+ "peerDependencies": {
382
+ "postcss": "^8.1.0"
383
+ }
384
+ },
385
+ "node_modules/baseline-browser-mapping": {
386
+ "version": "2.10.33",
387
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.33.tgz",
388
+ "integrity": "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==",
389
+ "dev": true,
390
+ "license": "Apache-2.0",
391
+ "bin": {
392
+ "baseline-browser-mapping": "dist/cli.cjs"
393
+ },
394
+ "engines": {
395
+ "node": ">=6.0.0"
396
+ }
397
+ },
398
+ "node_modules/binary-extensions": {
399
+ "version": "2.3.0",
400
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
401
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
402
+ "dev": true,
403
+ "license": "MIT",
404
+ "engines": {
405
+ "node": ">=8"
406
+ },
407
+ "funding": {
408
+ "url": "https://github.com/sponsors/sindresorhus"
409
+ }
410
+ },
411
+ "node_modules/braces": {
412
+ "version": "3.0.3",
413
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
414
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
415
+ "dev": true,
416
+ "license": "MIT",
417
+ "dependencies": {
418
+ "fill-range": "^7.1.1"
419
+ },
420
+ "engines": {
421
+ "node": ">=8"
422
+ }
423
+ },
424
+ "node_modules/browserslist": {
425
+ "version": "4.28.2",
426
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
427
+ "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
428
+ "dev": true,
429
+ "funding": [
430
+ {
431
+ "type": "opencollective",
432
+ "url": "https://opencollective.com/browserslist"
433
+ },
434
+ {
435
+ "type": "tidelift",
436
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
437
+ },
438
+ {
439
+ "type": "github",
440
+ "url": "https://github.com/sponsors/ai"
441
+ }
442
+ ],
443
+ "license": "MIT",
444
+ "dependencies": {
445
+ "baseline-browser-mapping": "^2.10.12",
446
+ "caniuse-lite": "^1.0.30001782",
447
+ "electron-to-chromium": "^1.5.328",
448
+ "node-releases": "^2.0.36",
449
+ "update-browserslist-db": "^1.2.3"
450
+ },
451
+ "bin": {
452
+ "browserslist": "cli.js"
453
+ },
454
+ "engines": {
455
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
456
+ }
457
+ },
458
+ "node_modules/busboy": {
459
+ "version": "1.6.0",
460
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
461
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
462
+ "dependencies": {
463
+ "streamsearch": "^1.1.0"
464
+ },
465
+ "engines": {
466
+ "node": ">=10.16.0"
467
+ }
468
+ },
469
+ "node_modules/camelcase-css": {
470
+ "version": "2.0.1",
471
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
472
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
473
+ "dev": true,
474
+ "license": "MIT",
475
+ "engines": {
476
+ "node": ">= 6"
477
+ }
478
+ },
479
+ "node_modules/caniuse-lite": {
480
+ "version": "1.0.30001793",
481
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz",
482
+ "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==",
483
+ "funding": [
484
+ {
485
+ "type": "opencollective",
486
+ "url": "https://opencollective.com/browserslist"
487
+ },
488
+ {
489
+ "type": "tidelift",
490
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
491
+ },
492
+ {
493
+ "type": "github",
494
+ "url": "https://github.com/sponsors/ai"
495
+ }
496
+ ],
497
+ "license": "CC-BY-4.0"
498
+ },
499
+ "node_modules/chokidar": {
500
+ "version": "3.6.0",
501
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
502
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
503
+ "dev": true,
504
+ "license": "MIT",
505
+ "dependencies": {
506
+ "anymatch": "~3.1.2",
507
+ "braces": "~3.0.2",
508
+ "glob-parent": "~5.1.2",
509
+ "is-binary-path": "~2.1.0",
510
+ "is-glob": "~4.0.1",
511
+ "normalize-path": "~3.0.0",
512
+ "readdirp": "~3.6.0"
513
+ },
514
+ "engines": {
515
+ "node": ">= 8.10.0"
516
+ },
517
+ "funding": {
518
+ "url": "https://paulmillr.com/funding/"
519
+ },
520
+ "optionalDependencies": {
521
+ "fsevents": "~2.3.2"
522
+ }
523
+ },
524
+ "node_modules/chokidar/node_modules/glob-parent": {
525
+ "version": "5.1.2",
526
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
527
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
528
+ "dev": true,
529
+ "license": "ISC",
530
+ "dependencies": {
531
+ "is-glob": "^4.0.1"
532
+ },
533
+ "engines": {
534
+ "node": ">= 6"
535
+ }
536
+ },
537
+ "node_modules/client-only": {
538
+ "version": "0.0.1",
539
+ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
540
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
541
+ "license": "MIT"
542
+ },
543
+ "node_modules/commander": {
544
+ "version": "4.1.1",
545
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
546
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
547
+ "dev": true,
548
+ "license": "MIT",
549
+ "engines": {
550
+ "node": ">= 6"
551
+ }
552
+ },
553
+ "node_modules/cssesc": {
554
+ "version": "3.0.0",
555
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
556
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
557
+ "dev": true,
558
+ "license": "MIT",
559
+ "bin": {
560
+ "cssesc": "bin/cssesc"
561
+ },
562
+ "engines": {
563
+ "node": ">=4"
564
+ }
565
+ },
566
+ "node_modules/csstype": {
567
+ "version": "3.2.3",
568
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
569
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
570
+ "dev": true,
571
+ "license": "MIT"
572
+ },
573
+ "node_modules/didyoumean": {
574
+ "version": "1.2.2",
575
+ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
576
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
577
+ "dev": true,
578
+ "license": "Apache-2.0"
579
+ },
580
+ "node_modules/dlv": {
581
+ "version": "1.1.3",
582
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
583
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
584
+ "dev": true,
585
+ "license": "MIT"
586
+ },
587
+ "node_modules/electron-to-chromium": {
588
+ "version": "1.5.364",
589
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.364.tgz",
590
+ "integrity": "sha512-G/dYE3+AYhyHwzTwg8UbnXf7zqMERYh7l2jJ3QujhFsH8agSYwtnGAR2aZ7f0AakIKJXd5En/Hre4igIUrdlYw==",
591
+ "dev": true,
592
+ "license": "ISC"
593
+ },
594
+ "node_modules/es-errors": {
595
+ "version": "1.3.0",
596
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
597
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
598
+ "dev": true,
599
+ "license": "MIT",
600
+ "engines": {
601
+ "node": ">= 0.4"
602
+ }
603
+ },
604
+ "node_modules/escalade": {
605
+ "version": "3.2.0",
606
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
607
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
608
+ "dev": true,
609
+ "license": "MIT",
610
+ "engines": {
611
+ "node": ">=6"
612
+ }
613
+ },
614
+ "node_modules/fast-glob": {
615
+ "version": "3.3.3",
616
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
617
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
618
+ "dev": true,
619
+ "license": "MIT",
620
+ "dependencies": {
621
+ "@nodelib/fs.stat": "^2.0.2",
622
+ "@nodelib/fs.walk": "^1.2.3",
623
+ "glob-parent": "^5.1.2",
624
+ "merge2": "^1.3.0",
625
+ "micromatch": "^4.0.8"
626
+ },
627
+ "engines": {
628
+ "node": ">=8.6.0"
629
+ }
630
+ },
631
+ "node_modules/fast-glob/node_modules/glob-parent": {
632
+ "version": "5.1.2",
633
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
634
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
635
+ "dev": true,
636
+ "license": "ISC",
637
+ "dependencies": {
638
+ "is-glob": "^4.0.1"
639
+ },
640
+ "engines": {
641
+ "node": ">= 6"
642
+ }
643
+ },
644
+ "node_modules/fastq": {
645
+ "version": "1.20.1",
646
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
647
+ "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
648
+ "dev": true,
649
+ "license": "ISC",
650
+ "dependencies": {
651
+ "reusify": "^1.0.4"
652
+ }
653
+ },
654
+ "node_modules/fill-range": {
655
+ "version": "7.1.1",
656
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
657
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
658
+ "dev": true,
659
+ "license": "MIT",
660
+ "dependencies": {
661
+ "to-regex-range": "^5.0.1"
662
+ },
663
+ "engines": {
664
+ "node": ">=8"
665
+ }
666
+ },
667
+ "node_modules/fraction.js": {
668
+ "version": "4.3.7",
669
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
670
+ "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
671
+ "dev": true,
672
+ "license": "MIT",
673
+ "engines": {
674
+ "node": "*"
675
+ },
676
+ "funding": {
677
+ "type": "patreon",
678
+ "url": "https://github.com/sponsors/rawify"
679
+ }
680
+ },
681
+ "node_modules/fsevents": {
682
+ "version": "2.3.3",
683
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
684
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
685
+ "dev": true,
686
+ "hasInstallScript": true,
687
+ "license": "MIT",
688
+ "optional": true,
689
+ "os": [
690
+ "darwin"
691
+ ],
692
+ "engines": {
693
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
694
+ }
695
+ },
696
+ "node_modules/function-bind": {
697
+ "version": "1.1.2",
698
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
699
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
700
+ "dev": true,
701
+ "license": "MIT",
702
+ "funding": {
703
+ "url": "https://github.com/sponsors/ljharb"
704
+ }
705
+ },
706
+ "node_modules/glob-parent": {
707
+ "version": "6.0.2",
708
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
709
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
710
+ "dev": true,
711
+ "license": "ISC",
712
+ "dependencies": {
713
+ "is-glob": "^4.0.3"
714
+ },
715
+ "engines": {
716
+ "node": ">=10.13.0"
717
+ }
718
+ },
719
+ "node_modules/graceful-fs": {
720
+ "version": "4.2.11",
721
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
722
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
723
+ "license": "ISC"
724
+ },
725
+ "node_modules/hasown": {
726
+ "version": "2.0.4",
727
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
728
+ "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
729
+ "dev": true,
730
+ "license": "MIT",
731
+ "dependencies": {
732
+ "function-bind": "^1.1.2"
733
+ },
734
+ "engines": {
735
+ "node": ">= 0.4"
736
+ }
737
+ },
738
+ "node_modules/is-binary-path": {
739
+ "version": "2.1.0",
740
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
741
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
742
+ "dev": true,
743
+ "license": "MIT",
744
+ "dependencies": {
745
+ "binary-extensions": "^2.0.0"
746
+ },
747
+ "engines": {
748
+ "node": ">=8"
749
+ }
750
+ },
751
+ "node_modules/is-core-module": {
752
+ "version": "2.16.2",
753
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
754
+ "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
755
+ "dev": true,
756
+ "license": "MIT",
757
+ "dependencies": {
758
+ "hasown": "^2.0.3"
759
+ },
760
+ "engines": {
761
+ "node": ">= 0.4"
762
+ },
763
+ "funding": {
764
+ "url": "https://github.com/sponsors/ljharb"
765
+ }
766
+ },
767
+ "node_modules/is-extglob": {
768
+ "version": "2.1.1",
769
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
770
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
771
+ "dev": true,
772
+ "license": "MIT",
773
+ "engines": {
774
+ "node": ">=0.10.0"
775
+ }
776
+ },
777
+ "node_modules/is-glob": {
778
+ "version": "4.0.3",
779
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
780
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
781
+ "dev": true,
782
+ "license": "MIT",
783
+ "dependencies": {
784
+ "is-extglob": "^2.1.1"
785
+ },
786
+ "engines": {
787
+ "node": ">=0.10.0"
788
+ }
789
+ },
790
+ "node_modules/is-number": {
791
+ "version": "7.0.0",
792
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
793
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
794
+ "dev": true,
795
+ "license": "MIT",
796
+ "engines": {
797
+ "node": ">=0.12.0"
798
+ }
799
+ },
800
+ "node_modules/jiti": {
801
+ "version": "1.21.7",
802
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
803
+ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
804
+ "dev": true,
805
+ "license": "MIT",
806
+ "bin": {
807
+ "jiti": "bin/jiti.js"
808
+ }
809
+ },
810
+ "node_modules/js-tokens": {
811
+ "version": "4.0.0",
812
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
813
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
814
+ "license": "MIT"
815
+ },
816
+ "node_modules/lilconfig": {
817
+ "version": "2.1.0",
818
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
819
+ "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
820
+ "dev": true,
821
+ "license": "MIT",
822
+ "engines": {
823
+ "node": ">=10"
824
+ }
825
+ },
826
+ "node_modules/lines-and-columns": {
827
+ "version": "1.2.4",
828
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
829
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
830
+ "dev": true,
831
+ "license": "MIT"
832
+ },
833
+ "node_modules/loose-envify": {
834
+ "version": "1.4.0",
835
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
836
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
837
+ "license": "MIT",
838
+ "dependencies": {
839
+ "js-tokens": "^3.0.0 || ^4.0.0"
840
+ },
841
+ "bin": {
842
+ "loose-envify": "cli.js"
843
+ }
844
+ },
845
+ "node_modules/merge2": {
846
+ "version": "1.4.1",
847
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
848
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
849
+ "dev": true,
850
+ "license": "MIT",
851
+ "engines": {
852
+ "node": ">= 8"
853
+ }
854
+ },
855
+ "node_modules/micromatch": {
856
+ "version": "4.0.8",
857
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
858
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
859
+ "dev": true,
860
+ "license": "MIT",
861
+ "dependencies": {
862
+ "braces": "^3.0.3",
863
+ "picomatch": "^2.3.1"
864
+ },
865
+ "engines": {
866
+ "node": ">=8.6"
867
+ }
868
+ },
869
+ "node_modules/mz": {
870
+ "version": "2.7.0",
871
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
872
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
873
+ "dev": true,
874
+ "license": "MIT",
875
+ "dependencies": {
876
+ "any-promise": "^1.0.0",
877
+ "object-assign": "^4.0.1",
878
+ "thenify-all": "^1.0.0"
879
+ }
880
+ },
881
+ "node_modules/nanoid": {
882
+ "version": "3.3.12",
883
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
884
+ "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
885
+ "funding": [
886
+ {
887
+ "type": "github",
888
+ "url": "https://github.com/sponsors/ai"
889
+ }
890
+ ],
891
+ "license": "MIT",
892
+ "bin": {
893
+ "nanoid": "bin/nanoid.cjs"
894
+ },
895
+ "engines": {
896
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
897
+ }
898
+ },
899
+ "node_modules/next": {
900
+ "version": "14.2.35",
901
+ "resolved": "https://registry.npmjs.org/next/-/next-14.2.35.tgz",
902
+ "integrity": "sha512-KhYd2Hjt/O1/1aZVX3dCwGXM1QmOV4eNM2UTacK5gipDdPN/oHHK/4oVGy7X8GMfPMsUTUEmGlsy0EY1YGAkig==",
903
+ "license": "MIT",
904
+ "dependencies": {
905
+ "@next/env": "14.2.35",
906
+ "@swc/helpers": "0.5.5",
907
+ "busboy": "1.6.0",
908
+ "caniuse-lite": "^1.0.30001579",
909
+ "graceful-fs": "^4.2.11",
910
+ "postcss": "8.4.31",
911
+ "styled-jsx": "5.1.1"
912
+ },
913
+ "bin": {
914
+ "next": "dist/bin/next"
915
+ },
916
+ "engines": {
917
+ "node": ">=18.17.0"
918
+ },
919
+ "optionalDependencies": {
920
+ "@next/swc-darwin-arm64": "14.2.33",
921
+ "@next/swc-darwin-x64": "14.2.33",
922
+ "@next/swc-linux-arm64-gnu": "14.2.33",
923
+ "@next/swc-linux-arm64-musl": "14.2.33",
924
+ "@next/swc-linux-x64-gnu": "14.2.33",
925
+ "@next/swc-linux-x64-musl": "14.2.33",
926
+ "@next/swc-win32-arm64-msvc": "14.2.33",
927
+ "@next/swc-win32-ia32-msvc": "14.2.33",
928
+ "@next/swc-win32-x64-msvc": "14.2.33"
929
+ },
930
+ "peerDependencies": {
931
+ "@opentelemetry/api": "^1.1.0",
932
+ "@playwright/test": "^1.41.2",
933
+ "react": "^18.2.0",
934
+ "react-dom": "^18.2.0",
935
+ "sass": "^1.3.0"
936
+ },
937
+ "peerDependenciesMeta": {
938
+ "@opentelemetry/api": {
939
+ "optional": true
940
+ },
941
+ "@playwright/test": {
942
+ "optional": true
943
+ },
944
+ "sass": {
945
+ "optional": true
946
+ }
947
+ }
948
+ },
949
+ "node_modules/next/node_modules/postcss": {
950
+ "version": "8.4.31",
951
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
952
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
953
+ "funding": [
954
+ {
955
+ "type": "opencollective",
956
+ "url": "https://opencollective.com/postcss/"
957
+ },
958
+ {
959
+ "type": "tidelift",
960
+ "url": "https://tidelift.com/funding/github/npm/postcss"
961
+ },
962
+ {
963
+ "type": "github",
964
+ "url": "https://github.com/sponsors/ai"
965
+ }
966
+ ],
967
+ "license": "MIT",
968
+ "dependencies": {
969
+ "nanoid": "^3.3.6",
970
+ "picocolors": "^1.0.0",
971
+ "source-map-js": "^1.0.2"
972
+ },
973
+ "engines": {
974
+ "node": "^10 || ^12 || >=14"
975
+ }
976
+ },
977
+ "node_modules/node-releases": {
978
+ "version": "2.0.46",
979
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.46.tgz",
980
+ "integrity": "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==",
981
+ "dev": true,
982
+ "license": "MIT",
983
+ "engines": {
984
+ "node": ">=18"
985
+ }
986
+ },
987
+ "node_modules/normalize-path": {
988
+ "version": "3.0.0",
989
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
990
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
991
+ "dev": true,
992
+ "license": "MIT",
993
+ "engines": {
994
+ "node": ">=0.10.0"
995
+ }
996
+ },
997
+ "node_modules/normalize-range": {
998
+ "version": "0.1.2",
999
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
1000
+ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
1001
+ "dev": true,
1002
+ "license": "MIT",
1003
+ "engines": {
1004
+ "node": ">=0.10.0"
1005
+ }
1006
+ },
1007
+ "node_modules/object-assign": {
1008
+ "version": "4.1.1",
1009
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
1010
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
1011
+ "dev": true,
1012
+ "license": "MIT",
1013
+ "engines": {
1014
+ "node": ">=0.10.0"
1015
+ }
1016
+ },
1017
+ "node_modules/object-hash": {
1018
+ "version": "3.0.0",
1019
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
1020
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
1021
+ "dev": true,
1022
+ "license": "MIT",
1023
+ "engines": {
1024
+ "node": ">= 6"
1025
+ }
1026
+ },
1027
+ "node_modules/path-parse": {
1028
+ "version": "1.0.7",
1029
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
1030
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
1031
+ "dev": true,
1032
+ "license": "MIT"
1033
+ },
1034
+ "node_modules/picocolors": {
1035
+ "version": "1.1.1",
1036
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
1037
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
1038
+ "license": "ISC"
1039
+ },
1040
+ "node_modules/picomatch": {
1041
+ "version": "2.3.2",
1042
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
1043
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
1044
+ "dev": true,
1045
+ "license": "MIT",
1046
+ "engines": {
1047
+ "node": ">=8.6"
1048
+ },
1049
+ "funding": {
1050
+ "url": "https://github.com/sponsors/jonschlinkert"
1051
+ }
1052
+ },
1053
+ "node_modules/pify": {
1054
+ "version": "2.3.0",
1055
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
1056
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
1057
+ "dev": true,
1058
+ "license": "MIT",
1059
+ "engines": {
1060
+ "node": ">=0.10.0"
1061
+ }
1062
+ },
1063
+ "node_modules/pirates": {
1064
+ "version": "4.0.7",
1065
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
1066
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
1067
+ "dev": true,
1068
+ "license": "MIT",
1069
+ "engines": {
1070
+ "node": ">= 6"
1071
+ }
1072
+ },
1073
+ "node_modules/postcss": {
1074
+ "version": "8.5.10",
1075
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz",
1076
+ "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==",
1077
+ "dev": true,
1078
+ "funding": [
1079
+ {
1080
+ "type": "opencollective",
1081
+ "url": "https://opencollective.com/postcss/"
1082
+ },
1083
+ {
1084
+ "type": "tidelift",
1085
+ "url": "https://tidelift.com/funding/github/npm/postcss"
1086
+ },
1087
+ {
1088
+ "type": "github",
1089
+ "url": "https://github.com/sponsors/ai"
1090
+ }
1091
+ ],
1092
+ "license": "MIT",
1093
+ "dependencies": {
1094
+ "nanoid": "^3.3.11",
1095
+ "picocolors": "^1.1.1",
1096
+ "source-map-js": "^1.2.1"
1097
+ },
1098
+ "engines": {
1099
+ "node": "^10 || ^12 || >=14"
1100
+ }
1101
+ },
1102
+ "node_modules/postcss-import": {
1103
+ "version": "15.1.0",
1104
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
1105
+ "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
1106
+ "dev": true,
1107
+ "license": "MIT",
1108
+ "dependencies": {
1109
+ "postcss-value-parser": "^4.0.0",
1110
+ "read-cache": "^1.0.0",
1111
+ "resolve": "^1.1.7"
1112
+ },
1113
+ "engines": {
1114
+ "node": ">=14.0.0"
1115
+ },
1116
+ "peerDependencies": {
1117
+ "postcss": "^8.0.0"
1118
+ }
1119
+ },
1120
+ "node_modules/postcss-js": {
1121
+ "version": "4.1.0",
1122
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz",
1123
+ "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==",
1124
+ "dev": true,
1125
+ "funding": [
1126
+ {
1127
+ "type": "opencollective",
1128
+ "url": "https://opencollective.com/postcss/"
1129
+ },
1130
+ {
1131
+ "type": "github",
1132
+ "url": "https://github.com/sponsors/ai"
1133
+ }
1134
+ ],
1135
+ "license": "MIT",
1136
+ "dependencies": {
1137
+ "camelcase-css": "^2.0.1"
1138
+ },
1139
+ "engines": {
1140
+ "node": "^12 || ^14 || >= 16"
1141
+ },
1142
+ "peerDependencies": {
1143
+ "postcss": "^8.4.21"
1144
+ }
1145
+ },
1146
+ "node_modules/postcss-nested": {
1147
+ "version": "6.2.0",
1148
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
1149
+ "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
1150
+ "dev": true,
1151
+ "funding": [
1152
+ {
1153
+ "type": "opencollective",
1154
+ "url": "https://opencollective.com/postcss/"
1155
+ },
1156
+ {
1157
+ "type": "github",
1158
+ "url": "https://github.com/sponsors/ai"
1159
+ }
1160
+ ],
1161
+ "license": "MIT",
1162
+ "dependencies": {
1163
+ "postcss-selector-parser": "^6.1.1"
1164
+ },
1165
+ "engines": {
1166
+ "node": ">=12.0"
1167
+ },
1168
+ "peerDependencies": {
1169
+ "postcss": "^8.2.14"
1170
+ }
1171
+ },
1172
+ "node_modules/postcss-selector-parser": {
1173
+ "version": "6.1.2",
1174
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
1175
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
1176
+ "dev": true,
1177
+ "license": "MIT",
1178
+ "dependencies": {
1179
+ "cssesc": "^3.0.0",
1180
+ "util-deprecate": "^1.0.2"
1181
+ },
1182
+ "engines": {
1183
+ "node": ">=4"
1184
+ }
1185
+ },
1186
+ "node_modules/postcss-value-parser": {
1187
+ "version": "4.2.0",
1188
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
1189
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
1190
+ "dev": true,
1191
+ "license": "MIT"
1192
+ },
1193
+ "node_modules/queue-microtask": {
1194
+ "version": "1.2.3",
1195
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
1196
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
1197
+ "dev": true,
1198
+ "funding": [
1199
+ {
1200
+ "type": "github",
1201
+ "url": "https://github.com/sponsors/feross"
1202
+ },
1203
+ {
1204
+ "type": "patreon",
1205
+ "url": "https://www.patreon.com/feross"
1206
+ },
1207
+ {
1208
+ "type": "consulting",
1209
+ "url": "https://feross.org/support"
1210
+ }
1211
+ ],
1212
+ "license": "MIT"
1213
+ },
1214
+ "node_modules/react": {
1215
+ "version": "18.3.1",
1216
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
1217
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
1218
+ "license": "MIT",
1219
+ "dependencies": {
1220
+ "loose-envify": "^1.1.0"
1221
+ },
1222
+ "engines": {
1223
+ "node": ">=0.10.0"
1224
+ }
1225
+ },
1226
+ "node_modules/react-dom": {
1227
+ "version": "18.3.1",
1228
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
1229
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
1230
+ "license": "MIT",
1231
+ "dependencies": {
1232
+ "loose-envify": "^1.1.0",
1233
+ "scheduler": "^0.23.2"
1234
+ },
1235
+ "peerDependencies": {
1236
+ "react": "^18.3.1"
1237
+ }
1238
+ },
1239
+ "node_modules/read-cache": {
1240
+ "version": "1.0.0",
1241
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
1242
+ "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
1243
+ "dev": true,
1244
+ "license": "MIT",
1245
+ "dependencies": {
1246
+ "pify": "^2.3.0"
1247
+ }
1248
+ },
1249
+ "node_modules/readdirp": {
1250
+ "version": "3.6.0",
1251
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
1252
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
1253
+ "dev": true,
1254
+ "license": "MIT",
1255
+ "dependencies": {
1256
+ "picomatch": "^2.2.1"
1257
+ },
1258
+ "engines": {
1259
+ "node": ">=8.10.0"
1260
+ }
1261
+ },
1262
+ "node_modules/resolve": {
1263
+ "version": "1.22.12",
1264
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
1265
+ "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
1266
+ "dev": true,
1267
+ "license": "MIT",
1268
+ "dependencies": {
1269
+ "es-errors": "^1.3.0",
1270
+ "is-core-module": "^2.16.1",
1271
+ "path-parse": "^1.0.7",
1272
+ "supports-preserve-symlinks-flag": "^1.0.0"
1273
+ },
1274
+ "bin": {
1275
+ "resolve": "bin/resolve"
1276
+ },
1277
+ "engines": {
1278
+ "node": ">= 0.4"
1279
+ },
1280
+ "funding": {
1281
+ "url": "https://github.com/sponsors/ljharb"
1282
+ }
1283
+ },
1284
+ "node_modules/reusify": {
1285
+ "version": "1.1.0",
1286
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
1287
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
1288
+ "dev": true,
1289
+ "license": "MIT",
1290
+ "engines": {
1291
+ "iojs": ">=1.0.0",
1292
+ "node": ">=0.10.0"
1293
+ }
1294
+ },
1295
+ "node_modules/run-parallel": {
1296
+ "version": "1.2.0",
1297
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
1298
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
1299
+ "dev": true,
1300
+ "funding": [
1301
+ {
1302
+ "type": "github",
1303
+ "url": "https://github.com/sponsors/feross"
1304
+ },
1305
+ {
1306
+ "type": "patreon",
1307
+ "url": "https://www.patreon.com/feross"
1308
+ },
1309
+ {
1310
+ "type": "consulting",
1311
+ "url": "https://feross.org/support"
1312
+ }
1313
+ ],
1314
+ "license": "MIT",
1315
+ "dependencies": {
1316
+ "queue-microtask": "^1.2.2"
1317
+ }
1318
+ },
1319
+ "node_modules/scheduler": {
1320
+ "version": "0.23.2",
1321
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
1322
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
1323
+ "license": "MIT",
1324
+ "dependencies": {
1325
+ "loose-envify": "^1.1.0"
1326
+ }
1327
+ },
1328
+ "node_modules/source-map-js": {
1329
+ "version": "1.2.1",
1330
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
1331
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
1332
+ "license": "BSD-3-Clause",
1333
+ "engines": {
1334
+ "node": ">=0.10.0"
1335
+ }
1336
+ },
1337
+ "node_modules/streamsearch": {
1338
+ "version": "1.1.0",
1339
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
1340
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
1341
+ "engines": {
1342
+ "node": ">=10.0.0"
1343
+ }
1344
+ },
1345
+ "node_modules/styled-jsx": {
1346
+ "version": "5.1.1",
1347
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
1348
+ "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
1349
+ "license": "MIT",
1350
+ "dependencies": {
1351
+ "client-only": "0.0.1"
1352
+ },
1353
+ "engines": {
1354
+ "node": ">= 12.0.0"
1355
+ },
1356
+ "peerDependencies": {
1357
+ "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
1358
+ },
1359
+ "peerDependenciesMeta": {
1360
+ "@babel/core": {
1361
+ "optional": true
1362
+ },
1363
+ "babel-plugin-macros": {
1364
+ "optional": true
1365
+ }
1366
+ }
1367
+ },
1368
+ "node_modules/sucrase": {
1369
+ "version": "3.35.1",
1370
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
1371
+ "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==",
1372
+ "dev": true,
1373
+ "license": "MIT",
1374
+ "dependencies": {
1375
+ "@jridgewell/gen-mapping": "^0.3.2",
1376
+ "commander": "^4.0.0",
1377
+ "lines-and-columns": "^1.1.6",
1378
+ "mz": "^2.7.0",
1379
+ "pirates": "^4.0.1",
1380
+ "tinyglobby": "^0.2.11",
1381
+ "ts-interface-checker": "^0.1.9"
1382
+ },
1383
+ "bin": {
1384
+ "sucrase": "bin/sucrase",
1385
+ "sucrase-node": "bin/sucrase-node"
1386
+ },
1387
+ "engines": {
1388
+ "node": ">=16 || 14 >=14.17"
1389
+ }
1390
+ },
1391
+ "node_modules/supports-preserve-symlinks-flag": {
1392
+ "version": "1.0.0",
1393
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
1394
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
1395
+ "dev": true,
1396
+ "license": "MIT",
1397
+ "engines": {
1398
+ "node": ">= 0.4"
1399
+ },
1400
+ "funding": {
1401
+ "url": "https://github.com/sponsors/ljharb"
1402
+ }
1403
+ },
1404
+ "node_modules/tailwindcss": {
1405
+ "version": "3.4.14",
1406
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz",
1407
+ "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==",
1408
+ "dev": true,
1409
+ "license": "MIT",
1410
+ "dependencies": {
1411
+ "@alloc/quick-lru": "^5.2.0",
1412
+ "arg": "^5.0.2",
1413
+ "chokidar": "^3.5.3",
1414
+ "didyoumean": "^1.2.2",
1415
+ "dlv": "^1.1.3",
1416
+ "fast-glob": "^3.3.0",
1417
+ "glob-parent": "^6.0.2",
1418
+ "is-glob": "^4.0.3",
1419
+ "jiti": "^1.21.0",
1420
+ "lilconfig": "^2.1.0",
1421
+ "micromatch": "^4.0.5",
1422
+ "normalize-path": "^3.0.0",
1423
+ "object-hash": "^3.0.0",
1424
+ "picocolors": "^1.0.0",
1425
+ "postcss": "^8.4.23",
1426
+ "postcss-import": "^15.1.0",
1427
+ "postcss-js": "^4.0.1",
1428
+ "postcss-load-config": "^4.0.1",
1429
+ "postcss-nested": "^6.0.1",
1430
+ "postcss-selector-parser": "^6.0.11",
1431
+ "resolve": "^1.22.2",
1432
+ "sucrase": "^3.32.0"
1433
+ },
1434
+ "bin": {
1435
+ "tailwind": "lib/cli.js",
1436
+ "tailwindcss": "lib/cli.js"
1437
+ },
1438
+ "engines": {
1439
+ "node": ">=14.0.0"
1440
+ }
1441
+ },
1442
+ "node_modules/tailwindcss/node_modules/postcss-load-config": {
1443
+ "version": "4.0.2",
1444
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
1445
+ "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
1446
+ "dev": true,
1447
+ "funding": [
1448
+ {
1449
+ "type": "opencollective",
1450
+ "url": "https://opencollective.com/postcss/"
1451
+ },
1452
+ {
1453
+ "type": "github",
1454
+ "url": "https://github.com/sponsors/ai"
1455
+ }
1456
+ ],
1457
+ "license": "MIT",
1458
+ "dependencies": {
1459
+ "lilconfig": "^3.0.0",
1460
+ "yaml": "^2.3.4"
1461
+ },
1462
+ "engines": {
1463
+ "node": ">= 14"
1464
+ },
1465
+ "peerDependencies": {
1466
+ "postcss": ">=8.0.9",
1467
+ "ts-node": ">=9.0.0"
1468
+ },
1469
+ "peerDependenciesMeta": {
1470
+ "postcss": {
1471
+ "optional": true
1472
+ },
1473
+ "ts-node": {
1474
+ "optional": true
1475
+ }
1476
+ }
1477
+ },
1478
+ "node_modules/tailwindcss/node_modules/postcss-load-config/node_modules/lilconfig": {
1479
+ "version": "3.1.3",
1480
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
1481
+ "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
1482
+ "dev": true,
1483
+ "license": "MIT",
1484
+ "engines": {
1485
+ "node": ">=14"
1486
+ },
1487
+ "funding": {
1488
+ "url": "https://github.com/sponsors/antonk52"
1489
+ }
1490
+ },
1491
+ "node_modules/thenify": {
1492
+ "version": "3.3.1",
1493
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
1494
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
1495
+ "dev": true,
1496
+ "license": "MIT",
1497
+ "dependencies": {
1498
+ "any-promise": "^1.0.0"
1499
+ }
1500
+ },
1501
+ "node_modules/thenify-all": {
1502
+ "version": "1.6.0",
1503
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
1504
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
1505
+ "dev": true,
1506
+ "license": "MIT",
1507
+ "dependencies": {
1508
+ "thenify": ">= 3.1.0 < 4"
1509
+ },
1510
+ "engines": {
1511
+ "node": ">=0.8"
1512
+ }
1513
+ },
1514
+ "node_modules/tinyglobby": {
1515
+ "version": "0.2.17",
1516
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
1517
+ "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
1518
+ "dev": true,
1519
+ "license": "MIT",
1520
+ "dependencies": {
1521
+ "fdir": "^6.5.0",
1522
+ "picomatch": "^4.0.4"
1523
+ },
1524
+ "engines": {
1525
+ "node": ">=12.0.0"
1526
+ },
1527
+ "funding": {
1528
+ "url": "https://github.com/sponsors/SuperchupuDev"
1529
+ }
1530
+ },
1531
+ "node_modules/tinyglobby/node_modules/fdir": {
1532
+ "version": "6.5.0",
1533
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
1534
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
1535
+ "dev": true,
1536
+ "license": "MIT",
1537
+ "engines": {
1538
+ "node": ">=12.0.0"
1539
+ },
1540
+ "peerDependencies": {
1541
+ "picomatch": "^3 || ^4"
1542
+ },
1543
+ "peerDependenciesMeta": {
1544
+ "picomatch": {
1545
+ "optional": true
1546
+ }
1547
+ }
1548
+ },
1549
+ "node_modules/tinyglobby/node_modules/picomatch": {
1550
+ "version": "4.0.4",
1551
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
1552
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
1553
+ "dev": true,
1554
+ "license": "MIT",
1555
+ "engines": {
1556
+ "node": ">=12"
1557
+ },
1558
+ "funding": {
1559
+ "url": "https://github.com/sponsors/jonschlinkert"
1560
+ }
1561
+ },
1562
+ "node_modules/to-regex-range": {
1563
+ "version": "5.0.1",
1564
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1565
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1566
+ "dev": true,
1567
+ "license": "MIT",
1568
+ "dependencies": {
1569
+ "is-number": "^7.0.0"
1570
+ },
1571
+ "engines": {
1572
+ "node": ">=8.0"
1573
+ }
1574
+ },
1575
+ "node_modules/ts-interface-checker": {
1576
+ "version": "0.1.13",
1577
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
1578
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
1579
+ "dev": true,
1580
+ "license": "Apache-2.0"
1581
+ },
1582
+ "node_modules/tslib": {
1583
+ "version": "2.8.1",
1584
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
1585
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
1586
+ "license": "0BSD"
1587
+ },
1588
+ "node_modules/typescript": {
1589
+ "version": "5.6.3",
1590
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
1591
+ "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
1592
+ "dev": true,
1593
+ "license": "Apache-2.0",
1594
+ "bin": {
1595
+ "tsc": "bin/tsc",
1596
+ "tsserver": "bin/tsserver"
1597
+ },
1598
+ "engines": {
1599
+ "node": ">=14.17"
1600
+ }
1601
+ },
1602
+ "node_modules/undici-types": {
1603
+ "version": "6.19.8",
1604
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
1605
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
1606
+ "dev": true,
1607
+ "license": "MIT"
1608
+ },
1609
+ "node_modules/update-browserslist-db": {
1610
+ "version": "1.2.3",
1611
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
1612
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
1613
+ "dev": true,
1614
+ "funding": [
1615
+ {
1616
+ "type": "opencollective",
1617
+ "url": "https://opencollective.com/browserslist"
1618
+ },
1619
+ {
1620
+ "type": "tidelift",
1621
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
1622
+ },
1623
+ {
1624
+ "type": "github",
1625
+ "url": "https://github.com/sponsors/ai"
1626
+ }
1627
+ ],
1628
+ "license": "MIT",
1629
+ "dependencies": {
1630
+ "escalade": "^3.2.0",
1631
+ "picocolors": "^1.1.1"
1632
+ },
1633
+ "bin": {
1634
+ "update-browserslist-db": "cli.js"
1635
+ },
1636
+ "peerDependencies": {
1637
+ "browserslist": ">= 4.21.0"
1638
+ }
1639
+ },
1640
+ "node_modules/util-deprecate": {
1641
+ "version": "1.0.2",
1642
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
1643
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
1644
+ "dev": true,
1645
+ "license": "MIT"
1646
+ },
1647
+ "node_modules/yaml": {
1648
+ "version": "2.9.0",
1649
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
1650
+ "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
1651
+ "dev": true,
1652
+ "license": "ISC",
1653
+ "bin": {
1654
+ "yaml": "bin.mjs"
1655
+ },
1656
+ "engines": {
1657
+ "node": ">= 14.6"
1658
+ },
1659
+ "funding": {
1660
+ "url": "https://github.com/sponsors/eemeli"
1661
+ }
1662
+ }
1663
+ }
1664
+ }
web/package.json ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "self-improving-agent-web",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "next dev",
7
+ "build": "next build",
8
+ "start": "next start"
9
+ },
10
+ "dependencies": {
11
+ "next": "14.2.35",
12
+ "react": "18.3.1",
13
+ "react-dom": "18.3.1"
14
+ },
15
+ "devDependencies": {
16
+ "@types/node": "20.16.11",
17
+ "@types/react": "18.3.11",
18
+ "@types/react-dom": "18.3.0",
19
+ "autoprefixer": "10.4.20",
20
+ "postcss": "8.5.10",
21
+ "tailwindcss": "3.4.14",
22
+ "typescript": "5.6.3"
23
+ }
24
+ }
web/postcss.config.mjs ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ /** @type {import('postcss-load-config').Config} */
2
+ const config = {
3
+ plugins: {
4
+ tailwindcss: {},
5
+ autoprefixer: {},
6
+ },
7
+ };
8
+
9
+ export default config;
web/tailwind.config.ts ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { Config } from "tailwindcss";
2
+
3
+ const config: Config = {
4
+ content: [
5
+ "./app/**/*.{ts,tsx}",
6
+ "./components/**/*.{ts,tsx}",
7
+ ],
8
+ theme: {
9
+ extend: {
10
+ colors: {
11
+ // Restrained, dashboard-style neutral palette.
12
+ ink: {
13
+ 950: "#0a0a0b",
14
+ 900: "#0e0e10",
15
+ 850: "#141417",
16
+ 800: "#1b1b1f",
17
+ 700: "#26262b",
18
+ 600: "#3a3a42",
19
+ },
20
+ },
21
+ fontFamily: {
22
+ sans: [
23
+ "ui-sans-serif",
24
+ "system-ui",
25
+ "-apple-system",
26
+ "Segoe UI",
27
+ "Roboto",
28
+ "Helvetica Neue",
29
+ "Arial",
30
+ "sans-serif",
31
+ ],
32
+ mono: [
33
+ "ui-monospace",
34
+ "SFMono-Regular",
35
+ "Menlo",
36
+ "Consolas",
37
+ "Liberation Mono",
38
+ "monospace",
39
+ ],
40
+ },
41
+ },
42
+ },
43
+ plugins: [],
44
+ };
45
+
46
+ export default config;
web/tsconfig.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2017",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "esnext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "preserve",
15
+ "incremental": true,
16
+ "plugins": [{ "name": "next" }],
17
+ "paths": {
18
+ "@/*": ["./*"]
19
+ }
20
+ },
21
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
22
+ "exclude": ["node_modules"]
23
+ }