diff --git a/.eslintrc.cjs b/.eslintrc.cjs
new file mode 100644
index 0000000..0d41776
--- /dev/null
+++ b/.eslintrc.cjs
@@ -0,0 +1,18 @@
+/** @type { import("eslint").Linter.Config } */
+module.exports = {
+ root: true,
+ env: { node: true, es2022: true },
+ extends: ["eslint:recommended", "prettier"],
+ ignorePatterns: [
+ "node_modules",
+ ".next",
+ "dist",
+ "build",
+ "coverage",
+ "*.config.js",
+ "*.config.cjs",
+ "*.config.mjs",
+ "*.config.ts",
+ ],
+};
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..adfc278
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,34 @@
+# Dependencies
+node_modules/
+.pnpm-store/
+
+# Build outputs
+.next/
+out/
+dist/
+build/
+*.tsbuildinfo
+
+# Environment
+.env
+.env.local
+.env.*.local
+
+# IDE / OS
+.idea/
+.vscode/
+*.swp
+.DS_Store
+Thumbs.db
+
+# Debug / logs
+npm-debug.log*
+pnpm-debug.log*
+*.log
+
+# Testing
+coverage/
+.nyc_output/
+
+# Misc
+*.pem
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 0000000..209e3ef
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+20
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..8683e95
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,8 @@
+node_modules
+.next
+dist
+build
+coverage
+*.min.js
+pnpm-lock.yaml
+package-lock.json
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 0000000..3d03824
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,9 @@
+{
+ "semi": true,
+ "singleQuote": false,
+ "tabWidth": 2,
+ "trailingComma": "es5",
+ "printWidth": 100,
+ "bracketSameLine": false,
+ "endOfLine": "lf"
+}
diff --git a/DBIS/.env.example b/DBIS/.env.example
new file mode 100644
index 0000000..8e389e0
--- /dev/null
+++ b/DBIS/.env.example
@@ -0,0 +1,8 @@
+# Next.js
+NEXTAUTH_URL=http://localhost:3000
+
+# OIDC / OAuth 2.0 (placeholder until identity provider is configured)
+# OIDC_ISSUER=
+# OIDC_CLIENT_ID=
+# OIDC_CLIENT_SECRET=
+# OIDC_REDIRECT_URI=
diff --git a/DBIS/.eslintrc.cjs b/DBIS/.eslintrc.cjs
new file mode 100644
index 0000000..53dff50
--- /dev/null
+++ b/DBIS/.eslintrc.cjs
@@ -0,0 +1,5 @@
+/** @type { import("eslint").Linter.Config } */
+module.exports = {
+ root: true,
+ extends: ["../.eslintrc.cjs", "next/core-web-vitals"],
+};
diff --git a/DBIS/README.md b/DBIS/README.md
new file mode 100644
index 0000000..2d6b6d2
--- /dev/null
+++ b/DBIS/README.md
@@ -0,0 +1,29 @@
+# DBIS Portal
+
+Portal for the **Digital Bank of International Settlements**.
+
+**Gitea repository:** https://gitea.d-bis.org/Gov_Web_Portals/DBIS.git Next-generation web application following the shared tech stack and policies.
+
+## Run locally
+
+```bash
+pnpm install
+pnpm dev
+```
+
+Open [http://localhost:3000](http://localhost:3000).
+
+## Environment
+
+Copy `.env.example` to `.env.local` and set values. No secrets in repo.
+
+## Standards
+
+- [TECH_STACK.md](../TECH_STACK.md)
+- [TECH_POLICIES.md](../TECH_POLICIES.md)
+- [PORTAL_NAVIGATION.md](../PORTAL_NAVIGATION.md)
+- [ORG_STRUCTURE.md](../ORG_STRUCTURE.md)
+
+## Structure
+
+Same app structure as other portals: public routes, transparency, workflow (submit/apply/report/request), dashboard, auth. Entity-specific routes: Financial Bulletins, Monetary Operations.
diff --git a/DBIS/app/(auth)/login/page.tsx b/DBIS/app/(auth)/login/page.tsx
new file mode 100644
index 0000000..48101a9
--- /dev/null
+++ b/DBIS/app/(auth)/login/page.tsx
@@ -0,0 +1,55 @@
+"use client";
+
+import { Suspense } from "react";
+import { useSearchParams } from "next/navigation";
+import Link from "next/link";
+
+function LoginForm() {
+ const searchParams = useSearchParams();
+ const returnUrl = searchParams.get("returnUrl") ?? "/dashboard";
+
+ return (
+
+
Sign in
+
+ Placeholder login. Replace with OIDC/OAuth 2.0 when identity provider is configured.
+
+
+
+
+ Return to previous page
+
+
+
+ );
+}
+
+export default function LoginPage() {
+ return (
+ Loading...}>
+
+
+ );
+}
diff --git a/DBIS/app/(auth)/logout/page.tsx b/DBIS/app/(auth)/logout/page.tsx
new file mode 100644
index 0000000..fd763a6
--- /dev/null
+++ b/DBIS/app/(auth)/logout/page.tsx
@@ -0,0 +1,20 @@
+"use client";
+
+import { useEffect } from "react";
+import Link from "next/link";
+
+export default function LogoutPage() {
+ useEffect(() => {
+ document.cookie = "portal-role=; path=/; max-age=0";
+ }, []);
+
+ return (
+
+
Signed out
+
You have been signed out.
+
+ Return to home
+
+
+ );
+}
diff --git a/DBIS/app/(public)/about/page.tsx b/DBIS/app/(public)/about/page.tsx
new file mode 100644
index 0000000..0b87c58
--- /dev/null
+++ b/DBIS/app/(public)/about/page.tsx
@@ -0,0 +1,8 @@
+export default function AboutPage() {
+ return (
+
+
Mandate
+
About the Digital Bank of International Settlements.
+
+ );
+}
diff --git a/DBIS/app/(public)/accreditation/page.tsx b/DBIS/app/(public)/accreditation/page.tsx
new file mode 100644
index 0000000..c5e95d2
--- /dev/null
+++ b/DBIS/app/(public)/accreditation/page.tsx
@@ -0,0 +1,8 @@
+export default function AccreditationPage() {
+ return (
+
+
Accreditation
+
Accreditation and credentials.
+
+ );
+}
diff --git a/DBIS/app/(public)/contact/page.tsx b/DBIS/app/(public)/contact/page.tsx
new file mode 100644
index 0000000..7bb6a85
--- /dev/null
+++ b/DBIS/app/(public)/contact/page.tsx
@@ -0,0 +1,8 @@
+export default function ContactPage() {
+ return (
+
+
Contact
+
General contact and enquiries.
+
+ );
+}
diff --git a/DBIS/app/(public)/departments/page.tsx b/DBIS/app/(public)/departments/page.tsx
new file mode 100644
index 0000000..ed01731
--- /dev/null
+++ b/DBIS/app/(public)/departments/page.tsx
@@ -0,0 +1,8 @@
+export default function DepartmentsPage() {
+ return (
+
+
Departments
+
Mission departments and programs.
+
+ );
+}
diff --git a/DBIS/app/(public)/documents/page.tsx b/DBIS/app/(public)/documents/page.tsx
new file mode 100644
index 0000000..c641e1d
--- /dev/null
+++ b/DBIS/app/(public)/documents/page.tsx
@@ -0,0 +1,8 @@
+export default function DocumentsPage() {
+ return (
+
+
Documents
+
Library, standards, and directives.
+
+ );
+}
diff --git a/DBIS/app/(public)/governance/page.tsx b/DBIS/app/(public)/governance/page.tsx
new file mode 100644
index 0000000..8cf0212
--- /dev/null
+++ b/DBIS/app/(public)/governance/page.tsx
@@ -0,0 +1,8 @@
+export default function GovernancePage() {
+ return (
+
+
Governance
+
Charters, instruments, and governance.
+
+ );
+}
diff --git a/DBIS/app/(public)/leadership/page.tsx b/DBIS/app/(public)/leadership/page.tsx
new file mode 100644
index 0000000..ff1f679
--- /dev/null
+++ b/DBIS/app/(public)/leadership/page.tsx
@@ -0,0 +1,8 @@
+export default function LeadershipPage() {
+ return (
+
+
Leadership
+
Executive leadership and secretariat.
+
+ );
+}
diff --git a/DBIS/app/(public)/membership/page.tsx b/DBIS/app/(public)/membership/page.tsx
new file mode 100644
index 0000000..cf191d0
--- /dev/null
+++ b/DBIS/app/(public)/membership/page.tsx
@@ -0,0 +1,8 @@
+export default function MembershipPage() {
+ return (
+
+
Membership
+
Member directory and accreditation.
+
+ );
+}
diff --git a/DBIS/app/(public)/news/page.tsx b/DBIS/app/(public)/news/page.tsx
new file mode 100644
index 0000000..57d0061
--- /dev/null
+++ b/DBIS/app/(public)/news/page.tsx
@@ -0,0 +1,8 @@
+export default function NewsPage() {
+ return (
+
+
News
+
News and announcements.
+
+ );
+}
diff --git a/DBIS/app/(public)/org-chart/page.tsx b/DBIS/app/(public)/org-chart/page.tsx
new file mode 100644
index 0000000..e01d431
--- /dev/null
+++ b/DBIS/app/(public)/org-chart/page.tsx
@@ -0,0 +1,8 @@
+export default function OrgChartPage() {
+ return (
+
+
Org Chart
+
Organizational structure.
+
+ );
+}
diff --git a/DBIS/app/(public)/programs/page.tsx b/DBIS/app/(public)/programs/page.tsx
new file mode 100644
index 0000000..57d0bb0
--- /dev/null
+++ b/DBIS/app/(public)/programs/page.tsx
@@ -0,0 +1,8 @@
+export default function ProgramsPage() {
+ return (
+
+
Programs
+
Programs and initiatives.
+
+ );
+}
diff --git a/DBIS/app/(public)/publications/page.tsx b/DBIS/app/(public)/publications/page.tsx
new file mode 100644
index 0000000..6b329f6
--- /dev/null
+++ b/DBIS/app/(public)/publications/page.tsx
@@ -0,0 +1,8 @@
+export default function PublicationsPage() {
+ return (
+
+
Publications
+
Publications and reports.
+
+ );
+}
diff --git a/DBIS/app/(public)/regions/page.tsx b/DBIS/app/(public)/regions/page.tsx
new file mode 100644
index 0000000..66978cc
--- /dev/null
+++ b/DBIS/app/(public)/regions/page.tsx
@@ -0,0 +1,8 @@
+export default function RegionsPage() {
+ return (
+
+
Regional Offices
+
Americas, EMEA, APAC delegations and field missions.
+
+ );
+}
diff --git a/DBIS/app/(public)/standards/page.tsx b/DBIS/app/(public)/standards/page.tsx
new file mode 100644
index 0000000..9327ef0
--- /dev/null
+++ b/DBIS/app/(public)/standards/page.tsx
@@ -0,0 +1,8 @@
+export default function StandardsPage() {
+ return (
+
+
Standards
+
Standards and codes.
+
+ );
+}
diff --git a/DBIS/app/api/auth/mock-login/route.ts b/DBIS/app/api/auth/mock-login/route.ts
new file mode 100644
index 0000000..57f672f
--- /dev/null
+++ b/DBIS/app/api/auth/mock-login/route.ts
@@ -0,0 +1,10 @@
+import { NextRequest, NextResponse } from "next/server";
+
+export async function POST(request: NextRequest) {
+ const form = await request.formData();
+ const returnUrl = (form.get("returnUrl") as string) ?? "/dashboard";
+ const role = (form.get("role") as string) ?? "member";
+ const res = NextResponse.redirect(new URL(returnUrl, request.url));
+ res.cookies.set("portal-role", role, { path: "/", httpOnly: true, maxAge: 60 * 60 * 24 });
+ return res;
+}
diff --git a/DBIS/app/apply/page.tsx b/DBIS/app/apply/page.tsx
new file mode 100644
index 0000000..7ee15cb
--- /dev/null
+++ b/DBIS/app/apply/page.tsx
@@ -0,0 +1,8 @@
+export default function ApplyPage() {
+ return (
+
+
Apply
+
Apply for membership or accreditation.
+
+ );
+}
diff --git a/DBIS/app/dashboard/layout.tsx b/DBIS/app/dashboard/layout.tsx
new file mode 100644
index 0000000..680435b
--- /dev/null
+++ b/DBIS/app/dashboard/layout.tsx
@@ -0,0 +1,17 @@
+import Link from "next/link";
+import type { ReactNode } from "react";
+
+export default function DashboardLayout({ children }: { children: ReactNode }) {
+ return (
+
+
+
{children}
+
+ );
+}
diff --git a/DBIS/app/dashboard/page.tsx b/DBIS/app/dashboard/page.tsx
new file mode 100644
index 0000000..199cd04
--- /dev/null
+++ b/DBIS/app/dashboard/page.tsx
@@ -0,0 +1,8 @@
+export default function DashboardPage() {
+ return (
+
+
Dashboard
+
Role-based dashboard.
+
+ );
+}
diff --git a/DBIS/app/dashboard/requests/page.tsx b/DBIS/app/dashboard/requests/page.tsx
new file mode 100644
index 0000000..eb94812
--- /dev/null
+++ b/DBIS/app/dashboard/requests/page.tsx
@@ -0,0 +1,8 @@
+export default function RequestsPage() {
+ return (
+
+
My requests
+
Track your requests.
+
+ );
+}
diff --git a/DBIS/app/dashboard/submissions/page.tsx b/DBIS/app/dashboard/submissions/page.tsx
new file mode 100644
index 0000000..dc57c54
--- /dev/null
+++ b/DBIS/app/dashboard/submissions/page.tsx
@@ -0,0 +1,8 @@
+export default function SubmissionsPage() {
+ return (
+
+
My submissions
+
Track your submissions and status.
+
+ );
+}
diff --git a/DBIS/app/departments/monetary-operations/page.tsx b/DBIS/app/departments/monetary-operations/page.tsx
new file mode 100644
index 0000000..b92072a
--- /dev/null
+++ b/DBIS/app/departments/monetary-operations/page.tsx
@@ -0,0 +1,8 @@
+export default function MonetaryOperationsPage() {
+ return (
+
+
Monetary Operations
+
Digital reserves and monetary operations.
+
+ );
+}
diff --git a/DBIS/app/documents/bulletins/page.tsx b/DBIS/app/documents/bulletins/page.tsx
new file mode 100644
index 0000000..ce3a40d
--- /dev/null
+++ b/DBIS/app/documents/bulletins/page.tsx
@@ -0,0 +1,8 @@
+export default function BulletinsPage() {
+ return (
+
+
Financial Bulletins
+
DBIS financial bulletins and reports.
+
+ );
+}
diff --git a/DBIS/app/globals.css b/DBIS/app/globals.css
new file mode 100644
index 0000000..b5c61c9
--- /dev/null
+++ b/DBIS/app/globals.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/DBIS/app/layout.tsx b/DBIS/app/layout.tsx
new file mode 100644
index 0000000..b847156
--- /dev/null
+++ b/DBIS/app/layout.tsx
@@ -0,0 +1,34 @@
+import type { Metadata } from "next";
+import type { ReactNode } from "react";
+import "./globals.css";
+import { Header } from "@/components/layout/Header";
+import { Footer } from "@/components/layout/Footer";
+
+export const metadata: Metadata = {
+ title: "Digital Bank of International Settlements",
+ description: "Official portal of the Digital Bank of International Settlements",
+};
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: ReactNode;
+}>) {
+ return (
+
+
+
+ Skip to main content
+
+
+
+ {children}
+
+
+
+
+ );
+}
diff --git a/DBIS/app/membership/renewals/page.tsx b/DBIS/app/membership/renewals/page.tsx
new file mode 100644
index 0000000..79e5a75
--- /dev/null
+++ b/DBIS/app/membership/renewals/page.tsx
@@ -0,0 +1,8 @@
+export default function RenewalsPage() {
+ return (
+
+
Renewals and Attestations
+
Annual renewals for members.
+
+ );
+}
diff --git a/DBIS/app/page.tsx b/DBIS/app/page.tsx
new file mode 100644
index 0000000..b0c3be8
--- /dev/null
+++ b/DBIS/app/page.tsx
@@ -0,0 +1,24 @@
+export default function HomePage() {
+ return (
+
+
Digital Bank of International Settlements
+
+ Welcome to the official portal. Explore mandate, governance, documents, and services.
+
+
+
+ );
+}
diff --git a/DBIS/app/report/page.tsx b/DBIS/app/report/page.tsx
new file mode 100644
index 0000000..6ae4c22
--- /dev/null
+++ b/DBIS/app/report/page.tsx
@@ -0,0 +1,8 @@
+export default function ReportPage() {
+ return (
+
+
Report
+
Report incidents or compliance matters.
+
+ );
+}
diff --git a/DBIS/app/request/page.tsx b/DBIS/app/request/page.tsx
new file mode 100644
index 0000000..6e653db
--- /dev/null
+++ b/DBIS/app/request/page.tsx
@@ -0,0 +1,8 @@
+export default function RequestPage() {
+ return (
+
+
Request
+
Request documents or support.
+
+ );
+}
diff --git a/DBIS/app/submit/page.tsx b/DBIS/app/submit/page.tsx
new file mode 100644
index 0000000..62e1cba
--- /dev/null
+++ b/DBIS/app/submit/page.tsx
@@ -0,0 +1,8 @@
+export default function SubmitPage() {
+ return (
+
+
Submit
+
Submission portal.
+
+ );
+}
diff --git a/DBIS/app/transparency/audit/page.tsx b/DBIS/app/transparency/audit/page.tsx
new file mode 100644
index 0000000..5fe7056
--- /dev/null
+++ b/DBIS/app/transparency/audit/page.tsx
@@ -0,0 +1,8 @@
+export default function AuditPage() {
+ return (
+
+
Audit Reports
+
Audit reports and findings tracker.
+
+ );
+}
diff --git a/DBIS/app/transparency/data-protection/page.tsx b/DBIS/app/transparency/data-protection/page.tsx
new file mode 100644
index 0000000..b2454b3
--- /dev/null
+++ b/DBIS/app/transparency/data-protection/page.tsx
@@ -0,0 +1,8 @@
+export default function DataProtectionPage() {
+ return (
+
+
Data Protection and Records
+
Records retention and data protection.
+
+ );
+}
diff --git a/DBIS/app/transparency/ethics/page.tsx b/DBIS/app/transparency/ethics/page.tsx
new file mode 100644
index 0000000..ff5b47d
--- /dev/null
+++ b/DBIS/app/transparency/ethics/page.tsx
@@ -0,0 +1,8 @@
+export default function EthicsPage() {
+ return (
+
+
Ethics and Conduct
+
Ethics and conduct policies.
+
+ );
+}
diff --git a/DBIS/app/transparency/page.tsx b/DBIS/app/transparency/page.tsx
new file mode 100644
index 0000000..f676261
--- /dev/null
+++ b/DBIS/app/transparency/page.tsx
@@ -0,0 +1,8 @@
+export default function TransparencyPage() {
+ return (
+
+
Transparency
+
Audit, ethics, whistleblower, sanctions, and data protection.
+
+ );
+}
diff --git a/DBIS/app/transparency/sanctions/page.tsx b/DBIS/app/transparency/sanctions/page.tsx
new file mode 100644
index 0000000..adf23fe
--- /dev/null
+++ b/DBIS/app/transparency/sanctions/page.tsx
@@ -0,0 +1,8 @@
+export default function SanctionsPage() {
+ return (
+
+
Sanctions and Restricted Parties
+
Eligibility and restricted parties.
+
+ );
+}
diff --git a/DBIS/app/transparency/whistleblower/page.tsx b/DBIS/app/transparency/whistleblower/page.tsx
new file mode 100644
index 0000000..5d9a692
--- /dev/null
+++ b/DBIS/app/transparency/whistleblower/page.tsx
@@ -0,0 +1,8 @@
+export default function WhistleblowerPage() {
+ return (
+
+
Whistleblower Intake
+
Secure anonymous reporting.
+
+ );
+}
diff --git a/DBIS/components/layout/Footer.tsx b/DBIS/components/layout/Footer.tsx
new file mode 100644
index 0000000..e337806
--- /dev/null
+++ b/DBIS/components/layout/Footer.tsx
@@ -0,0 +1,48 @@
+import Link from "next/link";
+import { navItems } from "@/lib/nav-config";
+
+const footerLinks = [
+ { label: "About", href: "/about" },
+ { label: "Documents", href: "/documents" },
+ { label: "Transparency", href: "/transparency" },
+ { label: "Contact", href: "/contact" },
+ { label: "Regional Offices", href: "/regions" },
+];
+
+function flatNavItems(items: typeof navItems): { label: string; href: string }[] {
+ const out: { label: string; href: string }[] = [];
+ for (const item of items) {
+ if (item.children) {
+ for (const c of item.children) out.push({ label: c.label, href: c.href });
+ } else {
+ out.push({ label: item.label, href: item.href });
+ }
+ }
+ return out;
+}
+
+export function Footer() {
+ const flat = flatNavItems(navItems);
+ const keyLinks = footerLinks.length ? footerLinks : flat.slice(0, 6);
+
+ return (
+
+ );
+}
diff --git a/DBIS/components/layout/Header.tsx b/DBIS/components/layout/Header.tsx
new file mode 100644
index 0000000..7f5dbf9
--- /dev/null
+++ b/DBIS/components/layout/Header.tsx
@@ -0,0 +1,58 @@
+"use client";
+
+import Link from "next/link";
+import { useState } from "react";
+import { navItems } from "@/lib/nav-config";
+import { NavDropdown } from "./NavDropdown";
+import { MobileNav } from "./MobileNav";
+
+export function Header() {
+ const [mobileOpen, setMobileOpen] = useState(false);
+
+ return (
+
+
+
+ DBIS
+
+
+
+
+ Sign in
+
+
+
+
+ setMobileOpen(false)} />
+
+ );
+}
diff --git a/DBIS/components/layout/MobileNav.tsx b/DBIS/components/layout/MobileNav.tsx
new file mode 100644
index 0000000..6b94745
--- /dev/null
+++ b/DBIS/components/layout/MobileNav.tsx
@@ -0,0 +1,57 @@
+"use client";
+
+import Link from "next/link";
+import type { NavItem } from "@public-web-portals/shared";
+
+export function MobileNav({
+ items,
+ open,
+ onClose,
+}: {
+ items: NavItem[];
+ open: boolean;
+ onClose: () => void;
+}) {
+ if (!open) return null;
+
+ return (
+
+ );
+}
diff --git a/DBIS/components/layout/NavDropdown.tsx b/DBIS/components/layout/NavDropdown.tsx
new file mode 100644
index 0000000..d9c6b1b
--- /dev/null
+++ b/DBIS/components/layout/NavDropdown.tsx
@@ -0,0 +1,57 @@
+"use client";
+
+import Link from "next/link";
+import { useState, useRef, useEffect } from "react";
+import type { NavItem } from "@public-web-portals/shared";
+
+export function NavDropdown({ item }: { item: NavItem }) {
+ const [open, setOpen] = useState(false);
+ const ref = useRef(null);
+
+ useEffect(() => {
+ function handleClickOutside(event: MouseEvent) {
+ if (ref.current && !ref.current.contains(event.target as Node)) setOpen(false);
+ }
+ document.addEventListener("mousedown", handleClickOutside);
+ return () => document.removeEventListener("mousedown", handleClickOutside);
+ }, []);
+
+ return (
+
+
+
+
+ );
+}
diff --git a/DBIS/lib/auth.ts b/DBIS/lib/auth.ts
new file mode 100644
index 0000000..1077579
--- /dev/null
+++ b/DBIS/lib/auth.ts
@@ -0,0 +1,10 @@
+import type { SessionOrNull } from "@public-web-portals/shared";
+
+/**
+ * Placeholder session. Replace with OIDC/OAuth 2.0 when identity provider is configured.
+ * TECH_POLICIES: use httpOnly cookies / secure token storage.
+ */
+export async function getSession(): Promise {
+ // TODO: read session from cookie or header (e.g. NextAuth, OIDC)
+ return null;
+}
diff --git a/DBIS/lib/nav-config.ts b/DBIS/lib/nav-config.ts
new file mode 100644
index 0000000..36906b8
--- /dev/null
+++ b/DBIS/lib/nav-config.ts
@@ -0,0 +1,4 @@
+import { getNavForPortal } from "@public-web-portals/shared";
+
+export const portalId = "DBIS" as const;
+export const navItems = getNavForPortal(portalId);
diff --git a/DBIS/lib/rbac.ts b/DBIS/lib/rbac.ts
new file mode 100644
index 0000000..75a5b51
--- /dev/null
+++ b/DBIS/lib/rbac.ts
@@ -0,0 +1,66 @@
+import type { Role } from "@public-web-portals/shared";
+
+/** Route prefixes that require any authenticated role */
+const protectedPrefixes = [
+ "/dashboard",
+ "/submit",
+ "/apply",
+ "/report",
+ "/request",
+ "/membership/renewals",
+];
+
+/** Route prefixes that require admin role */
+const adminOnlyPrefixes = ["/dashboard/admin"];
+
+/** Routes that are always public (no auth) */
+const publicPaths = [
+ "/",
+ "/about",
+ "/governance",
+ "/leadership",
+ "/org-chart",
+ "/departments",
+ "/programs",
+ "/membership",
+ "/accreditation",
+ "/documents",
+ "/standards",
+ "/news",
+ "/publications",
+ "/contact",
+ "/regions",
+ "/transparency",
+ "/login",
+ "/logout",
+];
+
+function pathIsPublic(pathname: string): boolean {
+ if (publicPaths.includes(pathname)) return true;
+ if (pathname.startsWith("/transparency/")) return true;
+ return false;
+}
+
+function pathIsProtected(pathname: string): boolean {
+ return protectedPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
+}
+
+function pathIsAdminOnly(pathname: string): boolean {
+ return adminOnlyPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
+}
+
+export function canAccess(pathname: string, role: Role | null): boolean {
+ if (pathIsPublic(pathname)) return true;
+ if (role == null) return false;
+ if (pathIsAdminOnly(pathname)) return role === "admin";
+ if (pathIsProtected(pathname)) return true;
+ return false;
+}
+
+export function requiresAuth(pathname: string): boolean {
+ return pathIsProtected(pathname);
+}
+
+export function requiresAdmin(pathname: string): boolean {
+ return pathIsAdminOnly(pathname);
+}
diff --git a/DBIS/middleware.ts b/DBIS/middleware.ts
new file mode 100644
index 0000000..a1e26cd
--- /dev/null
+++ b/DBIS/middleware.ts
@@ -0,0 +1,39 @@
+import { NextResponse } from "next/server";
+import type { NextRequest } from "next/server";
+import { canAccess, requiresAuth, requiresAdmin } from "./lib/rbac";
+import type { Role } from "@public-web-portals/shared";
+
+const LOGIN = "/login";
+
+function getRoleFromCookie(request: NextRequest): Role | null {
+ const role = request.cookies.get("portal-role")?.value;
+ if (!role) return null;
+ const valid: Role[] = ["member", "judge", "clerk", "diplomat", "donor", "staff", "admin"];
+ return valid.includes(role as Role) ? (role as Role) : null;
+}
+
+export function middleware(request: NextRequest) {
+ const pathname = request.nextUrl.pathname;
+ const role = getRoleFromCookie(request);
+
+ if (requiresAdmin(pathname) && role !== "admin") {
+ return NextResponse.redirect(new URL("/dashboard", request.url));
+ }
+
+ if (requiresAuth(pathname)) {
+ if (role == null) {
+ const url = new URL(LOGIN, request.url);
+ url.searchParams.set("returnUrl", pathname);
+ return NextResponse.redirect(url);
+ }
+ if (!canAccess(pathname, role)) {
+ return NextResponse.redirect(new URL("/dashboard", request.url));
+ }
+ }
+
+ return NextResponse.next();
+}
+
+export const config = {
+ matcher: ["/((?!_next/static|_next/image|favicon.ico|api).*)"],
+};
diff --git a/DBIS/next-env.d.ts b/DBIS/next-env.d.ts
new file mode 100644
index 0000000..40c3d68
--- /dev/null
+++ b/DBIS/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
diff --git a/DBIS/next.config.js b/DBIS/next.config.js
new file mode 100644
index 0000000..d0d6b18
--- /dev/null
+++ b/DBIS/next.config.js
@@ -0,0 +1,32 @@
+/** @type { import('next').NextConfig } */
+const nextConfig = {
+ transpilePackages: ["@public-web-portals/shared"],
+ async headers() {
+ return [
+ {
+ source: "/:path*",
+ headers: [
+ { key: "X-Frame-Options", value: "DENY" },
+ { key: "X-Content-Type-Options", value: "nosniff" },
+ { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
+ {
+ key: "Content-Security-Policy",
+ value: [
+ "default-src 'self'",
+ "script-src 'self'",
+ "style-src 'self' 'unsafe-inline'",
+ "img-src 'self' data: https:",
+ "font-src 'self'",
+ "connect-src 'self'",
+ "frame-ancestors 'none'",
+ "base-uri 'self'",
+ "form-action 'self'",
+ ].join("; "),
+ },
+ ],
+ },
+ ];
+ },
+};
+
+module.exports = nextConfig;
diff --git a/DBIS/package.json b/DBIS/package.json
new file mode 100644
index 0000000..8f34394
--- /dev/null
+++ b/DBIS/package.json
@@ -0,0 +1,32 @@
+{
+ "name": "portal-dbis",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev --port 3000",
+ "build": "next build",
+ "start": "next start --port 3000",
+ "lint": "eslint . --max-warnings 0 --config ../.eslintrc.cjs",
+ "typecheck": "tsc --noEmit"
+ },
+ "dependencies": {
+ "@public-web-portals/shared": "workspace:*",
+ "next": "^14.2.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@types/node": "^20.10.0",
+ "@types/react": "^18.2.0",
+ "@types/react-dom": "^18.2.0",
+ "autoprefixer": "^10.4.0",
+ "eslint": "^8.56.0",
+ "eslint-config-next": "^14.2.0",
+ "postcss": "^8.4.0",
+ "tailwindcss": "^3.4.0",
+ "typescript": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+}
diff --git a/DBIS/postcss.config.js b/DBIS/postcss.config.js
new file mode 100644
index 0000000..12a703d
--- /dev/null
+++ b/DBIS/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/DBIS/tailwind.config.ts b/DBIS/tailwind.config.ts
new file mode 100644
index 0000000..aae1628
--- /dev/null
+++ b/DBIS/tailwind.config.ts
@@ -0,0 +1,15 @@
+import type { Config } from "tailwindcss";
+import { designTokens } from "@public-web-portals/shared";
+
+const config: Config = {
+ content: [
+ "./app/**/*.{js,ts,jsx,tsx,mdx}",
+ "./components/**/*.{js,ts,jsx,tsx,mdx}",
+ ],
+ theme: {
+ extend: designTokens as Record,
+ },
+ plugins: [],
+};
+
+export default config;
diff --git a/DBIS/tsconfig.json b/DBIS/tsconfig.json
new file mode 100644
index 0000000..cd32290
--- /dev/null
+++ b/DBIS/tsconfig.json
@@ -0,0 +1,30 @@
+{
+ "extends": "../tsconfig.base.json",
+ "compilerOptions": {
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "jsx": "preserve",
+ "noEmit": true,
+ "incremental": true,
+ "paths": {
+ "@/*": [
+ "./*"
+ ]
+ },
+ "allowJs": true
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/ICCC/.env.example b/ICCC/.env.example
new file mode 100644
index 0000000..8e389e0
--- /dev/null
+++ b/ICCC/.env.example
@@ -0,0 +1,8 @@
+# Next.js
+NEXTAUTH_URL=http://localhost:3000
+
+# OIDC / OAuth 2.0 (placeholder until identity provider is configured)
+# OIDC_ISSUER=
+# OIDC_CLIENT_ID=
+# OIDC_CLIENT_SECRET=
+# OIDC_REDIRECT_URI=
diff --git a/ICCC/.eslintrc.cjs b/ICCC/.eslintrc.cjs
new file mode 100644
index 0000000..53dff50
--- /dev/null
+++ b/ICCC/.eslintrc.cjs
@@ -0,0 +1,5 @@
+/** @type { import("eslint").Linter.Config } */
+module.exports = {
+ root: true,
+ extends: ["../.eslintrc.cjs", "next/core-web-vitals"],
+};
diff --git a/ICCC/README.md b/ICCC/README.md
new file mode 100644
index 0000000..8f2dc25
--- /dev/null
+++ b/ICCC/README.md
@@ -0,0 +1,29 @@
+# ICCC Portal
+
+Portal for the **International Criminal Court of Commerce**.
+
+**Gitea repository:** https://gitea.d-bis.org/Gov_Web_Portals/ICCC.git Next-generation web application following the shared tech stack and policies.
+
+## Run locally
+
+```bash
+pnpm install
+pnpm dev
+```
+
+Open [http://localhost:3000](http://localhost:3000).
+
+## Environment
+
+Copy `.env.example` to `.env.local` and set values. No secrets in repo.
+
+## Standards
+
+- [TECH_STACK.md](../TECH_STACK.md)
+- [TECH_POLICIES.md](../TECH_POLICIES.md)
+- [PORTAL_NAVIGATION.md](../PORTAL_NAVIGATION.md)
+- [ORG_STRUCTURE.md](../ORG_STRUCTURE.md)
+
+## Structure
+
+Same app structure as other portals: public routes, transparency, workflow (submit/apply/report/request), dashboard, auth. Entity-specific routes: Case Law, Registry, Chambers, Judgments.
diff --git a/ICCC/app/(auth)/login/page.tsx b/ICCC/app/(auth)/login/page.tsx
new file mode 100644
index 0000000..48101a9
--- /dev/null
+++ b/ICCC/app/(auth)/login/page.tsx
@@ -0,0 +1,55 @@
+"use client";
+
+import { Suspense } from "react";
+import { useSearchParams } from "next/navigation";
+import Link from "next/link";
+
+function LoginForm() {
+ const searchParams = useSearchParams();
+ const returnUrl = searchParams.get("returnUrl") ?? "/dashboard";
+
+ return (
+
+
Sign in
+
+ Placeholder login. Replace with OIDC/OAuth 2.0 when identity provider is configured.
+
+
+
+
+ Return to previous page
+
+
+
+ );
+}
+
+export default function LoginPage() {
+ return (
+ Loading...}>
+
+
+ );
+}
diff --git a/ICCC/app/(auth)/logout/page.tsx b/ICCC/app/(auth)/logout/page.tsx
new file mode 100644
index 0000000..fd763a6
--- /dev/null
+++ b/ICCC/app/(auth)/logout/page.tsx
@@ -0,0 +1,20 @@
+"use client";
+
+import { useEffect } from "react";
+import Link from "next/link";
+
+export default function LogoutPage() {
+ useEffect(() => {
+ document.cookie = "portal-role=; path=/; max-age=0";
+ }, []);
+
+ return (
+
+
Signed out
+
You have been signed out.
+
+ Return to home
+
+
+ );
+}
diff --git a/ICCC/app/(public)/about/page.tsx b/ICCC/app/(public)/about/page.tsx
new file mode 100644
index 0000000..0b87c58
--- /dev/null
+++ b/ICCC/app/(public)/about/page.tsx
@@ -0,0 +1,8 @@
+export default function AboutPage() {
+ return (
+
+
Mandate
+
About the Digital Bank of International Settlements.
+
+ );
+}
diff --git a/ICCC/app/(public)/accreditation/page.tsx b/ICCC/app/(public)/accreditation/page.tsx
new file mode 100644
index 0000000..c5e95d2
--- /dev/null
+++ b/ICCC/app/(public)/accreditation/page.tsx
@@ -0,0 +1,8 @@
+export default function AccreditationPage() {
+ return (
+
+
Accreditation
+
Accreditation and credentials.
+
+ );
+}
diff --git a/ICCC/app/(public)/contact/page.tsx b/ICCC/app/(public)/contact/page.tsx
new file mode 100644
index 0000000..7bb6a85
--- /dev/null
+++ b/ICCC/app/(public)/contact/page.tsx
@@ -0,0 +1,8 @@
+export default function ContactPage() {
+ return (
+
+
Contact
+
General contact and enquiries.
+
+ );
+}
diff --git a/ICCC/app/(public)/departments/page.tsx b/ICCC/app/(public)/departments/page.tsx
new file mode 100644
index 0000000..ed01731
--- /dev/null
+++ b/ICCC/app/(public)/departments/page.tsx
@@ -0,0 +1,8 @@
+export default function DepartmentsPage() {
+ return (
+
+
Departments
+
Mission departments and programs.
+
+ );
+}
diff --git a/ICCC/app/(public)/documents/page.tsx b/ICCC/app/(public)/documents/page.tsx
new file mode 100644
index 0000000..c641e1d
--- /dev/null
+++ b/ICCC/app/(public)/documents/page.tsx
@@ -0,0 +1,8 @@
+export default function DocumentsPage() {
+ return (
+
+
Documents
+
Library, standards, and directives.
+
+ );
+}
diff --git a/ICCC/app/(public)/governance/page.tsx b/ICCC/app/(public)/governance/page.tsx
new file mode 100644
index 0000000..8cf0212
--- /dev/null
+++ b/ICCC/app/(public)/governance/page.tsx
@@ -0,0 +1,8 @@
+export default function GovernancePage() {
+ return (
+
+
Governance
+
Charters, instruments, and governance.
+
+ );
+}
diff --git a/ICCC/app/(public)/leadership/page.tsx b/ICCC/app/(public)/leadership/page.tsx
new file mode 100644
index 0000000..ff1f679
--- /dev/null
+++ b/ICCC/app/(public)/leadership/page.tsx
@@ -0,0 +1,8 @@
+export default function LeadershipPage() {
+ return (
+
+
Leadership
+
Executive leadership and secretariat.
+
+ );
+}
diff --git a/ICCC/app/(public)/membership/page.tsx b/ICCC/app/(public)/membership/page.tsx
new file mode 100644
index 0000000..cf191d0
--- /dev/null
+++ b/ICCC/app/(public)/membership/page.tsx
@@ -0,0 +1,8 @@
+export default function MembershipPage() {
+ return (
+
+
Membership
+
Member directory and accreditation.
+
+ );
+}
diff --git a/ICCC/app/(public)/news/page.tsx b/ICCC/app/(public)/news/page.tsx
new file mode 100644
index 0000000..57d0061
--- /dev/null
+++ b/ICCC/app/(public)/news/page.tsx
@@ -0,0 +1,8 @@
+export default function NewsPage() {
+ return (
+
+
News
+
News and announcements.
+
+ );
+}
diff --git a/ICCC/app/(public)/org-chart/page.tsx b/ICCC/app/(public)/org-chart/page.tsx
new file mode 100644
index 0000000..e01d431
--- /dev/null
+++ b/ICCC/app/(public)/org-chart/page.tsx
@@ -0,0 +1,8 @@
+export default function OrgChartPage() {
+ return (
+
+
Org Chart
+
Organizational structure.
+
+ );
+}
diff --git a/ICCC/app/(public)/programs/page.tsx b/ICCC/app/(public)/programs/page.tsx
new file mode 100644
index 0000000..57d0bb0
--- /dev/null
+++ b/ICCC/app/(public)/programs/page.tsx
@@ -0,0 +1,8 @@
+export default function ProgramsPage() {
+ return (
+
+
Programs
+
Programs and initiatives.
+
+ );
+}
diff --git a/ICCC/app/(public)/publications/page.tsx b/ICCC/app/(public)/publications/page.tsx
new file mode 100644
index 0000000..6b329f6
--- /dev/null
+++ b/ICCC/app/(public)/publications/page.tsx
@@ -0,0 +1,8 @@
+export default function PublicationsPage() {
+ return (
+
+
Publications
+
Publications and reports.
+
+ );
+}
diff --git a/ICCC/app/(public)/regions/page.tsx b/ICCC/app/(public)/regions/page.tsx
new file mode 100644
index 0000000..66978cc
--- /dev/null
+++ b/ICCC/app/(public)/regions/page.tsx
@@ -0,0 +1,8 @@
+export default function RegionsPage() {
+ return (
+
+
Regional Offices
+
Americas, EMEA, APAC delegations and field missions.
+
+ );
+}
diff --git a/ICCC/app/(public)/standards/page.tsx b/ICCC/app/(public)/standards/page.tsx
new file mode 100644
index 0000000..9327ef0
--- /dev/null
+++ b/ICCC/app/(public)/standards/page.tsx
@@ -0,0 +1,8 @@
+export default function StandardsPage() {
+ return (
+
+
Standards
+
Standards and codes.
+
+ );
+}
diff --git a/ICCC/app/api/auth/mock-login/route.ts b/ICCC/app/api/auth/mock-login/route.ts
new file mode 100644
index 0000000..57f672f
--- /dev/null
+++ b/ICCC/app/api/auth/mock-login/route.ts
@@ -0,0 +1,10 @@
+import { NextRequest, NextResponse } from "next/server";
+
+export async function POST(request: NextRequest) {
+ const form = await request.formData();
+ const returnUrl = (form.get("returnUrl") as string) ?? "/dashboard";
+ const role = (form.get("role") as string) ?? "member";
+ const res = NextResponse.redirect(new URL(returnUrl, request.url));
+ res.cookies.set("portal-role", role, { path: "/", httpOnly: true, maxAge: 60 * 60 * 24 });
+ return res;
+}
diff --git a/ICCC/app/apply/page.tsx b/ICCC/app/apply/page.tsx
new file mode 100644
index 0000000..7ee15cb
--- /dev/null
+++ b/ICCC/app/apply/page.tsx
@@ -0,0 +1,8 @@
+export default function ApplyPage() {
+ return (
+
+
Apply
+
Apply for membership or accreditation.
+
+ );
+}
diff --git a/ICCC/app/case-law/page.tsx b/ICCC/app/case-law/page.tsx
new file mode 100644
index 0000000..4f44594
--- /dev/null
+++ b/ICCC/app/case-law/page.tsx
@@ -0,0 +1,8 @@
+export default function CaseLawPage() {
+ return (
+
+
Case Law
+
Case law and decisions.
+
+ );
+}
diff --git a/ICCC/app/chambers/page.tsx b/ICCC/app/chambers/page.tsx
new file mode 100644
index 0000000..f8be373
--- /dev/null
+++ b/ICCC/app/chambers/page.tsx
@@ -0,0 +1,8 @@
+export default function ChambersPage() {
+ return (
+
+
Chambers
+
Trial and appeals chambers.
+
+ );
+}
diff --git a/ICCC/app/dashboard/layout.tsx b/ICCC/app/dashboard/layout.tsx
new file mode 100644
index 0000000..680435b
--- /dev/null
+++ b/ICCC/app/dashboard/layout.tsx
@@ -0,0 +1,17 @@
+import Link from "next/link";
+import type { ReactNode } from "react";
+
+export default function DashboardLayout({ children }: { children: ReactNode }) {
+ return (
+
+
+
{children}
+
+ );
+}
diff --git a/ICCC/app/dashboard/page.tsx b/ICCC/app/dashboard/page.tsx
new file mode 100644
index 0000000..199cd04
--- /dev/null
+++ b/ICCC/app/dashboard/page.tsx
@@ -0,0 +1,8 @@
+export default function DashboardPage() {
+ return (
+
+
Dashboard
+
Role-based dashboard.
+
+ );
+}
diff --git a/ICCC/app/dashboard/requests/page.tsx b/ICCC/app/dashboard/requests/page.tsx
new file mode 100644
index 0000000..eb94812
--- /dev/null
+++ b/ICCC/app/dashboard/requests/page.tsx
@@ -0,0 +1,8 @@
+export default function RequestsPage() {
+ return (
+
+
My requests
+
Track your requests.
+
+ );
+}
diff --git a/ICCC/app/dashboard/submissions/page.tsx b/ICCC/app/dashboard/submissions/page.tsx
new file mode 100644
index 0000000..dc57c54
--- /dev/null
+++ b/ICCC/app/dashboard/submissions/page.tsx
@@ -0,0 +1,8 @@
+export default function SubmissionsPage() {
+ return (
+
+
My submissions
+
Track your submissions and status.
+
+ );
+}
diff --git a/ICCC/app/globals.css b/ICCC/app/globals.css
new file mode 100644
index 0000000..b5c61c9
--- /dev/null
+++ b/ICCC/app/globals.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/ICCC/app/judgments/page.tsx b/ICCC/app/judgments/page.tsx
new file mode 100644
index 0000000..32357f7
--- /dev/null
+++ b/ICCC/app/judgments/page.tsx
@@ -0,0 +1,8 @@
+export default function JudgmentsPage() {
+ return (
+
+
Judgments
+
Judgments, orders, and remedies.
+
+ );
+}
diff --git a/ICCC/app/layout.tsx b/ICCC/app/layout.tsx
new file mode 100644
index 0000000..af93b88
--- /dev/null
+++ b/ICCC/app/layout.tsx
@@ -0,0 +1,34 @@
+import type { Metadata } from "next";
+import type { ReactNode } from "react";
+import "./globals.css";
+import { Header } from "@/components/layout/Header";
+import { Footer } from "@/components/layout/Footer";
+
+export const metadata: Metadata = {
+ title: "International Criminal Court of Commerce",
+ description: "Official portal of the International Criminal Court of Commerce",
+};
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: ReactNode;
+}>) {
+ return (
+
+
+
+ Skip to main content
+
+
+
+ {children}
+
+
+
+
+ );
+}
diff --git a/ICCC/app/membership/renewals/page.tsx b/ICCC/app/membership/renewals/page.tsx
new file mode 100644
index 0000000..79e5a75
--- /dev/null
+++ b/ICCC/app/membership/renewals/page.tsx
@@ -0,0 +1,8 @@
+export default function RenewalsPage() {
+ return (
+
+
Renewals and Attestations
+
Annual renewals for members.
+
+ );
+}
diff --git a/ICCC/app/page.tsx b/ICCC/app/page.tsx
new file mode 100644
index 0000000..93ccd9e
--- /dev/null
+++ b/ICCC/app/page.tsx
@@ -0,0 +1,24 @@
+export default function HomePage() {
+ return (
+
+
International Criminal Court of Commerce
+
+ Welcome to the official portal. Explore registry, chambers, case law, and judgments.
+
+
+
+ );
+}
diff --git a/ICCC/app/registry/page.tsx b/ICCC/app/registry/page.tsx
new file mode 100644
index 0000000..3fa35bd
--- /dev/null
+++ b/ICCC/app/registry/page.tsx
@@ -0,0 +1,8 @@
+export default function RegistryPage() {
+ return (
+
+
Registry
+
Clerk of Court and registry.
+
+ );
+}
diff --git a/ICCC/app/report/page.tsx b/ICCC/app/report/page.tsx
new file mode 100644
index 0000000..6ae4c22
--- /dev/null
+++ b/ICCC/app/report/page.tsx
@@ -0,0 +1,8 @@
+export default function ReportPage() {
+ return (
+
+
Report
+
Report incidents or compliance matters.
+
+ );
+}
diff --git a/ICCC/app/request/page.tsx b/ICCC/app/request/page.tsx
new file mode 100644
index 0000000..6e653db
--- /dev/null
+++ b/ICCC/app/request/page.tsx
@@ -0,0 +1,8 @@
+export default function RequestPage() {
+ return (
+
+
Request
+
Request documents or support.
+
+ );
+}
diff --git a/ICCC/app/submit/page.tsx b/ICCC/app/submit/page.tsx
new file mode 100644
index 0000000..62e1cba
--- /dev/null
+++ b/ICCC/app/submit/page.tsx
@@ -0,0 +1,8 @@
+export default function SubmitPage() {
+ return (
+
+
Submit
+
Submission portal.
+
+ );
+}
diff --git a/ICCC/app/transparency/audit/page.tsx b/ICCC/app/transparency/audit/page.tsx
new file mode 100644
index 0000000..5fe7056
--- /dev/null
+++ b/ICCC/app/transparency/audit/page.tsx
@@ -0,0 +1,8 @@
+export default function AuditPage() {
+ return (
+
+
Audit Reports
+
Audit reports and findings tracker.
+
+ );
+}
diff --git a/ICCC/app/transparency/data-protection/page.tsx b/ICCC/app/transparency/data-protection/page.tsx
new file mode 100644
index 0000000..b2454b3
--- /dev/null
+++ b/ICCC/app/transparency/data-protection/page.tsx
@@ -0,0 +1,8 @@
+export default function DataProtectionPage() {
+ return (
+
+
Data Protection and Records
+
Records retention and data protection.
+
+ );
+}
diff --git a/ICCC/app/transparency/ethics/page.tsx b/ICCC/app/transparency/ethics/page.tsx
new file mode 100644
index 0000000..ff5b47d
--- /dev/null
+++ b/ICCC/app/transparency/ethics/page.tsx
@@ -0,0 +1,8 @@
+export default function EthicsPage() {
+ return (
+
+
Ethics and Conduct
+
Ethics and conduct policies.
+
+ );
+}
diff --git a/ICCC/app/transparency/page.tsx b/ICCC/app/transparency/page.tsx
new file mode 100644
index 0000000..f676261
--- /dev/null
+++ b/ICCC/app/transparency/page.tsx
@@ -0,0 +1,8 @@
+export default function TransparencyPage() {
+ return (
+
+
Transparency
+
Audit, ethics, whistleblower, sanctions, and data protection.
+
+ );
+}
diff --git a/ICCC/app/transparency/sanctions/page.tsx b/ICCC/app/transparency/sanctions/page.tsx
new file mode 100644
index 0000000..adf23fe
--- /dev/null
+++ b/ICCC/app/transparency/sanctions/page.tsx
@@ -0,0 +1,8 @@
+export default function SanctionsPage() {
+ return (
+
+
Sanctions and Restricted Parties
+
Eligibility and restricted parties.
+
+ );
+}
diff --git a/ICCC/app/transparency/whistleblower/page.tsx b/ICCC/app/transparency/whistleblower/page.tsx
new file mode 100644
index 0000000..5d9a692
--- /dev/null
+++ b/ICCC/app/transparency/whistleblower/page.tsx
@@ -0,0 +1,8 @@
+export default function WhistleblowerPage() {
+ return (
+
+
Whistleblower Intake
+
Secure anonymous reporting.
+
+ );
+}
diff --git a/ICCC/components/layout/Footer.tsx b/ICCC/components/layout/Footer.tsx
new file mode 100644
index 0000000..4480f1b
--- /dev/null
+++ b/ICCC/components/layout/Footer.tsx
@@ -0,0 +1,48 @@
+import Link from "next/link";
+import { navItems } from "@/lib/nav-config";
+
+const footerLinks = [
+ { label: "About", href: "/about" },
+ { label: "Documents", href: "/documents" },
+ { label: "Transparency", href: "/transparency" },
+ { label: "Contact", href: "/contact" },
+ { label: "Regional Offices", href: "/regions" },
+];
+
+function flatNavItems(items: typeof navItems): { label: string; href: string }[] {
+ const out: { label: string; href: string }[] = [];
+ for (const item of items) {
+ if (item.children) {
+ for (const c of item.children) out.push({ label: c.label, href: c.href });
+ } else {
+ out.push({ label: item.label, href: item.href });
+ }
+ }
+ return out;
+}
+
+export function Footer() {
+ const flat = flatNavItems(navItems);
+ const keyLinks = footerLinks.length ? footerLinks : flat.slice(0, 6);
+
+ return (
+
+ );
+}
diff --git a/ICCC/components/layout/Header.tsx b/ICCC/components/layout/Header.tsx
new file mode 100644
index 0000000..30fe0fb
--- /dev/null
+++ b/ICCC/components/layout/Header.tsx
@@ -0,0 +1,58 @@
+"use client";
+
+import Link from "next/link";
+import { useState } from "react";
+import { navItems } from "@/lib/nav-config";
+import { NavDropdown } from "./NavDropdown";
+import { MobileNav } from "./MobileNav";
+
+export function Header() {
+ const [mobileOpen, setMobileOpen] = useState(false);
+
+ return (
+
+
+
+ ICCC
+
+
+
+
+ Sign in
+
+
+
+
+ setMobileOpen(false)} />
+
+ );
+}
diff --git a/ICCC/components/layout/MobileNav.tsx b/ICCC/components/layout/MobileNav.tsx
new file mode 100644
index 0000000..6b94745
--- /dev/null
+++ b/ICCC/components/layout/MobileNav.tsx
@@ -0,0 +1,57 @@
+"use client";
+
+import Link from "next/link";
+import type { NavItem } from "@public-web-portals/shared";
+
+export function MobileNav({
+ items,
+ open,
+ onClose,
+}: {
+ items: NavItem[];
+ open: boolean;
+ onClose: () => void;
+}) {
+ if (!open) return null;
+
+ return (
+
+ );
+}
diff --git a/ICCC/components/layout/NavDropdown.tsx b/ICCC/components/layout/NavDropdown.tsx
new file mode 100644
index 0000000..d9c6b1b
--- /dev/null
+++ b/ICCC/components/layout/NavDropdown.tsx
@@ -0,0 +1,57 @@
+"use client";
+
+import Link from "next/link";
+import { useState, useRef, useEffect } from "react";
+import type { NavItem } from "@public-web-portals/shared";
+
+export function NavDropdown({ item }: { item: NavItem }) {
+ const [open, setOpen] = useState(false);
+ const ref = useRef(null);
+
+ useEffect(() => {
+ function handleClickOutside(event: MouseEvent) {
+ if (ref.current && !ref.current.contains(event.target as Node)) setOpen(false);
+ }
+ document.addEventListener("mousedown", handleClickOutside);
+ return () => document.removeEventListener("mousedown", handleClickOutside);
+ }, []);
+
+ return (
+
+
+
+
+ );
+}
diff --git a/ICCC/lib/auth.ts b/ICCC/lib/auth.ts
new file mode 100644
index 0000000..1077579
--- /dev/null
+++ b/ICCC/lib/auth.ts
@@ -0,0 +1,10 @@
+import type { SessionOrNull } from "@public-web-portals/shared";
+
+/**
+ * Placeholder session. Replace with OIDC/OAuth 2.0 when identity provider is configured.
+ * TECH_POLICIES: use httpOnly cookies / secure token storage.
+ */
+export async function getSession(): Promise {
+ // TODO: read session from cookie or header (e.g. NextAuth, OIDC)
+ return null;
+}
diff --git a/ICCC/lib/nav-config.ts b/ICCC/lib/nav-config.ts
new file mode 100644
index 0000000..7ecc4e6
--- /dev/null
+++ b/ICCC/lib/nav-config.ts
@@ -0,0 +1,4 @@
+import { getNavForPortal } from "@public-web-portals/shared";
+
+export const portalId = "ICCC" as const;
+export const navItems = getNavForPortal(portalId);
diff --git a/ICCC/lib/rbac.ts b/ICCC/lib/rbac.ts
new file mode 100644
index 0000000..75a5b51
--- /dev/null
+++ b/ICCC/lib/rbac.ts
@@ -0,0 +1,66 @@
+import type { Role } from "@public-web-portals/shared";
+
+/** Route prefixes that require any authenticated role */
+const protectedPrefixes = [
+ "/dashboard",
+ "/submit",
+ "/apply",
+ "/report",
+ "/request",
+ "/membership/renewals",
+];
+
+/** Route prefixes that require admin role */
+const adminOnlyPrefixes = ["/dashboard/admin"];
+
+/** Routes that are always public (no auth) */
+const publicPaths = [
+ "/",
+ "/about",
+ "/governance",
+ "/leadership",
+ "/org-chart",
+ "/departments",
+ "/programs",
+ "/membership",
+ "/accreditation",
+ "/documents",
+ "/standards",
+ "/news",
+ "/publications",
+ "/contact",
+ "/regions",
+ "/transparency",
+ "/login",
+ "/logout",
+];
+
+function pathIsPublic(pathname: string): boolean {
+ if (publicPaths.includes(pathname)) return true;
+ if (pathname.startsWith("/transparency/")) return true;
+ return false;
+}
+
+function pathIsProtected(pathname: string): boolean {
+ return protectedPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
+}
+
+function pathIsAdminOnly(pathname: string): boolean {
+ return adminOnlyPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
+}
+
+export function canAccess(pathname: string, role: Role | null): boolean {
+ if (pathIsPublic(pathname)) return true;
+ if (role == null) return false;
+ if (pathIsAdminOnly(pathname)) return role === "admin";
+ if (pathIsProtected(pathname)) return true;
+ return false;
+}
+
+export function requiresAuth(pathname: string): boolean {
+ return pathIsProtected(pathname);
+}
+
+export function requiresAdmin(pathname: string): boolean {
+ return pathIsAdminOnly(pathname);
+}
diff --git a/ICCC/middleware.ts b/ICCC/middleware.ts
new file mode 100644
index 0000000..a1e26cd
--- /dev/null
+++ b/ICCC/middleware.ts
@@ -0,0 +1,39 @@
+import { NextResponse } from "next/server";
+import type { NextRequest } from "next/server";
+import { canAccess, requiresAuth, requiresAdmin } from "./lib/rbac";
+import type { Role } from "@public-web-portals/shared";
+
+const LOGIN = "/login";
+
+function getRoleFromCookie(request: NextRequest): Role | null {
+ const role = request.cookies.get("portal-role")?.value;
+ if (!role) return null;
+ const valid: Role[] = ["member", "judge", "clerk", "diplomat", "donor", "staff", "admin"];
+ return valid.includes(role as Role) ? (role as Role) : null;
+}
+
+export function middleware(request: NextRequest) {
+ const pathname = request.nextUrl.pathname;
+ const role = getRoleFromCookie(request);
+
+ if (requiresAdmin(pathname) && role !== "admin") {
+ return NextResponse.redirect(new URL("/dashboard", request.url));
+ }
+
+ if (requiresAuth(pathname)) {
+ if (role == null) {
+ const url = new URL(LOGIN, request.url);
+ url.searchParams.set("returnUrl", pathname);
+ return NextResponse.redirect(url);
+ }
+ if (!canAccess(pathname, role)) {
+ return NextResponse.redirect(new URL("/dashboard", request.url));
+ }
+ }
+
+ return NextResponse.next();
+}
+
+export const config = {
+ matcher: ["/((?!_next/static|_next/image|favicon.ico|api).*)"],
+};
diff --git a/ICCC/next-env.d.ts b/ICCC/next-env.d.ts
new file mode 100644
index 0000000..40c3d68
--- /dev/null
+++ b/ICCC/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
diff --git a/ICCC/next.config.js b/ICCC/next.config.js
new file mode 100644
index 0000000..d0d6b18
--- /dev/null
+++ b/ICCC/next.config.js
@@ -0,0 +1,32 @@
+/** @type { import('next').NextConfig } */
+const nextConfig = {
+ transpilePackages: ["@public-web-portals/shared"],
+ async headers() {
+ return [
+ {
+ source: "/:path*",
+ headers: [
+ { key: "X-Frame-Options", value: "DENY" },
+ { key: "X-Content-Type-Options", value: "nosniff" },
+ { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
+ {
+ key: "Content-Security-Policy",
+ value: [
+ "default-src 'self'",
+ "script-src 'self'",
+ "style-src 'self' 'unsafe-inline'",
+ "img-src 'self' data: https:",
+ "font-src 'self'",
+ "connect-src 'self'",
+ "frame-ancestors 'none'",
+ "base-uri 'self'",
+ "form-action 'self'",
+ ].join("; "),
+ },
+ ],
+ },
+ ];
+ },
+};
+
+module.exports = nextConfig;
diff --git a/ICCC/package.json b/ICCC/package.json
new file mode 100644
index 0000000..7204ea8
--- /dev/null
+++ b/ICCC/package.json
@@ -0,0 +1,32 @@
+{
+ "name": "portal-iccc",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev --port 3000",
+ "build": "next build",
+ "start": "next start --port 3000",
+ "lint": "eslint . --max-warnings 0 --config ../.eslintrc.cjs",
+ "typecheck": "tsc --noEmit"
+ },
+ "dependencies": {
+ "@public-web-portals/shared": "workspace:*",
+ "next": "^14.2.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@types/node": "^20.10.0",
+ "@types/react": "^18.2.0",
+ "@types/react-dom": "^18.2.0",
+ "autoprefixer": "^10.4.0",
+ "eslint": "^8.56.0",
+ "eslint-config-next": "^14.2.0",
+ "postcss": "^8.4.0",
+ "tailwindcss": "^3.4.0",
+ "typescript": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+}
diff --git a/ICCC/postcss.config.js b/ICCC/postcss.config.js
new file mode 100644
index 0000000..12a703d
--- /dev/null
+++ b/ICCC/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/ICCC/tailwind.config.ts b/ICCC/tailwind.config.ts
new file mode 100644
index 0000000..aae1628
--- /dev/null
+++ b/ICCC/tailwind.config.ts
@@ -0,0 +1,15 @@
+import type { Config } from "tailwindcss";
+import { designTokens } from "@public-web-portals/shared";
+
+const config: Config = {
+ content: [
+ "./app/**/*.{js,ts,jsx,tsx,mdx}",
+ "./components/**/*.{js,ts,jsx,tsx,mdx}",
+ ],
+ theme: {
+ extend: designTokens as Record,
+ },
+ plugins: [],
+};
+
+export default config;
diff --git a/ICCC/tsconfig.json b/ICCC/tsconfig.json
new file mode 100644
index 0000000..cd32290
--- /dev/null
+++ b/ICCC/tsconfig.json
@@ -0,0 +1,30 @@
+{
+ "extends": "../tsconfig.base.json",
+ "compilerOptions": {
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "jsx": "preserve",
+ "noEmit": true,
+ "incremental": true,
+ "paths": {
+ "@/*": [
+ "./*"
+ ]
+ },
+ "allowJs": true
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/OMNL/.env.example b/OMNL/.env.example
new file mode 100644
index 0000000..8e389e0
--- /dev/null
+++ b/OMNL/.env.example
@@ -0,0 +1,8 @@
+# Next.js
+NEXTAUTH_URL=http://localhost:3000
+
+# OIDC / OAuth 2.0 (placeholder until identity provider is configured)
+# OIDC_ISSUER=
+# OIDC_CLIENT_ID=
+# OIDC_CLIENT_SECRET=
+# OIDC_REDIRECT_URI=
diff --git a/OMNL/.eslintrc.cjs b/OMNL/.eslintrc.cjs
new file mode 100644
index 0000000..53dff50
--- /dev/null
+++ b/OMNL/.eslintrc.cjs
@@ -0,0 +1,5 @@
+/** @type { import("eslint").Linter.Config } */
+module.exports = {
+ root: true,
+ extends: ["../.eslintrc.cjs", "next/core-web-vitals"],
+};
diff --git a/OMNL/README.md b/OMNL/README.md
new file mode 100644
index 0000000..7b4bad7
--- /dev/null
+++ b/OMNL/README.md
@@ -0,0 +1,29 @@
+# OMNL Portal
+
+Portal for the **Organisation Mondiale du Numérique**.
+
+**Gitea repository:** https://gitea.d-bis.org/Gov_Web_Portals/OMNL.git Next-generation web application following the shared tech stack and policies.
+
+## Run locally
+
+```bash
+pnpm install
+pnpm dev
+```
+
+Open [http://localhost:3000](http://localhost:3000).
+
+## Environment
+
+Copy `.env.example` to `.env.local` and set values. No secrets in repo.
+
+## Standards
+
+- [TECH_STACK.md](../TECH_STACK.md)
+- [TECH_POLICIES.md](../TECH_POLICIES.md)
+- [PORTAL_NAVIGATION.md](../PORTAL_NAVIGATION.md)
+- [ORG_STRUCTURE.md](../ORG_STRUCTURE.md)
+
+## Structure
+
+Same app structure as other portals: public routes, transparency, workflow (submit/apply/report/request), dashboard, auth. Entity-specific routes: Programs and Impact, Standards, Cyber Resilience.
diff --git a/OMNL/app/(auth)/login/page.tsx b/OMNL/app/(auth)/login/page.tsx
new file mode 100644
index 0000000..48101a9
--- /dev/null
+++ b/OMNL/app/(auth)/login/page.tsx
@@ -0,0 +1,55 @@
+"use client";
+
+import { Suspense } from "react";
+import { useSearchParams } from "next/navigation";
+import Link from "next/link";
+
+function LoginForm() {
+ const searchParams = useSearchParams();
+ const returnUrl = searchParams.get("returnUrl") ?? "/dashboard";
+
+ return (
+
+
Sign in
+
+ Placeholder login. Replace with OIDC/OAuth 2.0 when identity provider is configured.
+
+
+
+
+ Return to previous page
+
+
+
+ );
+}
+
+export default function LoginPage() {
+ return (
+ Loading...}>
+
+
+ );
+}
diff --git a/OMNL/app/(auth)/logout/page.tsx b/OMNL/app/(auth)/logout/page.tsx
new file mode 100644
index 0000000..fd763a6
--- /dev/null
+++ b/OMNL/app/(auth)/logout/page.tsx
@@ -0,0 +1,20 @@
+"use client";
+
+import { useEffect } from "react";
+import Link from "next/link";
+
+export default function LogoutPage() {
+ useEffect(() => {
+ document.cookie = "portal-role=; path=/; max-age=0";
+ }, []);
+
+ return (
+
+
Signed out
+
You have been signed out.
+
+ Return to home
+
+
+ );
+}
diff --git a/OMNL/app/(public)/about/page.tsx b/OMNL/app/(public)/about/page.tsx
new file mode 100644
index 0000000..0b87c58
--- /dev/null
+++ b/OMNL/app/(public)/about/page.tsx
@@ -0,0 +1,8 @@
+export default function AboutPage() {
+ return (
+
+
Mandate
+
About the Digital Bank of International Settlements.
+
+ );
+}
diff --git a/OMNL/app/(public)/accreditation/page.tsx b/OMNL/app/(public)/accreditation/page.tsx
new file mode 100644
index 0000000..c5e95d2
--- /dev/null
+++ b/OMNL/app/(public)/accreditation/page.tsx
@@ -0,0 +1,8 @@
+export default function AccreditationPage() {
+ return (
+
+
Accreditation
+
Accreditation and credentials.
+
+ );
+}
diff --git a/OMNL/app/(public)/contact/page.tsx b/OMNL/app/(public)/contact/page.tsx
new file mode 100644
index 0000000..7bb6a85
--- /dev/null
+++ b/OMNL/app/(public)/contact/page.tsx
@@ -0,0 +1,8 @@
+export default function ContactPage() {
+ return (
+
+
Contact
+
General contact and enquiries.
+
+ );
+}
diff --git a/OMNL/app/(public)/departments/page.tsx b/OMNL/app/(public)/departments/page.tsx
new file mode 100644
index 0000000..ed01731
--- /dev/null
+++ b/OMNL/app/(public)/departments/page.tsx
@@ -0,0 +1,8 @@
+export default function DepartmentsPage() {
+ return (
+
+
Departments
+
Mission departments and programs.
+
+ );
+}
diff --git a/OMNL/app/(public)/documents/page.tsx b/OMNL/app/(public)/documents/page.tsx
new file mode 100644
index 0000000..c641e1d
--- /dev/null
+++ b/OMNL/app/(public)/documents/page.tsx
@@ -0,0 +1,8 @@
+export default function DocumentsPage() {
+ return (
+
+
Documents
+
Library, standards, and directives.
+
+ );
+}
diff --git a/OMNL/app/(public)/governance/page.tsx b/OMNL/app/(public)/governance/page.tsx
new file mode 100644
index 0000000..8cf0212
--- /dev/null
+++ b/OMNL/app/(public)/governance/page.tsx
@@ -0,0 +1,8 @@
+export default function GovernancePage() {
+ return (
+
+
Governance
+
Charters, instruments, and governance.
+
+ );
+}
diff --git a/OMNL/app/(public)/leadership/page.tsx b/OMNL/app/(public)/leadership/page.tsx
new file mode 100644
index 0000000..ff1f679
--- /dev/null
+++ b/OMNL/app/(public)/leadership/page.tsx
@@ -0,0 +1,8 @@
+export default function LeadershipPage() {
+ return (
+
+
Leadership
+
Executive leadership and secretariat.
+
+ );
+}
diff --git a/OMNL/app/(public)/membership/page.tsx b/OMNL/app/(public)/membership/page.tsx
new file mode 100644
index 0000000..cf191d0
--- /dev/null
+++ b/OMNL/app/(public)/membership/page.tsx
@@ -0,0 +1,8 @@
+export default function MembershipPage() {
+ return (
+
+
Membership
+
Member directory and accreditation.
+
+ );
+}
diff --git a/OMNL/app/(public)/news/page.tsx b/OMNL/app/(public)/news/page.tsx
new file mode 100644
index 0000000..57d0061
--- /dev/null
+++ b/OMNL/app/(public)/news/page.tsx
@@ -0,0 +1,8 @@
+export default function NewsPage() {
+ return (
+
+
News
+
News and announcements.
+
+ );
+}
diff --git a/OMNL/app/(public)/org-chart/page.tsx b/OMNL/app/(public)/org-chart/page.tsx
new file mode 100644
index 0000000..e01d431
--- /dev/null
+++ b/OMNL/app/(public)/org-chart/page.tsx
@@ -0,0 +1,8 @@
+export default function OrgChartPage() {
+ return (
+
+
Org Chart
+
Organizational structure.
+
+ );
+}
diff --git a/OMNL/app/(public)/programs/page.tsx b/OMNL/app/(public)/programs/page.tsx
new file mode 100644
index 0000000..57d0bb0
--- /dev/null
+++ b/OMNL/app/(public)/programs/page.tsx
@@ -0,0 +1,8 @@
+export default function ProgramsPage() {
+ return (
+
+
Programs
+
Programs and initiatives.
+
+ );
+}
diff --git a/OMNL/app/(public)/publications/page.tsx b/OMNL/app/(public)/publications/page.tsx
new file mode 100644
index 0000000..6b329f6
--- /dev/null
+++ b/OMNL/app/(public)/publications/page.tsx
@@ -0,0 +1,8 @@
+export default function PublicationsPage() {
+ return (
+
+
Publications
+
Publications and reports.
+
+ );
+}
diff --git a/OMNL/app/(public)/regions/page.tsx b/OMNL/app/(public)/regions/page.tsx
new file mode 100644
index 0000000..66978cc
--- /dev/null
+++ b/OMNL/app/(public)/regions/page.tsx
@@ -0,0 +1,8 @@
+export default function RegionsPage() {
+ return (
+
+
Regional Offices
+
Americas, EMEA, APAC delegations and field missions.
+
+ );
+}
diff --git a/OMNL/app/(public)/standards/page.tsx b/OMNL/app/(public)/standards/page.tsx
new file mode 100644
index 0000000..9327ef0
--- /dev/null
+++ b/OMNL/app/(public)/standards/page.tsx
@@ -0,0 +1,8 @@
+export default function StandardsPage() {
+ return (
+
+
Standards
+
Standards and codes.
+
+ );
+}
diff --git a/OMNL/app/api/auth/mock-login/route.ts b/OMNL/app/api/auth/mock-login/route.ts
new file mode 100644
index 0000000..57f672f
--- /dev/null
+++ b/OMNL/app/api/auth/mock-login/route.ts
@@ -0,0 +1,10 @@
+import { NextRequest, NextResponse } from "next/server";
+
+export async function POST(request: NextRequest) {
+ const form = await request.formData();
+ const returnUrl = (form.get("returnUrl") as string) ?? "/dashboard";
+ const role = (form.get("role") as string) ?? "member";
+ const res = NextResponse.redirect(new URL(returnUrl, request.url));
+ res.cookies.set("portal-role", role, { path: "/", httpOnly: true, maxAge: 60 * 60 * 24 });
+ return res;
+}
diff --git a/OMNL/app/apply/page.tsx b/OMNL/app/apply/page.tsx
new file mode 100644
index 0000000..7ee15cb
--- /dev/null
+++ b/OMNL/app/apply/page.tsx
@@ -0,0 +1,8 @@
+export default function ApplyPage() {
+ return (
+
+
Apply
+
Apply for membership or accreditation.
+
+ );
+}
diff --git a/OMNL/app/dashboard/layout.tsx b/OMNL/app/dashboard/layout.tsx
new file mode 100644
index 0000000..680435b
--- /dev/null
+++ b/OMNL/app/dashboard/layout.tsx
@@ -0,0 +1,17 @@
+import Link from "next/link";
+import type { ReactNode } from "react";
+
+export default function DashboardLayout({ children }: { children: ReactNode }) {
+ return (
+
+
+
{children}
+
+ );
+}
diff --git a/OMNL/app/dashboard/page.tsx b/OMNL/app/dashboard/page.tsx
new file mode 100644
index 0000000..199cd04
--- /dev/null
+++ b/OMNL/app/dashboard/page.tsx
@@ -0,0 +1,8 @@
+export default function DashboardPage() {
+ return (
+
+
Dashboard
+
Role-based dashboard.
+
+ );
+}
diff --git a/OMNL/app/dashboard/requests/page.tsx b/OMNL/app/dashboard/requests/page.tsx
new file mode 100644
index 0000000..eb94812
--- /dev/null
+++ b/OMNL/app/dashboard/requests/page.tsx
@@ -0,0 +1,8 @@
+export default function RequestsPage() {
+ return (
+
+
My requests
+
Track your requests.
+
+ );
+}
diff --git a/OMNL/app/dashboard/submissions/page.tsx b/OMNL/app/dashboard/submissions/page.tsx
new file mode 100644
index 0000000..dc57c54
--- /dev/null
+++ b/OMNL/app/dashboard/submissions/page.tsx
@@ -0,0 +1,8 @@
+export default function SubmissionsPage() {
+ return (
+
+
My submissions
+
Track your submissions and status.
+
+ );
+}
diff --git a/OMNL/app/departments/cyber-resilience/page.tsx b/OMNL/app/departments/cyber-resilience/page.tsx
new file mode 100644
index 0000000..8040c4f
--- /dev/null
+++ b/OMNL/app/departments/cyber-resilience/page.tsx
@@ -0,0 +1,8 @@
+export default function CyberResiliencePage() {
+ return (
+
+
Cyber Resilience
+
Incident coordination and cyber resilience.
+
+ );
+}
diff --git a/OMNL/app/documents/standards/page.tsx b/OMNL/app/documents/standards/page.tsx
new file mode 100644
index 0000000..02460af
--- /dev/null
+++ b/OMNL/app/documents/standards/page.tsx
@@ -0,0 +1,8 @@
+export default function DocumentsStandardsPage() {
+ return (
+
+
Standards
+
Digital standards and interoperability.
+
+ );
+}
diff --git a/OMNL/app/globals.css b/OMNL/app/globals.css
new file mode 100644
index 0000000..b5c61c9
--- /dev/null
+++ b/OMNL/app/globals.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/OMNL/app/layout.tsx b/OMNL/app/layout.tsx
new file mode 100644
index 0000000..28796e3
--- /dev/null
+++ b/OMNL/app/layout.tsx
@@ -0,0 +1,34 @@
+import type { Metadata } from "next";
+import type { ReactNode } from "react";
+import "./globals.css";
+import { Header } from "@/components/layout/Header";
+import { Footer } from "@/components/layout/Footer";
+
+export const metadata: Metadata = {
+ title: "Organisation Mondiale du Numérique",
+ description: "Official portal of the Organisation Mondiale du Numérique",
+};
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: ReactNode;
+}>) {
+ return (
+
+
+
+ Skip to main content
+
+
+
+ {children}
+
+
+
+
+ );
+}
diff --git a/OMNL/app/membership/renewals/page.tsx b/OMNL/app/membership/renewals/page.tsx
new file mode 100644
index 0000000..79e5a75
--- /dev/null
+++ b/OMNL/app/membership/renewals/page.tsx
@@ -0,0 +1,8 @@
+export default function RenewalsPage() {
+ return (
+
+
Renewals and Attestations
+
Annual renewals for members.
+
+ );
+}
diff --git a/OMNL/app/page.tsx b/OMNL/app/page.tsx
new file mode 100644
index 0000000..fac9a35
--- /dev/null
+++ b/OMNL/app/page.tsx
@@ -0,0 +1,24 @@
+export default function HomePage() {
+ return (
+
+
Organisation Mondiale du Numérique
+
+ Welcome to the official portal. Digital standards, identity, and cyber resilience.
+
+
+
+ );
+}
diff --git a/OMNL/app/report/page.tsx b/OMNL/app/report/page.tsx
new file mode 100644
index 0000000..6ae4c22
--- /dev/null
+++ b/OMNL/app/report/page.tsx
@@ -0,0 +1,8 @@
+export default function ReportPage() {
+ return (
+
+
Report
+
Report incidents or compliance matters.
+
+ );
+}
diff --git a/OMNL/app/request/page.tsx b/OMNL/app/request/page.tsx
new file mode 100644
index 0000000..6e653db
--- /dev/null
+++ b/OMNL/app/request/page.tsx
@@ -0,0 +1,8 @@
+export default function RequestPage() {
+ return (
+
+
Request
+
Request documents or support.
+
+ );
+}
diff --git a/OMNL/app/submit/page.tsx b/OMNL/app/submit/page.tsx
new file mode 100644
index 0000000..62e1cba
--- /dev/null
+++ b/OMNL/app/submit/page.tsx
@@ -0,0 +1,8 @@
+export default function SubmitPage() {
+ return (
+
+
Submit
+
Submission portal.
+
+ );
+}
diff --git a/OMNL/app/transparency/audit/page.tsx b/OMNL/app/transparency/audit/page.tsx
new file mode 100644
index 0000000..5fe7056
--- /dev/null
+++ b/OMNL/app/transparency/audit/page.tsx
@@ -0,0 +1,8 @@
+export default function AuditPage() {
+ return (
+
+
Audit Reports
+
Audit reports and findings tracker.
+
+ );
+}
diff --git a/OMNL/app/transparency/data-protection/page.tsx b/OMNL/app/transparency/data-protection/page.tsx
new file mode 100644
index 0000000..b2454b3
--- /dev/null
+++ b/OMNL/app/transparency/data-protection/page.tsx
@@ -0,0 +1,8 @@
+export default function DataProtectionPage() {
+ return (
+
+
Data Protection and Records
+
Records retention and data protection.
+
+ );
+}
diff --git a/OMNL/app/transparency/ethics/page.tsx b/OMNL/app/transparency/ethics/page.tsx
new file mode 100644
index 0000000..ff5b47d
--- /dev/null
+++ b/OMNL/app/transparency/ethics/page.tsx
@@ -0,0 +1,8 @@
+export default function EthicsPage() {
+ return (
+
+
Ethics and Conduct
+
Ethics and conduct policies.
+
+ );
+}
diff --git a/OMNL/app/transparency/page.tsx b/OMNL/app/transparency/page.tsx
new file mode 100644
index 0000000..f676261
--- /dev/null
+++ b/OMNL/app/transparency/page.tsx
@@ -0,0 +1,8 @@
+export default function TransparencyPage() {
+ return (
+
+
Transparency
+
Audit, ethics, whistleblower, sanctions, and data protection.
+
+ );
+}
diff --git a/OMNL/app/transparency/sanctions/page.tsx b/OMNL/app/transparency/sanctions/page.tsx
new file mode 100644
index 0000000..adf23fe
--- /dev/null
+++ b/OMNL/app/transparency/sanctions/page.tsx
@@ -0,0 +1,8 @@
+export default function SanctionsPage() {
+ return (
+
+
Sanctions and Restricted Parties
+
Eligibility and restricted parties.
+
+ );
+}
diff --git a/OMNL/app/transparency/whistleblower/page.tsx b/OMNL/app/transparency/whistleblower/page.tsx
new file mode 100644
index 0000000..5d9a692
--- /dev/null
+++ b/OMNL/app/transparency/whistleblower/page.tsx
@@ -0,0 +1,8 @@
+export default function WhistleblowerPage() {
+ return (
+
+
Whistleblower Intake
+
Secure anonymous reporting.
+
+ );
+}
diff --git a/OMNL/components/layout/Footer.tsx b/OMNL/components/layout/Footer.tsx
new file mode 100644
index 0000000..63b1cb6
--- /dev/null
+++ b/OMNL/components/layout/Footer.tsx
@@ -0,0 +1,48 @@
+import Link from "next/link";
+import { navItems } from "@/lib/nav-config";
+
+const footerLinks = [
+ { label: "About", href: "/about" },
+ { label: "Documents", href: "/documents" },
+ { label: "Transparency", href: "/transparency" },
+ { label: "Contact", href: "/contact" },
+ { label: "Regional Offices", href: "/regions" },
+];
+
+function flatNavItems(items: typeof navItems): { label: string; href: string }[] {
+ const out: { label: string; href: string }[] = [];
+ for (const item of items) {
+ if (item.children) {
+ for (const c of item.children) out.push({ label: c.label, href: c.href });
+ } else {
+ out.push({ label: item.label, href: item.href });
+ }
+ }
+ return out;
+}
+
+export function Footer() {
+ const flat = flatNavItems(navItems);
+ const keyLinks = footerLinks.length ? footerLinks : flat.slice(0, 6);
+
+ return (
+
+ );
+}
diff --git a/OMNL/components/layout/Header.tsx b/OMNL/components/layout/Header.tsx
new file mode 100644
index 0000000..0cbfc91
--- /dev/null
+++ b/OMNL/components/layout/Header.tsx
@@ -0,0 +1,58 @@
+"use client";
+
+import Link from "next/link";
+import { useState } from "react";
+import { navItems } from "@/lib/nav-config";
+import { NavDropdown } from "./NavDropdown";
+import { MobileNav } from "./MobileNav";
+
+export function Header() {
+ const [mobileOpen, setMobileOpen] = useState(false);
+
+ return (
+
+
+
+ OMNL
+
+
+
+
+ Sign in
+
+
+
+
+ setMobileOpen(false)} />
+
+ );
+}
diff --git a/OMNL/components/layout/MobileNav.tsx b/OMNL/components/layout/MobileNav.tsx
new file mode 100644
index 0000000..6b94745
--- /dev/null
+++ b/OMNL/components/layout/MobileNav.tsx
@@ -0,0 +1,57 @@
+"use client";
+
+import Link from "next/link";
+import type { NavItem } from "@public-web-portals/shared";
+
+export function MobileNav({
+ items,
+ open,
+ onClose,
+}: {
+ items: NavItem[];
+ open: boolean;
+ onClose: () => void;
+}) {
+ if (!open) return null;
+
+ return (
+
+ );
+}
diff --git a/OMNL/components/layout/NavDropdown.tsx b/OMNL/components/layout/NavDropdown.tsx
new file mode 100644
index 0000000..d9c6b1b
--- /dev/null
+++ b/OMNL/components/layout/NavDropdown.tsx
@@ -0,0 +1,57 @@
+"use client";
+
+import Link from "next/link";
+import { useState, useRef, useEffect } from "react";
+import type { NavItem } from "@public-web-portals/shared";
+
+export function NavDropdown({ item }: { item: NavItem }) {
+ const [open, setOpen] = useState(false);
+ const ref = useRef(null);
+
+ useEffect(() => {
+ function handleClickOutside(event: MouseEvent) {
+ if (ref.current && !ref.current.contains(event.target as Node)) setOpen(false);
+ }
+ document.addEventListener("mousedown", handleClickOutside);
+ return () => document.removeEventListener("mousedown", handleClickOutside);
+ }, []);
+
+ return (
+
+
+
+
+ );
+}
diff --git a/OMNL/lib/auth.ts b/OMNL/lib/auth.ts
new file mode 100644
index 0000000..1077579
--- /dev/null
+++ b/OMNL/lib/auth.ts
@@ -0,0 +1,10 @@
+import type { SessionOrNull } from "@public-web-portals/shared";
+
+/**
+ * Placeholder session. Replace with OIDC/OAuth 2.0 when identity provider is configured.
+ * TECH_POLICIES: use httpOnly cookies / secure token storage.
+ */
+export async function getSession(): Promise {
+ // TODO: read session from cookie or header (e.g. NextAuth, OIDC)
+ return null;
+}
diff --git a/OMNL/lib/nav-config.ts b/OMNL/lib/nav-config.ts
new file mode 100644
index 0000000..e07e7e8
--- /dev/null
+++ b/OMNL/lib/nav-config.ts
@@ -0,0 +1,4 @@
+import { getNavForPortal } from "@public-web-portals/shared";
+
+export const portalId = "OMNL" as const;
+export const navItems = getNavForPortal(portalId);
diff --git a/OMNL/lib/rbac.ts b/OMNL/lib/rbac.ts
new file mode 100644
index 0000000..75a5b51
--- /dev/null
+++ b/OMNL/lib/rbac.ts
@@ -0,0 +1,66 @@
+import type { Role } from "@public-web-portals/shared";
+
+/** Route prefixes that require any authenticated role */
+const protectedPrefixes = [
+ "/dashboard",
+ "/submit",
+ "/apply",
+ "/report",
+ "/request",
+ "/membership/renewals",
+];
+
+/** Route prefixes that require admin role */
+const adminOnlyPrefixes = ["/dashboard/admin"];
+
+/** Routes that are always public (no auth) */
+const publicPaths = [
+ "/",
+ "/about",
+ "/governance",
+ "/leadership",
+ "/org-chart",
+ "/departments",
+ "/programs",
+ "/membership",
+ "/accreditation",
+ "/documents",
+ "/standards",
+ "/news",
+ "/publications",
+ "/contact",
+ "/regions",
+ "/transparency",
+ "/login",
+ "/logout",
+];
+
+function pathIsPublic(pathname: string): boolean {
+ if (publicPaths.includes(pathname)) return true;
+ if (pathname.startsWith("/transparency/")) return true;
+ return false;
+}
+
+function pathIsProtected(pathname: string): boolean {
+ return protectedPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
+}
+
+function pathIsAdminOnly(pathname: string): boolean {
+ return adminOnlyPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
+}
+
+export function canAccess(pathname: string, role: Role | null): boolean {
+ if (pathIsPublic(pathname)) return true;
+ if (role == null) return false;
+ if (pathIsAdminOnly(pathname)) return role === "admin";
+ if (pathIsProtected(pathname)) return true;
+ return false;
+}
+
+export function requiresAuth(pathname: string): boolean {
+ return pathIsProtected(pathname);
+}
+
+export function requiresAdmin(pathname: string): boolean {
+ return pathIsAdminOnly(pathname);
+}
diff --git a/OMNL/middleware.ts b/OMNL/middleware.ts
new file mode 100644
index 0000000..a1e26cd
--- /dev/null
+++ b/OMNL/middleware.ts
@@ -0,0 +1,39 @@
+import { NextResponse } from "next/server";
+import type { NextRequest } from "next/server";
+import { canAccess, requiresAuth, requiresAdmin } from "./lib/rbac";
+import type { Role } from "@public-web-portals/shared";
+
+const LOGIN = "/login";
+
+function getRoleFromCookie(request: NextRequest): Role | null {
+ const role = request.cookies.get("portal-role")?.value;
+ if (!role) return null;
+ const valid: Role[] = ["member", "judge", "clerk", "diplomat", "donor", "staff", "admin"];
+ return valid.includes(role as Role) ? (role as Role) : null;
+}
+
+export function middleware(request: NextRequest) {
+ const pathname = request.nextUrl.pathname;
+ const role = getRoleFromCookie(request);
+
+ if (requiresAdmin(pathname) && role !== "admin") {
+ return NextResponse.redirect(new URL("/dashboard", request.url));
+ }
+
+ if (requiresAuth(pathname)) {
+ if (role == null) {
+ const url = new URL(LOGIN, request.url);
+ url.searchParams.set("returnUrl", pathname);
+ return NextResponse.redirect(url);
+ }
+ if (!canAccess(pathname, role)) {
+ return NextResponse.redirect(new URL("/dashboard", request.url));
+ }
+ }
+
+ return NextResponse.next();
+}
+
+export const config = {
+ matcher: ["/((?!_next/static|_next/image|favicon.ico|api).*)"],
+};
diff --git a/OMNL/next-env.d.ts b/OMNL/next-env.d.ts
new file mode 100644
index 0000000..40c3d68
--- /dev/null
+++ b/OMNL/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
diff --git a/OMNL/next.config.js b/OMNL/next.config.js
new file mode 100644
index 0000000..d0d6b18
--- /dev/null
+++ b/OMNL/next.config.js
@@ -0,0 +1,32 @@
+/** @type { import('next').NextConfig } */
+const nextConfig = {
+ transpilePackages: ["@public-web-portals/shared"],
+ async headers() {
+ return [
+ {
+ source: "/:path*",
+ headers: [
+ { key: "X-Frame-Options", value: "DENY" },
+ { key: "X-Content-Type-Options", value: "nosniff" },
+ { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
+ {
+ key: "Content-Security-Policy",
+ value: [
+ "default-src 'self'",
+ "script-src 'self'",
+ "style-src 'self' 'unsafe-inline'",
+ "img-src 'self' data: https:",
+ "font-src 'self'",
+ "connect-src 'self'",
+ "frame-ancestors 'none'",
+ "base-uri 'self'",
+ "form-action 'self'",
+ ].join("; "),
+ },
+ ],
+ },
+ ];
+ },
+};
+
+module.exports = nextConfig;
diff --git a/OMNL/package.json b/OMNL/package.json
new file mode 100644
index 0000000..56abfc6
--- /dev/null
+++ b/OMNL/package.json
@@ -0,0 +1,32 @@
+{
+ "name": "portal-omnl",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev --port 3000",
+ "build": "next build",
+ "start": "next start --port 3000",
+ "lint": "eslint . --max-warnings 0 --config ../.eslintrc.cjs",
+ "typecheck": "tsc --noEmit"
+ },
+ "dependencies": {
+ "@public-web-portals/shared": "workspace:*",
+ "next": "^14.2.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@types/node": "^20.10.0",
+ "@types/react": "^18.2.0",
+ "@types/react-dom": "^18.2.0",
+ "autoprefixer": "^10.4.0",
+ "eslint": "^8.56.0",
+ "eslint-config-next": "^14.2.0",
+ "postcss": "^8.4.0",
+ "tailwindcss": "^3.4.0",
+ "typescript": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+}
diff --git a/OMNL/postcss.config.js b/OMNL/postcss.config.js
new file mode 100644
index 0000000..12a703d
--- /dev/null
+++ b/OMNL/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/OMNL/tailwind.config.ts b/OMNL/tailwind.config.ts
new file mode 100644
index 0000000..aae1628
--- /dev/null
+++ b/OMNL/tailwind.config.ts
@@ -0,0 +1,15 @@
+import type { Config } from "tailwindcss";
+import { designTokens } from "@public-web-portals/shared";
+
+const config: Config = {
+ content: [
+ "./app/**/*.{js,ts,jsx,tsx,mdx}",
+ "./components/**/*.{js,ts,jsx,tsx,mdx}",
+ ],
+ theme: {
+ extend: designTokens as Record,
+ },
+ plugins: [],
+};
+
+export default config;
diff --git a/OMNL/tsconfig.json b/OMNL/tsconfig.json
new file mode 100644
index 0000000..cd32290
--- /dev/null
+++ b/OMNL/tsconfig.json
@@ -0,0 +1,30 @@
+{
+ "extends": "../tsconfig.base.json",
+ "compilerOptions": {
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "jsx": "preserve",
+ "noEmit": true,
+ "incremental": true,
+ "paths": {
+ "@/*": [
+ "./*"
+ ]
+ },
+ "allowJs": true
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/ORG_STRUCTURE.md b/ORG_STRUCTURE.md
new file mode 100644
index 0000000..f3f7c67
--- /dev/null
+++ b/ORG_STRUCTURE.md
@@ -0,0 +1,150 @@
+# Org Structure Modules — Public Web Portals
+
+Repeatable organizational-structure modules for all four portals (DBIS, ICCC, OMNL, XOM). Use as the single source of truth for governance, departments, and portal content structure. Slight tailoring per entity is noted in **§3 Core Mission Departments**.
+
+---
+
+## 1) Top-Level Governance Layer
+
+| Unit | Role |
+|------|------|
+| **Sovereign Council / Board of Governors** | Highest strategic authority |
+| **Executive Secretariat** | Day-to-day execution |
+| **Charters & Instruments Office** | Constitutions, bylaws, mandates, resolutions |
+| **Inspector General / Audit & Integrity Office** | Internal control and investigations |
+
+---
+
+## 2) Executive Administration Layer
+
+| Unit | Role |
+|------|------|
+| **Office of the President / Grand Master / Secretary-General** | Entity head |
+| **Chief of Staff** | Coordination and priorities |
+| **Legal Affairs & Treaty Office** | MOUs, protocols, recognition, dispute posture |
+| **Strategic Communications** | Press, publications, brand, protocol |
+
+---
+
+## 3) Core “Mission” Departments (by entity)
+
+### DBIS — Digital Bank of International Settlements
+
+- Monetary Operations / Digital Reserves
+- Settlement & Clearing
+- Supervision, Risk & Prudential Standards
+- Treasury, Liquidity & Capital
+- Member Institutions / Counterparty Relations
+- Financial Intelligence & Compliance
+
+### ICCC — International Criminal Court of Commerce
+
+- Registry / Clerk of Court
+- Investigations & Enforcement Liaison
+- Prosecution / Charging Authority
+- Defense / Public Counsel Office
+- Chambers (Trial / Appeals)
+- Evidence, Chain-of-Custody & Forensics
+- Judgments, Orders & Remedies
+
+### OMNL — Organisation Mondiale du Numérique
+
+- Digital Standards & Interoperability
+- Identity, Trust & Credentialing
+- Digital Inclusion & Capacity Building
+- Cyber Resilience & Incident Coordination
+- Research, Labs & Emerging Tech
+- Member States / Partners & Programs
+
+### XOM — Sovereign Military Hospitaller Order of St. John of Jerusalem of Rhodes and of Malta
+
+- Hospitaller Services / Humanitarian Missions
+- Medical & Relief Operations
+- Diplomatic & Protocol Affairs
+- Commandery / Priories Administration
+- Volunteer Corps & Logistics
+- Donor Stewardship & Philanthropy
+- Safeguarding & Ethics
+
+---
+
+## 4) Regional / Field Structure (all entities)
+
+- **Regions** — Americas, EMEA, APAC
+- **Country Delegations / Chapters**
+- **Program Offices / Field Missions**
+- **Local Compliance & Reporting**
+
+---
+
+## 5) Oversight, Compliance, and Safeguards (must-have portal areas)
+
+- Ethics & Conduct
+- Sanctions / Restricted Parties / Eligibility
+- Data Protection & Records Retention
+- Whistleblower Intake
+- Procurement Integrity
+- Audit Reports & Findings Tracker
+
+---
+
+## 6) Membership & Credentialing (portal-native)
+
+- Member Directory / Accreditation
+- Roles & Permissions (RBAC)
+- Digital ID / Certificates / Badges
+- KYC/KYB-style onboarding (where relevant)
+- Annual Renewals + Attestations
+
+---
+
+## 7) Finance & Administration (shared services)
+
+- Budgeting & Planning
+- Grants / Contributions / Dues
+- Accounts Payable / Receivable
+- Vendor Management
+- HR & Appointments
+- Facilities / Asset Management
+
+---
+
+## 8) Knowledge, Publications, and Transparency
+
+| Area | DBIS | ICCC | OMNL | XOM |
+|------|------|------|------|-----|
+| **Library & Archives** | ✓ | ✓ | ✓ | ✓ |
+| **Standards / Codes / Directives** | ✓ | ✓ | ✓ | ✓ |
+| **Case Law / Decisions** | — | ✓ | — | — |
+| **Financial Bulletins** | ✓ | — | — | — |
+| **Programs & Impact Reports** | — | — | ✓ | ✓ |
+| **Public Register + Notices** | ✓ | ✓ | ✓ | ✓ |
+
+---
+
+## 9) Technology & Security (portal backbone)
+
+- CIO / Digital Services
+- Security Operations (SOC)
+- Identity & Access Management
+- Platform Engineering
+- Data & Analytics
+- Incident Response
+
+---
+
+## 10) Standard Portal “Sitemap” (high-level)
+
+- About / Mandate / Governance
+- Leadership / Org Chart
+- Departments & Programs
+- Membership / Accreditation
+- Documents / Standards / Directives
+- News / Publications
+- **Portals:** Submit / Apply / Report / Request
+- **Transparency:** Audit / Ethics / Whistleblower
+- Contact / Regional Offices
+
+---
+
+**Primary users (all portals):** Public, member institutions, judges/clerks, diplomats, donors, staff, and other stakeholders. See [PORTAL_NAVIGATION.md](./PORTAL_NAVIGATION.md) for menus, role-based dashboards, and workflows mapped to these users.
diff --git a/PORTAL_CHECKLIST.md b/PORTAL_CHECKLIST.md
new file mode 100644
index 0000000..e809601
--- /dev/null
+++ b/PORTAL_CHECKLIST.md
@@ -0,0 +1,45 @@
+# Portal readiness checklist
+
+Use this checklist for each governmental body portal (DBIS, XOM, OMNL, ICCC, etc.) before release. All items should be satisfied unless an exception is documented in TECH_POLICIES.md.
+
+## Tech stack
+
+- [ ] Next.js (App Router), TypeScript strict, Tailwind CSS
+- [ ] Extends root `tsconfig.base.json`
+- [ ] Uses shared ESLint and Prettier config (or equivalent rules)
+- [ ] pnpm, Node 20 LTS (`.nvmrc` or `engines` in package.json)
+
+## Security
+
+- [ ] No secrets in repo; env vars / vault only
+- [ ] `pnpm audit` (or equivalent) passing or risks documented
+- [ ] CSP configured (Next.js headers)
+- [ ] HTTPS only; no mixed content
+
+## Accessibility
+
+- [ ] WCAG 2.1 AA targeted; automated a11y checks in CI
+- [ ] Keyboard navigation and focus order verified
+- [ ] Critical flows tested with screen reader and zoom
+
+## Quality
+
+- [ ] Unit/component tests (Vitest + RTL); E2E (Playwright) for critical journeys
+- [ ] Coverage thresholds met
+- [ ] Lint and format pass in CI
+- [ ] TypeScript `tsc --noEmit` in CI
+
+## Documentation
+
+- [ ] Portal README: purpose, how to run, env vars, links to TECH_STACK + TECH_POLICIES
+- [ ] API contracts documented (if applicable)
+
+## DevOps
+
+- [ ] CI runs lint, test, build (and deploy per org process)
+- [ ] Same environment naming (e.g. dev / staging / production)
+- [ ] Dockerfile follows project pattern (if used)
+
+---
+
+Mark each item when the portal meets the requirement. Re-check after major changes or policy updates.
diff --git a/PORTAL_NAVIGATION.md b/PORTAL_NAVIGATION.md
new file mode 100644
index 0000000..b6c7004
--- /dev/null
+++ b/PORTAL_NAVIGATION.md
@@ -0,0 +1,116 @@
+# Portal Navigation & Role-Based Design — All Portals
+
+Final org-derived **sitemap**, **menus**, **role-based dashboards**, and **workflows** for DBIS, ICCC, OMNL, and XOM. Primary users: **all** (public, member institutions, judges/clerks, diplomats, donors, staff). Each portal implements the same navigation pattern with entity-specific labels and links.
+
+---
+
+## 1. Primary User Types & Needs
+
+| User type | Primary needs | Key portal areas |
+|-----------|----------------|-------------------|
+| **Public** | Mandate, news, documents, transparency, contact | About, News, Documents, Transparency, Contact |
+| **Member institutions** | Accreditation, standards, submissions, directory | Membership, Documents, Submit/Apply, Member directory |
+| **Judges / Clerks (ICCC)** | Cases, registry, evidence, judgments, procedures | Registry, Chambers, Case Law, Submit/Report |
+| **Diplomats** | Protocol, treaties, recognition, regional offices | Governance, Legal/Treaty, Regional offices, Contact |
+| **Donors (esp. XOM)** | Impact, stewardship, giving, reports | Programs & Impact, Donor Stewardship, Transparency |
+| **Staff / Internal** | RBAC, workflows, admin, HR, finance (internal) | Dashboards, Submit/Report/Request, Admin (by role) |
+
+---
+
+## 2. Global Sitemap (all four portals)
+
+Use this as the canonical URL and menu structure. Tailor **labels** and **entity-specific sections** per portal (see §5).
+
+| # | Section | Path (suggestion) | Notes |
+|---|---------|-------------------|--------|
+| 1 | About / Mandate / Governance | `/about`, `/governance` | Mandate, Charters & Instruments, Sovereign Council / Board |
+| 2 | Leadership / Org Chart | `/leadership`, `/org-chart` | Executive, departments (from ORG_STRUCTURE.md §1–3, 4) |
+| 3 | Departments & Programs | `/departments`, `/programs` | Links to mission departments + regional structure |
+| 4 | Membership / Accreditation | `/membership`, `/accreditation` | Directory, roles, digital ID, onboarding, renewals |
+| 5 | Documents / Standards / Directives | `/documents`, `/standards` | Library, codes, directives; entity-specific (Case Law, Bulletins, etc.) |
+| 6 | News / Publications | `/news`, `/publications` | Press, bulletins, impact reports (per entity) |
+| 7 | **Portals: Submit / Apply / Report / Request** | `/submit`, `/apply`, `/report`, `/request` | Role-gated where needed; clear CTAs |
+| 8 | **Transparency** | `/transparency` | Audit, Ethics, Whistleblower, Sanctions, Data protection |
+| 9 | Contact / Regional Offices | `/contact`, `/regions` | Regions, delegations, field missions |
+
+---
+
+## 3. Main Navigation (recommended)
+
+- **Desktop:** Horizontal top nav with dropdowns (or mega-menu) for sections 1–6; “Portals” and “Transparency” as prominent items; “Contact” right-aligned.
+- **Mobile:** Hamburger with same sections; “Portals” and “Transparency” visible in first screen.
+- **Footer:** Repeat key links (About, Documents, Transparency, Contact, Regional offices).
+
+**Suggested top-level items:**
+
+1. About (dropdown: Mandate, Governance, Leadership, Org Chart)
+2. Departments & Programs (dropdown: list from ORG_STRUCTURE §3 + Regional)
+3. Membership (dropdown: Accreditation, Directory, Digital ID, Onboarding)
+4. Documents (dropdown: Standards, Directives, [Case Law / Bulletins / Programs per entity])
+5. News & Publications
+6. **Portals** (dropdown: Submit, Apply, Report, Request — or direct links)
+7. **Transparency** (dropdown: Audit, Ethics, Whistleblower, Sanctions, Data Protection)
+8. Contact (dropdown: General, Regional Offices)
+
+---
+
+## 4. Role-Based Dashboards & Entry Points
+
+| Role | Dashboard / home after login | Key actions |
+|------|------------------------------|-------------|
+| **Anonymous / Public** | Public homepage; no dashboard | Browse About, Documents, News, Transparency; use Contact |
+| **Member** | Member dashboard: submissions, renewals, directory (view), documents | Apply, Submit, Renew, view Member directory |
+| **Judge / Clerk (ICCC)** | Court dashboard: case list, registry, calendar, procedures | Access Chambers, evidence, judgments, orders |
+| **Diplomat** | Protocol / treaty view: events, MOUs, recognition, regional contacts | Documents, Contact, Regional offices |
+| **Donor** | Donor dashboard: impact reports, giving history, stewardship (XOM-focused) | Reports, Donate, Contact |
+| **Staff (by RBAC)** | Role-specific dashboard: tasks, workflows, admin links | Submit, Report, Request; internal admin per permission |
+| **Admin** | Admin dashboard: users, roles, content, audit trail | RBAC, content, audit (per TECH_POLICIES) |
+
+- **RBAC:** Implement Roles & Permissions (ORG_STRUCTURE §6). Each portal defines roles (e.g. `public`, `member`, `judge`, `clerk`, `diplomat`, `donor`, `staff_*`, `admin`) and maps them to menus and routes.
+- **Landing:** After login, redirect to the role-appropriate dashboard or to a “Home” that shows role-relevant widgets (e.g. “Your submissions”, “Your cases”, “Recent notices”).
+
+---
+
+## 5. Entity-Specific Navigation Add-Ons
+
+| Portal | Extra nav / content | Typical paths |
+|--------|---------------------|----------------|
+| **DBIS** | Financial Bulletins, Monetary/Settlement docs | `/documents/bulletins`, `/departments/monetary-operations` |
+| **ICCC** | Case Law, Registry, Chambers, Judgments | `/case-law`, `/registry`, `/chambers`, `/judgments` |
+| **OMNL** | Programs & Impact, Standards, Cyber Resilience | `/programs`, `/documents/standards`, `/departments/cyber-resilience` |
+| **XOM** | Programs & Impact, Donor Stewardship, Humanitarian, Volunteering | `/programs`, `/donors`, `/get-involved`, `/departments/hospitaller-services` |
+
+Keep the **same top-level sitemap** (§2); add these as sub-sections or dropdown items under Documents, Departments, or Portals.
+
+---
+
+## 6. Required Workflows (all portals)
+
+Implement these as distinct flows with clear start/end and, where applicable, status tracking:
+
+| Workflow | Who | Entry point | Notes |
+|----------|-----|-------------|--------|
+| **Submit** | Members, staff, designated parties | `/submit` or Portals → Submit | Type of submission defined per entity (e.g. filings, reports) |
+| **Apply** | Applicants for membership, accreditation, programs | `/apply` or Portals → Apply | Link to KYC/KYB/onboarding where relevant |
+| **Report** | Staff, members, public (as allowed) | `/report` or Portals → Report | Incidents, compliance, other reportable events |
+| **Request** | Any authenticated role (as allowed) | `/request` or Portals → Request | Documents, access, support |
+| **Whistleblower** | Any (often anonymous) | `/transparency/whistleblower` | Secure intake; see Oversight (§5 in ORG_STRUCTURE) |
+| **Renewals / Attestations** | Members | Member dashboard or `/membership/renewals` | Annual renewals + attestations (ORG_STRUCTURE §6) |
+
+- Each workflow: dedicated route, optional wizard, confirmation, and (where applicable) “My submissions” / “My requests” in the role dashboard.
+- Transparency workflows (whistleblower, ethics, audit) must be discoverable from the **Transparency** section and footer.
+
+---
+
+## 7. Implementation Checklist (per portal)
+
+- [ ] Sitemap matches §2; entity-specific add-ons from §5.
+- [ ] Main nav matches §3; mobile and footer implemented.
+- [ ] Roles defined and mapped to dashboards (§4) and to RBAC (ORG_STRUCTURE §6).
+- [ ] Workflows in §6 implemented with clear entry points and status.
+- [ ] “Portals” (Submit / Apply / Report / Request) and “Transparency” visible without deep drilling.
+- [ ] Accessibility (keyboard, focus, labels) per TECH_POLICIES.md.
+
+---
+
+**References:** [ORG_STRUCTURE.md](./ORG_STRUCTURE.md) (governance and departments), [TECH_STACK.md](./TECH_STACK.md), [TECH_POLICIES.md](./TECH_POLICIES.md).
diff --git a/README.md b/README.md
index 3a2cda6..9f799c2 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,104 @@
+<<<<<<< HEAD
# gov-portals-monorepo
+=======
+# Gov Portals Monorepo
+
+Monorepo for next-generation governmental body web portals. Each subdirectory is named by the body’s **initials** and contains one portal application.
+
+**Repository:** https://gitea.d-bis.org/nsatoshi/gov-portals-monorepo.git
+
+# Gov Portals Monorepo
+
+Monorepo for next-generation governmental body web portals. Each subdirectory is named by the body's **initials** and contains one portal application.
+
+**Repository:** https://gitea.d-bis.org/nsatoshi/gov-portals-monorepo.git
+
+```bash
+git clone https://gitea.d-bis.org/nsatoshi/gov-portals-monorepo.git
+cd gov-portals-monorepo
+pnpm install
+```
+
+## Portals
+
+| Directory | Abbreviation | Official / long-form name |
+|-----------|----------------|----------------------------|
+| `DBIS/` | DBIS | Digital Bank of International Settlements |
+| `ICCC/` | ICCC | International Criminal Court of Commerce |
+| `OMNL/` | OMNL | Organisation Mondiale du Numérique |
+| `XOM/` | XOM | Sovereign Military Hospitaller Order of St. John of Jerusalem of Rhodes and of Malta |
+
+**Naming note (XOM):** The directory `XOM/` refers to the sovereign entity recognized in UN relations. In UN and official references the most common abbreviations are **SMOM** (Sovereign Military Order of Malta), **Sovereign Order of Malta**, or simply **Order of Malta**. This project uses **XOM** as the directory name; the official long-form name above is the UN/official style.
+
+## Monorepo and portal repos
+
+This project is a **monorepo**. The canonical repository is:
+
+- **Monorepo:** https://gitea.d-bis.org/nsatoshi/gov-portals-monorepo.git
+
+Optional per-portal Gitea repos (for mirroring or separate CI/deploy):
+
+| Portal | Repository |
+|--------|------------|
+| DBIS | https://gitea.d-bis.org/Gov_Web_Portals/DBIS.git |
+| ICCC | https://gitea.d-bis.org/Gov_Web_Portals/ICCC.git |
+| OMNL | https://gitea.d-bis.org/Gov_Web_Portals/OMNL.git |
+| XOM | https://gitea.d-bis.org/Gov_Web_Portals/XOM.git |
+
+To push the whole monorepo: `git remote add origin https://gitea.d-bis.org/nsatoshi/gov-portals-monorepo.git` (if not set), then `git push -u origin main`.
+
+## Standardization
+
+All portals **must** follow the same tech stack and policies:
+
+- **[TECH_STACK.md](./TECH_STACK.md)** — Mandatory technologies (Next.js, TypeScript, Tailwind, testing, etc.)
+- **[TECH_POLICIES.md](./TECH_POLICIES.md)** — Security, accessibility, quality, and governance
+
+Org structure and navigation (shared across DBIS, ICCC, OMNL, XOM):
+
+- **[ORG_STRUCTURE.md](./ORG_STRUCTURE.md)** — Governance layers, executive admin, mission departments per entity, regional structure, oversight, membership, finance, knowledge, technology
+- **[PORTAL_NAVIGATION.md](./PORTAL_NAVIGATION.md)** — Sitemap, main nav, role-based dashboards (public, members, judges/clerks, diplomats, donors, staff), and required workflows (Submit / Apply / Report / Request / Whistleblower)
+
+Shared config at repo root:
+
+- **TypeScript** — `tsconfig.base.json` (portals extend this)
+- **ESLint** — `.eslintrc.cjs` (portals extend and add Next/TypeScript rules)
+- **Prettier** — `.prettierrc.json`, `.prettierignore`
+- **Node** — `.nvmrc` (Node 20 LTS)
+
+## Scaffolding
+
+Each portal (DBIS, ICCC, OMNL, XOM) is scaffolded with the same Next.js App Router structure, navigation, and access control:
+
+- **Shared package** — `packages/shared` provides types (roles, session), nav/sitemap config (base + entity-specific), and Tailwind design tokens. Portals depend on `@public-web-portals/shared` and use `getNavForPortal(portalId)` for header/footer.
+- **Structure** — Public routes (about, governance, departments, membership, documents, news, contact, regions), transparency (audit, ethics, whistleblower, sanctions, data-protection), workflow routes (submit, apply, report, request), dashboard (home, submissions, requests), and auth (login, logout). Entity-specific routes vary per portal (see [PORTAL_NAVIGATION.md](./PORTAL_NAVIGATION.md) §5).
+- **Access** — Middleware enforces protected routes; placeholder auth uses a `portal-role` cookie. RBAC in `lib/rbac.ts` defines which roles can access which paths. Replace with OIDC/OAuth 2.0 when the identity provider is configured.
+
+See [PORTAL_NAVIGATION.md](./PORTAL_NAVIGATION.md) and [ORG_STRUCTURE.md](./ORG_STRUCTURE.md) for the full sitemap and org-derived navigation.
+
+## Root scripts
+
+From the repo root (e.g. for formatting/linting shared config files):
+
+```bash
+pnpm install
+pnpm run format:check
+pnpm run format
+pnpm run lint
+```
+
+## Adding a new portal
+
+1. Create a directory with the body’s initials.
+2. Bootstrap a Next.js app (TypeScript, Tailwind, App Router) per TECH_STACK.md.
+3. In the new portal, extend root configs:
+ - `tsconfig.json`: `"extends": "../tsconfig.base.json"` (or path to root).
+ - ESLint: extend root `.eslintrc.cjs` and add Next + TypeScript.
+ - Use root `.prettierrc.json` (or don’t override).
+4. Add a README in the portal linking to TECH_STACK.md and TECH_POLICIES.md.
+5. List the new portal in this README and in any CI/docs that enumerate portals.
+
+## Portal checklist
+
+Each portal should satisfy [PORTAL_CHECKLIST.md](./PORTAL_CHECKLIST.md) before release.
diff --git a/TECH_POLICIES.md b/TECH_POLICIES.md
new file mode 100644
index 0000000..c649cc7
--- /dev/null
+++ b/TECH_POLICIES.md
@@ -0,0 +1,126 @@
+# Tech Policies — Public Web Portals
+
+These policies apply to **all** governmental body web portals in this repository. They define security, accessibility, quality, and operational standards.
+
+---
+
+## 1. Security
+
+- **No secrets in repository**
+ No API keys, passwords, or tokens in source code, config files, or history. Use environment variables or a secure secrets store.
+
+- **Dependency hygiene**
+ - Dependencies must be from trusted registries (npm/pnpm).
+ - Run vulnerability scanning (e.g. `pnpm audit`, Snyk) in CI; fix or document accepted risks.
+ - Prefer minimal dependency set; justify new dependencies in PRs.
+
+- **Content Security Policy (CSP)**
+ Each portal must ship with a strict CSP (e.g. via Next.js headers). Nonces or hashes for inline scripts if required; avoid `unsafe-inline` where possible.
+
+- **HTTPS only**
+ All environments (dev/staging/production) must use HTTPS. No mixed content.
+
+- **Authentication**
+ Use the standardized OIDC/OAuth 2.0 flow. Session handling (e.g. httpOnly cookies, token storage) must follow the same security guidelines across portals.
+
+---
+
+## 2. Accessibility (WCAG 2.1 AA)
+
+- **Compliance**
+ All user-facing content and flows must meet WCAG 2.1 Level AA unless a formal exception is documented.
+
+- **Testing**
+ - Use automated tools (e.g. axe-core, Pa11y) in CI.
+ - Manual checks for keyboard navigation, screen reader, and zoom.
+ - Critical user journeys must have an accessibility sign-off before release.
+
+- **Design**
+ Color contrast, focus indicators, and touch targets must meet WCAG. Use the shared design system’s accessible components.
+
+---
+
+## 3. Browser & Device Support
+
+- **Browsers**
+ Support the current and previous major versions of:
+ Chrome, Firefox, Safari, Edge.
+ Exact versions and “current” definition are set in CI (e.g. browserslist).
+
+- **Devices**
+ Responsive design required; mobile and tablet are first-class. Test on real or emulated devices for critical flows.
+
+- **Progressive enhancement**
+ Core content and actions must work without JavaScript where feasible; enhance with JS for better UX.
+
+---
+
+## 4. Code Quality & Consistency
+
+- **TypeScript**
+ Strict mode. No `any` except where explicitly typed and commented. Public APIs must be fully typed.
+
+- **Lint & format**
+ - ESLint and Prettier configs are shared at repo root.
+ - CI fails on lint or format errors.
+ - No disabling rules without a documented exception.
+
+- **Naming & structure**
+ - Same folder conventions across portals (e.g. `app/`, `components/`, `lib/`).
+ - Shared glossary for common terms (e.g. “user”, “session”, “portal”) to keep copy and code consistent.
+
+---
+
+## 5. Testing
+
+- **Unit / component**
+ Vitest + React Testing Library. Critical business logic and shared components must have tests.
+
+- **E2E**
+ Playwright. Critical user journeys (e.g. login, main flows) must have E2E tests. Same browser matrix as production support.
+
+- **Coverage**
+ Minimum coverage thresholds (e.g. 80% for critical paths) enforced in CI. New code should not lower coverage without approval.
+
+---
+
+## 6. Documentation & Onboarding
+
+- **Per-portal README**
+ Each portal must have a README with: purpose, how to run locally, required env vars, and links to TECH_STACK.md and TECH_POLICIES.md.
+
+- **API contracts**
+ Document public APIs (OpenAPI or tRPC schema). Keep docs in sync with code.
+
+- **Changelog / releases**
+ Document breaking changes and notable updates. Use a consistent format (e.g. keep a CHANGELOG or use release notes).
+
+---
+
+## 7. Performance & Reliability
+
+- **Performance budgets**
+ Set and enforce budgets (e.g. LCP, FID, CLS) in CI where possible. No regression without approval.
+
+- **Error handling**
+ User-facing errors must be handled gracefully; no raw stack traces or internal details exposed.
+
+- **Logging & monitoring**
+ Use the same approach (e.g. structured logs, same log levels). No PII in logs.
+
+---
+
+## 8. Governance
+
+- **Changes to TECH_STACK.md and TECH_POLICIES.md**
+ Changes apply to all portals. Update stack/policies via a process that includes impact review (e.g. ADR or tech lead sign-off).
+
+- **Exceptions**
+ Any exception to these policies must be documented (what, why, expiry, owner) and reviewed periodically.
+
+- **Review cycle**
+ Stack and policies should be reviewed at least annually and after major incidents or audits.
+
+---
+
+*These policies sit alongside TECH_STACK.md. Portals must comply with both.*
diff --git a/TECH_STACK.md b/TECH_STACK.md
new file mode 100644
index 0000000..1cd59ff
--- /dev/null
+++ b/TECH_STACK.md
@@ -0,0 +1,104 @@
+# Standardized Tech Stack — Public Web Portals
+
+This document defines the **mandatory** technology stack for all governmental body web portals in this repository. Every portal (DBIS, XOM, OMNL, ICCC, and any future additions) **must** align with this stack.
+
+---
+
+## 1. Runtime & Language
+
+| Area | Choice | Version / Notes |
+|------|--------|------------------|
+| **Runtime** | Node.js | LTS (currently 20.x). Use `.nvmrc` or `engines` in `package.json`. |
+| **Language** | TypeScript | Strict mode enabled. All application code in `.ts` / `.tsx`. |
+| **Package manager** | pnpm | Use `pnpm-workspace.yaml` if sharing packages; otherwise pnpm per portal. |
+
+---
+
+## 2. Frontend
+
+| Area | Choice | Notes |
+|------|--------|--------|
+| **Framework** | Next.js | App Router. Enables SSR, static export, or hybrid as required. |
+| **UI library** | React | With React 18+ patterns (e.g. Suspense where appropriate). |
+| **Styling** | Tailwind CSS | With shared design tokens (colors, spacing, typography) from a common config. |
+| **Component library** | Shared design system or Radix/shadcn-style primitives | Headless components preferred for accessibility and branding consistency. |
+| **State** | React state + URL + (if needed) Zustand or TanStack Query | Avoid Redux unless explicitly justified. |
+| **Forms & validation** | React Hook Form + Zod | Same schema patterns across portals for API and forms. |
+| **Data fetching** | TanStack Query (React Query) + fetch or agreed HTTP client | Caching and loading/error states standardized. |
+
+---
+
+## 3. API & Backend
+
+| Area | Choice | Notes |
+|------|--------|--------|
+| **API style** | REST (JSON) or tRPC | One chosen standard for the whole project; document in each portal. |
+| **Auth** | OIDC / OAuth 2.0 | Same identity provider and flow across portals where possible. |
+| **API client** | Typed (OpenAPI/TRPC) | No untyped `any` for API responses. |
+
+---
+
+## 4. Testing
+
+| Area | Choice | Notes |
+|------|--------|--------|
+| **Unit / component** | Vitest + React Testing Library | Same patterns and helpers across portals. |
+| **E2E** | Playwright | Same browser matrix and base config. |
+| **Coverage** | Enforced minimum (e.g. 80% for critical paths) | Defined in TECH_POLICIES.md and CI. |
+
+---
+
+## 5. Quality & Tooling
+
+| Area | Choice | Notes |
+|------|--------|--------|
+| **Linting** | ESLint | Shared config at repo root; extends per portal if needed. |
+| **Formatting** | Prettier | Single shared config. No conflicting formatters. |
+| **Git hooks** | lint-staged + Husky (or equivalent) | Pre-commit: lint + format + typecheck. |
+| **Type checking** | `tsc --noEmit` | Required in CI; no `skipLibCheck` for library code unless justified. |
+
+---
+
+## 6. DevOps & Hosting
+
+| Area | Choice | Notes |
+|------|--------|--------|
+| **CI** | GitHub Actions (or org-standard CI) | Same workflow structure: lint, test, build, (deploy). |
+| **Containers** | Docker | Single Dockerfile pattern; multi-stage builds. |
+| **Environments** | dev / staging / production | Same naming and promotion rules. |
+| **Secrets** | Env vars from secure store (e.g. vault / CI secrets) | No secrets in repo or client bundles. |
+
+---
+
+## 7. Accessibility & Compliance
+
+| Area | Standard | Notes |
+|------|----------|--------|
+| **Accessibility** | WCAG 2.1 Level AA | Required; automated checks in CI where possible. |
+| **Semantic HTML** | Required | Use correct landmarks, headings, and ARIA only when necessary. |
+| **Browser support** | Per TECH_POLICIES.md | Same supported browsers and versions. |
+
+---
+
+## 8. Portal layout (per directory)
+
+Each portal directory (e.g. `DBIS/`, `XOM/`, `OMNL/`, `ICCC/`) must contain:
+
+- A **Next.js** application that uses the stack above.
+- A **README** with: purpose, how to run, env vars, and link to this TECH_STACK.
+- **Shared config** usage: extend root ESLint/Prettier/TypeScript where provided.
+- **Design tokens** aligned with the shared design system (e.g. from `shared/` or root config).
+
+---
+
+## 9. Adding a new portal
+
+1. Create a new directory with the governmental body’s initials.
+2. Bootstrap a Next.js app (TypeScript, Tailwind, App Router) that matches this stack.
+3. Copy or extend root configs (ESLint, Prettier, TS).
+4. Add a README and ensure TECH_STACK.md and TECH_POLICIES.md are linked and followed.
+5. Add the portal to any root-level scripts or docs that list portals.
+
+---
+
+*Last updated: 2025-02. Review periodically and update version numbers and tool choices in one place to keep all portals in sync.*
diff --git a/XOM/.env.example b/XOM/.env.example
new file mode 100644
index 0000000..8e389e0
--- /dev/null
+++ b/XOM/.env.example
@@ -0,0 +1,8 @@
+# Next.js
+NEXTAUTH_URL=http://localhost:3000
+
+# OIDC / OAuth 2.0 (placeholder until identity provider is configured)
+# OIDC_ISSUER=
+# OIDC_CLIENT_ID=
+# OIDC_CLIENT_SECRET=
+# OIDC_REDIRECT_URI=
diff --git a/XOM/.eslintrc.cjs b/XOM/.eslintrc.cjs
new file mode 100644
index 0000000..53dff50
--- /dev/null
+++ b/XOM/.eslintrc.cjs
@@ -0,0 +1,5 @@
+/** @type { import("eslint").Linter.Config } */
+module.exports = {
+ root: true,
+ extends: ["../.eslintrc.cjs", "next/core-web-vitals"],
+};
diff --git a/XOM/README.md b/XOM/README.md
new file mode 100644
index 0000000..57242a5
--- /dev/null
+++ b/XOM/README.md
@@ -0,0 +1,29 @@
+# XOM Portal
+
+Portal for the **Sovereign Military Hospitaller Order of St. John of Jerusalem of Rhodes and of Malta** (Order of Malta).
+
+**Gitea repository:** https://gitea.d-bis.org/Gov_Web_Portals/XOM.git
+
+## Run locally
+
+```bash
+pnpm install
+pnpm dev
+```
+
+Open [http://localhost:3000](http://localhost:3000).
+
+## Environment
+
+Copy `.env.example` to `.env.local` and set values. No secrets in repo.
+
+## Standards
+
+- [TECH_STACK.md](../TECH_STACK.md)
+- [TECH_POLICIES.md](../TECH_POLICIES.md)
+- [PORTAL_NAVIGATION.md](../PORTAL_NAVIGATION.md)
+- [ORG_STRUCTURE.md](../ORG_STRUCTURE.md)
+
+## Structure
+
+Same app structure as other portals: public routes, transparency, workflow (submit/apply/report/request), dashboard, auth. Entity-specific routes: Programs and Impact, Donors, Get Involved, Hospitaller Services.
diff --git a/XOM/app/(auth)/login/page.tsx b/XOM/app/(auth)/login/page.tsx
new file mode 100644
index 0000000..48101a9
--- /dev/null
+++ b/XOM/app/(auth)/login/page.tsx
@@ -0,0 +1,55 @@
+"use client";
+
+import { Suspense } from "react";
+import { useSearchParams } from "next/navigation";
+import Link from "next/link";
+
+function LoginForm() {
+ const searchParams = useSearchParams();
+ const returnUrl = searchParams.get("returnUrl") ?? "/dashboard";
+
+ return (
+
+
Sign in
+
+ Placeholder login. Replace with OIDC/OAuth 2.0 when identity provider is configured.
+
+
+
+
+ Return to previous page
+
+
+
+ );
+}
+
+export default function LoginPage() {
+ return (
+ Loading...}>
+
+
+ );
+}
diff --git a/XOM/app/(auth)/logout/page.tsx b/XOM/app/(auth)/logout/page.tsx
new file mode 100644
index 0000000..fd763a6
--- /dev/null
+++ b/XOM/app/(auth)/logout/page.tsx
@@ -0,0 +1,20 @@
+"use client";
+
+import { useEffect } from "react";
+import Link from "next/link";
+
+export default function LogoutPage() {
+ useEffect(() => {
+ document.cookie = "portal-role=; path=/; max-age=0";
+ }, []);
+
+ return (
+
+
Signed out
+
You have been signed out.
+
+ Return to home
+
+
+ );
+}
diff --git a/XOM/app/(public)/about/page.tsx b/XOM/app/(public)/about/page.tsx
new file mode 100644
index 0000000..0b87c58
--- /dev/null
+++ b/XOM/app/(public)/about/page.tsx
@@ -0,0 +1,8 @@
+export default function AboutPage() {
+ return (
+
+
Mandate
+
About the Digital Bank of International Settlements.
+
+ );
+}
diff --git a/XOM/app/(public)/accreditation/page.tsx b/XOM/app/(public)/accreditation/page.tsx
new file mode 100644
index 0000000..c5e95d2
--- /dev/null
+++ b/XOM/app/(public)/accreditation/page.tsx
@@ -0,0 +1,8 @@
+export default function AccreditationPage() {
+ return (
+
+
Accreditation
+
Accreditation and credentials.
+
+ );
+}
diff --git a/XOM/app/(public)/contact/page.tsx b/XOM/app/(public)/contact/page.tsx
new file mode 100644
index 0000000..7bb6a85
--- /dev/null
+++ b/XOM/app/(public)/contact/page.tsx
@@ -0,0 +1,8 @@
+export default function ContactPage() {
+ return (
+
+
Contact
+
General contact and enquiries.
+
+ );
+}
diff --git a/XOM/app/(public)/departments/page.tsx b/XOM/app/(public)/departments/page.tsx
new file mode 100644
index 0000000..ed01731
--- /dev/null
+++ b/XOM/app/(public)/departments/page.tsx
@@ -0,0 +1,8 @@
+export default function DepartmentsPage() {
+ return (
+
+
Departments
+
Mission departments and programs.
+
+ );
+}
diff --git a/XOM/app/(public)/documents/page.tsx b/XOM/app/(public)/documents/page.tsx
new file mode 100644
index 0000000..c641e1d
--- /dev/null
+++ b/XOM/app/(public)/documents/page.tsx
@@ -0,0 +1,8 @@
+export default function DocumentsPage() {
+ return (
+
+
Documents
+
Library, standards, and directives.
+
+ );
+}
diff --git a/XOM/app/(public)/governance/page.tsx b/XOM/app/(public)/governance/page.tsx
new file mode 100644
index 0000000..8cf0212
--- /dev/null
+++ b/XOM/app/(public)/governance/page.tsx
@@ -0,0 +1,8 @@
+export default function GovernancePage() {
+ return (
+
+
Governance
+
Charters, instruments, and governance.
+
+ );
+}
diff --git a/XOM/app/(public)/leadership/page.tsx b/XOM/app/(public)/leadership/page.tsx
new file mode 100644
index 0000000..ff1f679
--- /dev/null
+++ b/XOM/app/(public)/leadership/page.tsx
@@ -0,0 +1,8 @@
+export default function LeadershipPage() {
+ return (
+
+
Leadership
+
Executive leadership and secretariat.
+
+ );
+}
diff --git a/XOM/app/(public)/membership/page.tsx b/XOM/app/(public)/membership/page.tsx
new file mode 100644
index 0000000..cf191d0
--- /dev/null
+++ b/XOM/app/(public)/membership/page.tsx
@@ -0,0 +1,8 @@
+export default function MembershipPage() {
+ return (
+
+
Membership
+
Member directory and accreditation.
+
+ );
+}
diff --git a/XOM/app/(public)/news/page.tsx b/XOM/app/(public)/news/page.tsx
new file mode 100644
index 0000000..57d0061
--- /dev/null
+++ b/XOM/app/(public)/news/page.tsx
@@ -0,0 +1,8 @@
+export default function NewsPage() {
+ return (
+
+
News
+
News and announcements.
+
+ );
+}
diff --git a/XOM/app/(public)/org-chart/page.tsx b/XOM/app/(public)/org-chart/page.tsx
new file mode 100644
index 0000000..e01d431
--- /dev/null
+++ b/XOM/app/(public)/org-chart/page.tsx
@@ -0,0 +1,8 @@
+export default function OrgChartPage() {
+ return (
+
+
Org Chart
+
Organizational structure.
+
+ );
+}
diff --git a/XOM/app/(public)/programs/page.tsx b/XOM/app/(public)/programs/page.tsx
new file mode 100644
index 0000000..57d0bb0
--- /dev/null
+++ b/XOM/app/(public)/programs/page.tsx
@@ -0,0 +1,8 @@
+export default function ProgramsPage() {
+ return (
+
+
Programs
+
Programs and initiatives.
+
+ );
+}
diff --git a/XOM/app/(public)/publications/page.tsx b/XOM/app/(public)/publications/page.tsx
new file mode 100644
index 0000000..6b329f6
--- /dev/null
+++ b/XOM/app/(public)/publications/page.tsx
@@ -0,0 +1,8 @@
+export default function PublicationsPage() {
+ return (
+
+
Publications
+
Publications and reports.
+
+ );
+}
diff --git a/XOM/app/(public)/regions/page.tsx b/XOM/app/(public)/regions/page.tsx
new file mode 100644
index 0000000..66978cc
--- /dev/null
+++ b/XOM/app/(public)/regions/page.tsx
@@ -0,0 +1,8 @@
+export default function RegionsPage() {
+ return (
+
+
Regional Offices
+
Americas, EMEA, APAC delegations and field missions.
+
+ );
+}
diff --git a/XOM/app/(public)/standards/page.tsx b/XOM/app/(public)/standards/page.tsx
new file mode 100644
index 0000000..9327ef0
--- /dev/null
+++ b/XOM/app/(public)/standards/page.tsx
@@ -0,0 +1,8 @@
+export default function StandardsPage() {
+ return (
+
+
Standards
+
Standards and codes.
+
+ );
+}
diff --git a/XOM/app/api/auth/mock-login/route.ts b/XOM/app/api/auth/mock-login/route.ts
new file mode 100644
index 0000000..57f672f
--- /dev/null
+++ b/XOM/app/api/auth/mock-login/route.ts
@@ -0,0 +1,10 @@
+import { NextRequest, NextResponse } from "next/server";
+
+export async function POST(request: NextRequest) {
+ const form = await request.formData();
+ const returnUrl = (form.get("returnUrl") as string) ?? "/dashboard";
+ const role = (form.get("role") as string) ?? "member";
+ const res = NextResponse.redirect(new URL(returnUrl, request.url));
+ res.cookies.set("portal-role", role, { path: "/", httpOnly: true, maxAge: 60 * 60 * 24 });
+ return res;
+}
diff --git a/XOM/app/apply/page.tsx b/XOM/app/apply/page.tsx
new file mode 100644
index 0000000..7ee15cb
--- /dev/null
+++ b/XOM/app/apply/page.tsx
@@ -0,0 +1,8 @@
+export default function ApplyPage() {
+ return (
+
+
Apply
+
Apply for membership or accreditation.
+
+ );
+}
diff --git a/XOM/app/dashboard/layout.tsx b/XOM/app/dashboard/layout.tsx
new file mode 100644
index 0000000..680435b
--- /dev/null
+++ b/XOM/app/dashboard/layout.tsx
@@ -0,0 +1,17 @@
+import Link from "next/link";
+import type { ReactNode } from "react";
+
+export default function DashboardLayout({ children }: { children: ReactNode }) {
+ return (
+
+
+
{children}
+
+ );
+}
diff --git a/XOM/app/dashboard/page.tsx b/XOM/app/dashboard/page.tsx
new file mode 100644
index 0000000..199cd04
--- /dev/null
+++ b/XOM/app/dashboard/page.tsx
@@ -0,0 +1,8 @@
+export default function DashboardPage() {
+ return (
+
+
Dashboard
+
Role-based dashboard.
+
+ );
+}
diff --git a/XOM/app/dashboard/requests/page.tsx b/XOM/app/dashboard/requests/page.tsx
new file mode 100644
index 0000000..eb94812
--- /dev/null
+++ b/XOM/app/dashboard/requests/page.tsx
@@ -0,0 +1,8 @@
+export default function RequestsPage() {
+ return (
+
+
My requests
+
Track your requests.
+
+ );
+}
diff --git a/XOM/app/dashboard/submissions/page.tsx b/XOM/app/dashboard/submissions/page.tsx
new file mode 100644
index 0000000..dc57c54
--- /dev/null
+++ b/XOM/app/dashboard/submissions/page.tsx
@@ -0,0 +1,8 @@
+export default function SubmissionsPage() {
+ return (
+
+
My submissions
+
Track your submissions and status.
+
+ );
+}
diff --git a/XOM/app/departments/hospitaller-services/page.tsx b/XOM/app/departments/hospitaller-services/page.tsx
new file mode 100644
index 0000000..f1582ed
--- /dev/null
+++ b/XOM/app/departments/hospitaller-services/page.tsx
@@ -0,0 +1,8 @@
+export default function HospitallerServicesPage() {
+ return (
+
+
Hospitaller Services
+
Humanitarian missions and medical relief.
+
+ );
+}
diff --git a/XOM/app/donors/page.tsx b/XOM/app/donors/page.tsx
new file mode 100644
index 0000000..2cd7de6
--- /dev/null
+++ b/XOM/app/donors/page.tsx
@@ -0,0 +1,8 @@
+export default function DonorsPage() {
+ return (
+
+
Donors
+
Donor stewardship and philanthropy.
+
+ );
+}
diff --git a/XOM/app/get-involved/page.tsx b/XOM/app/get-involved/page.tsx
new file mode 100644
index 0000000..b9c8285
--- /dev/null
+++ b/XOM/app/get-involved/page.tsx
@@ -0,0 +1,8 @@
+export default function GetInvolvedPage() {
+ return (
+
+
Get Involved
+
Volunteer corps and how to contribute.
+
+ );
+}
diff --git a/XOM/app/globals.css b/XOM/app/globals.css
new file mode 100644
index 0000000..b5c61c9
--- /dev/null
+++ b/XOM/app/globals.css
@@ -0,0 +1,3 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
diff --git a/XOM/app/layout.tsx b/XOM/app/layout.tsx
new file mode 100644
index 0000000..a522b2e
--- /dev/null
+++ b/XOM/app/layout.tsx
@@ -0,0 +1,34 @@
+import type { Metadata } from "next";
+import type { ReactNode } from "react";
+import "./globals.css";
+import { Header } from "@/components/layout/Header";
+import { Footer } from "@/components/layout/Footer";
+
+export const metadata: Metadata = {
+ title: "Order of Malta",
+ description: "Official portal of the Sovereign Military Hospitaller Order of St. John of Jerusalem of Rhodes and of Malta",
+};
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: ReactNode;
+}>) {
+ return (
+
+
+
+ Skip to main content
+
+
+
+ {children}
+
+
+
+
+ );
+}
diff --git a/XOM/app/membership/renewals/page.tsx b/XOM/app/membership/renewals/page.tsx
new file mode 100644
index 0000000..79e5a75
--- /dev/null
+++ b/XOM/app/membership/renewals/page.tsx
@@ -0,0 +1,8 @@
+export default function RenewalsPage() {
+ return (
+
+
Renewals and Attestations
+
Annual renewals for members.
+
+ );
+}
diff --git a/XOM/app/page.tsx b/XOM/app/page.tsx
new file mode 100644
index 0000000..5d2946d
--- /dev/null
+++ b/XOM/app/page.tsx
@@ -0,0 +1,24 @@
+export default function HomePage() {
+ return (
+
+
Order of Malta
+
+ Welcome to the official portal. Humanitarian missions, donor stewardship, and volunteering.
+
+
+
+ );
+}
diff --git a/XOM/app/report/page.tsx b/XOM/app/report/page.tsx
new file mode 100644
index 0000000..6ae4c22
--- /dev/null
+++ b/XOM/app/report/page.tsx
@@ -0,0 +1,8 @@
+export default function ReportPage() {
+ return (
+
+
Report
+
Report incidents or compliance matters.
+
+ );
+}
diff --git a/XOM/app/request/page.tsx b/XOM/app/request/page.tsx
new file mode 100644
index 0000000..6e653db
--- /dev/null
+++ b/XOM/app/request/page.tsx
@@ -0,0 +1,8 @@
+export default function RequestPage() {
+ return (
+
+
Request
+
Request documents or support.
+
+ );
+}
diff --git a/XOM/app/submit/page.tsx b/XOM/app/submit/page.tsx
new file mode 100644
index 0000000..62e1cba
--- /dev/null
+++ b/XOM/app/submit/page.tsx
@@ -0,0 +1,8 @@
+export default function SubmitPage() {
+ return (
+
+
Submit
+
Submission portal.
+
+ );
+}
diff --git a/XOM/app/transparency/audit/page.tsx b/XOM/app/transparency/audit/page.tsx
new file mode 100644
index 0000000..5fe7056
--- /dev/null
+++ b/XOM/app/transparency/audit/page.tsx
@@ -0,0 +1,8 @@
+export default function AuditPage() {
+ return (
+
+
Audit Reports
+
Audit reports and findings tracker.
+
+ );
+}
diff --git a/XOM/app/transparency/data-protection/page.tsx b/XOM/app/transparency/data-protection/page.tsx
new file mode 100644
index 0000000..b2454b3
--- /dev/null
+++ b/XOM/app/transparency/data-protection/page.tsx
@@ -0,0 +1,8 @@
+export default function DataProtectionPage() {
+ return (
+
+
Data Protection and Records
+
Records retention and data protection.
+
+ );
+}
diff --git a/XOM/app/transparency/ethics/page.tsx b/XOM/app/transparency/ethics/page.tsx
new file mode 100644
index 0000000..ff5b47d
--- /dev/null
+++ b/XOM/app/transparency/ethics/page.tsx
@@ -0,0 +1,8 @@
+export default function EthicsPage() {
+ return (
+
+
Ethics and Conduct
+
Ethics and conduct policies.
+
+ );
+}
diff --git a/XOM/app/transparency/page.tsx b/XOM/app/transparency/page.tsx
new file mode 100644
index 0000000..f676261
--- /dev/null
+++ b/XOM/app/transparency/page.tsx
@@ -0,0 +1,8 @@
+export default function TransparencyPage() {
+ return (
+
+
Transparency
+
Audit, ethics, whistleblower, sanctions, and data protection.
+
+ );
+}
diff --git a/XOM/app/transparency/sanctions/page.tsx b/XOM/app/transparency/sanctions/page.tsx
new file mode 100644
index 0000000..adf23fe
--- /dev/null
+++ b/XOM/app/transparency/sanctions/page.tsx
@@ -0,0 +1,8 @@
+export default function SanctionsPage() {
+ return (
+
+
Sanctions and Restricted Parties
+
Eligibility and restricted parties.
+
+ );
+}
diff --git a/XOM/app/transparency/whistleblower/page.tsx b/XOM/app/transparency/whistleblower/page.tsx
new file mode 100644
index 0000000..5d9a692
--- /dev/null
+++ b/XOM/app/transparency/whistleblower/page.tsx
@@ -0,0 +1,8 @@
+export default function WhistleblowerPage() {
+ return (
+
+
Whistleblower Intake
+
Secure anonymous reporting.
+
+ );
+}
diff --git a/XOM/components/layout/Footer.tsx b/XOM/components/layout/Footer.tsx
new file mode 100644
index 0000000..7f98572
--- /dev/null
+++ b/XOM/components/layout/Footer.tsx
@@ -0,0 +1,48 @@
+import Link from "next/link";
+import { navItems } from "@/lib/nav-config";
+
+const footerLinks = [
+ { label: "About", href: "/about" },
+ { label: "Documents", href: "/documents" },
+ { label: "Transparency", href: "/transparency" },
+ { label: "Contact", href: "/contact" },
+ { label: "Regional Offices", href: "/regions" },
+];
+
+function flatNavItems(items: typeof navItems): { label: string; href: string }[] {
+ const out: { label: string; href: string }[] = [];
+ for (const item of items) {
+ if (item.children) {
+ for (const c of item.children) out.push({ label: c.label, href: c.href });
+ } else {
+ out.push({ label: item.label, href: item.href });
+ }
+ }
+ return out;
+}
+
+export function Footer() {
+ const flat = flatNavItems(navItems);
+ const keyLinks = footerLinks.length ? footerLinks : flat.slice(0, 6);
+
+ return (
+
+ );
+}
diff --git a/XOM/components/layout/Header.tsx b/XOM/components/layout/Header.tsx
new file mode 100644
index 0000000..f73eb44
--- /dev/null
+++ b/XOM/components/layout/Header.tsx
@@ -0,0 +1,58 @@
+"use client";
+
+import Link from "next/link";
+import { useState } from "react";
+import { navItems } from "@/lib/nav-config";
+import { NavDropdown } from "./NavDropdown";
+import { MobileNav } from "./MobileNav";
+
+export function Header() {
+ const [mobileOpen, setMobileOpen] = useState(false);
+
+ return (
+
+
+
+ XOM
+
+
+
+
+ Sign in
+
+
+
+
+ setMobileOpen(false)} />
+
+ );
+}
diff --git a/XOM/components/layout/MobileNav.tsx b/XOM/components/layout/MobileNav.tsx
new file mode 100644
index 0000000..6b94745
--- /dev/null
+++ b/XOM/components/layout/MobileNav.tsx
@@ -0,0 +1,57 @@
+"use client";
+
+import Link from "next/link";
+import type { NavItem } from "@public-web-portals/shared";
+
+export function MobileNav({
+ items,
+ open,
+ onClose,
+}: {
+ items: NavItem[];
+ open: boolean;
+ onClose: () => void;
+}) {
+ if (!open) return null;
+
+ return (
+
+ );
+}
diff --git a/XOM/components/layout/NavDropdown.tsx b/XOM/components/layout/NavDropdown.tsx
new file mode 100644
index 0000000..d9c6b1b
--- /dev/null
+++ b/XOM/components/layout/NavDropdown.tsx
@@ -0,0 +1,57 @@
+"use client";
+
+import Link from "next/link";
+import { useState, useRef, useEffect } from "react";
+import type { NavItem } from "@public-web-portals/shared";
+
+export function NavDropdown({ item }: { item: NavItem }) {
+ const [open, setOpen] = useState(false);
+ const ref = useRef(null);
+
+ useEffect(() => {
+ function handleClickOutside(event: MouseEvent) {
+ if (ref.current && !ref.current.contains(event.target as Node)) setOpen(false);
+ }
+ document.addEventListener("mousedown", handleClickOutside);
+ return () => document.removeEventListener("mousedown", handleClickOutside);
+ }, []);
+
+ return (
+
+
+
+
+ );
+}
diff --git a/XOM/lib/auth.ts b/XOM/lib/auth.ts
new file mode 100644
index 0000000..1077579
--- /dev/null
+++ b/XOM/lib/auth.ts
@@ -0,0 +1,10 @@
+import type { SessionOrNull } from "@public-web-portals/shared";
+
+/**
+ * Placeholder session. Replace with OIDC/OAuth 2.0 when identity provider is configured.
+ * TECH_POLICIES: use httpOnly cookies / secure token storage.
+ */
+export async function getSession(): Promise {
+ // TODO: read session from cookie or header (e.g. NextAuth, OIDC)
+ return null;
+}
diff --git a/XOM/lib/nav-config.ts b/XOM/lib/nav-config.ts
new file mode 100644
index 0000000..2722689
--- /dev/null
+++ b/XOM/lib/nav-config.ts
@@ -0,0 +1,4 @@
+import { getNavForPortal } from "@public-web-portals/shared";
+
+export const portalId = "XOM" as const;
+export const navItems = getNavForPortal(portalId);
diff --git a/XOM/lib/rbac.ts b/XOM/lib/rbac.ts
new file mode 100644
index 0000000..75a5b51
--- /dev/null
+++ b/XOM/lib/rbac.ts
@@ -0,0 +1,66 @@
+import type { Role } from "@public-web-portals/shared";
+
+/** Route prefixes that require any authenticated role */
+const protectedPrefixes = [
+ "/dashboard",
+ "/submit",
+ "/apply",
+ "/report",
+ "/request",
+ "/membership/renewals",
+];
+
+/** Route prefixes that require admin role */
+const adminOnlyPrefixes = ["/dashboard/admin"];
+
+/** Routes that are always public (no auth) */
+const publicPaths = [
+ "/",
+ "/about",
+ "/governance",
+ "/leadership",
+ "/org-chart",
+ "/departments",
+ "/programs",
+ "/membership",
+ "/accreditation",
+ "/documents",
+ "/standards",
+ "/news",
+ "/publications",
+ "/contact",
+ "/regions",
+ "/transparency",
+ "/login",
+ "/logout",
+];
+
+function pathIsPublic(pathname: string): boolean {
+ if (publicPaths.includes(pathname)) return true;
+ if (pathname.startsWith("/transparency/")) return true;
+ return false;
+}
+
+function pathIsProtected(pathname: string): boolean {
+ return protectedPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
+}
+
+function pathIsAdminOnly(pathname: string): boolean {
+ return adminOnlyPrefixes.some((p) => pathname === p || pathname.startsWith(p + "/"));
+}
+
+export function canAccess(pathname: string, role: Role | null): boolean {
+ if (pathIsPublic(pathname)) return true;
+ if (role == null) return false;
+ if (pathIsAdminOnly(pathname)) return role === "admin";
+ if (pathIsProtected(pathname)) return true;
+ return false;
+}
+
+export function requiresAuth(pathname: string): boolean {
+ return pathIsProtected(pathname);
+}
+
+export function requiresAdmin(pathname: string): boolean {
+ return pathIsAdminOnly(pathname);
+}
diff --git a/XOM/middleware.ts b/XOM/middleware.ts
new file mode 100644
index 0000000..a1e26cd
--- /dev/null
+++ b/XOM/middleware.ts
@@ -0,0 +1,39 @@
+import { NextResponse } from "next/server";
+import type { NextRequest } from "next/server";
+import { canAccess, requiresAuth, requiresAdmin } from "./lib/rbac";
+import type { Role } from "@public-web-portals/shared";
+
+const LOGIN = "/login";
+
+function getRoleFromCookie(request: NextRequest): Role | null {
+ const role = request.cookies.get("portal-role")?.value;
+ if (!role) return null;
+ const valid: Role[] = ["member", "judge", "clerk", "diplomat", "donor", "staff", "admin"];
+ return valid.includes(role as Role) ? (role as Role) : null;
+}
+
+export function middleware(request: NextRequest) {
+ const pathname = request.nextUrl.pathname;
+ const role = getRoleFromCookie(request);
+
+ if (requiresAdmin(pathname) && role !== "admin") {
+ return NextResponse.redirect(new URL("/dashboard", request.url));
+ }
+
+ if (requiresAuth(pathname)) {
+ if (role == null) {
+ const url = new URL(LOGIN, request.url);
+ url.searchParams.set("returnUrl", pathname);
+ return NextResponse.redirect(url);
+ }
+ if (!canAccess(pathname, role)) {
+ return NextResponse.redirect(new URL("/dashboard", request.url));
+ }
+ }
+
+ return NextResponse.next();
+}
+
+export const config = {
+ matcher: ["/((?!_next/static|_next/image|favicon.ico|api).*)"],
+};
diff --git a/XOM/next-env.d.ts b/XOM/next-env.d.ts
new file mode 100644
index 0000000..40c3d68
--- /dev/null
+++ b/XOM/next-env.d.ts
@@ -0,0 +1,5 @@
+///
+///
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
diff --git a/XOM/next.config.js b/XOM/next.config.js
new file mode 100644
index 0000000..d0d6b18
--- /dev/null
+++ b/XOM/next.config.js
@@ -0,0 +1,32 @@
+/** @type { import('next').NextConfig } */
+const nextConfig = {
+ transpilePackages: ["@public-web-portals/shared"],
+ async headers() {
+ return [
+ {
+ source: "/:path*",
+ headers: [
+ { key: "X-Frame-Options", value: "DENY" },
+ { key: "X-Content-Type-Options", value: "nosniff" },
+ { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
+ {
+ key: "Content-Security-Policy",
+ value: [
+ "default-src 'self'",
+ "script-src 'self'",
+ "style-src 'self' 'unsafe-inline'",
+ "img-src 'self' data: https:",
+ "font-src 'self'",
+ "connect-src 'self'",
+ "frame-ancestors 'none'",
+ "base-uri 'self'",
+ "form-action 'self'",
+ ].join("; "),
+ },
+ ],
+ },
+ ];
+ },
+};
+
+module.exports = nextConfig;
diff --git a/XOM/package.json b/XOM/package.json
new file mode 100644
index 0000000..0a34560
--- /dev/null
+++ b/XOM/package.json
@@ -0,0 +1,32 @@
+{
+ "name": "portal-xom",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev --port 3000",
+ "build": "next build",
+ "start": "next start --port 3000",
+ "lint": "eslint . --max-warnings 0 --config ../.eslintrc.cjs",
+ "typecheck": "tsc --noEmit"
+ },
+ "dependencies": {
+ "@public-web-portals/shared": "workspace:*",
+ "next": "^14.2.0",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "@types/node": "^20.10.0",
+ "@types/react": "^18.2.0",
+ "@types/react-dom": "^18.2.0",
+ "autoprefixer": "^10.4.0",
+ "eslint": "^8.56.0",
+ "eslint-config-next": "^14.2.0",
+ "postcss": "^8.4.0",
+ "tailwindcss": "^3.4.0",
+ "typescript": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+}
diff --git a/XOM/postcss.config.js b/XOM/postcss.config.js
new file mode 100644
index 0000000..12a703d
--- /dev/null
+++ b/XOM/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/XOM/tailwind.config.ts b/XOM/tailwind.config.ts
new file mode 100644
index 0000000..aae1628
--- /dev/null
+++ b/XOM/tailwind.config.ts
@@ -0,0 +1,15 @@
+import type { Config } from "tailwindcss";
+import { designTokens } from "@public-web-portals/shared";
+
+const config: Config = {
+ content: [
+ "./app/**/*.{js,ts,jsx,tsx,mdx}",
+ "./components/**/*.{js,ts,jsx,tsx,mdx}",
+ ],
+ theme: {
+ extend: designTokens as Record,
+ },
+ plugins: [],
+};
+
+export default config;
diff --git a/XOM/tsconfig.json b/XOM/tsconfig.json
new file mode 100644
index 0000000..cd32290
--- /dev/null
+++ b/XOM/tsconfig.json
@@ -0,0 +1,30 @@
+{
+ "extends": "../tsconfig.base.json",
+ "compilerOptions": {
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "jsx": "preserve",
+ "noEmit": true,
+ "incremental": true,
+ "paths": {
+ "@/*": [
+ "./*"
+ ]
+ },
+ "allowJs": true
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..e42b31f
--- /dev/null
+++ b/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "public-web-portals",
+ "private": true,
+ "description": "Root for governmental body web portals — shared configs and policies only",
+ "scripts": {
+ "lint": "eslint . --max-warnings 0",
+ "format": "prettier --write .",
+ "format:check": "prettier --check ."
+ },
+ "devDependencies": {
+ "eslint": "^8.56.0",
+ "eslint-config-prettier": "^9.1.0",
+ "prettier": "^3.2.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ },
+ "packageManager": "pnpm@8.15.0"
+}
diff --git a/packages/shared/package.json b/packages/shared/package.json
new file mode 100644
index 0000000..cdb804c
--- /dev/null
+++ b/packages/shared/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "@public-web-portals/shared",
+ "version": "0.1.0",
+ "private": true,
+ "type": "module",
+ "main": "./src/index.ts",
+ "types": "./src/index.ts",
+ "exports": {
+ ".": {
+ "types": "./src/index.ts",
+ "import": "./src/index.ts",
+ "require": "./src/index.ts"
+ }
+ },
+ "scripts": {},
+ "devDependencies": {
+ "typescript": "^5.3.0"
+ },
+ "files": [
+ "src"
+ ]
+}
diff --git a/packages/shared/src/design-tokens.ts b/packages/shared/src/design-tokens.ts
new file mode 100644
index 0000000..0f46feb
--- /dev/null
+++ b/packages/shared/src/design-tokens.ts
@@ -0,0 +1,54 @@
+/**
+ * Design tokens for Tailwind. Merge this into each portal's tailwind.config.
+ * TECH_STACK: shared design tokens (colors, spacing, typography).
+ */
+
+export const designTokens = {
+ colors: {
+ primary: {
+ 50: "#eff6ff",
+ 100: "#dbeafe",
+ 200: "#bfdbfe",
+ 300: "#93c5fd",
+ 400: "#60a5fa",
+ 500: "#3b82f6",
+ 600: "#2563eb",
+ 700: "#1d4ed8",
+ 800: "#1e40af",
+ 900: "#1e3a8a",
+ 950: "#172554",
+ },
+ neutral: {
+ 50: "#fafafa",
+ 100: "#f4f4f5",
+ 200: "#e4e4e7",
+ 300: "#d4d4d8",
+ 400: "#a1a1aa",
+ 500: "#71717a",
+ 600: "#52525b",
+ 700: "#3f3f46",
+ 800: "#27272a",
+ 900: "#18181b",
+ 950: "#09090b",
+ },
+ },
+ fontFamily: {
+ sans: ["var(--font-geist-sans)", "system-ui", "sans-serif"] as string[],
+ mono: ["var(--font-geist-mono)", "monospace"] as string[],
+ },
+ fontSize: {
+ xs: ["0.75rem", { lineHeight: "1rem" }],
+ sm: ["0.875rem", { lineHeight: "1.25rem" }],
+ base: ["1rem", { lineHeight: "1.5rem" }],
+ lg: ["1.125rem", { lineHeight: "1.75rem" }],
+ xl: ["1.25rem", { lineHeight: "1.75rem" }],
+ "2xl": ["1.5rem", { lineHeight: "2rem" }],
+ "3xl": ["1.875rem", { lineHeight: "2.25rem" }],
+ "4xl": ["2.25rem", { lineHeight: "2.5rem" }],
+ },
+ spacing: {
+ "18": "4.5rem",
+ "88": "22rem",
+ "128": "32rem",
+ },
+};
diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts
new file mode 100644
index 0000000..5893eac
--- /dev/null
+++ b/packages/shared/src/index.ts
@@ -0,0 +1,8 @@
+export type { Role, User, Session, SessionOrNull } from "./types";
+export type { NavItem, PortalId } from "./nav";
+export {
+ baseNavItems,
+ getEntityNavAddons,
+ getNavForPortal,
+} from "./nav";
+export { designTokens } from "./design-tokens";
diff --git a/packages/shared/src/nav.ts b/packages/shared/src/nav.ts
new file mode 100644
index 0000000..b98cda6
--- /dev/null
+++ b/packages/shared/src/nav.ts
@@ -0,0 +1,133 @@
+/**
+ * Nav item type and base nav config for all portals.
+ * PORTAL_NAVIGATION §2, §3, §5.
+ */
+
+export interface NavItem {
+ href: string;
+ label: string;
+ children?: NavItem[];
+}
+
+export const baseNavItems: NavItem[] = [
+ {
+ label: "About",
+ href: "/about",
+ children: [
+ { label: "Mandate", href: "/about" },
+ { label: "Governance", href: "/governance" },
+ { label: "Leadership", href: "/leadership" },
+ { label: "Org Chart", href: "/org-chart" },
+ ],
+ },
+ {
+ label: "Departments & Programs",
+ href: "/departments",
+ children: [
+ { label: "Departments", href: "/departments" },
+ { label: "Programs", href: "/programs" },
+ ],
+ },
+ {
+ label: "Membership",
+ href: "/membership",
+ children: [
+ { label: "Accreditation", href: "/accreditation" },
+ { label: "Directory", href: "/membership" },
+ { label: "Digital ID", href: "/membership" },
+ { label: "Onboarding", href: "/apply" },
+ ],
+ },
+ {
+ label: "Documents",
+ href: "/documents",
+ children: [
+ { label: "Standards", href: "/standards" },
+ { label: "Directives", href: "/documents" },
+ ],
+ },
+ { label: "News & Publications", href: "/news" },
+ {
+ label: "Portals",
+ href: "/submit",
+ children: [
+ { label: "Submit", href: "/submit" },
+ { label: "Apply", href: "/apply" },
+ { label: "Report", href: "/report" },
+ { label: "Request", href: "/request" },
+ ],
+ },
+ {
+ label: "Transparency",
+ href: "/transparency",
+ children: [
+ { label: "Audit", href: "/transparency/audit" },
+ { label: "Ethics", href: "/transparency/ethics" },
+ { label: "Whistleblower", href: "/transparency/whistleblower" },
+ { label: "Sanctions", href: "/transparency/sanctions" },
+ { label: "Data Protection", href: "/transparency/data-protection" },
+ ],
+ },
+ {
+ label: "Contact",
+ href: "/contact",
+ children: [
+ { label: "General", href: "/contact" },
+ { label: "Regional Offices", href: "/regions" },
+ ],
+ },
+];
+
+export type PortalId = "DBIS" | "ICCC" | "OMNL" | "XOM";
+
+/** Entity-specific nav add-ons per PORTAL_NAVIGATION §5 */
+export function getEntityNavAddons(portal: PortalId): NavItem[] {
+ switch (portal) {
+ case "DBIS":
+ return [
+ { label: "Financial Bulletins", href: "/documents/bulletins" },
+ { label: "Monetary Operations", href: "/departments/monetary-operations" },
+ ];
+ case "ICCC":
+ return [
+ { label: "Case Law", href: "/case-law" },
+ { label: "Registry", href: "/registry" },
+ { label: "Chambers", href: "/chambers" },
+ { label: "Judgments", href: "/judgments" },
+ ];
+ case "OMNL":
+ return [
+ { label: "Programs & Impact", href: "/programs" },
+ { label: "Standards", href: "/documents/standards" },
+ { label: "Cyber Resilience", href: "/departments/cyber-resilience" },
+ ];
+ case "XOM":
+ return [
+ { label: "Programs & Impact", href: "/programs" },
+ { label: "Donors", href: "/donors" },
+ { label: "Get Involved", href: "/get-involved" },
+ { label: "Hospitaller Services", href: "/departments/hospitaller-services" },
+ ];
+ default:
+ return [];
+ }
+}
+
+/** Full nav for a portal: base + entity add-ons merged into Documents/Departments where relevant */
+export function getNavForPortal(portal: PortalId): NavItem[] {
+ const addons = getEntityNavAddons(portal);
+ const docAddons = addons.filter((a) => a.href.startsWith("/documents") || a.href.startsWith("/standards"));
+ const deptAddons = addons.filter((a) => a.href.startsWith("/departments"));
+ const restAddons = addons.filter(
+ (a) => !a.href.startsWith("/documents") && !a.href.startsWith("/departments") && !a.href.startsWith("/standards")
+ );
+
+ const result = baseNavItems.map((item) => {
+ if (item.href === "/documents" && docAddons.length > 0)
+ return { ...item, children: [...(item.children ?? []), ...docAddons] };
+ if (item.label === "Departments & Programs" && deptAddons.length > 0)
+ return { ...item, children: [...(item.children ?? []), ...deptAddons] };
+ return { ...item, children: item.children ? [...item.children] : undefined };
+ });
+ return restAddons.length > 0 ? [...result, ...restAddons] : result;
+}
diff --git a/packages/shared/src/types.ts b/packages/shared/src/types.ts
new file mode 100644
index 0000000..fc417f6
--- /dev/null
+++ b/packages/shared/src/types.ts
@@ -0,0 +1,28 @@
+/**
+ * Role and session types for RBAC across all portals.
+ * Aligned with PORTAL_NAVIGATION §4.
+ */
+
+export type Role =
+ | "public"
+ | "member"
+ | "judge"
+ | "clerk"
+ | "diplomat"
+ | "donor"
+ | "staff"
+ | "admin";
+
+export interface User {
+ id: string;
+ email: string;
+ name: string | null;
+ role: Role;
+}
+
+export interface Session {
+ user: User;
+ expiresAt: number;
+}
+
+export type SessionOrNull = Session | null;
diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json
new file mode 100644
index 0000000..792172f
--- /dev/null
+++ b/packages/shared/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "./dist",
+ "rootDir": "./src"
+ },
+ "include": ["src"]
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..93e08ea
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,3510 @@
+lockfileVersion: '6.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ devDependencies:
+ eslint:
+ specifier: ^8.56.0
+ version: 8.57.1
+ eslint-config-prettier:
+ specifier: ^9.1.0
+ version: 9.1.2(eslint@8.57.1)
+ prettier:
+ specifier: ^3.2.0
+ version: 3.8.1
+
+ DBIS:
+ dependencies:
+ '@public-web-portals/shared':
+ specifier: workspace:*
+ version: link:../packages/shared
+ next:
+ specifier: ^14.2.0
+ version: 14.2.35(react-dom@18.3.1)(react@18.3.1)
+ react:
+ specifier: ^18.2.0
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.3.1(react@18.3.1)
+ devDependencies:
+ '@types/node':
+ specifier: ^20.10.0
+ version: 20.19.33
+ '@types/react':
+ specifier: ^18.2.0
+ version: 18.3.28
+ '@types/react-dom':
+ specifier: ^18.2.0
+ version: 18.3.7(@types/react@18.3.28)
+ autoprefixer:
+ specifier: ^10.4.0
+ version: 10.4.24(postcss@8.5.6)
+ eslint:
+ specifier: ^8.56.0
+ version: 8.57.1
+ eslint-config-next:
+ specifier: ^14.2.0
+ version: 14.2.35(eslint@8.57.1)(typescript@5.9.3)
+ postcss:
+ specifier: ^8.4.0
+ version: 8.5.6
+ tailwindcss:
+ specifier: ^3.4.0
+ version: 3.4.19
+ typescript:
+ specifier: ^5.3.0
+ version: 5.9.3
+
+ ICCC:
+ dependencies:
+ '@public-web-portals/shared':
+ specifier: workspace:*
+ version: link:../packages/shared
+ next:
+ specifier: ^14.2.0
+ version: 14.2.35(react-dom@18.3.1)(react@18.3.1)
+ react:
+ specifier: ^18.2.0
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.3.1(react@18.3.1)
+ devDependencies:
+ '@types/node':
+ specifier: ^20.10.0
+ version: 20.19.33
+ '@types/react':
+ specifier: ^18.2.0
+ version: 18.3.28
+ '@types/react-dom':
+ specifier: ^18.2.0
+ version: 18.3.7(@types/react@18.3.28)
+ autoprefixer:
+ specifier: ^10.4.0
+ version: 10.4.24(postcss@8.5.6)
+ eslint:
+ specifier: ^8.56.0
+ version: 8.57.1
+ eslint-config-next:
+ specifier: ^14.2.0
+ version: 14.2.35(eslint@8.57.1)(typescript@5.9.3)
+ postcss:
+ specifier: ^8.4.0
+ version: 8.5.6
+ tailwindcss:
+ specifier: ^3.4.0
+ version: 3.4.19
+ typescript:
+ specifier: ^5.3.0
+ version: 5.9.3
+
+ OMNL:
+ dependencies:
+ '@public-web-portals/shared':
+ specifier: workspace:*
+ version: link:../packages/shared
+ next:
+ specifier: ^14.2.0
+ version: 14.2.35(react-dom@18.3.1)(react@18.3.1)
+ react:
+ specifier: ^18.2.0
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.3.1(react@18.3.1)
+ devDependencies:
+ '@types/node':
+ specifier: ^20.10.0
+ version: 20.19.33
+ '@types/react':
+ specifier: ^18.2.0
+ version: 18.3.28
+ '@types/react-dom':
+ specifier: ^18.2.0
+ version: 18.3.7(@types/react@18.3.28)
+ autoprefixer:
+ specifier: ^10.4.0
+ version: 10.4.24(postcss@8.5.6)
+ eslint:
+ specifier: ^8.56.0
+ version: 8.57.1
+ eslint-config-next:
+ specifier: ^14.2.0
+ version: 14.2.35(eslint@8.57.1)(typescript@5.9.3)
+ postcss:
+ specifier: ^8.4.0
+ version: 8.5.6
+ tailwindcss:
+ specifier: ^3.4.0
+ version: 3.4.19
+ typescript:
+ specifier: ^5.3.0
+ version: 5.9.3
+
+ XOM:
+ dependencies:
+ '@public-web-portals/shared':
+ specifier: workspace:*
+ version: link:../packages/shared
+ next:
+ specifier: ^14.2.0
+ version: 14.2.35(react-dom@18.3.1)(react@18.3.1)
+ react:
+ specifier: ^18.2.0
+ version: 18.3.1
+ react-dom:
+ specifier: ^18.2.0
+ version: 18.3.1(react@18.3.1)
+ devDependencies:
+ '@types/node':
+ specifier: ^20.10.0
+ version: 20.19.33
+ '@types/react':
+ specifier: ^18.2.0
+ version: 18.3.28
+ '@types/react-dom':
+ specifier: ^18.2.0
+ version: 18.3.7(@types/react@18.3.28)
+ autoprefixer:
+ specifier: ^10.4.0
+ version: 10.4.24(postcss@8.5.6)
+ eslint:
+ specifier: ^8.56.0
+ version: 8.57.1
+ eslint-config-next:
+ specifier: ^14.2.0
+ version: 14.2.35(eslint@8.57.1)(typescript@5.9.3)
+ postcss:
+ specifier: ^8.4.0
+ version: 8.5.6
+ tailwindcss:
+ specifier: ^3.4.0
+ version: 3.4.19
+ typescript:
+ specifier: ^5.3.0
+ version: 5.9.3
+
+ packages/shared:
+ devDependencies:
+ typescript:
+ specifier: ^5.3.0
+ version: 5.9.3
+
+packages:
+
+ /@alloc/quick-lru@5.2.0:
+ resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /@emnapi/core@1.8.1:
+ resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==}
+ requiresBuild: true
+ dependencies:
+ '@emnapi/wasi-threads': 1.1.0
+ tslib: 2.8.1
+ dev: true
+ optional: true
+
+ /@emnapi/runtime@1.8.1:
+ resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==}
+ requiresBuild: true
+ dependencies:
+ tslib: 2.8.1
+ dev: true
+ optional: true
+
+ /@emnapi/wasi-threads@1.1.0:
+ resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}
+ requiresBuild: true
+ dependencies:
+ tslib: 2.8.1
+ dev: true
+ optional: true
+
+ /@eslint-community/eslint-utils@4.9.1(eslint@8.57.1):
+ resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+ dependencies:
+ eslint: 8.57.1
+ eslint-visitor-keys: 3.4.3
+ dev: true
+
+ /@eslint-community/regexpp@4.12.2:
+ resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==}
+ engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+ dev: true
+
+ /@eslint/eslintrc@2.1.4:
+ resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ ajv: 6.12.6
+ debug: 4.4.3
+ espree: 9.6.1
+ globals: 13.24.0
+ ignore: 5.3.2
+ import-fresh: 3.3.1
+ js-yaml: 4.1.1
+ minimatch: 3.1.2
+ strip-json-comments: 3.1.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@eslint/js@8.57.1:
+ resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
+ /@humanwhocodes/config-array@0.13.0:
+ resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==}
+ engines: {node: '>=10.10.0'}
+ deprecated: Use @eslint/config-array instead
+ dependencies:
+ '@humanwhocodes/object-schema': 2.0.3
+ debug: 4.4.3
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@humanwhocodes/module-importer@1.0.1:
+ resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
+ engines: {node: '>=12.22'}
+ dev: true
+
+ /@humanwhocodes/object-schema@2.0.3:
+ resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
+ deprecated: Use @eslint/object-schema instead
+ dev: true
+
+ /@isaacs/cliui@8.0.2:
+ resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==}
+ engines: {node: '>=12'}
+ dependencies:
+ string-width: 5.1.2
+ string-width-cjs: /string-width@4.2.3
+ strip-ansi: 7.1.2
+ strip-ansi-cjs: /strip-ansi@6.0.1
+ wrap-ansi: 8.1.0
+ wrap-ansi-cjs: /wrap-ansi@7.0.0
+ dev: true
+
+ /@jridgewell/gen-mapping@0.3.13:
+ resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+ '@jridgewell/trace-mapping': 0.3.31
+ dev: true
+
+ /@jridgewell/resolve-uri@3.1.2:
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+ dev: true
+
+ /@jridgewell/sourcemap-codec@1.5.5:
+ resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+ dev: true
+
+ /@jridgewell/trace-mapping@0.3.31:
+ resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.5.5
+ dev: true
+
+ /@napi-rs/wasm-runtime@0.2.12:
+ resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
+ requiresBuild: true
+ dependencies:
+ '@emnapi/core': 1.8.1
+ '@emnapi/runtime': 1.8.1
+ '@tybys/wasm-util': 0.10.1
+ dev: true
+ optional: true
+
+ /@next/env@14.2.35:
+ resolution: {integrity: sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==}
+ dev: false
+
+ /@next/eslint-plugin-next@14.2.35:
+ resolution: {integrity: sha512-Jw9A3ICz2183qSsqwi7fgq4SBPiNfmOLmTPXKvlnzstUwyvBrtySiY+8RXJweNAs9KThb1+bYhZh9XWcNOr2zQ==}
+ dependencies:
+ glob: 10.3.10
+ dev: true
+
+ /@next/swc-darwin-arm64@14.2.33:
+ resolution: {integrity: sha512-HqYnb6pxlsshoSTubdXKu15g3iivcbsMXg4bYpjL2iS/V6aQot+iyF4BUc2qA/J/n55YtvE4PHMKWBKGCF/+wA==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-darwin-x64@14.2.33:
+ resolution: {integrity: sha512-8HGBeAE5rX3jzKvF593XTTFg3gxeU4f+UWnswa6JPhzaR6+zblO5+fjltJWIZc4aUalqTclvN2QtTC37LxvZAA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-linux-arm64-gnu@14.2.33:
+ resolution: {integrity: sha512-JXMBka6lNNmqbkvcTtaX8Gu5by9547bukHQvPoLe9VRBx1gHwzf5tdt4AaezW85HAB3pikcvyqBToRTDA4DeLw==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-linux-arm64-musl@14.2.33:
+ resolution: {integrity: sha512-Bm+QulsAItD/x6Ih8wGIMfRJy4G73tu1HJsrccPW6AfqdZd0Sfm5Imhgkgq2+kly065rYMnCOxTBvmvFY1BKfg==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-linux-x64-gnu@14.2.33:
+ resolution: {integrity: sha512-FnFn+ZBgsVMbGDsTqo8zsnRzydvsGV8vfiWwUo1LD8FTmPTdV+otGSWKc4LJec0oSexFnCYVO4hX8P8qQKaSlg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-linux-x64-musl@14.2.33:
+ resolution: {integrity: sha512-345tsIWMzoXaQndUTDv1qypDRiebFxGYx9pYkhwY4hBRaOLt8UGfiWKr9FSSHs25dFIf8ZqIFaPdy5MljdoawA==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-win32-arm64-msvc@14.2.33:
+ resolution: {integrity: sha512-nscpt0G6UCTkrT2ppnJnFsYbPDQwmum4GNXYTeoTIdsmMydSKFz9Iny2jpaRupTb+Wl298+Rh82WKzt9LCcqSQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-win32-ia32-msvc@14.2.33:
+ resolution: {integrity: sha512-pc9LpGNKhJ0dXQhZ5QMmYxtARwwmWLpeocFmVG5Z0DzWq5Uf0izcI8tLc+qOpqxO1PWqZ5A7J1blrUIKrIFc7Q==}
+ engines: {node: '>= 10'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@next/swc-win32-x64-msvc@14.2.33:
+ resolution: {integrity: sha512-nOjfZMy8B94MdisuzZo9/57xuFVLHJaDj5e/xrduJp9CV2/HrfxTRH2fbyLe+K9QT41WBLUd4iXX3R7jBp0EUg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@nodelib/fs.scandir@2.1.5:
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+ dev: true
+
+ /@nodelib/fs.stat@2.0.5:
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /@nodelib/fs.walk@1.2.8:
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.20.1
+ dev: true
+
+ /@nolyfill/is-core-module@1.0.39:
+ resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
+ engines: {node: '>=12.4.0'}
+ dev: true
+
+ /@pkgjs/parseargs@0.11.0:
+ resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
+ engines: {node: '>=14'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rtsao/scc@1.1.0:
+ resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
+ dev: true
+
+ /@rushstack/eslint-patch@1.15.0:
+ resolution: {integrity: sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==}
+ dev: true
+
+ /@swc/counter@0.1.3:
+ resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
+ dev: false
+
+ /@swc/helpers@0.5.5:
+ resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==}
+ dependencies:
+ '@swc/counter': 0.1.3
+ tslib: 2.8.1
+ dev: false
+
+ /@tybys/wasm-util@0.10.1:
+ resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
+ requiresBuild: true
+ dependencies:
+ tslib: 2.8.1
+ dev: true
+ optional: true
+
+ /@types/json5@0.0.29:
+ resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
+ dev: true
+
+ /@types/node@20.19.33:
+ resolution: {integrity: sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw==}
+ dependencies:
+ undici-types: 6.21.0
+ dev: true
+
+ /@types/prop-types@15.7.15:
+ resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==}
+ dev: true
+
+ /@types/react-dom@18.3.7(@types/react@18.3.28):
+ resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==}
+ peerDependencies:
+ '@types/react': ^18.0.0
+ dependencies:
+ '@types/react': 18.3.28
+ dev: true
+
+ /@types/react@18.3.28:
+ resolution: {integrity: sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==}
+ dependencies:
+ '@types/prop-types': 15.7.15
+ csstype: 3.2.3
+ dev: true
+
+ /@typescript-eslint/eslint-plugin@8.55.0(@typescript-eslint/parser@8.55.0)(eslint@8.57.1)(typescript@5.9.3):
+ resolution: {integrity: sha512-1y/MVSz0NglV1ijHC8OT49mPJ4qhPYjiK08YUQVbIOyu+5k862LKUHFkpKHWu//zmr7hDR2rhwUm6gnCGNmGBQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ '@typescript-eslint/parser': ^8.55.0
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+ dependencies:
+ '@eslint-community/regexpp': 4.12.2
+ '@typescript-eslint/parser': 8.55.0(eslint@8.57.1)(typescript@5.9.3)
+ '@typescript-eslint/scope-manager': 8.55.0
+ '@typescript-eslint/type-utils': 8.55.0(eslint@8.57.1)(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.55.0(eslint@8.57.1)(typescript@5.9.3)
+ '@typescript-eslint/visitor-keys': 8.55.0
+ eslint: 8.57.1
+ ignore: 7.0.5
+ natural-compare: 1.4.0
+ ts-api-utils: 2.4.0(typescript@5.9.3)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/parser@8.55.0(eslint@8.57.1)(typescript@5.9.3):
+ resolution: {integrity: sha512-4z2nCSBfVIMnbuu8uinj+f0o4qOeggYJLbjpPHka3KH1om7e+H9yLKTYgksTaHcGco+NClhhY2vyO3HsMH1RGw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+ dependencies:
+ '@typescript-eslint/scope-manager': 8.55.0
+ '@typescript-eslint/types': 8.55.0
+ '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.9.3)
+ '@typescript-eslint/visitor-keys': 8.55.0
+ debug: 4.4.3
+ eslint: 8.57.1
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/project-service@8.55.0(typescript@5.9.3):
+ resolution: {integrity: sha512-zRcVVPFUYWa3kNnjaZGXSu3xkKV1zXy8M4nO/pElzQhFweb7PPtluDLQtKArEOGmjXoRjnUZ29NjOiF0eCDkcQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+ dependencies:
+ '@typescript-eslint/tsconfig-utils': 8.55.0(typescript@5.9.3)
+ '@typescript-eslint/types': 8.55.0
+ debug: 4.4.3
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/scope-manager@8.55.0:
+ resolution: {integrity: sha512-fVu5Omrd3jeqeQLiB9f1YsuK/iHFOwb04bCtY4BSCLgjNbOD33ZdV6KyEqplHr+IlpgT0QTZ/iJ+wT7hvTx49Q==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ dependencies:
+ '@typescript-eslint/types': 8.55.0
+ '@typescript-eslint/visitor-keys': 8.55.0
+ dev: true
+
+ /@typescript-eslint/tsconfig-utils@8.55.0(typescript@5.9.3):
+ resolution: {integrity: sha512-1R9cXqY7RQd7WuqSN47PK9EDpgFUK3VqdmbYrvWJZYDd0cavROGn+74ktWBlmJ13NXUQKlZ/iAEQHI/V0kKe0Q==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+ dependencies:
+ typescript: 5.9.3
+ dev: true
+
+ /@typescript-eslint/type-utils@8.55.0(eslint@8.57.1)(typescript@5.9.3):
+ resolution: {integrity: sha512-x1iH2unH4qAt6I37I2CGlsNs+B9WGxurP2uyZLRz6UJoZWDBx9cJL1xVN/FiOmHEONEg6RIufdvyT0TEYIgC5g==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+ dependencies:
+ '@typescript-eslint/types': 8.55.0
+ '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.55.0(eslint@8.57.1)(typescript@5.9.3)
+ debug: 4.4.3
+ eslint: 8.57.1
+ ts-api-utils: 2.4.0(typescript@5.9.3)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/types@8.55.0:
+ resolution: {integrity: sha512-ujT0Je8GI5BJWi+/mMoR0wxwVEQaxM+pi30xuMiJETlX80OPovb2p9E8ss87gnSVtYXtJoU9U1Cowcr6w2FE0w==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ dev: true
+
+ /@typescript-eslint/typescript-estree@8.55.0(typescript@5.9.3):
+ resolution: {integrity: sha512-EwrH67bSWdx/3aRQhCoxDaHM+CrZjotc2UCCpEDVqfCE+7OjKAGWNY2HsCSTEVvWH2clYQK8pdeLp42EVs+xQw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+ dependencies:
+ '@typescript-eslint/project-service': 8.55.0(typescript@5.9.3)
+ '@typescript-eslint/tsconfig-utils': 8.55.0(typescript@5.9.3)
+ '@typescript-eslint/types': 8.55.0
+ '@typescript-eslint/visitor-keys': 8.55.0
+ debug: 4.4.3
+ minimatch: 9.0.5
+ semver: 7.7.4
+ tinyglobby: 0.2.15
+ ts-api-utils: 2.4.0(typescript@5.9.3)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/utils@8.55.0(eslint@8.57.1)(typescript@5.9.3):
+ resolution: {integrity: sha512-BqZEsnPGdYpgyEIkDC1BadNY8oMwckftxBT+C8W0g1iKPdeqKZBtTfnvcq0nf60u7MkjFO8RBvpRGZBPw4L2ow==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+ dependencies:
+ '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1)
+ '@typescript-eslint/scope-manager': 8.55.0
+ '@typescript-eslint/types': 8.55.0
+ '@typescript-eslint/typescript-estree': 8.55.0(typescript@5.9.3)
+ eslint: 8.57.1
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@typescript-eslint/visitor-keys@8.55.0:
+ resolution: {integrity: sha512-AxNRwEie8Nn4eFS1FzDMJWIISMGoXMb037sgCBJ3UR6o0fQTzr2tqN9WT+DkWJPhIdQCfV7T6D387566VtnCJA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ dependencies:
+ '@typescript-eslint/types': 8.55.0
+ eslint-visitor-keys: 4.2.1
+ dev: true
+
+ /@ungap/structured-clone@1.3.0:
+ resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
+ dev: true
+
+ /@unrs/resolver-binding-android-arm-eabi@1.11.1:
+ resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-android-arm64@1.11.1:
+ resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-darwin-arm64@1.11.1:
+ resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-darwin-x64@1.11.1:
+ resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-freebsd-x64@1.11.1:
+ resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1:
+ resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-linux-arm-musleabihf@1.11.1:
+ resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-linux-arm64-gnu@1.11.1:
+ resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-linux-arm64-musl@1.11.1:
+ resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-linux-ppc64-gnu@1.11.1:
+ resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-linux-riscv64-gnu@1.11.1:
+ resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-linux-riscv64-musl@1.11.1:
+ resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-linux-s390x-gnu@1.11.1:
+ resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-linux-x64-gnu@1.11.1:
+ resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-linux-x64-musl@1.11.1:
+ resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-wasm32-wasi@1.11.1:
+ resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+ requiresBuild: true
+ dependencies:
+ '@napi-rs/wasm-runtime': 0.2.12
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-win32-arm64-msvc@1.11.1:
+ resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-win32-ia32-msvc@1.11.1:
+ resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@unrs/resolver-binding-win32-x64-msvc@1.11.1:
+ resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /acorn-jsx@5.3.2(acorn@8.15.0):
+ resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+ dependencies:
+ acorn: 8.15.0
+ dev: true
+
+ /acorn@8.15.0:
+ resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+ dev: true
+
+ /ajv@6.12.6:
+ resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-json-stable-stringify: 2.1.0
+ json-schema-traverse: 0.4.1
+ uri-js: 4.4.1
+ dev: true
+
+ /ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /ansi-regex@6.2.2:
+ resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+ dependencies:
+ color-convert: 2.0.1
+ dev: true
+
+ /ansi-styles@6.2.3:
+ resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /any-promise@1.3.0:
+ resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+ dev: true
+
+ /anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+ dev: true
+
+ /arg@5.0.2:
+ resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+ dev: true
+
+ /argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+ dev: true
+
+ /aria-query@5.3.2:
+ resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /array-buffer-byte-length@1.0.2:
+ resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ is-array-buffer: 3.0.5
+ dev: true
+
+ /array-includes@3.1.9:
+ resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ is-string: 1.1.1
+ math-intrinsics: 1.1.0
+ dev: true
+
+ /array.prototype.findlast@1.2.5:
+ resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ es-shim-unscopables: 1.1.0
+ dev: true
+
+ /array.prototype.findlastindex@1.2.6:
+ resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ es-shim-unscopables: 1.1.0
+ dev: true
+
+ /array.prototype.flat@1.3.3:
+ resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-shim-unscopables: 1.1.0
+ dev: true
+
+ /array.prototype.flatmap@1.3.3:
+ resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-shim-unscopables: 1.1.0
+ dev: true
+
+ /array.prototype.tosorted@1.1.4:
+ resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-errors: 1.3.0
+ es-shim-unscopables: 1.1.0
+ dev: true
+
+ /arraybuffer.prototype.slice@1.0.4:
+ resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ array-buffer-byte-length: 1.0.2
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ is-array-buffer: 3.0.5
+ dev: true
+
+ /ast-types-flow@0.0.8:
+ resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
+ dev: true
+
+ /async-function@1.0.0:
+ resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /autoprefixer@10.4.24(postcss@8.5.6):
+ resolution: {integrity: sha512-uHZg7N9ULTVbutaIsDRoUkoS8/h3bdsmVJYZ5l3wv8Cp/6UIIoRDm90hZ+BwxUj/hGBEzLxdHNSKuFpn8WOyZw==}
+ engines: {node: ^10 || ^12 || >=14}
+ hasBin: true
+ peerDependencies:
+ postcss: ^8.1.0
+ dependencies:
+ browserslist: 4.28.1
+ caniuse-lite: 1.0.30001769
+ fraction.js: 5.3.4
+ picocolors: 1.1.1
+ postcss: 8.5.6
+ postcss-value-parser: 4.2.0
+ dev: true
+
+ /available-typed-arrays@1.0.7:
+ resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ possible-typed-array-names: 1.1.0
+ dev: true
+
+ /axe-core@4.11.1:
+ resolution: {integrity: sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /axobject-query@4.1.0:
+ resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ dev: true
+
+ /baseline-browser-mapping@2.9.19:
+ resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==}
+ hasBin: true
+ dev: true
+
+ /binary-extensions@2.3.0:
+ resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /brace-expansion@1.1.12:
+ resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+ dev: true
+
+ /brace-expansion@2.0.2:
+ resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
+ dependencies:
+ balanced-match: 1.0.2
+ dev: true
+
+ /braces@3.0.3:
+ resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+ engines: {node: '>=8'}
+ dependencies:
+ fill-range: 7.1.1
+ dev: true
+
+ /browserslist@4.28.1:
+ resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+ dependencies:
+ baseline-browser-mapping: 2.9.19
+ caniuse-lite: 1.0.30001769
+ electron-to-chromium: 1.5.286
+ node-releases: 2.0.27
+ update-browserslist-db: 1.2.3(browserslist@4.28.1)
+ dev: true
+
+ /busboy@1.6.0:
+ resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
+ engines: {node: '>=10.16.0'}
+ dependencies:
+ streamsearch: 1.1.0
+ dev: false
+
+ /call-bind-apply-helpers@1.0.2:
+ resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+ dev: true
+
+ /call-bind@1.0.8:
+ resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==}
+ engines: {node: '>= 0.4'}
+ 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
+ dev: true
+
+ /call-bound@1.0.4:
+ resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ get-intrinsic: 1.3.0
+ dev: true
+
+ /callsites@3.1.0:
+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /camelcase-css@2.0.1:
+ resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /caniuse-lite@1.0.30001769:
+ resolution: {integrity: sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==}
+
+ /chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+ dev: true
+
+ /chokidar@3.6.0:
+ resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
+ engines: {node: '>= 8.10.0'}
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.3
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.3
+ dev: true
+
+ /client-only@0.0.1:
+ resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
+ dev: false
+
+ /color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+ dependencies:
+ color-name: 1.1.4
+ dev: true
+
+ /color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ dev: true
+
+ /commander@4.1.1:
+ resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+ dev: true
+
+ /cross-spawn@7.0.6:
+ resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
+ engines: {node: '>= 8'}
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+ dev: true
+
+ /cssesc@3.0.0:
+ resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+ engines: {node: '>=4'}
+ hasBin: true
+ dev: true
+
+ /csstype@3.2.3:
+ resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+ dev: true
+
+ /damerau-levenshtein@1.0.8:
+ resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
+ dev: true
+
+ /data-view-buffer@1.0.2:
+ resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-data-view: 1.0.2
+ dev: true
+
+ /data-view-byte-length@1.0.2:
+ resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-data-view: 1.0.2
+ dev: true
+
+ /data-view-byte-offset@1.0.1:
+ resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-data-view: 1.0.2
+ dev: true
+
+ /debug@3.2.7:
+ resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.3
+ dev: true
+
+ /debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.3
+ dev: true
+
+ /deep-is@0.1.4:
+ resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+ dev: true
+
+ /define-data-property@1.1.4:
+ resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ gopd: 1.2.0
+ dev: true
+
+ /define-properties@1.2.1:
+ resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.4
+ has-property-descriptors: 1.0.2
+ object-keys: 1.1.1
+ dev: true
+
+ /didyoumean@1.2.2:
+ resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
+ dev: true
+
+ /dlv@1.1.3:
+ resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
+ dev: true
+
+ /doctrine@2.1.0:
+ resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ esutils: 2.0.3
+ dev: true
+
+ /doctrine@3.0.0:
+ resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ esutils: 2.0.3
+ dev: true
+
+ /dunder-proto@1.0.1:
+ resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-errors: 1.3.0
+ gopd: 1.2.0
+ dev: true
+
+ /eastasianwidth@0.2.0:
+ resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+ dev: true
+
+ /electron-to-chromium@1.5.286:
+ resolution: {integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==}
+ dev: true
+
+ /emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+ dev: true
+
+ /emoji-regex@9.2.2:
+ resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+ dev: true
+
+ /es-abstract@1.24.1:
+ resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==}
+ engines: {node: '>= 0.4'}
+ 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.20
+ dev: true
+
+ /es-define-property@1.0.1:
+ resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /es-errors@1.3.0:
+ resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /es-iterator-helpers@1.2.2:
+ resolution: {integrity: sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ 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
+ safe-array-concat: 1.1.3
+ dev: true
+
+ /es-object-atoms@1.1.1:
+ resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ es-errors: 1.3.0
+ dev: true
+
+ /es-set-tostringtag@2.1.0:
+ resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ has-tostringtag: 1.0.2
+ hasown: 2.0.2
+ dev: true
+
+ /es-shim-unscopables@1.1.0:
+ resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ hasown: 2.0.2
+ dev: true
+
+ /es-to-primitive@1.3.0:
+ resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ is-callable: 1.2.7
+ is-date-object: 1.1.0
+ is-symbol: 1.1.1
+ dev: true
+
+ /escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /eslint-config-next@14.2.35(eslint@8.57.1)(typescript@5.9.3):
+ resolution: {integrity: sha512-BpLsv01UisH193WyT/1lpHqq5iJ/Orfz9h/NOOlAmTUq4GY349PextQ62K4XpnaM9supeiEn3TaOTeQO07gURg==}
+ peerDependencies:
+ eslint: ^7.23.0 || ^8.0.0
+ typescript: '>=3.3.1'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@next/eslint-plugin-next': 14.2.35
+ '@rushstack/eslint-patch': 1.15.0
+ '@typescript-eslint/eslint-plugin': 8.55.0(@typescript-eslint/parser@8.55.0)(eslint@8.57.1)(typescript@5.9.3)
+ '@typescript-eslint/parser': 8.55.0(eslint@8.57.1)(typescript@5.9.3)
+ eslint: 8.57.1
+ eslint-import-resolver-node: 0.3.9
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.1)
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.55.0)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1)
+ eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1)
+ eslint-plugin-react: 7.37.5(eslint@8.57.1)
+ eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.57.1)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - eslint-import-resolver-webpack
+ - eslint-plugin-import-x
+ - supports-color
+ dev: true
+
+ /eslint-config-prettier@9.1.2(eslint@8.57.1):
+ resolution: {integrity: sha512-iI1f+D2ViGn+uvv5HuHVUamg8ll4tN+JRHGc6IJi4TP9Kl976C57fzPXgseXNs8v0iA8aSJpHsTWjDb9QJamGQ==}
+ hasBin: true
+ peerDependencies:
+ eslint: '>=7.0.0'
+ dependencies:
+ eslint: 8.57.1
+ dev: true
+
+ /eslint-import-resolver-node@0.3.9:
+ resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
+ dependencies:
+ debug: 3.2.7
+ is-core-module: 2.16.1
+ resolve: 1.22.11
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.1):
+ resolution: {integrity: sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ eslint: '*'
+ eslint-plugin-import: '*'
+ eslint-plugin-import-x: '*'
+ peerDependenciesMeta:
+ eslint-plugin-import:
+ optional: true
+ eslint-plugin-import-x:
+ optional: true
+ dependencies:
+ '@nolyfill/is-core-module': 1.0.39
+ debug: 4.4.3
+ eslint: 8.57.1
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.55.0)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1)
+ get-tsconfig: 4.13.6
+ is-bun-module: 2.0.0
+ stable-hash: 0.0.5
+ tinyglobby: 0.2.15
+ unrs-resolver: 1.11.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /eslint-module-utils@2.12.1(@typescript-eslint/parser@8.55.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1):
+ resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ '@typescript-eslint/parser': '*'
+ eslint: '*'
+ eslint-import-resolver-node: '*'
+ eslint-import-resolver-typescript: '*'
+ eslint-import-resolver-webpack: '*'
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
+ eslint:
+ optional: true
+ eslint-import-resolver-node:
+ optional: true
+ eslint-import-resolver-typescript:
+ optional: true
+ eslint-import-resolver-webpack:
+ optional: true
+ dependencies:
+ '@typescript-eslint/parser': 8.55.0(eslint@8.57.1)(typescript@5.9.3)
+ debug: 3.2.7
+ eslint: 8.57.1
+ eslint-import-resolver-node: 0.3.9
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.1)
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.55.0)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1):
+ resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ '@typescript-eslint/parser': '*'
+ eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
+ dependencies:
+ '@rtsao/scc': 1.1.0
+ '@typescript-eslint/parser': 8.55.0(eslint@8.57.1)(typescript@5.9.3)
+ 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: 8.57.1
+ eslint-import-resolver-node: 0.3.9
+ eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.55.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.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
+ transitivePeerDependencies:
+ - eslint-import-resolver-typescript
+ - eslint-import-resolver-webpack
+ - supports-color
+ dev: true
+
+ /eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.1):
+ resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9
+ dependencies:
+ aria-query: 5.3.2
+ array-includes: 3.1.9
+ array.prototype.flatmap: 1.3.3
+ ast-types-flow: 0.0.8
+ axe-core: 4.11.1
+ axobject-query: 4.1.0
+ damerau-levenshtein: 1.0.8
+ emoji-regex: 9.2.2
+ eslint: 8.57.1
+ 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.1.0
+ string.prototype.includes: 2.0.1
+ dev: true
+
+ /eslint-plugin-react-hooks@5.0.0-canary-7118f5dd7-20230705(eslint@8.57.1):
+ resolution: {integrity: sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
+ dependencies:
+ eslint: 8.57.1
+ dev: true
+
+ /eslint-plugin-react@7.37.5(eslint@8.57.1):
+ resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7
+ dependencies:
+ array-includes: 3.1.9
+ 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.2
+ eslint: 8.57.1
+ estraverse: 5.3.0
+ hasown: 2.0.2
+ jsx-ast-utils: 3.3.5
+ 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
+ dev: true
+
+ /eslint-scope@7.2.2:
+ resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 5.3.0
+ dev: true
+
+ /eslint-visitor-keys@3.4.3:
+ resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dev: true
+
+ /eslint-visitor-keys@4.2.1:
+ resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ dev: true
+
+ /eslint@8.57.1:
+ resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
+ hasBin: true
+ dependencies:
+ '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1)
+ '@eslint-community/regexpp': 4.12.2
+ '@eslint/eslintrc': 2.1.4
+ '@eslint/js': 8.57.1
+ '@humanwhocodes/config-array': 0.13.0
+ '@humanwhocodes/module-importer': 1.0.1
+ '@nodelib/fs.walk': 1.2.8
+ '@ungap/structured-clone': 1.3.0
+ ajv: 6.12.6
+ chalk: 4.1.2
+ cross-spawn: 7.0.6
+ debug: 4.4.3
+ doctrine: 3.0.0
+ escape-string-regexp: 4.0.0
+ eslint-scope: 7.2.2
+ eslint-visitor-keys: 3.4.3
+ espree: 9.6.1
+ esquery: 1.7.0
+ esutils: 2.0.3
+ fast-deep-equal: 3.1.3
+ file-entry-cache: 6.0.1
+ find-up: 5.0.0
+ glob-parent: 6.0.2
+ globals: 13.24.0
+ graphemer: 1.4.0
+ ignore: 5.3.2
+ imurmurhash: 0.1.4
+ is-glob: 4.0.3
+ is-path-inside: 3.0.3
+ js-yaml: 4.1.1
+ json-stable-stringify-without-jsonify: 1.0.1
+ levn: 0.4.1
+ lodash.merge: 4.6.2
+ minimatch: 3.1.2
+ natural-compare: 1.4.0
+ optionator: 0.9.4
+ strip-ansi: 6.0.1
+ text-table: 0.2.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /espree@9.6.1:
+ resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ dependencies:
+ acorn: 8.15.0
+ acorn-jsx: 5.3.2(acorn@8.15.0)
+ eslint-visitor-keys: 3.4.3
+ dev: true
+
+ /esquery@1.7.0:
+ resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==}
+ engines: {node: '>=0.10'}
+ dependencies:
+ estraverse: 5.3.0
+ dev: true
+
+ /esrecurse@4.3.0:
+ resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+ engines: {node: '>=4.0'}
+ dependencies:
+ estraverse: 5.3.0
+ dev: true
+
+ /estraverse@5.3.0:
+ resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+ engines: {node: '>=4.0'}
+ dev: true
+
+ /esutils@2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+ dev: true
+
+ /fast-glob@3.3.3:
+ resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
+ engines: {node: '>=8.6.0'}
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.8
+ dev: true
+
+ /fast-json-stable-stringify@2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+ dev: true
+
+ /fast-levenshtein@2.0.6:
+ resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+ dev: true
+
+ /fastq@1.20.1:
+ resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
+ dependencies:
+ reusify: 1.1.0
+ dev: true
+
+ /fdir@6.5.0(picomatch@4.0.3):
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+ dependencies:
+ picomatch: 4.0.3
+ dev: true
+
+ /file-entry-cache@6.0.1:
+ resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
+ engines: {node: ^10.12.0 || >=12.0.0}
+ dependencies:
+ flat-cache: 3.2.0
+ dev: true
+
+ /fill-range@7.1.1:
+ resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+ engines: {node: '>=8'}
+ dependencies:
+ to-regex-range: 5.0.1
+ dev: true
+
+ /find-up@5.0.0:
+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+ engines: {node: '>=10'}
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+ dev: true
+
+ /flat-cache@3.2.0:
+ resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
+ engines: {node: ^10.12.0 || >=12.0.0}
+ dependencies:
+ flatted: 3.3.3
+ keyv: 4.5.4
+ rimraf: 3.0.2
+ dev: true
+
+ /flatted@3.3.3:
+ resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
+ dev: true
+
+ /for-each@0.3.5:
+ resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ is-callable: 1.2.7
+ dev: true
+
+ /foreground-child@3.3.1:
+ resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
+ engines: {node: '>=14'}
+ dependencies:
+ cross-spawn: 7.0.6
+ signal-exit: 4.1.0
+ dev: true
+
+ /fraction.js@5.3.4:
+ resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
+ dev: true
+
+ /fs.realpath@1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+ dev: true
+
+ /fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+ dev: true
+
+ /function.prototype.name@1.1.8:
+ resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ functions-have-names: 1.2.3
+ hasown: 2.0.2
+ is-callable: 1.2.7
+ dev: true
+
+ /functions-have-names@1.2.3:
+ resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+ dev: true
+
+ /generator-function@2.0.1:
+ resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /get-intrinsic@1.3.0:
+ resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
+ engines: {node: '>= 0.4'}
+ 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
+ dev: true
+
+ /get-proto@1.0.1:
+ resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ dunder-proto: 1.0.1
+ es-object-atoms: 1.1.1
+ dev: true
+
+ /get-symbol-description@1.1.0:
+ resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ dev: true
+
+ /get-tsconfig@4.13.6:
+ resolution: {integrity: sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==}
+ dependencies:
+ resolve-pkg-maps: 1.0.0
+ dev: true
+
+ /glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
+ /glob-parent@6.0.2:
+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+ engines: {node: '>=10.13.0'}
+ dependencies:
+ is-glob: 4.0.3
+ dev: true
+
+ /glob@10.3.10:
+ resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
+ hasBin: true
+ dependencies:
+ foreground-child: 3.3.1
+ jackspeak: 2.3.6
+ minimatch: 9.0.5
+ minipass: 7.1.2
+ path-scurry: 1.11.1
+ dev: true
+
+ /glob@7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+ dev: true
+
+ /globals@13.24.0:
+ resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
+ engines: {node: '>=8'}
+ dependencies:
+ type-fest: 0.20.2
+ dev: true
+
+ /globalthis@1.0.4:
+ resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-properties: 1.2.1
+ gopd: 1.2.0
+ dev: true
+
+ /gopd@1.2.0:
+ resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+ dev: false
+
+ /graphemer@1.4.0:
+ resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+ dev: true
+
+ /has-bigints@1.1.0:
+ resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /has-property-descriptors@1.0.2:
+ resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
+ dependencies:
+ es-define-property: 1.0.1
+ dev: true
+
+ /has-proto@1.2.0:
+ resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ dunder-proto: 1.0.1
+ dev: true
+
+ /has-symbols@1.1.0:
+ resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /has-tostringtag@1.0.2:
+ resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-symbols: 1.1.0
+ dev: true
+
+ /hasown@2.0.2:
+ resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ function-bind: 1.1.2
+ dev: true
+
+ /ignore@5.3.2:
+ resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
+ engines: {node: '>= 4'}
+ dev: true
+
+ /ignore@7.0.5:
+ resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
+ engines: {node: '>= 4'}
+ dev: true
+
+ /import-fresh@3.3.1:
+ resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
+ engines: {node: '>=6'}
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+ dev: true
+
+ /imurmurhash@0.1.4:
+ resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+ engines: {node: '>=0.8.19'}
+ dev: true
+
+ /inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+ dev: true
+
+ /inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+ dev: true
+
+ /internal-slot@1.1.0:
+ resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ es-errors: 1.3.0
+ hasown: 2.0.2
+ side-channel: 1.1.0
+ dev: true
+
+ /is-array-buffer@3.0.5:
+ resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+ dev: true
+
+ /is-async-function@2.1.1:
+ resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ async-function: 1.0.0
+ call-bound: 1.0.4
+ get-proto: 1.0.1
+ has-tostringtag: 1.0.2
+ safe-regex-test: 1.1.0
+ dev: true
+
+ /is-bigint@1.1.0:
+ resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ has-bigints: 1.1.0
+ dev: true
+
+ /is-binary-path@2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+ dependencies:
+ binary-extensions: 2.3.0
+ dev: true
+
+ /is-boolean-object@1.2.2:
+ resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+ dev: true
+
+ /is-bun-module@2.0.0:
+ resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==}
+ dependencies:
+ semver: 7.7.4
+ dev: true
+
+ /is-callable@1.2.7:
+ resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-core-module@2.16.1:
+ resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ hasown: 2.0.2
+ dev: true
+
+ /is-data-view@1.0.2:
+ resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+ is-typed-array: 1.1.15
+ dev: true
+
+ /is-date-object@1.1.0:
+ resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+ dev: true
+
+ /is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /is-finalizationregistry@1.1.1:
+ resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ dev: true
+
+ /is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-generator-function@1.1.2:
+ resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ generator-function: 2.0.1
+ get-proto: 1.0.1
+ has-tostringtag: 1.0.2
+ safe-regex-test: 1.1.0
+ dev: true
+
+ /is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ is-extglob: 2.1.1
+ dev: true
+
+ /is-map@2.0.3:
+ resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-negative-zero@2.0.3:
+ resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-number-object@1.1.1:
+ resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+ dev: true
+
+ /is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+ dev: true
+
+ /is-path-inside@3.0.3:
+ resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-regex@1.2.1:
+ resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ gopd: 1.2.0
+ has-tostringtag: 1.0.2
+ hasown: 2.0.2
+ dev: true
+
+ /is-set@2.0.3:
+ resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-shared-array-buffer@1.0.4:
+ resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ dev: true
+
+ /is-string@1.1.1:
+ resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+ dev: true
+
+ /is-symbol@1.1.1:
+ resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ has-symbols: 1.1.0
+ safe-regex-test: 1.1.0
+ dev: true
+
+ /is-typed-array@1.1.15:
+ resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ which-typed-array: 1.1.20
+ dev: true
+
+ /is-weakmap@2.0.2:
+ resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /is-weakref@1.1.1:
+ resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ dev: true
+
+ /is-weakset@2.0.4:
+ resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+ dev: true
+
+ /isarray@2.0.5:
+ resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
+ dev: true
+
+ /isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ dev: true
+
+ /iterator.prototype@1.1.5:
+ resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.4
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ has-symbols: 1.1.0
+ set-function-name: 2.0.2
+ dev: true
+
+ /jackspeak@2.3.6:
+ resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
+ engines: {node: '>=14'}
+ dependencies:
+ '@isaacs/cliui': 8.0.2
+ optionalDependencies:
+ '@pkgjs/parseargs': 0.11.0
+ dev: true
+
+ /jiti@1.21.7:
+ resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
+ hasBin: true
+ dev: true
+
+ /js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ /js-yaml@4.1.1:
+ resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
+ hasBin: true
+ dependencies:
+ argparse: 2.0.1
+ dev: true
+
+ /json-buffer@3.0.1:
+ resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+ dev: true
+
+ /json-schema-traverse@0.4.1:
+ resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+ dev: true
+
+ /json-stable-stringify-without-jsonify@1.0.1:
+ resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+ dev: true
+
+ /json5@1.0.2:
+ resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
+ hasBin: true
+ dependencies:
+ minimist: 1.2.8
+ dev: true
+
+ /jsx-ast-utils@3.3.5:
+ resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
+ engines: {node: '>=4.0'}
+ dependencies:
+ array-includes: 3.1.9
+ array.prototype.flat: 1.3.3
+ object.assign: 4.1.7
+ object.values: 1.2.1
+ dev: true
+
+ /keyv@4.5.4:
+ resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+ dependencies:
+ json-buffer: 3.0.1
+ dev: true
+
+ /language-subtag-registry@0.3.23:
+ resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==}
+ dev: true
+
+ /language-tags@1.0.9:
+ resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==}
+ engines: {node: '>=0.10'}
+ dependencies:
+ language-subtag-registry: 0.3.23
+ dev: true
+
+ /levn@0.4.1:
+ resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ dev: true
+
+ /lilconfig@3.1.3:
+ resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
+ engines: {node: '>=14'}
+ dev: true
+
+ /lines-and-columns@1.2.4:
+ resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+ dev: true
+
+ /locate-path@6.0.0:
+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-locate: 5.0.0
+ dev: true
+
+ /lodash.merge@4.6.2:
+ resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+ dev: true
+
+ /loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+ dependencies:
+ js-tokens: 4.0.0
+
+ /lru-cache@10.4.3:
+ resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
+ dev: true
+
+ /math-intrinsics@1.1.0:
+ resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+ dev: true
+
+ /micromatch@4.0.8:
+ resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
+ engines: {node: '>=8.6'}
+ dependencies:
+ braces: 3.0.3
+ picomatch: 2.3.1
+ dev: true
+
+ /minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+ dependencies:
+ brace-expansion: 1.1.12
+ dev: true
+
+ /minimatch@9.0.5:
+ resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ dependencies:
+ brace-expansion: 2.0.2
+ dev: true
+
+ /minimist@1.2.8:
+ resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+ dev: true
+
+ /minipass@7.1.2:
+ resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ dev: true
+
+ /ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+ dev: true
+
+ /mz@2.7.0:
+ resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+ dependencies:
+ any-promise: 1.3.0
+ object-assign: 4.1.1
+ thenify-all: 1.6.0
+ dev: true
+
+ /nanoid@3.3.11:
+ resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ /napi-postinstall@0.3.4:
+ resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==}
+ engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+ hasBin: true
+ dev: true
+
+ /natural-compare@1.4.0:
+ resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+ dev: true
+
+ /next@14.2.35(react-dom@18.3.1)(react@18.3.1):
+ resolution: {integrity: sha512-KhYd2Hjt/O1/1aZVX3dCwGXM1QmOV4eNM2UTacK5gipDdPN/oHHK/4oVGy7X8GMfPMsUTUEmGlsy0EY1YGAkig==}
+ engines: {node: '>=18.17.0'}
+ hasBin: true
+ peerDependencies:
+ '@opentelemetry/api': ^1.1.0
+ '@playwright/test': ^1.41.2
+ react: ^18.2.0
+ react-dom: ^18.2.0
+ sass: ^1.3.0
+ peerDependenciesMeta:
+ '@opentelemetry/api':
+ optional: true
+ '@playwright/test':
+ optional: true
+ sass:
+ optional: true
+ dependencies:
+ '@next/env': 14.2.35
+ '@swc/helpers': 0.5.5
+ busboy: 1.6.0
+ caniuse-lite: 1.0.30001769
+ graceful-fs: 4.2.11
+ postcss: 8.4.31
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ styled-jsx: 5.1.1(react@18.3.1)
+ optionalDependencies:
+ '@next/swc-darwin-arm64': 14.2.33
+ '@next/swc-darwin-x64': 14.2.33
+ '@next/swc-linux-arm64-gnu': 14.2.33
+ '@next/swc-linux-arm64-musl': 14.2.33
+ '@next/swc-linux-x64-gnu': 14.2.33
+ '@next/swc-linux-x64-musl': 14.2.33
+ '@next/swc-win32-arm64-msvc': 14.2.33
+ '@next/swc-win32-ia32-msvc': 14.2.33
+ '@next/swc-win32-x64-msvc': 14.2.33
+ transitivePeerDependencies:
+ - '@babel/core'
+ - babel-plugin-macros
+ dev: false
+
+ /node-releases@2.0.27:
+ resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
+ dev: true
+
+ /normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /object-hash@3.0.0:
+ resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /object-inspect@1.13.4:
+ resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /object-keys@1.1.1:
+ resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /object.assign@4.1.7:
+ resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+ has-symbols: 1.1.0
+ object-keys: 1.1.1
+ dev: true
+
+ /object.entries@1.1.9:
+ resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+ dev: true
+
+ /object.fromentries@2.0.8:
+ resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-object-atoms: 1.1.1
+ dev: true
+
+ /object.groupby@1.0.3:
+ resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ dev: true
+
+ /object.values@1.2.1:
+ resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+ dev: true
+
+ /once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+ dependencies:
+ wrappy: 1.0.2
+ dev: true
+
+ /optionator@0.9.4:
+ resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ deep-is: 0.1.4
+ fast-levenshtein: 2.0.6
+ levn: 0.4.1
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ word-wrap: 1.2.5
+ dev: true
+
+ /own-keys@1.0.1:
+ resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ get-intrinsic: 1.3.0
+ object-keys: 1.1.1
+ safe-push-apply: 1.0.0
+ dev: true
+
+ /p-limit@3.1.0:
+ resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ yocto-queue: 0.1.0
+ dev: true
+
+ /p-locate@5.0.0:
+ resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+ engines: {node: '>=10'}
+ dependencies:
+ p-limit: 3.1.0
+ dev: true
+
+ /parent-module@1.0.1:
+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+ engines: {node: '>=6'}
+ dependencies:
+ callsites: 3.1.0
+ dev: true
+
+ /path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-parse@1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+ dev: true
+
+ /path-scurry@1.11.1:
+ resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==}
+ engines: {node: '>=16 || 14 >=14.18'}
+ dependencies:
+ lru-cache: 10.4.3
+ minipass: 7.1.2
+ dev: true
+
+ /picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ /picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+ dev: true
+
+ /picomatch@4.0.3:
+ resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /pify@2.3.0:
+ resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /pirates@4.0.7:
+ resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /possible-typed-array-names@1.1.0:
+ resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /postcss-import@15.1.0(postcss@8.5.6):
+ resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ postcss: ^8.0.0
+ dependencies:
+ postcss: 8.5.6
+ postcss-value-parser: 4.2.0
+ read-cache: 1.0.0
+ resolve: 1.22.11
+ dev: true
+
+ /postcss-js@4.1.0(postcss@8.5.6):
+ resolution: {integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==}
+ engines: {node: ^12 || ^14 || >= 16}
+ peerDependencies:
+ postcss: ^8.4.21
+ dependencies:
+ camelcase-css: 2.0.1
+ postcss: 8.5.6
+ dev: true
+
+ /postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6):
+ resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ jiti: '>=1.21.0'
+ postcss: '>=8.0.9'
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ jiti:
+ optional: true
+ postcss:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+ dependencies:
+ jiti: 1.21.7
+ lilconfig: 3.1.3
+ postcss: 8.5.6
+ dev: true
+
+ /postcss-nested@6.2.0(postcss@8.5.6):
+ resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==}
+ engines: {node: '>=12.0'}
+ peerDependencies:
+ postcss: ^8.2.14
+ dependencies:
+ postcss: 8.5.6
+ postcss-selector-parser: 6.1.2
+ dev: true
+
+ /postcss-selector-parser@6.1.2:
+ resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
+ engines: {node: '>=4'}
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+ dev: true
+
+ /postcss-value-parser@4.2.0:
+ resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+ dev: true
+
+ /postcss@8.4.31:
+ resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+ dev: false
+
+ /postcss@8.5.6:
+ resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+ dev: true
+
+ /prelude-ls@1.2.1:
+ resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+ engines: {node: '>= 0.8.0'}
+ dev: true
+
+ /prettier@3.8.1:
+ resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==}
+ engines: {node: '>=14'}
+ hasBin: true
+ dev: true
+
+ /prop-types@15.8.1:
+ resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+ dependencies:
+ loose-envify: 1.4.0
+ object-assign: 4.1.1
+ react-is: 16.13.1
+ dev: true
+
+ /punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+ dev: true
+
+ /react-dom@18.3.1(react@18.3.1):
+ resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
+ peerDependencies:
+ react: ^18.3.1
+ dependencies:
+ loose-envify: 1.4.0
+ react: 18.3.1
+ scheduler: 0.23.2
+ dev: false
+
+ /react-is@16.13.1:
+ resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
+ dev: true
+
+ /react@18.3.1:
+ resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ loose-envify: 1.4.0
+ dev: false
+
+ /read-cache@1.0.0:
+ resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
+ dependencies:
+ pify: 2.3.0
+ dev: true
+
+ /readdirp@3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+ dependencies:
+ picomatch: 2.3.1
+ dev: true
+
+ /reflect.getprototypeof@1.0.10:
+ resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ which-builtin-type: 1.2.1
+ dev: true
+
+ /regexp.prototype.flags@1.5.4:
+ resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
+ engines: {node: '>= 0.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
+ dev: true
+
+ /resolve-from@4.0.0:
+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /resolve-pkg-maps@1.0.0:
+ resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+ dev: true
+
+ /resolve@1.22.11:
+ resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==}
+ engines: {node: '>= 0.4'}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.16.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+ dev: true
+
+ /resolve@2.0.0-next.5:
+ resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
+ hasBin: true
+ dependencies:
+ is-core-module: 2.16.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+ dev: true
+
+ /reusify@1.1.0:
+ resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ dev: true
+
+ /rimraf@3.0.2:
+ resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+ deprecated: Rimraf versions prior to v4 are no longer supported
+ hasBin: true
+ dependencies:
+ glob: 7.2.3
+ dev: true
+
+ /run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ dependencies:
+ queue-microtask: 1.2.3
+ dev: true
+
+ /safe-array-concat@1.1.3:
+ resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
+ engines: {node: '>=0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+ has-symbols: 1.1.0
+ isarray: 2.0.5
+ dev: true
+
+ /safe-push-apply@1.0.0:
+ resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ es-errors: 1.3.0
+ isarray: 2.0.5
+ dev: true
+
+ /safe-regex-test@1.1.0:
+ resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-regex: 1.2.1
+ dev: true
+
+ /scheduler@0.23.2:
+ resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
+ dependencies:
+ loose-envify: 1.4.0
+ dev: false
+
+ /semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+ dev: true
+
+ /semver@7.7.4:
+ resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dev: true
+
+ /set-function-length@1.2.2:
+ resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.4
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+ get-intrinsic: 1.3.0
+ gopd: 1.2.0
+ has-property-descriptors: 1.0.2
+ dev: true
+
+ /set-function-name@2.0.2:
+ resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ define-data-property: 1.1.4
+ es-errors: 1.3.0
+ functions-have-names: 1.2.3
+ has-property-descriptors: 1.0.2
+ dev: true
+
+ /set-proto@1.0.0:
+ resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ dunder-proto: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ dev: true
+
+ /shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+ dependencies:
+ shebang-regex: 3.0.0
+ dev: true
+
+ /shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /side-channel-list@1.0.0:
+ resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+ dev: true
+
+ /side-channel-map@1.0.1:
+ resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+ dev: true
+
+ /side-channel-weakmap@1.0.2:
+ resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-map: 1.0.1
+ dev: true
+
+ /side-channel@1.1.0:
+ resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-list: 1.0.0
+ side-channel-map: 1.0.1
+ side-channel-weakmap: 1.0.2
+ dev: true
+
+ /signal-exit@4.1.0:
+ resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
+ engines: {node: '>=14'}
+ dev: true
+
+ /source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ /stable-hash@0.0.5:
+ resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
+ dev: true
+
+ /stop-iteration-iterator@1.1.0:
+ resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ es-errors: 1.3.0
+ internal-slot: 1.1.0
+ dev: true
+
+ /streamsearch@1.1.0:
+ resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
+ engines: {node: '>=10.0.0'}
+ dev: false
+
+ /string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+ dev: true
+
+ /string-width@5.1.2:
+ resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
+ engines: {node: '>=12'}
+ dependencies:
+ eastasianwidth: 0.2.0
+ emoji-regex: 9.2.2
+ strip-ansi: 7.1.2
+ dev: true
+
+ /string.prototype.includes@2.0.1:
+ resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ dev: true
+
+ /string.prototype.matchall@4.0.12:
+ resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ gopd: 1.2.0
+ has-symbols: 1.1.0
+ internal-slot: 1.1.0
+ regexp.prototype.flags: 1.5.4
+ set-function-name: 2.0.2
+ side-channel: 1.1.0
+ dev: true
+
+ /string.prototype.repeat@1.0.0:
+ resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==}
+ dependencies:
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ dev: true
+
+ /string.prototype.trim@1.2.10:
+ resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-data-property: 1.1.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-object-atoms: 1.1.1
+ has-property-descriptors: 1.0.2
+ dev: true
+
+ /string.prototype.trimend@1.0.9:
+ resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+ dev: true
+
+ /string.prototype.trimstart@1.0.8:
+ resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+ dev: true
+
+ /strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+ dependencies:
+ ansi-regex: 5.0.1
+ dev: true
+
+ /strip-ansi@7.1.2:
+ resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==}
+ engines: {node: '>=12'}
+ dependencies:
+ ansi-regex: 6.2.2
+ dev: true
+
+ /strip-bom@3.0.0:
+ resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /strip-json-comments@3.1.1:
+ resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /styled-jsx@5.1.1(react@18.3.1):
+ resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==}
+ engines: {node: '>= 12.0.0'}
+ peerDependencies:
+ '@babel/core': '*'
+ babel-plugin-macros: '*'
+ react: '>= 16.8.0 || 17.x.x || ^18.0.0-0'
+ peerDependenciesMeta:
+ '@babel/core':
+ optional: true
+ babel-plugin-macros:
+ optional: true
+ dependencies:
+ client-only: 0.0.1
+ react: 18.3.1
+ dev: false
+
+ /sucrase@3.35.1:
+ resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ commander: 4.1.1
+ lines-and-columns: 1.2.4
+ mz: 2.7.0
+ pirates: 4.0.7
+ tinyglobby: 0.2.15
+ ts-interface-checker: 0.1.13
+ dev: true
+
+ /supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+ dependencies:
+ has-flag: 4.0.0
+ dev: true
+
+ /supports-preserve-symlinks-flag@1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+ dev: true
+
+ /tailwindcss@3.4.19:
+ resolution: {integrity: sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+ 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.3
+ 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.5.6
+ postcss-import: 15.1.0(postcss@8.5.6)
+ postcss-js: 4.1.0(postcss@8.5.6)
+ postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6)
+ postcss-nested: 6.2.0(postcss@8.5.6)
+ postcss-selector-parser: 6.1.2
+ resolve: 1.22.11
+ sucrase: 3.35.1
+ transitivePeerDependencies:
+ - tsx
+ - yaml
+ dev: true
+
+ /text-table@0.2.0:
+ resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
+ dev: true
+
+ /thenify-all@1.6.0:
+ resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
+ engines: {node: '>=0.8'}
+ dependencies:
+ thenify: 3.3.1
+ dev: true
+
+ /thenify@3.3.1:
+ resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+ dependencies:
+ any-promise: 1.3.0
+ dev: true
+
+ /tinyglobby@0.2.15:
+ resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
+ engines: {node: '>=12.0.0'}
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ dev: true
+
+ /to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+ dependencies:
+ is-number: 7.0.0
+ dev: true
+
+ /ts-api-utils@2.4.0(typescript@5.9.3):
+ resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==}
+ engines: {node: '>=18.12'}
+ peerDependencies:
+ typescript: '>=4.8.4'
+ dependencies:
+ typescript: 5.9.3
+ dev: true
+
+ /ts-interface-checker@0.1.13:
+ resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+ dev: true
+
+ /tsconfig-paths@3.15.0:
+ resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
+ dependencies:
+ '@types/json5': 0.0.29
+ json5: 1.0.2
+ minimist: 1.2.8
+ strip-bom: 3.0.0
+ dev: true
+
+ /tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
+ /type-check@0.4.0:
+ resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ prelude-ls: 1.2.1
+ dev: true
+
+ /type-fest@0.20.2:
+ resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /typed-array-buffer@1.0.3:
+ resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-typed-array: 1.1.15
+ dev: true
+
+ /typed-array-byte-length@1.0.3:
+ resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ for-each: 0.3.5
+ gopd: 1.2.0
+ has-proto: 1.2.0
+ is-typed-array: 1.1.15
+ dev: true
+
+ /typed-array-byte-offset@1.0.4:
+ resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ available-typed-arrays: 1.0.7
+ call-bind: 1.0.8
+ for-each: 0.3.5
+ gopd: 1.2.0
+ has-proto: 1.2.0
+ is-typed-array: 1.1.15
+ reflect.getprototypeof: 1.0.10
+ dev: true
+
+ /typed-array-length@1.0.7:
+ resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bind: 1.0.8
+ 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
+ dev: true
+
+ /typescript@5.9.3:
+ resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+ dev: true
+
+ /unbox-primitive@1.1.0:
+ resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ has-bigints: 1.1.0
+ has-symbols: 1.1.0
+ which-boxed-primitive: 1.1.1
+ dev: true
+
+ /undici-types@6.21.0:
+ resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+ dev: true
+
+ /unrs-resolver@1.11.1:
+ resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==}
+ requiresBuild: true
+ dependencies:
+ napi-postinstall: 0.3.4
+ optionalDependencies:
+ '@unrs/resolver-binding-android-arm-eabi': 1.11.1
+ '@unrs/resolver-binding-android-arm64': 1.11.1
+ '@unrs/resolver-binding-darwin-arm64': 1.11.1
+ '@unrs/resolver-binding-darwin-x64': 1.11.1
+ '@unrs/resolver-binding-freebsd-x64': 1.11.1
+ '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1
+ '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1
+ '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-arm64-musl': 1.11.1
+ '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1
+ '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-x64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-x64-musl': 1.11.1
+ '@unrs/resolver-binding-wasm32-wasi': 1.11.1
+ '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1
+ '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1
+ '@unrs/resolver-binding-win32-x64-msvc': 1.11.1
+ dev: true
+
+ /update-browserslist-db@1.2.3(browserslist@4.28.1):
+ resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+ dependencies:
+ browserslist: 4.28.1
+ escalade: 3.2.0
+ picocolors: 1.1.1
+ dev: true
+
+ /uri-js@4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+ dependencies:
+ punycode: 2.3.1
+ dev: true
+
+ /util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+ dev: true
+
+ /which-boxed-primitive@1.1.1:
+ resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ is-bigint: 1.1.0
+ is-boolean-object: 1.2.2
+ is-number-object: 1.1.1
+ is-string: 1.1.1
+ is-symbol: 1.1.1
+ dev: true
+
+ /which-builtin-type@1.2.1:
+ resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ call-bound: 1.0.4
+ function.prototype.name: 1.1.8
+ has-tostringtag: 1.0.2
+ is-async-function: 2.1.1
+ is-date-object: 1.1.0
+ is-finalizationregistry: 1.1.1
+ is-generator-function: 1.1.2
+ is-regex: 1.2.1
+ is-weakref: 1.1.1
+ isarray: 2.0.5
+ which-boxed-primitive: 1.1.1
+ which-collection: 1.0.2
+ which-typed-array: 1.1.20
+ dev: true
+
+ /which-collection@1.0.2:
+ resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ is-map: 2.0.3
+ is-set: 2.0.3
+ is-weakmap: 2.0.2
+ is-weakset: 2.0.4
+ dev: true
+
+ /which-typed-array@1.1.20:
+ resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==}
+ engines: {node: '>= 0.4'}
+ dependencies:
+ available-typed-arrays: 1.0.7
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ for-each: 0.3.5
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ has-tostringtag: 1.0.2
+ dev: true
+
+ /which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+ dependencies:
+ isexe: 2.0.0
+ dev: true
+
+ /word-wrap@1.2.5:
+ resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ dev: true
+
+ /wrap-ansi@8.1.0:
+ resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ ansi-styles: 6.2.3
+ string-width: 5.1.2
+ strip-ansi: 7.1.2
+ dev: true
+
+ /wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+ dev: true
+
+ /yocto-queue@0.1.0:
+ resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+ engines: {node: '>=10'}
+ dev: true
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
new file mode 100644
index 0000000..f9b5d92
--- /dev/null
+++ b/pnpm-workspace.yaml
@@ -0,0 +1,6 @@
+packages:
+ - "packages/*"
+ - "DBIS"
+ - "ICCC"
+ - "OMNL"
+ - "XOM"
diff --git a/tsconfig.base.json b/tsconfig.base.json
new file mode 100644
index 0000000..3fdcecd
--- /dev/null
+++ b/tsconfig.base.json
@@ -0,0 +1,20 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "compilerOptions": {
+ "target": "ES2022",
+ "lib": ["dom", "dom.iterable", "ES2022"],
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "strict": true,
+ "noEmit": true,
+ "noUncheckedIndexedAccess": true,
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "exclude": ["node_modules", "**/dist", "**/.next"]
+}