diff --git a/website/.eslintrc.json b/website/.eslintrc.json
new file mode 100644
index 0000000..bffb357
--- /dev/null
+++ b/website/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "next/core-web-vitals"
+}
diff --git a/website/.gitignore b/website/.gitignore
new file mode 100644
index 0000000..ed785d2
--- /dev/null
+++ b/website/.gitignore
@@ -0,0 +1,20 @@
+node_modules
+.next
+out
+dist
+build
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+.pnpm-debug.log*
+
+.env
+.env*.local
+
+.DS_Store
+*.pem
+
+.vercel
+*.tsbuildinfo
+next-env.d.ts
diff --git a/website/.prettierrc.json b/website/.prettierrc.json
new file mode 100644
index 0000000..2510718
--- /dev/null
+++ b/website/.prettierrc.json
@@ -0,0 +1,7 @@
+{
+ "semi": true,
+ "singleQuote": false,
+ "trailingComma": "es5",
+ "printWidth": 90,
+ "plugins": ["prettier-plugin-tailwindcss"]
+}
diff --git a/website/README.md b/website/README.md
new file mode 100644
index 0000000..d3b38d1
--- /dev/null
+++ b/website/README.md
@@ -0,0 +1,70 @@
+# Folio website
+
+Marketing and documentation site for [Folio](https://github.com/woosal1337/folio),
+the local-first meeting transcription app for macOS. Built with Next.js, React,
+TypeScript, and Tailwind CSS, and styled with Folio's own design tokens. Lives in
+`website/` inside the main Folio repository.
+
+## Stack
+
+- **Next.js 15** (App Router) + **React 18**
+- **TypeScript**
+- **Tailwind CSS 3** with Folio's color, type, and motion tokens
+- **Radix UI** primitives (tabs, accordion) and **lucide-react** icons
+- **Bun** as the package manager and runtime
+
+## Develop
+
+```sh
+bun install
+bun run dev
+```
+
+The site runs at `http://localhost:3000`.
+
+## Scripts
+
+| Script | What it does |
+| --- | --- |
+| `bun run dev` | Start the dev server |
+| `bun run build` | Production build |
+| `bun run start` | Serve the production build |
+| `bun run lint` | Lint with `next lint` |
+| `bun run typecheck` | Type-check without emitting |
+| `bun run format` | Format with Prettier |
+
+## Structure
+
+```
+website/
+├── app/ # routes (landing, features, docs/*)
+│ ├── layout.tsx # fonts, dark theme, header, footer
+│ ├── page.tsx # landing page
+│ ├── features/ # features page
+│ └── docs/ # documentation (overview, install, usage, architecture, ...)
+├── components/
+│ ├── ui/ # design-system primitives (button, card, badge, tabs, ...)
+│ ├── site/ # header, footer, logo, code blocks, sections
+│ ├── landing/ # landing-page sections and visuals
+│ └── docs/ # docs shell, sidebar, pager, and content primitives
+├── lib/ # site config, docs navigation, utils
+└── public/ # logo and favicon
+```
+
+## Design
+
+Dark mode only, with a monochrome palette taken straight from the Folio desktop app
+(`src/styles/globals.css` and `tailwind.config.ts` in the repo root): near-black
+surfaces, white and gray foreground, no accent color. The logo is Folio's own app
+mark, and the wordmark is set in Spectral. Body and headings use the system font
+stack (SF Pro on macOS), matching the app.
+
+## Deploy
+
+A standard Next.js App Router project. On Vercel, set the project root to `website/`,
+keep the default build command (`next build`), and Bun is detected from `bun.lock`.
+
+## Code style
+
+No source comments, per the Folio convention. Code is kept self-explanatory through
+naming and small components. Prose belongs in the docs, not in the source.
diff --git a/website/app/docs/architecture/page.tsx b/website/app/docs/architecture/page.tsx
new file mode 100644
index 0000000..c663e87
--- /dev/null
+++ b/website/app/docs/architecture/page.tsx
@@ -0,0 +1,209 @@
+import type { Metadata } from "next";
+import { siteConfig } from "@/lib/site-config";
+import { CodeBlock } from "@/components/site/code-block";
+import {
+ DocHeader,
+ DocH2,
+ Prose,
+ Callout,
+ FieldList,
+ Field,
+} from "@/components/docs/doc-primitives";
+
+export const metadata: Metadata = {
+ title: "Architecture",
+ description:
+ "How Folio is built, from the Rust core through the Tauri shell to the data flow that moves a meeting from microphone to markdown.",
+};
+
+const repositoryLayout = `folio/
+ Cargo.toml workspace root
+ rust-toolchain.toml Rust 1.88, both Apple targets
+ crates/
+ folio-core/ audio capture, storage, transcription, diarization
+ folio-cli/ CLI test harness
+ folio-mcp/ local MCP stdio server (notes, tasks, memories)
+ src-tauri/ Tauri 2 desktop binary
+ src/ React 18 + TypeScript + Tailwind frontend
+ Casks/ Homebrew cask (the repo doubles as its own tap)
+ docs/ repo-local documentation`;
+
+const dataFlow = `React (src/)
+ features/* + Zustand stores + shared/lib/ipc.ts
+ | invoke: JSON over Tauri IPC
+ v
+src-tauri/
+ commands/* + app/state.rs + folio-core re-exports
+ | direct function calls
+ v
+folio-core
+ audio:: + llm:: + memory:: + storage:: + transcription::
+ | OS APIs + OpenAI + whisper.cpp + SQLite
+ v
+Disk + Hardware + Network`;
+
+export default function ArchitecturePage() {
+ return (
+ <>
+
+
+ The stack
+
+
+ {siteConfig.name} is a Rust program with a desktop face. About 70
+ percent of the code is a Rust core that owns audio capture, storage,
+ and transcription. That core is wrapped by a Tauri 2 desktop binary,
+ which gives it a native window, OS permissions, and a menu-bar
+ presence without shipping a full browser engine.
+
+
+ The interface is a React 18 frontend written in TypeScript and styled
+ with Tailwind. The two halves talk over Tauri IPC. The types that
+ cross that boundary are not written twice. They are defined once in
+ Rust and generated to TypeScript with ts-rs, so the
+ frontend always sees the same shapes the core returns.
+
+
+
+ Repository layout
+
+
+ The repository is a single Cargo workspace plus the frontend and the
+ packaging it ships with. The Rust toolchain is pinned, the crates are
+ split by responsibility, and the Homebrew cask lives in the repository
+ itself, so the project doubles as its own tap.
+
+
+
+
+ The Rust core
+
+
+ The workspace holds three crates. Each has one job and a clear edge
+ against the others.
+
+
+
+
+ The framework-agnostic core. It owns audio capture, storage,
+ transcription, diarization, the agent, and the memory and task stores.
+ It is embeddable by the Tauri app, by the CLI, or by a future Swift
+ app via UniFFI.
+
+
+ A CLI test harness. It exercises the core from the terminal without
+ the desktop shell, which makes audio devices and recording easy to
+ probe in isolation.
+
+
+ The local MCP stdio server. It exposes notes, tasks, and memories to
+ MCP-aware tools with read-only access and no network hop.
+
+
+
+
+ A few rules hold across the core. FolioError is the
+ single public error type, so callers handle one shape instead of a
+ dozen. Logging goes through the tracing crate, never{" "}
+ println, and audio callbacks are alloc-free hot paths
+ that never log inside the callback body. macOS-specific code is gated
+ behind a cfg(target_os = "macos") attribute,
+ with stubs for other targets so the whole workspace still builds
+ everywhere.
+
+
+
+ Capture pipeline
+
+
+ When a meeting starts, {siteConfig.name} records two independent
+ streams. cpal captures the microphone. ScreenCaptureKit
+ captures system audio, which is everyone else on the call. Keeping the
+ streams separate is what makes the rest of the pipeline honest. Your
+ voice and the room never get mixed into one undecodable track.
+
+
+ The two streams rarely share a sample rate, so rubato{" "}
+ resamples them to a common rate, and hound writes the
+ result to WAV files on disk. The microphone track is always labelled{" "}
+ You, which the transcription and diarization steps then
+ rely on.
+
+
+
+
+ Transcription and diarization
+
+
+
+ Transcription runs locally by default. The bundled backend is
+ whisper.cpp through the whisper-rs bindings,
+ Metal-accelerated on Apple Silicon. This is the primary path and it
+ needs no network once the weights are present. The OpenAI Whisper API
+ is an opt-in fallback for faster cloud transcription on long meetings.
+ It needs an OpenAI key and it is never the default.
+
+
+ Diarization runs on-device against the system-audio track. It uses a
+ pyannote-segmentation-3.0 model plus a WeSpeaker speaker-embedding
+ model, both run through sherpa-onnx, then clusters the voices into
+ Speaker 1, Speaker 2, Speaker 3 and so on. The microphone is always{" "}
+ You, and no cloud is involved in diarization at all.
+
+
+
+ The IPC contract
+
+
+ Every Tauri command is the contract between the core and the frontend.
+ The argument and return types of those commands are defined in{" "}
+ folio-core and generated to TypeScript by{" "}
+ ts-rs. There is no second source of truth to keep in
+ sync. Running cargo test regenerates the bindings, and CI
+ catches any drift between what Rust declares and what TypeScript
+ expects, so a changed signature cannot silently reach the UI.
+
+
+
+
+ File-backed stores write in two phases. The canonical on-disk file
+ lands first. That is the .md for notes and the{" "}
+ .json for tasks. The derived index is written second. The
+ index is always rebuildable from the files, so the files are the
+ source of truth and the index is just a fast read path you can throw
+ away and regenerate.
+
+
+
+ Data flow
+
+
+ Top to bottom, a request starts in React, crosses the IPC boundary as
+ JSON, lands in the Tauri commands layer, and calls into{" "}
+ folio-core, which is the only layer that talks to the OS,
+ to OpenAI, to whisper.cpp, and to SQLite.
+
+
+
+
+
+ This page is the working summary. For the full account, including the
+ module boundaries inside folio-core and the reasoning
+ behind each layer, read the{" "}
+
+ architecture document
+ {" "}
+ in the repository.
+
+
+ >
+ );
+}
diff --git a/website/app/docs/connectors/page.tsx b/website/app/docs/connectors/page.tsx
new file mode 100644
index 0000000..abab480
--- /dev/null
+++ b/website/app/docs/connectors/page.tsx
@@ -0,0 +1,164 @@
+import type { Metadata } from "next";
+import Link from "next/link";
+import { siteConfig } from "@/lib/site-config";
+import { CodeBlock } from "@/components/site/code-block";
+import {
+ DocHeader,
+ DocH2,
+ Prose,
+ Callout,
+ Steps,
+ Step,
+ FieldList,
+ Field,
+} from "@/components/docs/doc-primitives";
+
+export const metadata: Metadata = {
+ title: "Connectors (MCP)",
+ description:
+ "Expose your transcripts, tasks, and memory to MCP-aware tools over a local stdio server, with nothing sent to a third party.",
+};
+
+const mcpConfig = `{
+ "mcpServers": {
+ "folio": {
+ "command": "folio-mcp",
+ "args": []
+ }
+ }
+}`;
+
+export default function ConnectorsPage() {
+ return (
+ <>
+
+
+ What is MCP
+
+
+ The Model Context Protocol is an open standard that lets an
+ application expose context and tools to an AI client through a small,
+ well-defined interface. A client connects to a server, lists the tools
+ it offers, and calls them on demand. The protocol does not require a
+ network. A server can run as a local process and speak to the client
+ over standard input and output.
+
+
+ {siteConfig.name} ships a local MCP server named folio-mcp.
+ It gives any MCP-aware tool read-only access to your
+ transcripts, tasks, and memories over stdio. There is no
+ cloud and no proxy. The server runs on your machine, reads from your
+ vault, and answers the client directly. The one exception is{" "}
+ create_task, which writes a new task back into your vault.
+
+
+
+ Setup
+
+
+ Enabling connectors takes two steps. Turn the server on inside{" "}
+ {siteConfig.name}, then point your MCP client at it.
+
+
+
+
+
+ Open Settings then Connectors and
+ enable the local MCP server. {siteConfig.name} runs{" "}
+ folio-mcp on your machine and serves it over{" "}
+ stdio.
+
+
+
+
+ Add the server to your MCP client configuration. The client launches{" "}
+ folio-mcp as a subprocess and talks to it over standard
+ input and output. A minimal configuration registers a single server
+ named folio with the command folio-mcp and
+ an empty argument list.
+
+
+
+
+
+ Compatible tools
+
+
+ Any tool that speaks the Model Context Protocol can connect to{" "}
+ folio-mcp. That includes the clients people most often
+ reach for.
+
+
+ Claude Desktop
+ Cursor
+ Claude Code
+ Any MCP client
+
+
+ The configuration shape varies slightly between clients, but the
+ server entry is the same. Register folio with the command{" "}
+ folio-mcp and no arguments.
+
+
+
+ Available tools
+
+
+ The server exposes a focused set of tools over MCP. Every tool reads
+ from your local vault. Only create_task writes.
+
+
+
+
+ Searches your stored memories and returns the entries that match a
+ query.
+
+
+ Lists your most recent meetings, newest first.
+
+
+ Returns the full transcript for a single meeting.
+
+
+ Returns the notes that fall within a start and end date.
+
+
+ Returns the notes stored under a given folder in your vault.
+
+
+ Returns the notes that involve a specific attendee.
+
+
+ Returns an exact quoted segment from a transcript with its speaker
+ attribution.
+
+
+ Searches transcripts for a decision and returns where it was made.
+
+
+ Lists the tasks held in your vault.
+
+
+ Creates a new task and writes it back into your vault. This is the one
+ write-style tool the server exposes.
+
+
+
+ Privacy and scope
+
+
+ Access runs over stdio and is read-only, with{" "}
+ create_task as the only exception. The server is scoped to
+ your local vault. Nothing is sent to a third party, and no cloud or
+ proxy sits between your client and your notes. For the full picture of
+ what stays on your machine, see the{" "}
+ privacy documentation.
+
+
+ >
+ );
+}
diff --git a/website/app/docs/faq/page.tsx b/website/app/docs/faq/page.tsx
new file mode 100644
index 0000000..27880ab
--- /dev/null
+++ b/website/app/docs/faq/page.tsx
@@ -0,0 +1,179 @@
+import type { Metadata } from "next";
+import Link from "next/link";
+import { siteConfig } from "@/lib/site-config";
+import {
+ DocHeader,
+ DocH2,
+ DocH3,
+ Prose,
+} from "@/components/docs/doc-primitives";
+
+export const metadata: Metadata = {
+ title: "FAQ",
+ description:
+ "Short answers to common questions about how Folio captures meetings, where your data lives, and which Macs it runs on.",
+};
+
+export default function FaqPage() {
+ return (
+ <>
+
+
+ Getting started
+
+
+ Does it join my calls as a bot?
+
+
+
+ No. {siteConfig.name} never joins your call. It is a menu-bar app that
+ captures the system audio on your Mac through ScreenCaptureKit, so it
+ works with any meeting tool without a participant showing up in the
+ call. There is no bot, no proxy, and no third-party service sitting
+ between you and the people you are talking to.
+
+
+
+
+ Do I need an account or API key?
+
+
+
+ No account is required. {siteConfig.name} works out of the box with
+ on-device transcription, so the local path needs no key and no sign-up.
+ An OpenAI key is only needed if you opt in to the cloud
+ transcription fallback. That fallback is never the default.
+
+
+
+
+ How does it know a meeting started?
+
+
+
+ {siteConfig.name} watches your calendar and your audio devices through
+ EventKit. When a meeting starts it records the system audio and your
+ microphone as two separate streams. There is no Google OAuth and no
+ Microsoft Graph involved.
+
+
+
+ Privacy and data
+
+
+ Does my audio ever leave my machine?
+
+
+
+ Not on the default path. Audio, transcripts, and notes stay on your
+ Mac. The only network calls {siteConfig.name} ever makes are a one-time
+ model-weights download on first use and the opt-in cloud and webhook
+ paths, all of which can be blocked. See the{" "}
+ privacy page for the full picture.
+
+
+
+ Where do my notes go?
+
+
+ {siteConfig.name} writes one markdown file per meeting into a vault
+ path you choose. Each file is plain markdown you can read, edit,
+ search, and back up with any tool. The frontmatter includes attendees,
+ duration, model, and source.
+
+
+
+ Can I run it offline?
+
+
+ Yes. Privacy Mode, under Settings then{" "}
+ Privacy, physically blocks every outbound HTTP call except
+ localhost. After the model weights are downloaded once, the app keeps
+ working end to end with Wi-Fi off.
+
+
+
+ Is anything encrypted?
+
+
+ Yes. Notes are encrypted at rest with AES-256-GCM and{" "}
+ Argon2id. There is no telemetry, no analytics, and no
+ crash reporting, and that absence is enforced in CI by a dedicated
+ no-telemetry job.
+
+
+
+ Platform and pricing
+
+ Which Macs are supported?
+
+
+ {siteConfig.name} runs on {siteConfig.platform}, on Apple Silicon or
+ Intel. Apple Silicon is the performance target, where on-device
+ transcription is Metal-accelerated. Intel users build from source.
+
+
+
+ Is it free and open source?
+
+
+ Yes. {siteConfig.name} is open source under the {siteConfig.license}{" "}
+ license. You can read the code, the{" "}
+
+ license
+
+ , and the full project on{" "}
+
+ GitHub
+
+ .
+
+
+
+
+ Is there a Windows or Linux version?
+
+
+
+ No. {siteConfig.name} is macOS only. It depends on macOS frameworks
+ such as ScreenCaptureKit and EventKit for capture and meeting
+ detection, so there is no Windows or Linux build.
+
+
+
+ How do I get speaker names?
+
+
+ {siteConfig.name} runs diarization on device, on the system-audio
+ track, and clusters the voices into Speaker 1,{" "}
+ Speaker 2, Speaker 3, and so on. Your own
+ microphone track is always labelled You. No cloud is
+ involved in diarization.
+
+
+
+
+
+ Still stuck? Start from the{" "}
+ documentation home, or open a question on{" "}
+
+ GitHub issues
+
+ .
+
+
+ >
+ );
+}
diff --git a/website/app/docs/how-to-use/page.tsx b/website/app/docs/how-to-use/page.tsx
new file mode 100644
index 0000000..2add3bf
--- /dev/null
+++ b/website/app/docs/how-to-use/page.tsx
@@ -0,0 +1,288 @@
+import type { Metadata } from "next";
+import Link from "next/link";
+
+import { siteConfig } from "@/lib/site-config";
+import { CodeBlock, CommandLine } from "@/components/site/code-block";
+import {
+ DocHeader,
+ DocH2,
+ DocH3,
+ Prose,
+ Callout,
+ Steps,
+ Step,
+ FieldList,
+ Field,
+ Kbd,
+ DocDivider,
+ CardGrid,
+ LinkCard,
+} from "@/components/docs/doc-primitives";
+
+export const metadata: Metadata = {
+ title: "How to use",
+ description:
+ "Go from first launch to a searchable vault of meeting notes with Folio, the local-first meeting transcription app for macOS.",
+};
+
+const exampleFrontmatter = `---
+attendees: [You, Speaker 1, Speaker 2]
+duration: 47m
+model: whisper.cpp
+source: system + microphone
+---`;
+
+export default function HowToUsePage() {
+ return (
+ <>
+
+
+ First launch
+
+
+ {siteConfig.name} is a menu-bar app. After you install it, it lives in
+ the macOS menu bar rather than the Dock, and it watches your calendar
+ and audio devices through EventKit. There is no window to keep open and
+ no bot that joins your calls.
+
+
+ On the first run, macOS prompts for two permissions. It asks for{" "}
+ microphone access so {siteConfig.name} can record your
+ voice, and for screen recording access, which is
+ required to capture system audio from the other participants. Grant
+ both. Without screen recording permission, the system-audio stream
+ cannot be captured.
+
+
+ {siteConfig.name} also downloads its model weights once on first use,
+ the first time it transcribes or diarizes locally. After that the
+ on-device path works without a network connection.
+
+
+ Finally, choose a vault path . This is the folder where{" "}
+ {siteConfig.name} writes one markdown file per meeting. Point it at a
+ plain directory, an existing notes folder, or anywhere you already back
+ up. The files are ordinary markdown, so any editor or sync tool can
+ read them.
+
+
+
+
+ Recording a conversation can be illegal without the other participants
+ consent. The rules vary by US state and by country, and many require
+ all-party consent. {siteConfig.name} gives you the tool. Obtaining
+ consent is on you. Tell people before you record.
+
+
+
+
+
+ Recording a meeting
+
+
+ {siteConfig.name} captures two independent streams for every meeting.
+ One is the system audio of everyone else on the call. The other is your
+ microphone. Keeping them separate is what makes accurate speaker labels
+ possible later.
+
+
+
+
+
+ {siteConfig.name} watches your calendar and audio devices through
+ EventKit. When a meeting begins, it has the context it needs to start
+ capturing. No meeting bot joins the call and no service is invited.
+
+
+
+
+ ScreenCaptureKit captures the system audio, and{" "}
+ cpal captures your microphone. The two are recorded as
+ distinct streams rather than one mixed track. rubato{" "}
+ handles resampling and hound writes the WAV files.
+
+
+
+
+ On the default path, the recordings never leave your Mac. Local
+ transcription with whisper.cpp and on-device diarization run against
+ the captured streams without any upload.
+
+
+
+
+ When the meeting ends, {siteConfig.name} writes a single markdown
+ file into your vault path. Your microphone track is always labelled{" "}
+ You, and the other voices are clustered into{" "}
+ Speaker 1, Speaker 2, and so on.
+
+
+
+
+
+
+ The note
+
+
+ Each meeting becomes one markdown file you can read, edit, search, and
+ back up with any tool. The file opens with YAML frontmatter, followed
+ by the speaker-labelled transcript and the decisions and tasks drawn
+ from it.
+
+
+ Frontmatter
+
+
+ The frontmatter block records the structured facts about the meeting.
+
+
+
+
+ The people on the call, including You for your microphone
+ track and the clustered speakers.
+
+ How long the meeting ran.
+
+ The transcription model that produced the text.
+
+ Where the audio came from.
+
+
+ Transcript, decisions, and tasks
+
+
+ Below the frontmatter sits the speaker-labelled transcript. Your own
+ microphone is always shown as You, and the system-audio
+ voices appear as Speaker 1, Speaker 2, and
+ so on. {siteConfig.name} also surfaces the decisions and tasks from the
+ conversation so the note is more than a wall of text.
+
+
+ Because the file is plain markdown, you stay in control. Rename a
+ speaker, fix a word, add a heading, or move the file. The note is yours
+ to keep.
+
+
+
+
+
+ Reviewing and searching
+
+
+ Notes accumulate into a vault you can navigate from inside{" "}
+ {siteConfig.name}. You can pull up past meetings, find the tasks that
+ came out of them, and search across the memory built from your notes.
+
+
+ The on-disk markdown files are the source of truth.{" "}
+ {siteConfig.name} uses a two-phase write, where the canonical file is
+ written first and the derived index second. The index is always
+ rebuildable from the files, so nothing is locked inside a database you
+ cannot read.
+
+
+ The same data is also reachable from MCP-aware tools through the local{" "}
+ folio-mcp server, which gives read-only access to your
+ transcripts, tasks, and memories over stdio. See{" "}
+ Connectors for how to wire it up.
+
+
+
+
+
+ Cloud transcription
+
+
+ The default transcription path is local. {siteConfig.name} bundles
+ whisper.cpp through the whisper-rs bindings, Metal-accelerated on Apple
+ Silicon, and this is the primary path for every meeting.
+
+
+ For long meetings, the OpenAI Whisper API is available as an opt-in
+ fallback for faster cloud transcription. It needs an OpenAI key, and
+ you turn it on yourself. It is never the default, and the local path
+ keeps working without it.
+
+
+
+
+ Cloud transcription sends audio to OpenAI, so it is a deliberate
+ choice rather than a default. Leave it off and everything stays on your
+ machine. Turn it on only when the speed of a cloud run is worth it for
+ a long recording.
+
+
+
+
+
+ Privacy Mode
+
+
+ When you want {siteConfig.name} fully airgapped, turn on Privacy Mode
+ under Settings then Privacy . It
+ physically blocks every outbound HTTP call except localhost. The app
+ keeps working end to end with Wi-Fi off.
+
+
+ {siteConfig.name} makes very few network calls to begin with. A
+ one-time model-weights download happens on first local transcription or
+ diarization, and the opt-in cloud-AI and webhook paths are the only
+ others. All of them can be blocked. Notes are also encrypted at rest
+ with AES-256-GCM and Argon2id, and {siteConfig.name} ships no
+ telemetry, analytics, or crash reporting.
+
+
+ For the full picture of what stays local and what crosses the network,
+ read the Privacy page.
+
+
+
+
+ Toggle Privacy Mode, turn off Wi-Fi, and record a meeting. The capture,
+ transcription, and diarization all run on-device, so the note still
+ lands in your vault.
+
+
+
+
+
+ Next steps
+
+
+ If you have not installed {siteConfig.name} yet, start with the install
+ guide. To connect your notes to an MCP-aware tool, head to Connectors.
+
+
+
+
+
+ Set up {siteConfig.name} on {siteConfig.platform} with Homebrew or a
+ direct download.
+
+
+ Give Claude Desktop, Cursor, or Claude Code read-only access through{" "}
+ folio-mcp.
+
+
+ See exactly what stays on your machine and what never leaves it.
+
+
+ {siteConfig.name} is {siteConfig.license} licensed and open on GitHub.
+
+
+
+
+ Hit a snag. Open an issue on{" "}
+
+ GitHub
+ {" "}
+ or press ? inside the app.
+
+
+ >
+ );
+}
diff --git a/website/app/docs/installation/page.tsx b/website/app/docs/installation/page.tsx
new file mode 100644
index 0000000..1da3881
--- /dev/null
+++ b/website/app/docs/installation/page.tsx
@@ -0,0 +1,192 @@
+import type { Metadata } from "next";
+import Link from "next/link";
+import { siteConfig } from "@/lib/site-config";
+import { CodeBlock, CommandLine } from "@/components/site/code-block";
+import {
+ DocHeader,
+ DocH2,
+ Prose,
+ Callout,
+ Steps,
+ Step,
+} from "@/components/docs/doc-primitives";
+
+export const metadata: Metadata = {
+ title: "Installation",
+ description: `Install ${siteConfig.name} on ${siteConfig.platform} with Homebrew or the notarized DMG, then grant the permissions it needs to capture audio.`,
+};
+
+const homebrewCommands = `${siteConfig.install.tapCommand}\n${siteConfig.install.installCommand}`;
+
+const sourceSetupCommands = `git clone ${siteConfig.links.github}
+cd folio
+bun install
+pre-commit install
+pre-commit install --hook-type commit-msg
+pre-commit install --hook-type pre-push`;
+
+export default function InstallationPage() {
+ return (
+ <>
+
+
+ Requirements
+
+
+ Folio runs on {siteConfig.platform} . Apple Silicon is
+ the performance target, and Intel Macs are supported by building from
+ source. Local transcription is Metal-accelerated on Apple Silicon.
+
+
+
+ macOS 13 Ventura or later , on Apple Silicon or
+ Intel.
+
+
+ A one-time model-weights download on first use. The
+ first local transcription or diarization fetches a few hundred
+ megabytes of weights, then Folio works offline.
+
+
+
+
+ Homebrew
+
+
+ Homebrew is the recommended way to install Folio. Tap the cask, then
+ install it. The two commands below run in order.
+
+
+
+
+
+ Once installed, {siteConfig.install.upgradeCommand} tracks
+ new releases and keeps your copy current.
+
+
+
+ Direct download
+
+
+ If you prefer a direct download, grab the latest Apple Silicon{" "}
+ .dmg from the{" "}
+
+ Releases page
+
+ . The file is named Folio_<version>_aarch64.dmg.
+ Open it and drag Folio to your Applications folder.
+
+
+ Releases are code-signed with a Developer ID and notarized by Apple, so
+ they open without a Gatekeeper prompt. Intel builds are not published
+ yet. On Intel, build from source.
+
+
+
+ Build from source
+
+
+
+ You need three toolchains in place before building.
+
+
+ Rust 1.88 via rustup, pinned in{" "}
+ rust-toolchain.toml.
+
+
+ Bun 1.3+ , the only JavaScript package manager
+ and runtime this repository uses.
+
+
+ Xcode command-line tools , installed with{" "}
+ xcode-select --install.
+
+
+
+
+
+
+
+ Clone the repo, install dependencies with Bun, and register the
+ pre-commit hooks.
+
+
+
+
+
+
+
+ Start the app in development. The first launch compiles the Rust
+ workspace in about 30 seconds on a warm cache.
+
+
+
+
+
+
+ Grant permissions
+
+
+ On first run, macOS prompts for the permissions Folio needs to capture
+ a meeting. Folio watches your calendar and audio devices through
+ EventKit. No bot joins the call.
+
+
+
+
+
+
+ macOS asks for microphone permission so Folio can record your
+ voice. Your microphone track is always labelled You.
+
+
+
+
+
+
+ macOS asks for screen recording permission. Folio uses it to
+ capture system audio, the other side of the conversation, as a
+ separate stream from your microphone.
+
+
+
+
+
+
+ System audio capture on macOS goes through ScreenCaptureKit, which is
+ gated behind the screen recording permission. Without it, Folio can
+ record your microphone but not the other participants. Grant screen
+ recording so both streams are captured.
+
+
+
+ Update and uninstall
+
+ To update Folio to the latest release, run the upgrade command.
+
+
+
+
+ To remove the app, run brew uninstall --cask folio.
+ Uninstalling removes the application only. Your markdown vault is left
+ untouched, since notes are plain files on disk that you own. You can
+ read, search, or back them up with any tool, with or without Folio
+ installed.
+
+
+ For the full source and signed releases, see the{" "}
+ how to use guide, or the project
+ on{" "}
+
+ GitHub
+
+ .
+
+
+ >
+ );
+}
diff --git a/website/app/docs/layout.tsx b/website/app/docs/layout.tsx
new file mode 100644
index 0000000..0103e4e
--- /dev/null
+++ b/website/app/docs/layout.tsx
@@ -0,0 +1,27 @@
+import { DocsSidebar } from "@/components/docs/docs-sidebar";
+import { DocsMobileNav } from "@/components/docs/docs-mobile-nav";
+import { DocPager } from "@/components/docs/doc-pager";
+
+export default function DocsLayout({ children }: { children: React.ReactNode }) {
+ return (
+
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+ );
+}
diff --git a/website/app/docs/page.tsx b/website/app/docs/page.tsx
new file mode 100644
index 0000000..0dfb5f1
--- /dev/null
+++ b/website/app/docs/page.tsx
@@ -0,0 +1,126 @@
+import type { Metadata } from "next";
+import Link from "next/link";
+
+import { siteConfig } from "@/lib/site-config";
+import { DocHeader, DocH2, Prose, Callout, CardGrid, LinkCard } from "@/components/docs/doc-primitives";
+
+export const metadata: Metadata = {
+ title: "Documentation",
+ description:
+ "Get started with Folio, the local-first app that captures, transcribes, and files your meetings on your own machine.",
+};
+
+export default function DocsOverviewPage() {
+ return (
+ <>
+
+
+
+
+
+ On the default path, audio, transcripts, and notes stay on your machine. Privacy Mode, under{" "}
+ Settings then Privacy , blocks every outbound HTTP call except{" "}
+ localhost, so you can airgap the app entirely and it still works end to end.
+
+
+
+
+ What is Folio
+
+
+ {siteConfig.name} is a menu-bar app for {siteConfig.platform}. When a meeting starts it records
+ your system audio and your microphone as two independent streams, transcribes them on-device, and writes one
+ markdown note per meeting into a vault path you choose. No meeting bot joins the call. There is no Google OAuth
+ and no Microsoft Graph. {siteConfig.name} watches your calendar and audio devices locally through EventKit.
+
+
+ The promise is simple. On the default path your audio never leaves your machine. Local transcription with{" "}
+ whisper.cpp is the primary path, on-device diarization separates voices, and the notes are plain
+ markdown files you can read, edit, search, and back up with any tool. {siteConfig.name} is{" "}
+
+ {siteConfig.license}
+ {" "}
+ licensed and open source on{" "}
+
+ GitHub
+
+ .
+
+
+
+ Core ideas
+
+
+ A few decisions shape everything else in {siteConfig.name}. Each one keeps your data on your machine and under
+ your control.
+
+
+
+ Two-stream capture. System audio and the microphone are recorded as separate streams. The
+ microphone track is always labelled You.
+
+
+ On-device transcription. The bundled backend is whisper.cpp through the{" "}
+ whisper-rs bindings, Metal-accelerated on Apple Silicon. The cloud is an opt-in fallback, never
+ the default.
+
+
+ On-device diarization. Voices on the system-audio track are clustered into Speaker 1,
+ Speaker 2, and so on, with no cloud involved.
+
+
+ One markdown note per meeting. Each meeting becomes a single markdown file in your vault,
+ with frontmatter for attendees, duration, model, and source.
+
+
+ A local MCP server. folio-mcp gives MCP-aware tools read-only access to your
+ transcripts, tasks, and memories over stdio. No cloud, no proxy.
+
+
+ Privacy Mode. A single switch physically blocks every outbound HTTP call except{" "}
+ localhost.
+
+
+
+
+ How the pieces fit
+
+
+ {siteConfig.name} runs in your menu bar and watches for meetings. When one starts it captures system audio and
+ your microphone, transcribes the audio on-device, separates the speakers, and writes a finished markdown note
+ into your vault. The vault is just a folder of files. From there your notes are searchable on disk, readable in
+ any editor, and reachable by MCP-aware tools through the local server.
+
+
+
+ Start here
+
+ Pick the path that matches what you need next.
+
+
+
+ Install with Homebrew or a signed direct download, and grant the macOS permissions {siteConfig.name} needs.
+
+
+ Record a meeting, read the resulting note, and learn how speakers and the You track appear.
+
+
+ The Rust core, the Tauri desktop binary, the three crates, and how data flows from capture to disk.
+
+
+ Wire up the local folio-mcp server so Claude, Cursor, and other MCP tools can read your notes.
+
+
+ What Folio does and does not send, Privacy Mode, encryption at rest, and recording consent.
+
+
+ Short answers to common questions about platforms, cost, cloud fallback, and your data.
+
+
+ >
+ );
+}
diff --git a/website/app/docs/privacy/page.tsx b/website/app/docs/privacy/page.tsx
new file mode 100644
index 0000000..ea17dc8
--- /dev/null
+++ b/website/app/docs/privacy/page.tsx
@@ -0,0 +1,186 @@
+import type { Metadata } from "next";
+import Link from "next/link";
+import { siteConfig } from "@/lib/site-config";
+import { CodeBlock, CommandLine } from "@/components/site/code-block";
+import {
+ DocHeader,
+ DocH2,
+ DocH3,
+ Prose,
+ Callout,
+ Steps,
+ Step,
+ FieldList,
+ Field,
+ Kbd,
+ DocDivider,
+ CardGrid,
+ LinkCard,
+} from "@/components/docs/doc-primitives";
+
+export const metadata: Metadata = {
+ title: "Privacy & consent",
+ description:
+ "How the private path is the default path in Folio, what stays on disk, the exact network surface, and your responsibility around recording consent.",
+};
+
+export default function PrivacyPage() {
+ return (
+ <>
+
+
+ What stays local
+
+
+ {siteConfig.name} is a local-first application. It captures system
+ audio and your microphone, transcribes on-device, and writes one
+ markdown note per meeting to a vault path you choose. On the default
+ path, none of that leaves your machine.
+
+ The guarantees that hold by default:
+
+
+ No telemetry, no analytics, no crash reporting. {" "}
+ This is not a setting you trust us to honor. It is enforced in CI by
+ a dedicated no-telemetry job that runs on every push and
+ pull request to main.
+
+
+ Audio, transcripts, and notes stay on disk. The
+ recorded streams, the on-device transcription output, and every
+ markdown note are written to your machine and read from your
+ machine.
+
+
+ Notes are encrypted at rest. {siteConfig.name}{" "}
+ encrypts notes with AES-256-GCM, with key derivation
+ through Argon2id.
+
+
+
+ Local transcription runs through whisper.cpp on-device,
+ and diarization runs on-device as well. Neither path sends audio to a
+ server.
+
+
+
+ The network surface
+
+
+ It is easier to trust a tool when you can name every call it is able
+ to make. {siteConfig.name} makes only these network calls, and each one
+ can be blocked.
+
+
+
+ A one-time model-weights download. On first local
+ transcription or diarization, {siteConfig.name} downloads the model
+ weights once. This is a few hundred megabytes, pulled from Hugging
+ Face and from the sherpa-onnx GitHub releases. After
+ that, the local path needs no network at all.
+
+
+ The opt-in cloud-AI path. The OpenAI Whisper API is
+ an opt-in fallback for faster cloud transcription on long meetings.
+ It needs an OpenAI key. It is never the default, and you choose when
+ to use it.
+
+
+ The opt-in webhook path. If you wire up a webhook,
+ {" "}
+ {siteConfig.name} can call it. This is opt-in and off until you set
+ it up.
+
+
+
+ Every item in that list can be blocked. If you never enable the
+ cloud-AI path or a webhook, and you keep the model weights you already
+ downloaded, {siteConfig.name} makes no outbound calls.
+
+
+
+ Privacy Mode
+
+
+ When you want a hard guarantee instead of a careful configuration,
+ turn on Privacy Mode under Settings then{" "}
+ Privacy . Privacy Mode physically blocks every outbound
+ HTTP call except localhost. There is nothing left to
+ forget about and no path to leak through.
+
+
+ The proof is that the app keeps working. With Privacy Mode on, you can
+ turn Wi-Fi off and {siteConfig.name} still records, transcribes,
+ diarizes, and writes notes end to end. The local pipeline does not
+ depend on the network, so removing the network changes nothing about
+ the result.
+
+
+ The one prerequisite is that the model weights are already on disk. If
+ you have run a local transcription or diarization once before, the
+ one-time download has already happened and Privacy Mode has nothing it
+ needs to reach for.
+
+
+
+ Data retention
+
+
+ {siteConfig.name} does not hold your data in a place you cannot see.
+ Notes are plain markdown files in the vault path you chose. You can
+ read them, edit them, search them, and back them up with any tool you
+ already use.
+
+
+ Retention is therefore in your hands. A note exists for exactly as long
+ as the file exists. When you delete the file, the note is gone. There
+ is no separate copy to clear and no server-side record to request the
+ deletion of. The on-disk file is the canonical artifact, and the
+ derived index is always rebuildable from the files.
+
+
+ For the full account of what {siteConfig.name} stores and what it never
+ touches, read the{" "}
+
+ privacy document
+
+ .
+
+
+
+ Recording consent
+
+
+ {siteConfig.name} gives you a recording tool. Using it lawfully is your
+ responsibility, and the law here is not uniform.
+
+
+
+
+ Recording a conversation can be illegal without the other participants
+ consent. The rules vary by US state and by country, and many require
+ all-party consent. {siteConfig.name} gives you the tool. Obtaining
+ consent is your responsibility. Tell people before you record.
+
+
+
+
+
+
+
+ For the complete and authoritative account of {siteConfig.name}{" "}
+ privacy, including the full list of what stays on your machine and what
+ the opt-in paths do, read the{" "}
+
+ full privacy document
+
+ .
+
+
+ >
+ );
+}
diff --git a/website/app/features/page.tsx b/website/app/features/page.tsx
new file mode 100644
index 0000000..ff01c5e
--- /dev/null
+++ b/website/app/features/page.tsx
@@ -0,0 +1,219 @@
+import type { Metadata } from "next";
+import Link from "next/link";
+import {
+ AudioLines,
+ Boxes,
+ BrainCircuit,
+ Check,
+ FileText,
+ Lock,
+ Plug,
+ Users,
+} from "lucide-react";
+
+import { siteConfig } from "@/lib/site-config";
+import { cn } from "@/lib/utils";
+import { Section, SectionHeading, Eyebrow } from "@/components/site/section";
+import { Button } from "@/components/ui/button";
+import { CommandLine } from "@/components/site/code-block";
+import { NotePreview } from "@/components/landing/note-preview";
+import { CapabilityTable } from "@/components/landing/capability-table";
+
+export const metadata: Metadata = {
+ title: "Features",
+ description:
+ "Everything Folio does, in detail: two-stream capture, on-device transcription and diarization, a markdown vault you own, local connectors, and a network you control.",
+};
+
+type FeatureBlock = {
+ icon: typeof AudioLines;
+ eyebrow: string;
+ title: string;
+ description: string;
+ points: string[];
+};
+
+const blocks: FeatureBlock[] = [
+ {
+ icon: AudioLines,
+ eyebrow: "Capture",
+ title: "Two streams, kept apart",
+ description:
+ "Folio records system audio and your microphone as independent tracks, so the transcript stays clean and every line is attributable.",
+ points: [
+ "cpal captures your microphone, ScreenCaptureKit captures system audio.",
+ "No bot joins the call, so there is nothing for other people to admit.",
+ "It watches your calendar and audio devices through EventKit, with no OAuth.",
+ "rubato resamples and hound writes WAV, entirely on disk.",
+ ],
+ },
+ {
+ icon: FileText,
+ eyebrow: "Transcription",
+ title: "On-device by default",
+ description:
+ "The bundled Whisper backend runs locally and is Metal-accelerated on Apple Silicon. Cloud transcription is an explicit choice, never the default.",
+ points: [
+ "whisper.cpp through whisper-rs handles local transcription.",
+ "OpenAI Whisper is an opt-in fallback for faster runs on long meetings.",
+ "Cloud calls require your own key and are gated behind a clear prompt.",
+ "Privacy Mode keeps everything local, even on long recordings.",
+ ],
+ },
+ {
+ icon: Users,
+ eyebrow: "Diarization",
+ title: "Who said what, computed locally",
+ description:
+ "Speakers are separated on-device with pyannote segmentation and a speaker-embedding model, both run through sherpa-onnx.",
+ points: [
+ "Voices on the system track are clustered into Speaker 1, 2, 3 and so on.",
+ "Your microphone is always labelled You.",
+ "Nothing about your voiceprint leaves the machine.",
+ "The result lands inline in the markdown transcript.",
+ ],
+ },
+ {
+ icon: BrainCircuit,
+ eyebrow: "Your vault",
+ title: "One markdown note per meeting",
+ description:
+ "Every conversation becomes a portable markdown file in a vault path you choose, with structured frontmatter and a clean transcript.",
+ points: [
+ "Frontmatter records attendees, duration, model, and source.",
+ "A two-phase write keeps the file canonical and the index rebuildable.",
+ "Decisions and tasks are pulled out so you can act on them.",
+ "Plain files mean any editor, any backup, no lock-in.",
+ ],
+ },
+ {
+ icon: Plug,
+ eyebrow: "Connectors",
+ title: "Your agents can read your meetings",
+ description:
+ "A local MCP server exposes transcripts, tasks, and memory to MCP-aware tools over stdio, read-only, with no cloud in the middle.",
+ points: [
+ "Works with Claude Desktop, Cursor, Claude Code, and any MCP client.",
+ "Search past meetings without leaving your editor.",
+ "Pull decisions and action items into your own workflow.",
+ "Scoped to read-only access over a local stdio connection.",
+ ],
+ },
+ {
+ icon: Lock,
+ eyebrow: "Privacy",
+ title: "The network is opt-in",
+ description:
+ "Folio is built so the private path is the easy path. Privacy Mode airgaps the app, and there is no telemetry to turn off.",
+ points: [
+ "No telemetry, no analytics, no crash reporting, enforced in CI.",
+ "Privacy Mode blocks every outbound call except localhost.",
+ "Notes are encrypted at rest with AES-256-GCM and Argon2id.",
+ "The app runs end to end with Wi-Fi off.",
+ ],
+ },
+];
+
+function FeatureSplit({ block, index }: { block: FeatureBlock; index: number }) {
+ const flipped = index % 2 === 1;
+ return (
+
+
+
{block.eyebrow}
+
+ {block.title}
+
+
+ {block.description}
+
+
+ {block.points.map((point) => (
+
+
+
+
+
+ {point}
+
+
+ ))}
+
+
+
+
+
+ );
+}
+
+export default function FeaturesPage() {
+ return (
+ <>
+
+
+
Features
+
+ Built to capture meetings without giving them away
+
+
+ {siteConfig.name} does the obvious thing well. It records, transcribes, and
+ files your meetings, and it does almost all of it on your own machine.
+
+
+
+ Install {siteConfig.name}
+
+
+ Read the docs
+
+
+
+
+
+
+ {blocks.map((block, index) => (
+
+ ))}
+
+
+
+
+
+
+
+
The output
+
+ Everything ends as a note you own
+
+
+ No dashboard to log into, no export to request. Each meeting is a markdown
+ file with frontmatter, a speaker-labelled transcript, and the decisions and
+ tasks that came out of it.
+
+
+
+ Plain files, in your vault, forever.
+
+
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/website/app/globals.css b/website/app/globals.css
new file mode 100644
index 0000000..624169a
--- /dev/null
+++ b/website/app/globals.css
@@ -0,0 +1,138 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+ :root {
+ --font-sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter", system-ui,
+ sans-serif;
+ --font-display: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Inter",
+ system-ui, sans-serif;
+ --font-serif: "Spectral", Georgia, ui-serif, serif;
+ --font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", monospace;
+
+ --background: 240 7% 6%;
+ --foreground: 0 0% 92%;
+ --card: 240 6% 10%;
+ --card-foreground: 0 0% 92%;
+ --popover: 240 6% 10%;
+ --popover-foreground: 0 0% 92%;
+
+ --primary: 0 0% 92%;
+ --primary-foreground: 240 7% 8%;
+
+ --secondary: 240 6% 14%;
+ --secondary-foreground: 0 0% 90%;
+
+ --muted: 240 5% 16%;
+ --muted-foreground: 240 5% 65%;
+
+ --accent: 240 5% 18%;
+ --accent-foreground: 0 0% 92%;
+
+ --destructive: 4 65% 55%;
+ --destructive-foreground: 0 0% 95%;
+
+ --signal: 0 0% 72%;
+ --signal-foreground: 240 7% 10%;
+
+ --border: 240 6% 18%;
+ --input: 240 6% 18%;
+ --ring: 0 0% 60%;
+
+ --radius: 0.75rem;
+
+ --motion-ms-fast: 120ms;
+ --motion-ms-snap: 200ms;
+ --motion-ms-modal: 350ms;
+ --motion-ms-deliberate: 480ms;
+ --motion-ease-standard: cubic-bezier(0.32, 0.72, 0, 1);
+ --motion-ease-emphasized: cubic-bezier(0.2, 0, 0, 1);
+ --motion-ease-decelerate: cubic-bezier(0, 0, 0.2, 1);
+ --motion-ease-accelerate: cubic-bezier(0.3, 0, 1, 1);
+ --motion-ease-overshoot: cubic-bezier(0.34, 1.56, 0.64, 1);
+ }
+
+ * {
+ @apply border-border;
+ }
+
+ html {
+ scroll-behavior: smooth;
+ scroll-padding-top: 5.5rem;
+ }
+
+ body {
+ @apply bg-background font-sans text-foreground antialiased;
+
+ font-feature-settings: "ss01", "cv02", "cv03", "cv04", "cv11";
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ }
+
+ ::selection {
+ background: hsl(var(--primary) / 0.18);
+ }
+
+ .font-mono {
+ font-variant-numeric: tabular-nums;
+ }
+
+ ::-webkit-scrollbar {
+ width: 11px;
+ height: 11px;
+ }
+ ::-webkit-scrollbar-track {
+ background: transparent;
+ }
+ ::-webkit-scrollbar-thumb {
+ background: hsl(var(--border));
+ border-radius: 999px;
+ border: 3px solid transparent;
+ background-clip: padding-box;
+ }
+ ::-webkit-scrollbar-thumb:hover {
+ background: hsl(var(--muted-foreground) / 0.4);
+ background-clip: padding-box;
+ border: 3px solid transparent;
+ }
+}
+
+@layer components {
+ .surface-grain {
+ background-image:
+ radial-gradient(transparent 1px, hsl(var(--background) / 0) 1px);
+ background-size: 3px 3px;
+ }
+
+ .hairline {
+ @apply border-border;
+ }
+
+ .text-balance {
+ text-wrap: balance;
+ }
+
+ .text-pretty {
+ text-wrap: pretty;
+ }
+
+ .focus-ring {
+ @apply outline-none ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2;
+ }
+}
+
+@media (prefers-reduced-motion: reduce) {
+ html {
+ scroll-behavior: auto;
+ }
+ *,
+ *::before,
+ *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+ }
+}
diff --git a/website/app/layout.tsx b/website/app/layout.tsx
new file mode 100644
index 0000000..e1995a1
--- /dev/null
+++ b/website/app/layout.tsx
@@ -0,0 +1,69 @@
+import type { Metadata, Viewport } from "next";
+
+import "@fontsource/inter/400.css";
+import "@fontsource/inter/500.css";
+import "@fontsource/inter/600.css";
+import "@fontsource/spectral/400.css";
+import "@fontsource/spectral/500.css";
+import "@fontsource/jetbrains-mono/400.css";
+import "@fontsource/jetbrains-mono/500.css";
+import "./globals.css";
+
+import { siteConfig } from "@/lib/site-config";
+import { SiteHeader } from "@/components/site/site-header";
+import { SiteFooter } from "@/components/site/site-footer";
+
+export const metadata: Metadata = {
+ metadataBase: new URL(siteConfig.url),
+ title: {
+ default: `${siteConfig.name} — ${siteConfig.tagline}`,
+ template: `%s — ${siteConfig.name}`,
+ },
+ description: siteConfig.description,
+ keywords: [
+ "meeting transcription",
+ "local-first",
+ "macOS",
+ "privacy",
+ "whisper",
+ "speaker diarization",
+ "markdown notes",
+ "MCP",
+ ],
+ authors: [{ name: "Folio" }],
+ openGraph: {
+ type: "website",
+ title: `${siteConfig.name} — ${siteConfig.tagline}`,
+ description: siteConfig.description,
+ url: siteConfig.url,
+ siteName: siteConfig.name,
+ },
+ twitter: {
+ card: "summary_large_image",
+ title: `${siteConfig.name} — ${siteConfig.tagline}`,
+ description: siteConfig.description,
+ },
+ icons: {
+ icon: "/favicon.svg",
+ },
+};
+
+export const viewport: Viewport = {
+ themeColor: "#0f0f12",
+};
+
+export default function RootLayout({
+ children,
+}: Readonly<{ children: React.ReactNode }>) {
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ );
+}
diff --git a/website/app/not-found.tsx b/website/app/not-found.tsx
new file mode 100644
index 0000000..4f0c147
--- /dev/null
+++ b/website/app/not-found.tsx
@@ -0,0 +1,29 @@
+import Link from "next/link";
+
+import { Button } from "@/components/ui/button";
+import { FolioMark } from "@/components/site/logo";
+
+export default function NotFound() {
+ return (
+
+
+
+ 404 — not found
+
+
+ This page left your machine
+
+
+ The page you are looking for does not exist. Everything else is still local.
+
+
+
+ Back home
+
+
+ Read the docs
+
+
+
+ );
+}
diff --git a/website/app/page.tsx b/website/app/page.tsx
new file mode 100644
index 0000000..35cd216
--- /dev/null
+++ b/website/app/page.tsx
@@ -0,0 +1,25 @@
+import { Hero } from "@/components/landing/hero";
+import { TrustBar } from "@/components/landing/trust-bar";
+import { FeatureGrid } from "@/components/landing/feature-grid";
+import { HowItWorks } from "@/components/landing/how-it-works";
+import { PrivacySection } from "@/components/landing/privacy-section";
+import { ConnectorsSection } from "@/components/landing/connectors-section";
+import { InstallSection } from "@/components/landing/install-section";
+import { FaqSection } from "@/components/landing/faq-section";
+import { CtaSection } from "@/components/landing/cta-section";
+
+export default function HomePage() {
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/website/bun.lock b/website/bun.lock
new file mode 100644
index 0000000..bf86b14
--- /dev/null
+++ b/website/bun.lock
@@ -0,0 +1,925 @@
+{
+ "lockfileVersion": 1,
+ "configVersion": 1,
+ "workspaces": {
+ "": {
+ "name": "folio-website",
+ "dependencies": {
+ "@fontsource/inter": "^5.1.1",
+ "@fontsource/jetbrains-mono": "^5.1.2",
+ "@fontsource/spectral": "^5.1.1",
+ "@radix-ui/react-accordion": "^1.2.3",
+ "@radix-ui/react-slot": "^1.1.2",
+ "@radix-ui/react-tabs": "^1.1.3",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "lucide-react": "^0.469.0",
+ "next": "15.1.6",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "tailwind-merge": "^2.6.0",
+ "tailwindcss-animate": "^1.0.7",
+ },
+ "devDependencies": {
+ "@types/node": "^22.10.5",
+ "@types/react": "^18.3.18",
+ "@types/react-dom": "^18.3.5",
+ "autoprefixer": "^10.4.20",
+ "eslint": "^9.18.0",
+ "eslint-config-next": "15.1.6",
+ "postcss": "^8.5.1",
+ "prettier": "^3.4.2",
+ "prettier-plugin-tailwindcss": "^0.6.9",
+ "tailwindcss": "^3.4.17",
+ "typescript": "^5.7.3",
+ },
+ },
+ },
+ "packages": {
+ "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
+
+ "@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="],
+
+ "@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="],
+
+ "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="],
+
+ "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="],
+
+ "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
+
+ "@eslint/config-array": ["@eslint/config-array@0.21.2", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.5" } }, "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw=="],
+
+ "@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="],
+
+ "@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="],
+
+ "@eslint/eslintrc": ["@eslint/eslintrc@3.3.5", "", { "dependencies": { "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" } }, "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg=="],
+
+ "@eslint/js": ["@eslint/js@9.39.4", "", {}, "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw=="],
+
+ "@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="],
+
+ "@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="],
+
+ "@fontsource/inter": ["@fontsource/inter@5.2.8", "", {}, "sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg=="],
+
+ "@fontsource/jetbrains-mono": ["@fontsource/jetbrains-mono@5.2.8", "", {}, "sha512-6w8/SG4kqvIMu7xd7wt6x3idn1Qux3p9N62s6G3rfldOUYHpWcc2FKrqf+Vo44jRvqWj2oAtTHrZXEP23oSKwQ=="],
+
+ "@fontsource/spectral": ["@fontsource/spectral@5.2.8", "", {}, "sha512-0CqZ8/z8A38BdeSz5t2NSd5tCO1R9P1k7SF2VpRLMbZTMSSR6+2Dk0ZBMfEQK/IrBLQS1HgHLMqpdTwRpnKpGQ=="],
+
+ "@humanfs/core": ["@humanfs/core@0.19.2", "", { "dependencies": { "@humanfs/types": "^0.15.0" } }, "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA=="],
+
+ "@humanfs/node": ["@humanfs/node@0.16.8", "", { "dependencies": { "@humanfs/core": "^0.19.2", "@humanfs/types": "^0.15.0", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ=="],
+
+ "@humanfs/types": ["@humanfs/types@0.15.0", "", {}, "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q=="],
+
+ "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
+
+ "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
+
+ "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
+
+ "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="],
+
+ "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="],
+
+ "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="],
+
+ "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="],
+
+ "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="],
+
+ "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.0.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA=="],
+
+ "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="],
+
+ "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA=="],
+
+ "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw=="],
+
+ "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="],
+
+ "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="],
+
+ "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.0.4" }, "os": "linux", "cpu": "s390x" }, "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q=="],
+
+ "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="],
+
+ "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g=="],
+
+ "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw=="],
+
+ "@img/sharp-wasm32": ["@img/sharp-wasm32@0.33.5", "", { "dependencies": { "@emnapi/runtime": "^1.2.0" }, "cpu": "none" }, "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg=="],
+
+ "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.33.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ=="],
+
+ "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="],
+
+ "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
+
+ "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
+
+ "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
+
+ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
+
+ "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.5", "", { "dependencies": { "@tybys/wasm-util": "^0.10.2" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q=="],
+
+ "@next/env": ["@next/env@15.1.6", "", {}, "sha512-d9AFQVPEYNr+aqokIiPLNK/MTyt3DWa/dpKveiAaVccUadFbhFEvY6FXYX2LJO2Hv7PHnLBu2oWwB4uBuHjr/w=="],
+
+ "@next/eslint-plugin-next": ["@next/eslint-plugin-next@15.1.6", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-+slMxhTgILUntZDGNgsKEYHUvpn72WP1YTlkmEhS51vnVd7S9jEEy0n9YAMcI21vUG4akTw9voWH02lrClt/yw=="],
+
+ "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@15.1.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-u7lg4Mpl9qWpKgy6NzEkz/w0/keEHtOybmIl0ykgItBxEM5mYotS5PmqTpo+Rhg8FiOiWgwr8USxmKQkqLBCrw=="],
+
+ "@next/swc-darwin-x64": ["@next/swc-darwin-x64@15.1.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-x1jGpbHbZoZ69nRuogGL2MYPLqohlhnT9OCU6E6QFewwup+z+M6r8oU47BTeJcWsF2sdBahp5cKiAcDbwwK/lg=="],
+
+ "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@15.1.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-jar9sFw0XewXsBzPf9runGzoivajeWJUc/JkfbLTC4it9EhU8v7tCRLH7l5Y1ReTMN6zKJO0kKAGqDk8YSO2bg=="],
+
+ "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@15.1.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-+n3u//bfsrIaZch4cgOJ3tXCTbSxz0s6brJtU3SzLOvkJlPQMJ+eHVRi6qM2kKKKLuMY+tcau8XD9CJ1OjeSQQ=="],
+
+ "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@15.1.6", "", { "os": "linux", "cpu": "x64" }, "sha512-SpuDEXixM3PycniL4iVCLyUyvcl6Lt0mtv3am08sucskpG0tYkW1KlRhTgj4LI5ehyxriVVcfdoxuuP8csi3kQ=="],
+
+ "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@15.1.6", "", { "os": "linux", "cpu": "x64" }, "sha512-L4druWmdFSZIIRhF+G60API5sFB7suTbDRhYWSjiw0RbE+15igQvE2g2+S973pMGvwN3guw7cJUjA/TmbPWTHQ=="],
+
+ "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@15.1.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-s8w6EeqNmi6gdvM19tqKKWbCyOBvXFbndkGHl+c9YrzsLARRdCHsD9S1fMj8gsXm9v8vhC8s3N8rjuC/XrtkEg=="],
+
+ "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@15.1.6", "", { "os": "win32", "cpu": "x64" }, "sha512-6xomMuu54FAFxttYr5PJbEfu96godcxBTRk1OhAvJq0/EnmFU/Ybiax30Snis4vdWZ9LGpf7Roy5fSs7v/5ROQ=="],
+
+ "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
+
+ "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
+
+ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
+
+ "@nolyfill/is-core-module": ["@nolyfill/is-core-module@1.0.39", "", {}, "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA=="],
+
+ "@radix-ui/primitive": ["@radix-ui/primitive@1.1.4", "", {}, "sha512-7AdCK9PQyiljKoBDbN8OuctCbd/esdwZPQ8RtOE3SsyQtUpiPb+ND75q0jEhC1m1ecBI0MFNeLJvwIh9iKHRcQ=="],
+
+ "@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-collapsible": "1.1.14", "@radix-ui/react-collection": "1.1.10", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-use-controllable-state": "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-iE8YB9nmTBH8zd73ofBISZ8JCzgMoMkATJr7qDwa6u5F1+7mTM81V6fa71jgZ65rpjVpecDf1vSnwIFP9Ly1zw=="],
+
+ "@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-use-controllable-state": "1.2.3", "@radix-ui/react-use-layout-effect": "1.1.2" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9bT+FvifX1FK2Mj6UEsTdyu0cN3JaA3KdfhaBao+ONrYFy/pyOy3TU1TNw7iOk1o+0hOEq67RojlUUmoFGwxyA=="],
+
+ "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.10", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-slot": "1.3.0" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-IVVz4EvBcKjrzKgof714qDnz/SzQAkLA2Emh5edlHbgcE6fNd3Un6CJLlaYcnm8N4JmAtzQgse4dOKxcD2yc9g=="],
+
+ "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA=="],
+
+ "@radix-ui/react-context": ["@radix-ui/react-context@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QwH4PO5urrbO+FaGd5Aglg+YJgWTyyuZ3g/6mKvsqraLkglDdckw9JafgL5McL5VEJ6EPNduPaT3ZE9BttDAqg=="],
+
+ "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-C3vFhbyi4SW3PmbAi6Awpu4OzJtd0MxGurvSsYtr7p7nM8RNB3VAF3CUmnp2j50knpkrRcB7+ycVXzgLgF6yNA=="],
+
+ "@radix-ui/react-id": ["@radix-ui/react-id@1.1.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA=="],
+
+ "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.6", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.2" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-zdTk4PlUO0E18HnZ3wYbW0KkJJxWCdiNYp6g6X1PtONFhxVkg01vliTJAmwIszU6mHiyBOoW9P0rAugl5/hULQ=="],
+
+ "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.6", "", { "dependencies": { "@radix-ui/react-slot": "1.3.0" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-wetd0QI77DbvrPpTAvH1SqOxsYF2wZe5TNxqwOd5Ty4XDpV3dpV0s8K/1MGMJBeY5o7lg8ub5VIt1Ub+yVen6g=="],
+
+ "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-collection": "1.1.10", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-controllable-state": "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9gkwneI0guf8JDmrFxPjJF6Ozzgioyw+/lonYNCwefS9ZHA05er0BVHiXr+LbWGHxUfczvMY6G1oiZZi1VzjRw=="],
+
+ "@radix-ui/react-slot": ["@radix-ui/react-slot@1.3.0", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-MojKku4U/miO8Av4Dkb+ctMAQx7JmY96LmtDQlAarCRtd7rN52QCSzBF+XAvr5S6coSVj9HEPBgHAHKEJVk/WA=="],
+
+ "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-roving-focus": "1.1.13", "@radix-ui/react-use-controllable-state": "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-kxc9gI6/HfcU4nfMMVS3AmQK414kbU1IE6UCJmMmxjhO3cRPXOyYnmvyKD+ODt7q56nRq9l7Wovi6uaGwKgMlg=="],
+
+ "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw=="],
+
+ "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.3", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.3", "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-PLzC90MS+ReootmjC597dvopoelpZ8Q61HJkDXZSExitIq7PL55vHNnesAHwguHK0aPfBnpdNzQtv1uliaqQrA=="],
+
+ "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.3", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-6c8ZqvPTWILEKnyVkP53EGRCcpnJiKTC21sS/6R1GF5xKyHJJWQEPfkqlcgUkdRQivd6tb23abUwe4ngWmY0JA=="],
+
+ "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA=="],
+
+ "@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="],
+
+ "@rushstack/eslint-patch": ["@rushstack/eslint-patch@1.16.1", "", {}, "sha512-TvZbIpeKqGQQ7X0zSCvPH9riMSFQFSggnfBjFZ1mEoILW+UuXCKwOoPcgjMwiUtRqFZ8jWhPJc4um14vC6I4ag=="],
+
+ "@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="],
+
+ "@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="],
+
+ "@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="],
+
+ "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="],
+
+ "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
+
+ "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
+
+ "@types/node": ["@types/node@22.19.21", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-VMeFBSCKQKmm2swI2kW51SFusDqekC6q9trBCvJ/JliDchFSuoYYKN7yVNjPthP1HKZcx3U1gI/wTcEBjEFKTA=="],
+
+ "@types/prop-types": ["@types/prop-types@15.7.15", "", {}, "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw=="],
+
+ "@types/react": ["@types/react@18.3.31", "", { "dependencies": { "@types/prop-types": "*", "csstype": "^3.2.2" } }, "sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw=="],
+
+ "@types/react-dom": ["@types/react-dom@18.3.7", "", { "peerDependencies": { "@types/react": "^18.0.0" } }, "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ=="],
+
+ "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.61.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.61.1", "@typescript-eslint/type-utils": "8.61.1", "@typescript-eslint/utils": "8.61.1", "@typescript-eslint/visitor-keys": "8.61.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.61.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-ZPlVl3PB3et/59Ne0fv/sci6ZXz4T4Hp4nTJ56i/Y0gR89ARb+KphojTq6j+56E5PIezmOIOOWyY+aWQFd+IkQ=="],
+
+ "@typescript-eslint/parser": ["@typescript-eslint/parser@8.61.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.61.1", "@typescript-eslint/types": "8.61.1", "@typescript-eslint/typescript-estree": "8.61.1", "@typescript-eslint/visitor-keys": "8.61.1", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-PJ5vePq5/ognBbrIcoC5+SHO5dfpeLPzP9FpLkzWrguoYQEeeSjlJpVwOpo1JRSTEi7dRcwNy4h4dzV70PqHcg=="],
+
+ "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.61.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.61.1", "@typescript-eslint/types": "^8.61.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-PrC4JYGmR241lYnfhmKGTXkFqv8+ymbTFgSAY0fVXpY82/QkMw5TZPl+vGzuDDU2QYJk9fIDOBTntF+yDv9LEA=="],
+
+ "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.61.1", "", { "dependencies": { "@typescript-eslint/types": "8.61.1", "@typescript-eslint/visitor-keys": "8.61.1" } }, "sha512-L2bdIeoQS8FlKAvONAr20w6OcLXeB+qiDKbAooS9A0Ben+iSIkBef0FxqwKWYqt5sa0i4KJtxVyVmhMylKzF5w=="],
+
+ "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.61.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-UN/H4di+OO7EWx2ovME+8t31YO+KVnK0RRKEHR3kOt21/Ay8BOq3M1OMvWs5vNiqcFCYGYoxK3MXPZzmMUE+yg=="],
+
+ "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.61.1", "", { "dependencies": { "@typescript-eslint/types": "8.61.1", "@typescript-eslint/typescript-estree": "8.61.1", "@typescript-eslint/utils": "8.61.1", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-GYRicKmVK0C4fsKgaACaknOUAq9Oa2kwsjnpFhFcS/5p4Ht5IP9OVLbgIgcK4SRk92nVHFluurg1lumD9dBcLw=="],
+
+ "@typescript-eslint/types": ["@typescript-eslint/types@8.61.1", "", {}, "sha512-G+CRlPqLv7Bz1IZVs03x5K59F1veqL0EJUROAdGhKsEq8qOiRiZbI+HUojPq5l0fEGOKModD9br6lObhB8zkoA=="],
+
+ "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.61.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.61.1", "@typescript-eslint/tsconfig-utils": "8.61.1", "@typescript-eslint/types": "8.61.1", "@typescript-eslint/visitor-keys": "8.61.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-u+oQD3BqYWPc8YV9Zab4vaJElJuwOLPRc10Jm1o/qS+6Qwen14HCWwx0Seo4LnSn2wxea2Ik8DxPt2/FHmuhrg=="],
+
+ "@typescript-eslint/utils": ["@typescript-eslint/utils@8.61.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.61.1", "@typescript-eslint/types": "8.61.1", "@typescript-eslint/typescript-estree": "8.61.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-1+P/3Dj6jvtybE1q0HQ6yBt/gq+oKJyLdEv4HdnqasaEXRSYCAsD59mXEVQnM/ULNdQxbX77tdG4jPRjIS6knA=="],
+
+ "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.61.1", "", { "dependencies": { "@typescript-eslint/types": "8.61.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-6fJ9MHWtK14C1DSkiMlHUSOmrVebL7150xZJBlJiL62jjhIA4JmOq6flwBgDxIdBKKdoiZRel+dfPD5MLfny3w=="],
+
+ "@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.12.2", "", { "os": "android", "cpu": "arm" }, "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w=="],
+
+ "@unrs/resolver-binding-android-arm64": ["@unrs/resolver-binding-android-arm64@1.12.2", "", { "os": "android", "cpu": "arm64" }, "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ=="],
+
+ "@unrs/resolver-binding-darwin-arm64": ["@unrs/resolver-binding-darwin-arm64@1.12.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w=="],
+
+ "@unrs/resolver-binding-darwin-x64": ["@unrs/resolver-binding-darwin-x64@1.12.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA=="],
+
+ "@unrs/resolver-binding-freebsd-x64": ["@unrs/resolver-binding-freebsd-x64@1.12.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg=="],
+
+ "@unrs/resolver-binding-linux-arm-gnueabihf": ["@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2", "", { "os": "linux", "cpu": "arm" }, "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A=="],
+
+ "@unrs/resolver-binding-linux-arm-musleabihf": ["@unrs/resolver-binding-linux-arm-musleabihf@1.12.2", "", { "os": "linux", "cpu": "arm" }, "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g=="],
+
+ "@unrs/resolver-binding-linux-arm64-gnu": ["@unrs/resolver-binding-linux-arm64-gnu@1.12.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg=="],
+
+ "@unrs/resolver-binding-linux-arm64-musl": ["@unrs/resolver-binding-linux-arm64-musl@1.12.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA=="],
+
+ "@unrs/resolver-binding-linux-loong64-gnu": ["@unrs/resolver-binding-linux-loong64-gnu@1.12.2", "", { "os": "linux", "cpu": "none" }, "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q=="],
+
+ "@unrs/resolver-binding-linux-loong64-musl": ["@unrs/resolver-binding-linux-loong64-musl@1.12.2", "", { "os": "linux", "cpu": "none" }, "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew=="],
+
+ "@unrs/resolver-binding-linux-ppc64-gnu": ["@unrs/resolver-binding-linux-ppc64-gnu@1.12.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg=="],
+
+ "@unrs/resolver-binding-linux-riscv64-gnu": ["@unrs/resolver-binding-linux-riscv64-gnu@1.12.2", "", { "os": "linux", "cpu": "none" }, "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A=="],
+
+ "@unrs/resolver-binding-linux-riscv64-musl": ["@unrs/resolver-binding-linux-riscv64-musl@1.12.2", "", { "os": "linux", "cpu": "none" }, "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w=="],
+
+ "@unrs/resolver-binding-linux-s390x-gnu": ["@unrs/resolver-binding-linux-s390x-gnu@1.12.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw=="],
+
+ "@unrs/resolver-binding-linux-x64-gnu": ["@unrs/resolver-binding-linux-x64-gnu@1.12.2", "", { "os": "linux", "cpu": "x64" }, "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ=="],
+
+ "@unrs/resolver-binding-linux-x64-musl": ["@unrs/resolver-binding-linux-x64-musl@1.12.2", "", { "os": "linux", "cpu": "x64" }, "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A=="],
+
+ "@unrs/resolver-binding-openharmony-arm64": ["@unrs/resolver-binding-openharmony-arm64@1.12.2", "", { "os": "none", "cpu": "arm64" }, "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ=="],
+
+ "@unrs/resolver-binding-wasm32-wasi": ["@unrs/resolver-binding-wasm32-wasi@1.12.2", "", { "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "cpu": "none" }, "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A=="],
+
+ "@unrs/resolver-binding-win32-arm64-msvc": ["@unrs/resolver-binding-win32-arm64-msvc@1.12.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g=="],
+
+ "@unrs/resolver-binding-win32-ia32-msvc": ["@unrs/resolver-binding-win32-ia32-msvc@1.12.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g=="],
+
+ "@unrs/resolver-binding-win32-x64-msvc": ["@unrs/resolver-binding-win32-x64-msvc@1.12.2", "", { "os": "win32", "cpu": "x64" }, "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA=="],
+
+ "acorn": ["acorn@8.17.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg=="],
+
+ "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
+
+ "ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="],
+
+ "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
+
+ "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="],
+
+ "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="],
+
+ "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="],
+
+ "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
+
+ "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="],
+
+ "array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="],
+
+ "array-includes": ["array-includes@3.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-object-atoms": "^1.1.1", "get-intrinsic": "^1.3.0", "is-string": "^1.1.1", "math-intrinsics": "^1.1.0" } }, "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ=="],
+
+ "array.prototype.findlast": ["array.prototype.findlast@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="],
+
+ "array.prototype.findlastindex": ["array.prototype.findlastindex@1.2.6", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-shim-unscopables": "^1.1.0" } }, "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ=="],
+
+ "array.prototype.flat": ["array.prototype.flat@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg=="],
+
+ "array.prototype.flatmap": ["array.prototype.flatmap@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg=="],
+
+ "array.prototype.tosorted": ["array.prototype.tosorted@1.1.4", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA=="],
+
+ "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="],
+
+ "ast-types-flow": ["ast-types-flow@0.0.8", "", {}, "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ=="],
+
+ "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="],
+
+ "autoprefixer": ["autoprefixer@10.5.0", "", { "dependencies": { "browserslist": "^4.28.2", "caniuse-lite": "^1.0.30001787", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong=="],
+
+ "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
+
+ "axe-core": ["axe-core@4.12.1", "", {}, "sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA=="],
+
+ "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
+
+ "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
+
+ "baseline-browser-mapping": ["baseline-browser-mapping@2.10.38", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw=="],
+
+ "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="],
+
+ "brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="],
+
+ "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
+
+ "browserslist": ["browserslist@4.28.2", "", { "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" } }, "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg=="],
+
+ "busboy": ["busboy@1.6.0", "", { "dependencies": { "streamsearch": "^1.1.0" } }, "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA=="],
+
+ "call-bind": ["call-bind@1.0.9", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "get-intrinsic": "^1.3.0", "set-function-length": "^1.2.2" } }, "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ=="],
+
+ "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
+
+ "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
+
+ "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
+
+ "camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="],
+
+ "caniuse-lite": ["caniuse-lite@1.0.30001799", "", {}, "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw=="],
+
+ "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
+
+ "chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
+
+ "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
+
+ "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
+
+ "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
+
+ "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="],
+
+ "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
+
+ "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
+
+ "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
+
+ "commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="],
+
+ "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
+
+ "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
+
+ "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
+
+ "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
+
+ "damerau-levenshtein": ["damerau-levenshtein@1.0.8", "", {}, "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA=="],
+
+ "data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="],
+
+ "data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="],
+
+ "data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="],
+
+ "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
+
+ "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
+
+ "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="],
+
+ "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="],
+
+ "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
+
+ "didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="],
+
+ "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="],
+
+ "doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="],
+
+ "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
+
+ "electron-to-chromium": ["electron-to-chromium@1.5.375", "", {}, "sha512-ZWP5eB4BVPW/ZYo9252hQZHZ5XavtsTgpbhcmMmRwymavC5AsLWQWBPaKMeNd2LW0KGby5HPXvj7+sr4ta5j/Q=="],
+
+ "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
+
+ "es-abstract": ["es-abstract@1.24.2", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg=="],
+
+ "es-abstract-get": ["es-abstract-get@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "es-object-atoms": "^1.1.2", "is-callable": "^1.2.7", "object-inspect": "^1.13.4" } }, "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg=="],
+
+ "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
+
+ "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
+
+ "es-iterator-helpers": ["es-iterator-helpers@1.3.3", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.1.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.3.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.5", "math-intrinsics": "^1.1.0" } }, "sha512-0PuBxFi+4uPanB97iDxCLWuHeYud2FALrw5HFZGtAF38UpJDbDC8frwp2cnDyae692CQ0dou60UwWfhgsa4U/g=="],
+
+ "es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="],
+
+ "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
+
+ "es-shim-unscopables": ["es-shim-unscopables@1.1.0", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw=="],
+
+ "es-to-primitive": ["es-to-primitive@1.3.1", "", { "dependencies": { "es-abstract-get": "^1.0.0", "es-errors": "^1.3.0", "is-callable": "^1.2.7", "is-date-object": "^1.1.0", "is-symbol": "^1.1.1" } }, "sha512-CxN9N56HYfd2m/acc/NOFrZQsN9kU4eh+2kk6A707Kz1krH8tKmfrs5RnftB8WNX80T0NS7vSQsDOlg23diR2g=="],
+
+ "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
+
+ "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
+
+ "eslint": ["eslint@9.39.4", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.2", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.5", "@eslint/js": "9.39.4", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ=="],
+
+ "eslint-config-next": ["eslint-config-next@15.1.6", "", { "dependencies": { "@next/eslint-plugin-next": "15.1.6", "@rushstack/eslint-patch": "^1.10.3", "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^5.0.0" }, "peerDependencies": { "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", "typescript": ">=3.3.1" }, "optionalPeers": ["typescript"] }, "sha512-Wd1uy6y7nBbXUSg9QAuQ+xYEKli5CgUhLjz1QHW11jLDis5vK5XB3PemL6jEmy7HrdhaRFDz+GTZ/3FoH+EUjg=="],
+
+ "eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.10", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.16.1", "resolve": "^2.0.0-next.6" } }, "sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ=="],
+
+ "eslint-import-resolver-typescript": ["eslint-import-resolver-typescript@3.10.1", "", { "dependencies": { "@nolyfill/is-core-module": "1.0.39", "debug": "^4.4.0", "get-tsconfig": "^4.10.0", "is-bun-module": "^2.0.0", "stable-hash": "^0.0.5", "tinyglobby": "^0.2.13", "unrs-resolver": "^1.6.2" }, "peerDependencies": { "eslint": "*", "eslint-plugin-import": "*", "eslint-plugin-import-x": "*" }, "optionalPeers": ["eslint-plugin-import", "eslint-plugin-import-x"] }, "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ=="],
+
+ "eslint-module-utils": ["eslint-module-utils@2.13.0", "", { "dependencies": { "debug": "^3.2.7" } }, "sha512-bLohSkT6469rRs8czj0tLTD8vaeIS/whvPRJVjDr7IuoTT1k5DYDERlNycjDj/HkOlvQdYurmfZ/g3fG5bgeLQ=="],
+
+ "eslint-plugin-import": ["eslint-plugin-import@2.32.0", "", { "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", "array.prototype.findlastindex": "^1.2.6", "array.prototype.flat": "^1.3.3", "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", "object.values": "^1.2.1", "semver": "^6.3.1", "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "peerDependencies": { "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA=="],
+
+ "eslint-plugin-jsx-a11y": ["eslint-plugin-jsx-a11y@6.10.2", "", { "dependencies": { "aria-query": "^5.3.2", "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", "axe-core": "^4.10.0", "axobject-query": "^4.1.0", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "safe-regex-test": "^1.0.3", "string.prototype.includes": "^2.0.1" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q=="],
+
+ "eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="],
+
+ "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="],
+
+ "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
+
+ "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
+
+ "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
+
+ "esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
+
+ "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
+
+ "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
+
+ "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
+
+ "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
+
+ "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
+
+ "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
+
+ "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
+
+ "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
+
+ "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
+
+ "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
+
+ "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
+
+ "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
+
+ "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
+
+ "flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="],
+
+ "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],
+
+ "fraction.js": ["fraction.js@5.3.4", "", {}, "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ=="],
+
+ "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
+
+ "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
+
+ "function.prototype.name": ["function.prototype.name@1.2.0", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2", "hasown": "^2.0.4", "is-callable": "^1.2.7", "is-document.all": "^1.0.0" } }, "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew=="],
+
+ "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="],
+
+ "generator-function": ["generator-function@2.0.1", "", {}, "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g=="],
+
+ "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
+
+ "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
+
+ "get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="],
+
+ "get-tsconfig": ["get-tsconfig@4.14.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-yTb+8DXzDREzgvYmh6s9vHsSVCHeC0G3PI5bEXNBHtmshPnO+S5O7qgLEOn0I5QvMy6kpZN8K1NKGyilLb93wA=="],
+
+ "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
+
+ "globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
+
+ "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="],
+
+ "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
+
+ "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="],
+
+ "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
+
+ "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="],
+
+ "has-proto": ["has-proto@1.2.0", "", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="],
+
+ "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
+
+ "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
+
+ "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="],
+
+ "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
+
+ "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
+
+ "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
+
+ "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="],
+
+ "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="],
+
+ "is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="],
+
+ "is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="],
+
+ "is-bigint": ["is-bigint@1.1.0", "", { "dependencies": { "has-bigints": "^1.0.2" } }, "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ=="],
+
+ "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="],
+
+ "is-boolean-object": ["is-boolean-object@1.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="],
+
+ "is-bun-module": ["is-bun-module@2.0.0", "", { "dependencies": { "semver": "^7.7.1" } }, "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ=="],
+
+ "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="],
+
+ "is-core-module": ["is-core-module@2.16.2", "", { "dependencies": { "hasown": "^2.0.3" } }, "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA=="],
+
+ "is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="],
+
+ "is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="],
+
+ "is-document.all": ["is-document.all@1.0.0", "", { "dependencies": { "call-bound": "^1.0.4" } }, "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g=="],
+
+ "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
+
+ "is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="],
+
+ "is-generator-function": ["is-generator-function@1.1.2", "", { "dependencies": { "call-bound": "^1.0.4", "generator-function": "^2.0.0", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA=="],
+
+ "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
+
+ "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="],
+
+ "is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="],
+
+ "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
+
+ "is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="],
+
+ "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="],
+
+ "is-set": ["is-set@2.0.3", "", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="],
+
+ "is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="],
+
+ "is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="],
+
+ "is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="],
+
+ "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="],
+
+ "is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="],
+
+ "is-weakref": ["is-weakref@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="],
+
+ "is-weakset": ["is-weakset@2.0.4", "", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="],
+
+ "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
+
+ "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
+
+ "iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="],
+
+ "jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="],
+
+ "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
+
+ "js-yaml": ["js-yaml@4.2.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw=="],
+
+ "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
+
+ "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
+
+ "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
+
+ "json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="],
+
+ "jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="],
+
+ "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
+
+ "language-subtag-registry": ["language-subtag-registry@0.3.23", "", {}, "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ=="],
+
+ "language-tags": ["language-tags@1.0.9", "", { "dependencies": { "language-subtag-registry": "^0.3.20" } }, "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA=="],
+
+ "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
+
+ "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="],
+
+ "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
+
+ "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
+
+ "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
+
+ "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
+
+ "lucide-react": ["lucide-react@0.469.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-28vvUnnKQ/dBwiCQtwJw7QauYnE7yd2Cyp4tTTJpvglX4EMpbflcdBgrgToX2j71B3YvugK/NH3BGUk+E/p/Fw=="],
+
+ "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
+
+ "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
+
+ "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
+
+ "minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
+
+ "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
+
+ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
+
+ "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="],
+
+ "nanoid": ["nanoid@3.3.13", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-sPdqC6ByMVVGvF1ynvvMo0/o+oD1VX7DaHhijt1bFgjvBkHBib4t49GoNDhf2NDta4oeUNlaGbSt5K7qjZ955Q=="],
+
+ "napi-postinstall": ["napi-postinstall@0.3.4", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ=="],
+
+ "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
+
+ "next": ["next@15.1.6", "", { "dependencies": { "@next/env": "15.1.6", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "15.1.6", "@next/swc-darwin-x64": "15.1.6", "@next/swc-linux-arm64-gnu": "15.1.6", "@next/swc-linux-arm64-musl": "15.1.6", "@next/swc-linux-x64-gnu": "15.1.6", "@next/swc-linux-x64-musl": "15.1.6", "@next/swc-win32-arm64-msvc": "15.1.6", "@next/swc-win32-x64-msvc": "15.1.6", "sharp": "^0.33.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-Hch4wzbaX0vKQtalpXvUiw5sYivBy4cm5rzUKrBnUB/y436LGrvOUqYvlSeNVCWFO/770gDlltR9gqZH62ct4Q=="],
+
+ "node-exports-info": ["node-exports-info@1.6.0", "", { "dependencies": { "array.prototype.flatmap": "^1.3.3", "es-errors": "^1.3.0", "object.entries": "^1.1.9", "semver": "^6.3.1" } }, "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw=="],
+
+ "node-releases": ["node-releases@2.0.48", "", {}, "sha512-1uz8041X6LoI6ZSdZacM9lVY28vuzDlSKitnpbSNK0RfKoIJkX29NBPVEFXhnuSuEOA9Ww0xnPJ+ILWbGAv8DA=="],
+
+ "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="],
+
+ "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
+
+ "object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="],
+
+ "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
+
+ "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="],
+
+ "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="],
+
+ "object.entries": ["object.entries@1.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.1" } }, "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw=="],
+
+ "object.fromentries": ["object.fromentries@2.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" } }, "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ=="],
+
+ "object.groupby": ["object.groupby@1.0.3", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2" } }, "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ=="],
+
+ "object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="],
+
+ "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
+
+ "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="],
+
+ "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
+
+ "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
+
+ "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
+
+ "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
+
+ "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
+
+ "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
+
+ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
+
+ "picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
+
+ "pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="],
+
+ "pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="],
+
+ "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
+
+ "postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="],
+
+ "postcss-import": ["postcss-import@15.1.0", "", { "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "peerDependencies": { "postcss": "^8.0.0" } }, "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew=="],
+
+ "postcss-js": ["postcss-js@4.1.0", "", { "dependencies": { "camelcase-css": "^2.0.1" }, "peerDependencies": { "postcss": "^8.4.21" } }, "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw=="],
+
+ "postcss-load-config": ["postcss-load-config@6.0.1", "", { "dependencies": { "lilconfig": "^3.1.1" }, "peerDependencies": { "jiti": ">=1.21.0", "postcss": ">=8.0.9", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["jiti", "postcss", "tsx", "yaml"] }, "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g=="],
+
+ "postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="],
+
+ "postcss-selector-parser": ["postcss-selector-parser@6.1.4", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ=="],
+
+ "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="],
+
+ "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
+
+ "prettier": ["prettier@3.8.4", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q=="],
+
+ "prettier-plugin-tailwindcss": ["prettier-plugin-tailwindcss@0.6.14", "", { "peerDependencies": { "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-hermes": "*", "@prettier/plugin-oxc": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@trivago/prettier-plugin-sort-imports": "*", "@zackad/prettier-plugin-twig": "*", "prettier": "^3.0", "prettier-plugin-astro": "*", "prettier-plugin-css-order": "*", "prettier-plugin-import-sort": "*", "prettier-plugin-jsdoc": "*", "prettier-plugin-marko": "*", "prettier-plugin-multiline-arrays": "*", "prettier-plugin-organize-attributes": "*", "prettier-plugin-organize-imports": "*", "prettier-plugin-sort-imports": "*", "prettier-plugin-style-order": "*", "prettier-plugin-svelte": "*" }, "optionalPeers": ["@ianvs/prettier-plugin-sort-imports", "@prettier/plugin-hermes", "@prettier/plugin-oxc", "@prettier/plugin-pug", "@shopify/prettier-plugin-liquid", "@trivago/prettier-plugin-sort-imports", "@zackad/prettier-plugin-twig", "prettier-plugin-astro", "prettier-plugin-css-order", "prettier-plugin-import-sort", "prettier-plugin-jsdoc", "prettier-plugin-marko", "prettier-plugin-multiline-arrays", "prettier-plugin-organize-attributes", "prettier-plugin-organize-imports", "prettier-plugin-sort-imports", "prettier-plugin-style-order", "prettier-plugin-svelte"] }, "sha512-pi2e/+ZygeIqntN+vC573BcW5Cve8zUB0SSAGxqpB4f96boZF4M3phPVoOFCeypwkpRYdi7+jQ5YJJUwrkGUAg=="],
+
+ "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
+
+ "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
+
+ "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
+
+ "react": ["react@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ=="],
+
+ "react-dom": ["react-dom@18.3.1", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" }, "peerDependencies": { "react": "^18.3.1" } }, "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw=="],
+
+ "react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
+
+ "read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="],
+
+ "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
+
+ "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="],
+
+ "regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="],
+
+ "resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="],
+
+ "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
+
+ "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
+
+ "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
+
+ "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
+
+ "safe-array-concat": ["safe-array-concat@1.1.4", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "get-intrinsic": "^1.3.0", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg=="],
+
+ "safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="],
+
+ "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="],
+
+ "scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="],
+
+ "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
+
+ "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="],
+
+ "set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="],
+
+ "set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="],
+
+ "sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="],
+
+ "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
+
+ "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
+
+ "side-channel": ["side-channel@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4", "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ=="],
+
+ "side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="],
+
+ "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
+
+ "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
+
+ "simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="],
+
+ "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
+
+ "stable-hash": ["stable-hash@0.0.5", "", {}, "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA=="],
+
+ "stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="],
+
+ "streamsearch": ["streamsearch@1.1.0", "", {}, "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="],
+
+ "string.prototype.includes": ["string.prototype.includes@2.0.1", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3" } }, "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg=="],
+
+ "string.prototype.matchall": ["string.prototype.matchall@4.0.12", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA=="],
+
+ "string.prototype.repeat": ["string.prototype.repeat@1.0.0", "", { "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" } }, "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w=="],
+
+ "string.prototype.trim": ["string.prototype.trim@1.2.11", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "es-object-atoms": "^1.1.2", "has-property-descriptors": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w=="],
+
+ "string.prototype.trimend": ["string.prototype.trimend@1.0.10", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.2" } }, "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw=="],
+
+ "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="],
+
+ "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="],
+
+ "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
+
+ "styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="],
+
+ "sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="],
+
+ "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
+
+ "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
+
+ "tailwind-merge": ["tailwind-merge@2.6.1", "", {}, "sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ=="],
+
+ "tailwindcss": ["tailwindcss@3.4.19", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.7", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ=="],
+
+ "tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="],
+
+ "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="],
+
+ "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="],
+
+ "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="],
+
+ "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
+
+ "ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="],
+
+ "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="],
+
+ "tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="],
+
+ "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+
+ "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
+
+ "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="],
+
+ "typed-array-byte-length": ["typed-array-byte-length@1.0.3", "", { "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" } }, "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg=="],
+
+ "typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="],
+
+ "typed-array-length": ["typed-array-length@1.0.8", "", { "dependencies": { "call-bind": "^1.0.9", "for-each": "^0.3.5", "gopd": "^1.2.0", "is-typed-array": "^1.1.15", "possible-typed-array-names": "^1.1.0", "reflect.getprototypeof": "^1.0.10" } }, "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g=="],
+
+ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
+
+ "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
+
+ "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
+
+ "unrs-resolver": ["unrs-resolver@1.12.2", "", { "dependencies": { "napi-postinstall": "^0.3.4" }, "optionalDependencies": { "@unrs/resolver-binding-android-arm-eabi": "1.12.2", "@unrs/resolver-binding-android-arm64": "1.12.2", "@unrs/resolver-binding-darwin-arm64": "1.12.2", "@unrs/resolver-binding-darwin-x64": "1.12.2", "@unrs/resolver-binding-freebsd-x64": "1.12.2", "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", "@unrs/resolver-binding-linux-x64-musl": "1.12.2", "@unrs/resolver-binding-openharmony-arm64": "1.12.2", "@unrs/resolver-binding-wasm32-wasi": "1.12.2", "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" } }, "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ=="],
+
+ "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
+
+ "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
+
+ "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
+
+ "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
+
+ "which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="],
+
+ "which-builtin-type": ["which-builtin-type@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" } }, "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q=="],
+
+ "which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="],
+
+ "which-typed-array": ["which-typed-array@1.1.22", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.9", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw=="],
+
+ "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
+
+ "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
+
+ "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
+
+ "@next/eslint-plugin-next/fast-glob": ["fast-glob@3.3.1", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg=="],
+
+ "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
+
+ "@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
+
+ "@typescript-eslint/typescript-estree/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="],
+
+ "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
+
+ "@unrs/resolver-binding-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="],
+
+ "chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
+
+ "eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
+
+ "eslint-import-resolver-node/resolve": ["resolve@2.0.0-next.7", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.2", "node-exports-info": "^1.6.0", "object-keys": "^1.1.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ=="],
+
+ "eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
+
+ "eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
+
+ "eslint-plugin-react/resolve": ["resolve@2.0.0-next.7", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.2", "node-exports-info": "^1.6.0", "object-keys": "^1.1.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ=="],
+
+ "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
+
+ "is-bun-module/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="],
+
+ "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
+
+ "sharp/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="],
+
+ "tinyglobby/picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],
+
+ "@next/eslint-plugin-next/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
+
+ "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="],
+
+ "@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
+ }
+}
diff --git a/website/components/docs/doc-pager.tsx b/website/components/docs/doc-pager.tsx
new file mode 100644
index 0000000..cf7b4a0
--- /dev/null
+++ b/website/components/docs/doc-pager.tsx
@@ -0,0 +1,51 @@
+"use client";
+
+import Link from "next/link";
+import { usePathname } from "next/navigation";
+import { ArrowLeft, ArrowRight } from "lucide-react";
+
+import { docPager } from "@/lib/docs-nav";
+
+export function DocPager() {
+ const pathname = usePathname();
+ const { prev, next } = docPager(pathname);
+
+ if (!prev && !next) {
+ return null;
+ }
+
+ return (
+
+ {prev ? (
+
+
+
+ Previous
+
+
+ {prev.title}
+
+
+ ) : (
+
+ )}
+ {next && (
+
+
+ Next
+
+
+
+ {next.title}
+
+
+ )}
+
+ );
+}
diff --git a/website/components/docs/doc-primitives.tsx b/website/components/docs/doc-primitives.tsx
new file mode 100644
index 0000000..d07c704
--- /dev/null
+++ b/website/components/docs/doc-primitives.tsx
@@ -0,0 +1,229 @@
+import * as React from "react";
+import Link from "next/link";
+import { AlertTriangle, ArrowUpRight, Info, Lightbulb, ShieldAlert } from "lucide-react";
+
+import { cn } from "@/lib/utils";
+import { Eyebrow } from "@/components/site/section";
+
+export function DocHeader({
+ eyebrow,
+ title,
+ description,
+}: {
+ eyebrow?: string;
+ title: string;
+ description?: React.ReactNode;
+}) {
+ return (
+
+ {eyebrow && {eyebrow} }
+
+ {title}
+
+ {description && (
+
+ {description}
+
+ )}
+
+ );
+}
+
+export function DocH2({ id, children }: { id: string; children: React.ReactNode }) {
+ return (
+
+ );
+}
+
+export function DocH3({ id, children }: { id?: string; children: React.ReactNode }) {
+ return (
+
+ {children}
+
+ );
+}
+
+export function Prose({
+ className,
+ children,
+}: {
+ className?: string;
+ children: React.ReactNode;
+}) {
+ return (
+ strong]:text-foreground",
+ "[&_code]:rounded [&_code]:bg-muted [&_code]:px-1.5 [&_code]:py-0.5 [&_code]:font-mono [&_code]:text-[0.85em] [&_code]:text-foreground",
+ "[&_blockquote]:my-4 [&_blockquote]:border-l-2 [&_blockquote]:border-primary/40 [&_blockquote]:pl-4 [&_blockquote]:italic",
+ className
+ )}
+ >
+ {children}
+
+ );
+}
+
+const calloutStyles = {
+ note: {
+ icon: Info,
+ container: "border-border bg-secondary/60",
+ accent: "text-muted-foreground",
+ },
+ tip: {
+ icon: Lightbulb,
+ container: "border-border bg-card",
+ accent: "text-foreground",
+ },
+ warning: {
+ icon: AlertTriangle,
+ container: "border-foreground/15 bg-muted/70",
+ accent: "text-foreground",
+ },
+ privacy: {
+ icon: ShieldAlert,
+ container: "border-foreground/25 bg-secondary",
+ accent: "text-foreground",
+ },
+} as const;
+
+export function Callout({
+ variant = "note",
+ title,
+ children,
+}: {
+ variant?: keyof typeof calloutStyles;
+ title?: string;
+ children: React.ReactNode;
+}) {
+ const style = calloutStyles[variant];
+ const Icon = style.icon;
+ return (
+
+
+
+ {title &&
{title}
}
+
+ {children}
+
+
+
+ );
+}
+
+export function Steps({ children }: { children: React.ReactNode }) {
+ return (
+ {children}
+ );
+}
+
+export function Step({
+ n,
+ title,
+ children,
+}: {
+ n: number;
+ title: string;
+ children: React.ReactNode;
+}) {
+ return (
+
+
+ {n}
+
+ {title}
+
+ {children}
+
+
+ );
+}
+
+export function FieldList({ children }: { children: React.ReactNode }) {
+ return (
+
+ {children}
+
+ );
+}
+
+export function Field({
+ name,
+ type,
+ children,
+}: {
+ name: string;
+ type?: string;
+ children: React.ReactNode;
+}) {
+ return (
+
+
+ {name}
+ {type && {type} }
+
+ {children}
+
+ );
+}
+
+export function Kbd({ children }: { children: React.ReactNode }) {
+ return (
+
+ {children}
+
+ );
+}
+
+export function DocDivider() {
+ return ;
+}
+
+export function CardGrid({ children }: { children: React.ReactNode }) {
+ return {children}
;
+}
+
+export function LinkCard({
+ href,
+ title,
+ children,
+ external,
+}: {
+ href: string;
+ title: string;
+ children: React.ReactNode;
+ external?: boolean;
+}) {
+ return (
+
+
+
+ {title}
+
+
+
+ {children}
+
+ );
+}
diff --git a/website/components/docs/docs-mobile-nav.tsx b/website/components/docs/docs-mobile-nav.tsx
new file mode 100644
index 0000000..ce18178
--- /dev/null
+++ b/website/components/docs/docs-mobile-nav.tsx
@@ -0,0 +1,38 @@
+"use client";
+
+import * as React from "react";
+import { usePathname } from "next/navigation";
+import { ChevronDown, Menu } from "lucide-react";
+
+import { docsFlat } from "@/lib/docs-nav";
+import { DocsSidebar } from "@/components/docs/docs-sidebar";
+
+export function DocsMobileNav() {
+ const pathname = usePathname();
+ const [open, setOpen] = React.useState(false);
+ const current = docsFlat.find((item) => item.href === pathname);
+
+ return (
+
+
setOpen((value) => !value)}
+ aria-expanded={open}
+ className="flex w-full items-center justify-between rounded-lg border border-border bg-card px-4 py-2.5 text-ms-15 font-medium shadow-sm focus-ring"
+ >
+
+
+ {current ? current.title : "Documentation"}
+
+
+
+ {open && (
+
+ setOpen(false)} />
+
+ )}
+
+ );
+}
diff --git a/website/components/docs/docs-sidebar.tsx b/website/components/docs/docs-sidebar.tsx
new file mode 100644
index 0000000..34346e8
--- /dev/null
+++ b/website/components/docs/docs-sidebar.tsx
@@ -0,0 +1,45 @@
+"use client";
+
+import Link from "next/link";
+import { usePathname } from "next/navigation";
+
+import { cn } from "@/lib/utils";
+import { docsNav } from "@/lib/docs-nav";
+
+export function DocsSidebar({ onNavigate }: { onNavigate?: () => void }) {
+ const pathname = usePathname();
+
+ return (
+
+ {docsNav.map((section) => (
+
+
+ {section.title}
+
+
+ {section.items.map((item) => {
+ const active = pathname === item.href;
+ return (
+
+
+ {item.title}
+
+
+ );
+ })}
+
+
+ ))}
+
+ );
+}
diff --git a/website/components/landing/capability-table.tsx b/website/components/landing/capability-table.tsx
new file mode 100644
index 0000000..77bd97d
--- /dev/null
+++ b/website/components/landing/capability-table.tsx
@@ -0,0 +1,63 @@
+import { Check, Minus } from "lucide-react";
+
+import { cn } from "@/lib/utils";
+
+type Row = {
+ capability: string;
+ local: boolean;
+ detail: string;
+};
+
+const rows: Row[] = [
+ { capability: "Audio capture", local: true, detail: "cpal + ScreenCaptureKit" },
+ { capability: "Transcription", local: true, detail: "whisper.cpp, Metal-accelerated" },
+ { capability: "Speaker diarization", local: true, detail: "pyannote + sherpa-onnx" },
+ { capability: "Note storage", local: true, detail: "Markdown in your vault" },
+ { capability: "Encryption at rest", local: true, detail: "AES-256-GCM + Argon2id" },
+ { capability: "Connectors (MCP)", local: true, detail: "stdio, read-only" },
+ { capability: "Cloud transcription", local: false, detail: "Opt-in OpenAI Whisper" },
+ { capability: "Chat & webhooks", local: false, detail: "Opt-in, Privacy Mode blocks" },
+];
+
+export function CapabilityTable() {
+ return (
+
+
+ Capability
+ Runs
+ Backend
+
+
+ {rows.map((row) => (
+
+ {row.capability}
+
+ {row.local ? (
+ <>
+
+ local
+ >
+ ) : (
+ <>
+
+ opt-in
+ >
+ )}
+
+ {row.detail}
+
+ ))}
+
+
+ );
+}
diff --git a/website/components/landing/connectors-section.tsx b/website/components/landing/connectors-section.tsx
new file mode 100644
index 0000000..99813b8
--- /dev/null
+++ b/website/components/landing/connectors-section.tsx
@@ -0,0 +1,59 @@
+import Link from "next/link";
+import { ArrowRight, Terminal } from "lucide-react";
+
+import { Section, SectionHeading } from "@/components/site/section";
+import { Button } from "@/components/ui/button";
+import { CodeBlock } from "@/components/site/code-block";
+
+const tools = ["Claude Desktop", "Cursor", "Claude Code", "Any MCP client"];
+
+const mcpConfig = `{
+ "mcpServers": {
+ "folio": {
+ "command": "folio-mcp",
+ "args": []
+ }
+ }
+}`;
+
+export function ConnectorsSection() {
+ return (
+
+
+
+
+
+ {tools.map((tool) => (
+
+
+ {tool}
+
+ ))}
+
+
+
+
+
+
+ Search past meetings without leaving your editor.
+ Pull decisions and action items into your workflow.
+ Everything runs on stdio, scoped to read-only.
+
+
+
+ Set up connectors
+
+
+
+
+
+
+ );
+}
diff --git a/website/components/landing/cta-section.tsx b/website/components/landing/cta-section.tsx
new file mode 100644
index 0000000..120f94f
--- /dev/null
+++ b/website/components/landing/cta-section.tsx
@@ -0,0 +1,53 @@
+import Link from "next/link";
+import { ArrowRight } from "lucide-react";
+
+import { siteConfig } from "@/lib/site-config";
+import { Button } from "@/components/ui/button";
+import { CommandLine } from "@/components/site/code-block";
+import { FolioMark } from "@/components/site/logo";
+import { WaveBars } from "@/components/landing/wave-bars";
+
+export function CtaSection() {
+ return (
+
+
+
+
+
+
+ Own your meeting notes
+
+
+ Install {siteConfig.name}, grant microphone and screen-recording permission,
+ and your next meeting writes itself to your vault.
+
+
+
+
+
+ Install for {siteConfig.platform}
+
+
+
+
+
+ Star on GitHub
+
+
+
+
+
+
+
+ );
+}
diff --git a/website/components/landing/faq-section.tsx b/website/components/landing/faq-section.tsx
new file mode 100644
index 0000000..1a8b42d
--- /dev/null
+++ b/website/components/landing/faq-section.tsx
@@ -0,0 +1,70 @@
+import Link from "next/link";
+
+import { Section, SectionHeading } from "@/components/site/section";
+import {
+ Accordion,
+ AccordionContent,
+ AccordionItem,
+ AccordionTrigger,
+} from "@/components/ui/accordion";
+
+const faqs = [
+ {
+ question: "Does my audio ever leave my machine?",
+ answer:
+ "Not on the default path. Capture, transcription, and diarization all run on-device. The only network calls are the one-time model download and the opt-in cloud-AI and webhook paths, all of which Privacy Mode can block.",
+ },
+ {
+ question: "Does it join my calls as a bot?",
+ answer:
+ "No. Folio captures system audio directly through ScreenCaptureKit, so there is no bot in the meeting and nothing for other participants to admit.",
+ },
+ {
+ question: "Where do my notes go?",
+ answer:
+ "Each meeting becomes a markdown file in the vault path you choose, with frontmatter for attendees, duration, model, and source. They are plain files you can read, edit, and back up however you like.",
+ },
+ {
+ question: "Do I need an account or API key?",
+ answer:
+ "No account, ever. Local transcription works out of the box. An OpenAI key is only needed if you opt into cloud transcription or chat features.",
+ },
+ {
+ question: "Which Macs are supported?",
+ answer:
+ "macOS 13 Ventura or later, on Apple Silicon or Intel. Apple Silicon is the performance target and gets Metal-accelerated Whisper.",
+ },
+];
+
+export function FaqSection() {
+ return (
+
+
+
+
+ {faqs.map((faq) => (
+
+ {faq.question}
+ {faq.answer}
+
+ ))}
+
+
+ More in the{" "}
+
+ full FAQ
+ {" "}
+ and the{" "}
+
+ documentation
+
+ .
+
+
+
+ );
+}
diff --git a/website/components/landing/feature-grid.tsx b/website/components/landing/feature-grid.tsx
new file mode 100644
index 0000000..9e3e2b7
--- /dev/null
+++ b/website/components/landing/feature-grid.tsx
@@ -0,0 +1,100 @@
+import {
+ AudioLines,
+ Braces,
+ FileText,
+ Plug,
+ ShieldCheck,
+ Users,
+} from "lucide-react";
+
+import { cn } from "@/lib/utils";
+import { Section, SectionHeading } from "@/components/site/section";
+import { WaveBars } from "@/components/landing/wave-bars";
+
+type Feature = {
+ icon: typeof FileText;
+ title: string;
+ description: string;
+ className?: string;
+ accent?: boolean;
+};
+
+const features: Feature[] = [
+ {
+ icon: AudioLines,
+ title: "Two streams, captured separately",
+ description:
+ "System audio and your microphone are recorded as independent tracks via cpal and ScreenCaptureKit, so the transcript stays clean and attributable.",
+ className: "lg:col-span-2",
+ accent: true,
+ },
+ {
+ icon: ShieldCheck,
+ title: "Private by default",
+ description:
+ "The default path keeps audio, transcripts, and notes on your machine. Privacy Mode physically blocks every outbound call except localhost.",
+ },
+ {
+ icon: Users,
+ title: "On-device diarization",
+ description:
+ "Speakers are separated locally with pyannote segmentation and a speaker-embedding model. Your microphone is always labelled You.",
+ },
+ {
+ icon: FileText,
+ title: "One markdown note per meeting",
+ description:
+ "Every meeting becomes a portable markdown file in your own vault, with frontmatter for attendees, duration, model, and source.",
+ className: "lg:col-span-2",
+ },
+ {
+ icon: Plug,
+ title: "Connect your tools",
+ description:
+ "A local MCP server gives Claude, Cursor, and Claude Code read-only access to your transcripts, tasks, and memory over stdio.",
+ },
+ {
+ icon: Braces,
+ title: "Yours to own",
+ description:
+ "Plain files on disk, an open IPC contract, and an Apache-2.0 codebase. No lock-in, no account, no cloud dependency.",
+ className: "lg:col-span-2",
+ },
+];
+
+export function FeatureGrid() {
+ return (
+
+
+
+
+ {features.map((feature) => (
+
+
+
+
+
+ {feature.accent && (
+
+ )}
+
+ {feature.title}
+
+ {feature.description}
+
+
+ ))}
+
+
+ );
+}
diff --git a/website/components/landing/hero.tsx b/website/components/landing/hero.tsx
new file mode 100644
index 0000000..b0f0824
--- /dev/null
+++ b/website/components/landing/hero.tsx
@@ -0,0 +1,69 @@
+import Link from "next/link";
+import { ArrowRight, ShieldCheck } from "lucide-react";
+
+import { siteConfig } from "@/lib/site-config";
+import { Button } from "@/components/ui/button";
+import { CommandLine } from "@/components/site/code-block";
+import { NotePreview } from "@/components/landing/note-preview";
+
+export function Hero() {
+ return (
+
+
+
+
+
+
+ Local-first · No telemetry · {siteConfig.platform}
+
+
+
+ Meeting notes that never leave your Mac.
+
+
+
+ {siteConfig.name} captures system audio and your microphone, transcribes
+ on-device, and writes a clean markdown note per meeting to your own vault.
+ Private by default.
+
+
+
+
+
+ Install {siteConfig.name}
+
+
+
+
+ Read the docs
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/website/components/landing/how-it-works.tsx b/website/components/landing/how-it-works.tsx
new file mode 100644
index 0000000..a4e0c07
--- /dev/null
+++ b/website/components/landing/how-it-works.tsx
@@ -0,0 +1,68 @@
+import { CalendarClock, Mic, ScrollText, Sparkles } from "lucide-react";
+
+import { Section, SectionHeading } from "@/components/site/section";
+
+const steps = [
+ {
+ icon: CalendarClock,
+ step: "01",
+ title: "It notices the meeting",
+ description:
+ "Folio watches your calendar and audio devices through EventKit. No Google OAuth, no Microsoft Graph, no meeting bots.",
+ },
+ {
+ icon: Mic,
+ step: "02",
+ title: "It records both sides",
+ description:
+ "When the call starts, system audio and your microphone are captured as separate streams and written to WAV on disk.",
+ },
+ {
+ icon: ScrollText,
+ step: "03",
+ title: "It transcribes locally",
+ description:
+ "The bundled Whisper backend transcribes on-device and diarizes speakers. Cloud transcription is an explicit opt-in, never the default.",
+ },
+ {
+ icon: Sparkles,
+ step: "04",
+ title: "It writes the note",
+ description:
+ "A markdown file lands in your vault with frontmatter, speaker-labelled transcript, decisions, and tasks. Searchable forever.",
+ },
+];
+
+export function HowItWorks() {
+ return (
+
+
+
+
+ {steps.map((item) => (
+
+
+
+
+
+
+ {item.step}
+
+
+ {item.title}
+
+ {item.description}
+
+
+ ))}
+
+
+ );
+}
diff --git a/website/components/landing/install-section.tsx b/website/components/landing/install-section.tsx
new file mode 100644
index 0000000..0372f96
--- /dev/null
+++ b/website/components/landing/install-section.tsx
@@ -0,0 +1,71 @@
+import Link from "next/link";
+import { ArrowRight } from "lucide-react";
+
+import { siteConfig } from "@/lib/site-config";
+import { Section, SectionHeading } from "@/components/site/section";
+import { Button } from "@/components/ui/button";
+import { CodeBlock } from "@/components/site/code-block";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
+
+const homebrew = `${siteConfig.install.tapCommand}
+${siteConfig.install.installCommand}`;
+
+const source = `git clone ${siteConfig.links.github}.git
+cd folio
+bun install
+bun tauri dev`;
+
+export function InstallSection() {
+ return (
+
+
+
+
+
+
+ Homebrew
+ Direct download
+ From source
+
+
+
+
+
+
+
+
+
+ Grab the latest Apple Silicon .dmg{" "}
+ from the releases page, open it, and drag Folio to Applications. Builds
+ are code-signed and notarized, so they open without a Gatekeeper prompt.
+
+
+
+ Download the latest release
+
+
+
+
+
+
+
+
+
+
+
+
+ Already installed? Update any time with{" "}
+
+ {siteConfig.install.upgradeCommand}
+
+ .
+
+
+
+ );
+}
diff --git a/website/components/landing/note-preview.tsx b/website/components/landing/note-preview.tsx
new file mode 100644
index 0000000..40a3e4d
--- /dev/null
+++ b/website/components/landing/note-preview.tsx
@@ -0,0 +1,74 @@
+import { FileText, Hash, Lock } from "lucide-react";
+
+import { cn } from "@/lib/utils";
+import { WaveBars } from "@/components/landing/wave-bars";
+
+const transcript = [
+ { speaker: "You", tone: "primary", line: "Let's lock the launch date before we scope the rest." },
+ { speaker: "Speaker 2", tone: "muted", line: "Works for me. I'll own the migration checklist." },
+ { speaker: "Speaker 3", tone: "muted", line: "I can have the pricing page ready by Thursday." },
+ { speaker: "You", tone: "primary", line: "Decision: ship on the 24th, freeze scope Friday." },
+];
+
+export function NotePreview({ className }: { className?: string }) {
+ return (
+
+
+
+
+
+ launch-sync-2026-06-18.md
+
+
+
+
+ local
+
+
+
+
+
+ title : Launch sync
+
+
+ attendees : You, Speaker 2, Speaker 3
+
+
+ duration : 28m · model : whisper-large-v3
+
+
+ source : on-device
+
+
+
+
+ {transcript.map((row, index) => (
+
+
+ {row.speaker}
+
+
{row.line}
+
+ ))}
+
+
+
+
+
+ 1 decision · 2 tasks
+
+
+
+
+ );
+}
diff --git a/website/components/landing/privacy-section.tsx b/website/components/landing/privacy-section.tsx
new file mode 100644
index 0000000..0234667
--- /dev/null
+++ b/website/components/landing/privacy-section.tsx
@@ -0,0 +1,90 @@
+import Link from "next/link";
+import { ArrowRight, Check, WifiOff } from "lucide-react";
+
+import { siteConfig } from "@/lib/site-config";
+import { Section, SectionHeading } from "@/components/site/section";
+import { Button } from "@/components/ui/button";
+
+const guarantees = [
+ "No telemetry, no analytics, no crash reporting — enforced in CI.",
+ "Audio, transcripts, and notes stay on disk on the default path.",
+ "Privacy Mode blocks every outbound call except localhost.",
+ "Notes are encrypted at rest with AES-256-GCM and Argon2id.",
+];
+
+const egress = [
+ { label: "Microphone capture", status: "local", blocked: false },
+ { label: "System audio capture", status: "local", blocked: false },
+ { label: "Whisper transcription", status: "local", blocked: false },
+ { label: "Speaker diarization", status: "local", blocked: false },
+ { label: "Outbound HTTP", status: "blocked", blocked: true },
+];
+
+export function PrivacySection() {
+ return (
+
+
+
+
+
+ {guarantees.map((item) => (
+
+
+
+
+
+ {item}
+
+
+ ))}
+
+
+
+ How privacy works
+
+
+
+
+
+
+
+
+ Privacy Mode
+
+
+
+ airgapped
+
+
+
+ {egress.map((row) => (
+
+ {row.label}
+
+ {row.status}
+
+
+ ))}
+
+
+ Full details, retention, and the recording-consent guide live in the{" "}
+
+ privacy documentation
+
+ . {siteConfig.name} gives you the tool; obtaining consent is your responsibility.
+
+
+
+
+ );
+}
diff --git a/website/components/landing/trust-bar.tsx b/website/components/landing/trust-bar.tsx
new file mode 100644
index 0000000..4642212
--- /dev/null
+++ b/website/components/landing/trust-bar.tsx
@@ -0,0 +1,27 @@
+import { Cpu, GitBranch, MicOff, WifiOff } from "lucide-react";
+
+const signals = [
+ { icon: Cpu, label: "On-device transcription", detail: "Metal-accelerated Whisper" },
+ { icon: WifiOff, label: "Works fully offline", detail: "Privacy Mode airgap" },
+ { icon: MicOff, label: "No bots in your calls", detail: "System audio capture" },
+ { icon: GitBranch, label: "Open source", detail: "Apache-2.0 licensed" },
+];
+
+export function TrustBar() {
+ return (
+
+
+ {signals.map((item) => (
+
+
+
{item.label}
+
{item.detail}
+
+ ))}
+
+
+ );
+}
diff --git a/website/components/landing/wave-bars.tsx b/website/components/landing/wave-bars.tsx
new file mode 100644
index 0000000..c149ba4
--- /dev/null
+++ b/website/components/landing/wave-bars.tsx
@@ -0,0 +1,37 @@
+import { cn } from "@/lib/utils";
+
+const pattern = [
+ 0.3, 0.55, 0.85, 0.45, 0.7, 1, 0.6, 0.35, 0.8, 0.5, 0.9, 0.4, 0.65, 0.95, 0.5, 0.75,
+ 0.35, 0.6, 0.85, 0.45,
+];
+
+export function WaveBars({
+ className,
+ bars = pattern,
+ animated = true,
+}: {
+ className?: string;
+ bars?: number[];
+ animated?: boolean;
+}) {
+ return (
+
+ {bars.map((height, index) => (
+
+ ))}
+
+ );
+}
diff --git a/website/components/site/code-block.tsx b/website/components/site/code-block.tsx
new file mode 100644
index 0000000..66ebfdd
--- /dev/null
+++ b/website/components/site/code-block.tsx
@@ -0,0 +1,83 @@
+"use client";
+
+import * as React from "react";
+import { Check, Copy } from "lucide-react";
+
+import { cn } from "@/lib/utils";
+
+export function CopyButton({ value, className }: { value: string; className?: string }) {
+ const [copied, setCopied] = React.useState(false);
+
+ const copy = React.useCallback(() => {
+ void navigator.clipboard.writeText(value).then(() => {
+ setCopied(true);
+ window.setTimeout(() => setCopied(false), 1600);
+ });
+ }, [value]);
+
+ return (
+
+ {copied ? (
+
+ ) : (
+
+ )}
+
+ );
+}
+
+export function CodeBlock({
+ code,
+ label,
+ className,
+}: {
+ code: string;
+ label?: string;
+ className?: string;
+}) {
+ return (
+
+
+
+ {label ?? "shell"}
+
+
+
+
+ {code}
+
+
+ );
+}
+
+export function CommandLine({ command, className }: { command: string; className?: string }) {
+ return (
+
+
+
+ $
+
+ {command}
+
+
+
+ );
+}
diff --git a/website/components/site/logo.tsx b/website/components/site/logo.tsx
new file mode 100644
index 0000000..1d66e19
--- /dev/null
+++ b/website/components/site/logo.tsx
@@ -0,0 +1,118 @@
+import { cn } from "@/lib/utils";
+import { siteConfig } from "@/lib/site-config";
+
+export function FolioMark({ className }: { className?: string }) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export function Logo({
+ className,
+ showWordmark = true,
+}: {
+ className?: string;
+ showWordmark?: boolean;
+}) {
+ return (
+
+
+ {showWordmark && (
+
+ {siteConfig.wordmark}
+
+ )}
+
+ );
+}
diff --git a/website/components/site/mobile-nav.tsx b/website/components/site/mobile-nav.tsx
new file mode 100644
index 0000000..7fb84ad
--- /dev/null
+++ b/website/components/site/mobile-nav.tsx
@@ -0,0 +1,71 @@
+"use client";
+
+import * as React from "react";
+import Link from "next/link";
+import { Menu, X } from "lucide-react";
+
+import { cn } from "@/lib/utils";
+import { mainNav, siteConfig } from "@/lib/site-config";
+import { Button } from "@/components/ui/button";
+import { Logo } from "@/components/site/logo";
+
+export function MobileNav() {
+ const [open, setOpen] = React.useState(false);
+
+ React.useEffect(() => {
+ document.body.style.overflow = open ? "hidden" : "";
+ return () => {
+ document.body.style.overflow = "";
+ };
+ }, [open]);
+
+ return (
+
+
setOpen(true)}
+ aria-label="Open menu"
+ className="inline-flex h-9 w-9 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-ring"
+ >
+
+
+
+ {open && (
+
+
+
+ setOpen(false)}
+ aria-label="Close menu"
+ className="inline-flex h-9 w-9 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus-ring"
+ >
+
+
+
+
+ {mainNav.map((item) => (
+ setOpen(false)}
+ target={item.external ? "_blank" : undefined}
+ rel={item.external ? "noreferrer" : undefined}
+ className={cn(
+ "rounded-lg px-3 py-3 text-ms-22 font-medium tracking-tight transition-colors hover:bg-accent"
+ )}
+ >
+ {item.label}
+
+ ))}
+
+ setOpen(false)}>
+ Install {siteConfig.name}
+
+
+
+
+ )}
+
+ );
+}
diff --git a/website/components/site/section.tsx b/website/components/site/section.tsx
new file mode 100644
index 0000000..817375b
--- /dev/null
+++ b/website/components/site/section.tsx
@@ -0,0 +1,72 @@
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+export function Section({
+ className,
+ containerClassName,
+ children,
+ ...props
+}: React.HTMLAttributes & { containerClassName?: string }) {
+ return (
+
+ );
+}
+
+export function Eyebrow({
+ className,
+ children,
+}: {
+ className?: string;
+ children: React.ReactNode;
+}) {
+ return (
+
+
+ {children}
+
+ );
+}
+
+export function SectionHeading({
+ eyebrow,
+ title,
+ description,
+ align = "left",
+ className,
+}: {
+ eyebrow?: string;
+ title: React.ReactNode;
+ description?: React.ReactNode;
+ align?: "left" | "center";
+ className?: string;
+}) {
+ return (
+
+ {eyebrow && (
+
{eyebrow}
+ )}
+
+ {title}
+
+ {description && (
+
+ {description}
+
+ )}
+
+ );
+}
diff --git a/website/components/site/site-footer.tsx b/website/components/site/site-footer.tsx
new file mode 100644
index 0000000..75ff530
--- /dev/null
+++ b/website/components/site/site-footer.tsx
@@ -0,0 +1,65 @@
+import Link from "next/link";
+import { Github } from "lucide-react";
+
+import { footerNav, siteConfig } from "@/lib/site-config";
+import { Logo } from "@/components/site/logo";
+
+export function SiteFooter() {
+ return (
+
+
+
+
+
+
+ {siteConfig.description}
+
+
+
+ github.com/woosal1337/folio
+
+
+
+
+ {footerNav.map((group) => (
+
+
+ {group.title}
+
+
+ {group.items.map((item) => (
+
+
+ {item.label}
+
+
+ ))}
+
+
+ ))}
+
+
+
+
+
+ {siteConfig.license} licensed. Built for {siteConfig.platform}. Audio stays on
+ your machine.
+
+
+ Folio v{siteConfig.version}
+
+
+
+
+ );
+}
diff --git a/website/components/site/site-header.tsx b/website/components/site/site-header.tsx
new file mode 100644
index 0000000..027b423
--- /dev/null
+++ b/website/components/site/site-header.tsx
@@ -0,0 +1,50 @@
+import Link from "next/link";
+import { Github } from "lucide-react";
+
+import { mainNav, siteConfig } from "@/lib/site-config";
+import { Button } from "@/components/ui/button";
+import { Logo } from "@/components/site/logo";
+import { MobileNav } from "@/components/site/mobile-nav";
+
+export function SiteHeader() {
+ return (
+
+ );
+}
diff --git a/website/components/ui/accordion.tsx b/website/components/ui/accordion.tsx
new file mode 100644
index 0000000..d3400b4
--- /dev/null
+++ b/website/components/ui/accordion.tsx
@@ -0,0 +1,57 @@
+"use client";
+
+import * as React from "react";
+import * as AccordionPrimitive from "@radix-ui/react-accordion";
+import { ChevronDown } from "lucide-react";
+
+import { cn } from "@/lib/utils";
+
+const Accordion = AccordionPrimitive.Root;
+
+const AccordionItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+AccordionItem.displayName = "AccordionItem";
+
+const AccordionTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+ svg]:rotate-180",
+ className
+ )}
+ {...props}
+ >
+ {children}
+
+
+
+));
+AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
+
+const AccordionContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+ {children}
+
+));
+AccordionContent.displayName = AccordionPrimitive.Content.displayName;
+
+export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
diff --git a/website/components/ui/badge.tsx b/website/components/ui/badge.tsx
new file mode 100644
index 0000000..6b30d4b
--- /dev/null
+++ b/website/components/ui/badge.tsx
@@ -0,0 +1,36 @@
+import * as React from "react";
+import { cva, type VariantProps } from "class-variance-authority";
+
+import { cn } from "@/lib/utils";
+
+const badgeVariants = cva(
+ "inline-flex items-center gap-1.5 rounded-full border px-2.5 py-0.5 text-xs font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
+ {
+ variants: {
+ variant: {
+ default:
+ "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
+ secondary:
+ "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ destructive:
+ "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
+ outline: "border-border text-foreground",
+ accent: "border-transparent bg-accent text-accent-foreground",
+ signal: "border-transparent bg-signal text-signal-foreground",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ }
+);
+
+export interface BadgeProps
+ extends React.HTMLAttributes,
+ VariantProps {}
+
+function Badge({ className, variant, ...props }: BadgeProps) {
+ return
;
+}
+
+export { Badge, badgeVariants };
diff --git a/website/components/ui/button.tsx b/website/components/ui/button.tsx
new file mode 100644
index 0000000..8dd7924
--- /dev/null
+++ b/website/components/ui/button.tsx
@@ -0,0 +1,56 @@
+import * as React from "react";
+import { Slot } from "@radix-ui/react-slot";
+import { cva, type VariantProps } from "class-variance-authority";
+
+import { cn } from "@/lib/utils";
+
+const buttonVariants = cva(
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
+ {
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
+ destructive:
+ "bg-destructive text-destructive-foreground hover:bg-destructive/90",
+ outline:
+ "border border-input bg-card hover:bg-accent hover:text-accent-foreground",
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ ghost: "hover:bg-accent hover:text-accent-foreground",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ size: {
+ default: "h-9 px-4 py-2",
+ sm: "h-8 rounded-md px-3 text-xs",
+ lg: "h-11 rounded-lg px-6 text-[15px]",
+ xl: "h-14 rounded-lg px-8 text-base",
+ icon: "h-9 w-9",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ }
+);
+
+export interface ButtonProps
+ extends React.ButtonHTMLAttributes,
+ VariantProps {
+ asChild?: boolean;
+}
+
+export const Button = React.forwardRef(
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
+ const Comp = asChild ? Slot : "button";
+ return (
+
+ );
+ }
+);
+Button.displayName = "Button";
+
+export { buttonVariants };
diff --git a/website/components/ui/card.tsx b/website/components/ui/card.tsx
new file mode 100644
index 0000000..2baa419
--- /dev/null
+++ b/website/components/ui/card.tsx
@@ -0,0 +1,63 @@
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+const Card = React.forwardRef>(
+ ({ className, ...props }, ref) => (
+
+ )
+);
+Card.displayName = "Card";
+
+const CardHeader = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardHeader.displayName = "CardHeader";
+
+const CardTitle = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardTitle.displayName = "CardTitle";
+
+const CardDescription = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardDescription.displayName = "CardDescription";
+
+const CardContent = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardContent.displayName = "CardContent";
+
+const CardFooter = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+));
+CardFooter.displayName = "CardFooter";
+
+export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
diff --git a/website/components/ui/separator.tsx b/website/components/ui/separator.tsx
new file mode 100644
index 0000000..295d54d
--- /dev/null
+++ b/website/components/ui/separator.tsx
@@ -0,0 +1,24 @@
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+export function Separator({
+ className,
+ orientation = "horizontal",
+ ...props
+}: React.HTMLAttributes & {
+ orientation?: "horizontal" | "vertical";
+}) {
+ return (
+
+ );
+}
diff --git a/website/components/ui/tabs.tsx b/website/components/ui/tabs.tsx
new file mode 100644
index 0000000..224902e
--- /dev/null
+++ b/website/components/ui/tabs.tsx
@@ -0,0 +1,55 @@
+"use client";
+
+import * as React from "react";
+import * as TabsPrimitive from "@radix-ui/react-tabs";
+
+import { cn } from "@/lib/utils";
+
+const Tabs = TabsPrimitive.Root;
+
+const TabsList = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsList.displayName = TabsPrimitive.List.displayName;
+
+const TabsTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
+
+const TabsContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+TabsContent.displayName = TabsPrimitive.Content.displayName;
+
+export { Tabs, TabsList, TabsTrigger, TabsContent };
diff --git a/website/lib/docs-nav.ts b/website/lib/docs-nav.ts
new file mode 100644
index 0000000..dfb5afd
--- /dev/null
+++ b/website/lib/docs-nav.ts
@@ -0,0 +1,76 @@
+export type DocLink = {
+ title: string;
+ href: string;
+ summary: string;
+};
+
+export type DocSection = {
+ title: string;
+ items: DocLink[];
+};
+
+export const docsNav: DocSection[] = [
+ {
+ title: "Getting started",
+ items: [
+ {
+ title: "Overview",
+ href: "/docs",
+ summary: "What Folio is, the core ideas, and how the pieces fit together.",
+ },
+ {
+ title: "Installation",
+ href: "/docs/installation",
+ summary: "Install with Homebrew or the notarized DMG, then grant permissions.",
+ },
+ {
+ title: "How to use",
+ href: "/docs/how-to-use",
+ summary: "From first launch to a searchable vault of meeting notes.",
+ },
+ ],
+ },
+ {
+ title: "Going deeper",
+ items: [
+ {
+ title: "Architecture",
+ href: "/docs/architecture",
+ summary: "The Rust core, the capture pipeline, and the data flow, explained.",
+ },
+ {
+ title: "Connectors (MCP)",
+ href: "/docs/connectors",
+ summary: "Expose transcripts, tasks, and memory to MCP-aware tools, locally.",
+ },
+ {
+ title: "Privacy & consent",
+ href: "/docs/privacy",
+ summary: "Privacy Mode, the network surface, retention, and recording consent.",
+ },
+ ],
+ },
+ {
+ title: "Reference",
+ items: [
+ {
+ title: "FAQ",
+ href: "/docs/faq",
+ summary: "Short answers to the questions people ask before installing.",
+ },
+ ],
+ },
+];
+
+export const docsFlat: DocLink[] = docsNav.flatMap((section) => section.items);
+
+export function docPager(pathname: string) {
+ const index = docsFlat.findIndex((item) => item.href === pathname);
+ if (index === -1) {
+ return { prev: null, next: null };
+ }
+ return {
+ prev: index > 0 ? docsFlat[index - 1] : null,
+ next: index < docsFlat.length - 1 ? docsFlat[index + 1] : null,
+ };
+}
diff --git a/website/lib/site-config.ts b/website/lib/site-config.ts
new file mode 100644
index 0000000..9461888
--- /dev/null
+++ b/website/lib/site-config.ts
@@ -0,0 +1,67 @@
+export const siteConfig = {
+ name: "Folio",
+ wordmark: "Folio",
+ tagline: "Local-first meeting notes for macOS",
+ description:
+ "Folio captures system audio and your microphone, transcribes on-device, and writes a markdown note per meeting to your own vault. Audio never leaves your machine.",
+ url: "https://folio.app",
+ version: "1.1.0",
+ license: "Apache-2.0",
+ platform: "macOS 13+",
+ links: {
+ github: "https://github.com/woosal1337/folio",
+ releases: "https://github.com/woosal1337/folio/releases/latest",
+ issues: "https://github.com/woosal1337/folio/issues",
+ privacy: "https://github.com/woosal1337/folio/blob/main/docs/PRIVACY.md",
+ architecture: "https://github.com/woosal1337/folio/blob/main/docs/ARCHITECTURE.md",
+ license: "https://github.com/woosal1337/folio/blob/main/LICENSE",
+ },
+ install: {
+ tapCommand: "brew tap woosal1337/folio https://github.com/woosal1337/folio",
+ installCommand: "brew install --cask folio",
+ upgradeCommand: "brew upgrade --cask folio",
+ },
+} as const;
+
+export type NavItem = {
+ label: string;
+ href: string;
+ external?: boolean;
+};
+
+export const mainNav: NavItem[] = [
+ { label: "Features", href: "/features" },
+ { label: "Docs", href: "/docs" },
+ { label: "Privacy", href: "/docs/privacy" },
+ { label: "GitHub", href: siteConfig.links.github, external: true },
+];
+
+export const footerNav: { title: string; items: NavItem[] }[] = [
+ {
+ title: "Product",
+ items: [
+ { label: "Overview", href: "/" },
+ { label: "Features", href: "/features" },
+ { label: "Install", href: "/docs/installation" },
+ { label: "Changelog", href: `${siteConfig.links.github}/blob/main/CHANGELOG.md`, external: true },
+ ],
+ },
+ {
+ title: "Documentation",
+ items: [
+ { label: "Getting started", href: "/docs" },
+ { label: "How to use", href: "/docs/how-to-use" },
+ { label: "Architecture", href: "/docs/architecture" },
+ { label: "Connectors (MCP)", href: "/docs/connectors" },
+ ],
+ },
+ {
+ title: "Trust",
+ items: [
+ { label: "Privacy", href: "/docs/privacy" },
+ { label: "Security", href: `${siteConfig.links.github}/blob/main/SECURITY.md`, external: true },
+ { label: "License", href: siteConfig.links.license, external: true },
+ { label: "FAQ", href: "/docs/faq" },
+ ],
+ },
+];
diff --git a/website/lib/utils.ts b/website/lib/utils.ts
new file mode 100644
index 0000000..a5ef193
--- /dev/null
+++ b/website/lib/utils.ts
@@ -0,0 +1,6 @@
+import { clsx, type ClassValue } from "clsx";
+import { twMerge } from "tailwind-merge";
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs));
+}
diff --git a/website/next.config.mjs b/website/next.config.mjs
new file mode 100644
index 0000000..8c5b457
--- /dev/null
+++ b/website/next.config.mjs
@@ -0,0 +1,6 @@
+const nextConfig = {
+ reactStrictMode: true,
+ poweredByHeader: false,
+};
+
+export default nextConfig;
diff --git a/website/package.json b/website/package.json
new file mode 100644
index 0000000..7a24183
--- /dev/null
+++ b/website/package.json
@@ -0,0 +1,44 @@
+{
+ "name": "folio-website",
+ "version": "1.0.0",
+ "private": true,
+ "license": "Apache-2.0",
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint",
+ "typecheck": "tsc --noEmit",
+ "format": "prettier --write .",
+ "format:check": "prettier --check ."
+ },
+ "dependencies": {
+ "@fontsource/inter": "^5.1.1",
+ "@fontsource/jetbrains-mono": "^5.1.2",
+ "@fontsource/spectral": "^5.1.1",
+ "@radix-ui/react-accordion": "^1.2.3",
+ "@radix-ui/react-slot": "^1.1.2",
+ "@radix-ui/react-tabs": "^1.1.3",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "lucide-react": "^0.469.0",
+ "next": "15.1.6",
+ "react": "^18.3.1",
+ "react-dom": "^18.3.1",
+ "tailwind-merge": "^2.6.0",
+ "tailwindcss-animate": "^1.0.7"
+ },
+ "devDependencies": {
+ "@types/node": "^22.10.5",
+ "@types/react": "^18.3.18",
+ "@types/react-dom": "^18.3.5",
+ "autoprefixer": "^10.4.20",
+ "eslint": "^9.18.0",
+ "eslint-config-next": "15.1.6",
+ "postcss": "^8.5.1",
+ "prettier": "^3.4.2",
+ "prettier-plugin-tailwindcss": "^0.6.9",
+ "tailwindcss": "^3.4.17",
+ "typescript": "^5.7.3"
+ }
+}
diff --git a/website/postcss.config.js b/website/postcss.config.js
new file mode 100644
index 0000000..12a703d
--- /dev/null
+++ b/website/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/website/public/favicon.svg b/website/public/favicon.svg
new file mode 100644
index 0000000..3dd0e3d
--- /dev/null
+++ b/website/public/favicon.svg
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/website/public/folio-logo.svg b/website/public/folio-logo.svg
new file mode 100644
index 0000000..1fcf80a
--- /dev/null
+++ b/website/public/folio-logo.svg
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/website/tailwind.config.ts b/website/tailwind.config.ts
new file mode 100644
index 0000000..5345721
--- /dev/null
+++ b/website/tailwind.config.ts
@@ -0,0 +1,124 @@
+import type { Config } from "tailwindcss";
+
+const config: Config = {
+ darkMode: ["class", '[data-theme="dark"]'],
+ content: [
+ "./app/**/*.{ts,tsx}",
+ "./components/**/*.{ts,tsx}",
+ "./lib/**/*.{ts,tsx}",
+ ],
+ theme: {
+ container: {
+ center: true,
+ padding: "1.5rem",
+ screens: {
+ "2xl": "1200px",
+ },
+ },
+ extend: {
+ colors: {
+ border: "hsl(var(--border))",
+ input: "hsl(var(--input))",
+ ring: "hsl(var(--ring))",
+ background: "hsl(var(--background))",
+ foreground: "hsl(var(--foreground))",
+ primary: {
+ DEFAULT: "hsl(var(--primary))",
+ foreground: "hsl(var(--primary-foreground))",
+ },
+ secondary: {
+ DEFAULT: "hsl(var(--secondary))",
+ foreground: "hsl(var(--secondary-foreground))",
+ },
+ destructive: {
+ DEFAULT: "hsl(var(--destructive))",
+ foreground: "hsl(var(--destructive-foreground))",
+ },
+ muted: {
+ DEFAULT: "hsl(var(--muted))",
+ foreground: "hsl(var(--muted-foreground))",
+ },
+ accent: {
+ DEFAULT: "hsl(var(--accent))",
+ foreground: "hsl(var(--accent-foreground))",
+ },
+ popover: {
+ DEFAULT: "hsl(var(--popover))",
+ foreground: "hsl(var(--popover-foreground))",
+ },
+ card: {
+ DEFAULT: "hsl(var(--card))",
+ foreground: "hsl(var(--card-foreground))",
+ },
+ signal: {
+ DEFAULT: "hsl(var(--signal))",
+ foreground: "hsl(var(--signal-foreground))",
+ },
+ },
+ borderRadius: {
+ "2xl": "calc(var(--radius) + 8px)",
+ xl: "calc(var(--radius) + 4px)",
+ lg: "var(--radius)",
+ md: "calc(var(--radius) - 2px)",
+ sm: "calc(var(--radius) - 4px)",
+ },
+ fontFamily: {
+ sans: ["var(--font-sans)", "-apple-system", "BlinkMacSystemFont", "system-ui", "sans-serif"],
+ display: ["var(--font-display)", "-apple-system", "BlinkMacSystemFont", "system-ui", "sans-serif"],
+ serif: ["var(--font-serif)", "Spectral", "Georgia", "ui-serif", "serif"],
+ wordmark: ["var(--font-serif)", "Spectral", "Georgia", "ui-serif", "serif"],
+ mono: ["var(--font-mono)", "JetBrains Mono", "ui-monospace", "monospace"],
+ },
+ fontSize: {
+ "2xs": ["0.6875rem", { lineHeight: "1rem" }],
+ "ms-13": ["0.8125rem", { lineHeight: "1.125rem" }],
+ "ms-15": ["0.9375rem", { lineHeight: "1.375rem" }],
+ "ms-17": ["1.0625rem", { lineHeight: "1.5rem" }],
+ "ms-22": ["1.375rem", { lineHeight: "1.75rem" }],
+ "ms-28": ["1.75rem", { lineHeight: "2.125rem" }],
+ "ms-34": ["2.125rem", { lineHeight: "2.5rem" }],
+ "ms-45": ["2.8125rem", { lineHeight: "3.25rem" }],
+ "ms-57": ["3.5625rem", { lineHeight: "1.05" }],
+ "ms-72": ["4.5rem", { lineHeight: "1.02" }],
+ },
+ maxWidth: {
+ prose: "44rem",
+ },
+ boxShadow: {
+ soft: "0 1px 2px hsl(20 14% 10% / 0.04), 0 8px 24px hsl(20 14% 10% / 0.06)",
+ lift: "0 2px 4px hsl(20 14% 10% / 0.05), 0 18px 48px hsl(20 14% 10% / 0.10)",
+ },
+ keyframes: {
+ "accordion-down": {
+ from: { height: "0" },
+ to: { height: "var(--radix-accordion-content-height)" },
+ },
+ "accordion-up": {
+ from: { height: "var(--radix-accordion-content-height)" },
+ to: { height: "0" },
+ },
+ "pulse-record": {
+ "0%, 100%": { opacity: "1" },
+ "50%": { opacity: "0.5" },
+ },
+ "fade-up": {
+ from: { opacity: "0", transform: "translateY(12px)" },
+ to: { opacity: "1", transform: "translateY(0)" },
+ },
+ "wave-rise": {
+ "0%, 100%": { transform: "scaleY(0.35)" },
+ "50%": { transform: "scaleY(1)" },
+ },
+ },
+ animation: {
+ "accordion-down": "accordion-down 0.2s ease-out",
+ "accordion-up": "accordion-up 0.2s ease-out",
+ "pulse-record": "pulse-record 1.4s ease-in-out infinite",
+ "fade-up": "fade-up 0.5s cubic-bezier(0.32, 0.72, 0, 1) both",
+ },
+ },
+ },
+ plugins: [require("tailwindcss-animate")],
+};
+
+export default config;
diff --git a/website/tsconfig.json b/website/tsconfig.json
new file mode 100644
index 0000000..0c66908
--- /dev/null
+++ b/website/tsconfig.json
@@ -0,0 +1,23 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [{ "name": "next" }],
+ "paths": {
+ "@/*": ["./*"]
+ }
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+ "exclude": ["node_modules"]
+}