diff --git a/app/account/(orderId)/orders/[id]/page.tsx b/app/account/(orderId)/orders/[id]/page.tsx
index 8868b2f2a..9d889d95d 100644
--- a/app/account/(orderId)/orders/[id]/page.tsx
+++ b/app/account/(orderId)/orders/[id]/page.tsx
@@ -1,18 +1,19 @@
 import { ArrowLeftIcon, CheckCircleIcon, TruckIcon } from '@heroicons/react/24/outline';
-import ActivateWarranty from 'components/orders/activate-warranty';
+import OrderConfirmation from 'components/orders/order-confirmation';
+import PaymentsDetails from 'components/orders/payment-details';
 import OrderSummary from 'components/orders/order-summary';
 import OrderSummaryMobile from 'components/orders/order-summary-mobile';
-import Price from 'components/price';
 import Badge from 'components/ui/badge';
-import { Card } from 'components/ui/card';
+import { Card } from 'components/ui';
 import Heading from 'components/ui/heading';
 import Label from 'components/ui/label';
 import Text from 'components/ui/text';
-import { getCustomerOrder, getOrderMetafields } from 'lib/shopify';
+import { getCustomerOrder } from 'lib/shopify';
 import { Fulfillment, Order } from 'lib/shopify/types';
 import { toPrintDate } from 'lib/utils';
 import Image from 'next/image';
 import Link from 'next/link';
+import ActivateWarranty from 'components/orders/activate-warranty';
 
 function Unfulfilled({ order }: { order: Order }) {
   // Build a map of line item IDs to quantities fulfilled
@@ -144,30 +145,6 @@ function Fulfillments({ order }: { order: Order }) {
   );
 }
 
-function PaymentsDetails({ order }: { order: Order }) {
-  return (
-    <>
-      {order.transactions.map((transaction, index) => (
-        <div key={index} className="flex items-start gap-2">
-          {/* eslint-disable-next-line @next/next/no-img-element */}
-          <img src={transaction.paymentIcon.url} alt={transaction.paymentIcon.altText} width={36} />
-          <div>
-            <Text>
-              Ending with {transaction.paymentDetails.last4} -
-              <Price
-                as="span"
-                amount={transaction.transactionAmount.amount}
-                currencyCode={transaction.transactionAmount.currencyCode}
-              />
-            </Text>
-            <Label>{toPrintDate(transaction.processedAt)}</Label>
-          </div>
-        </div>
-      ))}
-    </>
-  );
-}
-
 function OrderDetails({ order }: { order: Order }) {
   return (
     <Card className="flex flex-col gap-4">
@@ -228,10 +205,7 @@ function OrderDetails({ order }: { order: Order }) {
 }
 
 export default async function OrderPage({ params }: { params: { id: string } }) {
-  const [order, orderMetafields] = await Promise.all([
-    getCustomerOrder(params.id),
-    getOrderMetafields(params.id)
-  ]);
+  const order = await getCustomerOrder(params.id);
 
   return (
     <>
@@ -247,7 +221,10 @@ export default async function OrderPage({ params }: { params: { id: string } })
               <Label>Confirmed {toPrintDate(order.processedAt)}</Label>
             </div>
           </div>
-          <ActivateWarranty order={order} orderMetafields={orderMetafields} />
+          <div className="flex items-start gap-2">
+            <OrderConfirmation order={order} />
+            <ActivateWarranty order={order} />
+          </div>
         </div>
         <div className="flex items-start gap-6">
           <div className="flex flex-1 flex-col gap-6">
diff --git a/app/account/(orders)/page.tsx b/app/account/(orders)/page.tsx
index 03fa41fd7..3e833f54f 100644
--- a/app/account/(orders)/page.tsx
+++ b/app/account/(orders)/page.tsx
@@ -1,18 +1,19 @@
 import { InformationCircleIcon } from '@heroicons/react/24/outline';
-import ActivateWarranty from 'components/orders/activate-warranty';
 import MobileOrderActions from 'components/orders/mobile-order-actions';
 import OrdersHeader from 'components/orders/orders-header';
 import Price from 'components/price';
-import { getCustomerOrders, getOrdersMetafields } from 'lib/shopify';
-import { toPrintDate } from 'lib/utils';
+import { getCustomerOrders } from 'lib/shopify';
+import { isBeforeToday, toPrintDate } from 'lib/utils';
 import Image from 'next/image';
 import Link from 'next/link';
+import { Button } from 'components/ui';
+import dynamic from 'next/dynamic';
+
+const OrderConfirmation = dynamic(() => import('components/orders/order-confirmation'));
+const ActivateWarranty = dynamic(() => import('components/orders/activate-warranty'));
 
 export default async function AccountPage() {
-  const [orders, ordersMetafields] = await Promise.all([
-    getCustomerOrders(),
-    getOrdersMetafields()
-  ]);
+  const orders = await getCustomerOrders();
 
   return (
     <div className="py-5 sm:py-10">
@@ -54,17 +55,19 @@ export default async function AccountPage() {
                     )}
                   </dl>
 
-                  <MobileOrderActions order={order} orderMetafields={ordersMetafields[order.id]} />
+                  <MobileOrderActions order={order} />
 
                   <div className="hidden lg:col-span-2 lg:flex lg:items-center lg:justify-end lg:space-x-4">
-                    <Link
-                      href={`/account/orders/${order.normalizedId}`}
-                      className="flex items-center justify-center rounded-md border border-gray-300 bg-white px-2.5 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
-                    >
-                      <span>View Order</span>
-                      <span className="sr-only">{order.normalizedId}</span>
+                    <Link href={`/account/orders/${order.normalizedId}`} passHref legacyBehavior>
+                      <Button as="a">
+                        View Order
+                        <span className="sr-only">{order.normalizedId}</span>
+                      </Button>
                     </Link>
-                    <ActivateWarranty order={order} orderMetafields={ordersMetafields[order.id]} />
+                    {!isBeforeToday(order?.warrantyActivationDeadline?.value) && (
+                      <ActivateWarranty order={order} />
+                    )}
+                    {!order.orderConfirmation && <OrderConfirmation order={order} />}
                   </div>
                 </div>
 
diff --git a/app/api/orders/confirmation/route.ts b/app/api/orders/confirmation/route.ts
new file mode 100644
index 000000000..7fe51f09e
--- /dev/null
+++ b/app/api/orders/confirmation/route.ts
@@ -0,0 +1,7 @@
+import { getOrderConfirmationContent } from 'lib/shopify';
+
+export async function GET() {
+  const data = await getOrderConfirmationContent();
+
+  return Response.json({ ...data });
+}
diff --git a/components/filters/hompage-filters.tsx b/components/filters/hompage-filters.tsx
index 3dee1888a..9ca2d509a 100644
--- a/components/filters/hompage-filters.tsx
+++ b/components/filters/hompage-filters.tsx
@@ -1,4 +1,4 @@
-import { getMenu, getMetaobjects } from 'lib/shopify';
+import { getAllMetaobjects, getMenu } from 'lib/shopify';
 import FiltersList from './filters-list';
 
 const title: Record<string, string> = {
@@ -12,9 +12,9 @@ const title: Record<string, string> = {
 const { STORE_PREFIX } = process.env;
 
 const HomePageFilters = async () => {
-  const yearsData = getMetaobjects('make_model_year_composite');
-  const modelsData = getMetaobjects('make_model_composite');
-  const makesData = getMetaobjects('make');
+  const yearsData = getAllMetaobjects('make_model_year_composite');
+  const modelsData = getAllMetaobjects('make_model_composite');
+  const makesData = getAllMetaobjects('make');
 
   const [years, models, makes] = await Promise.all([yearsData, modelsData, makesData]);
   const menu = await getMenu('main-menu');
diff --git a/components/orders/actions.ts b/components/orders/actions.tsx
similarity index 56%
rename from components/orders/actions.ts
rename to components/orders/actions.tsx
index 4fad38bfe..becf68b23 100644
--- a/components/orders/actions.ts
+++ b/components/orders/actions.tsx
@@ -1,9 +1,16 @@
 'use server';
 
+import { renderToBuffer } from '@react-pdf/renderer';
+import OrderConfirmationPdf from 'components/orders/order-confirmation-pdf';
 import { handleUploadFile } from 'components/form/file-input/actions';
 import { TAGS } from 'lib/constants';
 import { updateOrderMetafields } from 'lib/shopify';
-import { ShopifyOrderMetafield, UpdateOrderMetafieldInput } from 'lib/shopify/types';
+import {
+  Order,
+  OrderConfirmationContent,
+  ShopifyOrderMetafield,
+  UpdateOrderMetafieldInput
+} from 'lib/shopify/types';
 import { revalidateTag } from 'next/cache';
 
 const getMetafieldValue = (
@@ -16,11 +23,7 @@ const getMetafieldValue = (
     : { ...newValue, namespace: 'custom' };
 };
 
-export const activateWarranty = async (
-  orderId: string,
-  formData: FormData,
-  orderMetafields?: ShopifyOrderMetafield
-) => {
+export const activateWarranty = async (order: Order, formData: FormData) => {
   let odometerFileId = null;
   let installationFileId = null;
   const odometerFile = formData.get('warranty_activation_odometer');
@@ -32,7 +35,7 @@ export const activateWarranty = async (
   if (installationFile) {
     installationFileId = await handleUploadFile({ file: installationFile as File });
   }
-  console.log(formData.get('warranty_activation_self_install'));
+
   // https://shopify.dev/docs/api/admin-graphql/2024-01/mutations/orderUpdate
   const rawFormData = [
     getMetafieldValue(
@@ -42,7 +45,7 @@ export const activateWarranty = async (
         value: odometerFileId,
         type: 'file_reference'
       },
-      orderMetafields
+      order
     ),
     getMetafieldValue(
       'warrantyActivationInstallation',
@@ -51,7 +54,7 @@ export const activateWarranty = async (
         value: installationFileId,
         type: 'file_reference'
       },
-      orderMetafields
+      order
     ),
     getMetafieldValue(
       'warrantyActivationSelfInstall',
@@ -60,7 +63,7 @@ export const activateWarranty = async (
         value: formData.get('warranty_activation_self_install') === 'on' ? 'true' : 'false',
         type: 'boolean'
       },
-      orderMetafields
+      order
     ),
     getMetafieldValue(
       'warrantyActivationMileage',
@@ -69,7 +72,7 @@ export const activateWarranty = async (
         value: formData.get('warranty_activation_mileage') as string | null,
         type: 'number_integer'
       },
-      orderMetafields
+      order
     ),
     getMetafieldValue(
       'warrantyActivationVIN',
@@ -78,13 +81,76 @@ export const activateWarranty = async (
         value: formData.get('warranty_activation_vin') as string | null,
         type: 'single_line_text_field'
       },
-      orderMetafields
+      order
     )
   ];
 
   try {
     await updateOrderMetafields({
-      orderId,
+      orderId: order.id,
+      metafields: rawFormData
+    });
+
+    revalidateTag(TAGS.orderMetafields);
+  } catch (error) {
+    console.log('activateWarranty action', error);
+  }
+};
+
+async function generateOrderConfirmationPDF(
+  order: Order,
+  content: OrderConfirmationContent,
+  signature1: string,
+  signature2: string,
+  signDate: string
+) {
+  return renderToBuffer(
+    <OrderConfirmationPdf
+      order={order}
+      content={content}
+      signature1={signature1}
+      signature2={signature2}
+      date={signDate}
+    />
+  );
+}
+
+type ConfirmOrderOptions = {
+  order: Order;
+  content: OrderConfirmationContent;
+  formData: FormData;
+};
+
+export const confirmOrder = async ({ order, content, formData }: ConfirmOrderOptions) => {
+  const signature1 = formData.get('signature1') as string;
+  const signature2 = formData.get('signature2') as string;
+  const signDate = formData.get('date') as string;
+
+  const pdfBuffer = await generateOrderConfirmationPDF(
+    order,
+    content,
+    signature1,
+    signature2,
+    signDate
+  );
+
+  const fileName = `${new Date().getTime()}-${order.name}-signaturePdf.pdf`;
+  const file = new File([pdfBuffer], fileName, { type: 'application/pdf' });
+
+  const confirmationPDFId = await handleUploadFile({ file });
+
+  const rawFormData = [
+    {
+      key: 'customer_confirmation',
+      value: confirmationPDFId,
+      type: 'file_reference',
+      namespace: 'custom'
+    }
+  ];
+
+  try {
+    await updateOrderMetafields({
+      orderId: order.id,
       metafields: rawFormData
     });
 
diff --git a/components/orders/activate-warranty-modal.tsx b/components/orders/activate-warranty-modal.tsx
index a06264afe..39e74ab25 100644
--- a/components/orders/activate-warranty-modal.tsx
+++ b/components/orders/activate-warranty-modal.tsx
@@ -6,23 +6,17 @@ import CheckboxField from 'components/form/checkbox-field';
 import FileInput from 'components/form/file-input';
 import Input from 'components/form/input-field';
 import LoadingDots from 'components/loading-dots';
-import { ShopifyOrderMetafield } from 'lib/shopify/types';
+import { Order } from 'lib/shopify/types';
 import { FormEventHandler, useRef, useTransition } from 'react';
 import { activateWarranty } from './actions';
 
 type ActivateWarrantyModalProps = {
   isOpen: boolean;
   onClose: () => void;
-  orderId: string;
-  orderMetafields?: ShopifyOrderMetafield;
+  order: Order;
 };
 
-function ActivateWarrantyModal({
-  onClose,
-  isOpen,
-  orderId,
-  orderMetafields
-}: ActivateWarrantyModalProps) {
+function ActivateWarrantyModal({ onClose, isOpen, order }: ActivateWarrantyModalProps) {
   const [pending, startTransition] = useTransition();
   const formRef = useRef<HTMLFormElement>(null);
 
@@ -33,7 +27,7 @@ function ActivateWarrantyModal({
     const formData = new FormData(form);
 
     startTransition(async () => {
-      await activateWarranty(orderId, formData, orderMetafields);
+      await activateWarranty(order, formData);
       form.reset();
       onClose();
     });
@@ -59,28 +53,28 @@ function ActivateWarrantyModal({
               <FileInput
                 label="Odometer"
                 name="warranty_activation_odometer"
-                fileId={orderMetafields?.warrantyActivationOdometer?.value}
+                fileId={order?.warrantyActivationOdometer?.value}
               />
               <FileInput
                 label="Installation Receipt"
                 name="warranty_activation_installation"
-                fileId={orderMetafields?.warrantyActivationInstallation?.value}
+                fileId={order?.warrantyActivationInstallation?.value}
               />
               <CheckboxField
                 label="Self Installed"
                 name="warranty_activation_self_install"
-                defaultChecked={orderMetafields?.warrantyActivationSelfInstall?.value === 'true'}
+                defaultChecked={order?.warrantyActivationSelfInstall?.value === 'true'}
               />
               <Input
                 label="Customer Mileage"
                 name="warranty_activation_mileage"
                 type="number"
-                defaultValue={orderMetafields?.warrantyActivationMileage?.value}
+                defaultValue={order?.warrantyActivationMileage?.value}
               />
               <Input
                 label="Customer VIN"
                 name="warranty_activation_vin"
-                defaultValue={orderMetafields?.warrantyActivationVIN?.value}
+                defaultValue={order?.warrantyActivationVIN?.value}
               />
             </div>
             <div className="mt-4 flex w-full justify-end gap-4">
diff --git a/components/orders/activate-warranty.tsx b/components/orders/activate-warranty.tsx
index b98c4cac2..42afa2989 100644
--- a/components/orders/activate-warranty.tsx
+++ b/components/orders/activate-warranty.tsx
@@ -1,20 +1,20 @@
 'use client';
 
-import { Order, ShopifyOrderMetafield, WarrantyStatus } from 'lib/shopify/types';
+import { Order, WarrantyStatus } from 'lib/shopify/types';
 import { isBeforeToday } from 'lib/utils';
 import { useState } from 'react';
 import ActivateWarrantyModal from './activate-warranty-modal';
 import WarrantyActivatedBadge from './warranty-activated-badge';
+import { Button } from 'components/ui';
 
 type ActivateWarrantyModalProps = {
   order: Order;
-  orderMetafields?: ShopifyOrderMetafield;
 };
 
-const ActivateWarranty = ({ order, orderMetafields }: ActivateWarrantyModalProps) => {
+const ActivateWarranty = ({ order }: ActivateWarrantyModalProps) => {
   const [isOpen, setIsOpen] = useState(false);
-  const isWarrantyActivated = orderMetafields?.warrantyStatus?.value === WarrantyStatus.Activated;
-  const isPassDeadline = isBeforeToday(orderMetafields?.warrantyActivationDeadline?.value);
+  const isWarrantyActivated = order?.warrantyStatus?.value === WarrantyStatus.Activated;
+  const isPassDeadline = isBeforeToday(order?.warrantyActivationDeadline?.value);
 
   if (isWarrantyActivated) {
     return <WarrantyActivatedBadge />;
@@ -26,18 +26,8 @@ const ActivateWarranty = ({ order, orderMetafields }: ActivateWarrantyModalProps
 
   return (
     <>
-      <button
-        className="flex h-fit items-center justify-center rounded-md border border-gray-300 bg-white px-2.5 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
-        onClick={() => setIsOpen(true)}
-      >
-        Activate Warranty
-      </button>
-      <ActivateWarrantyModal
-        isOpen={isOpen}
-        onClose={() => setIsOpen(false)}
-        orderId={order.id}
-        orderMetafields={orderMetafields}
-      />
+      <Button onClick={() => setIsOpen(true)}>Activate Warranty</Button>
+      <ActivateWarrantyModal isOpen={isOpen} onClose={() => setIsOpen(false)} order={order} />
     </>
   );
 };
diff --git a/components/orders/mobile-order-actions.tsx b/components/orders/mobile-order-actions.tsx
index e49b01463..6df4f57c3 100644
--- a/components/orders/mobile-order-actions.tsx
+++ b/components/orders/mobile-order-actions.tsx
@@ -1,24 +1,24 @@
 'use client';
 
+import dynamic from 'next/dynamic';
 import { Button, Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react';
 import { EllipsisVerticalIcon } from '@heroicons/react/24/solid';
 import clsx from 'clsx';
-import { Order, ShopifyOrderMetafield, WarrantyStatus } from 'lib/shopify/types';
+import { Order, WarrantyStatus } from 'lib/shopify/types';
 import { isBeforeToday } from 'lib/utils';
 import Link from 'next/link';
 import { useState } from 'react';
 import ActivateWarrantyModal from './activate-warranty-modal';
 
-const MobileOrderActions = ({
-  order,
-  orderMetafields
-}: {
-  order: Order;
-  orderMetafields?: ShopifyOrderMetafield;
-}) => {
-  const [isOpen, setIsOpen] = useState(false);
-  const isWarrantyActivated = orderMetafields?.warrantyStatus?.value === WarrantyStatus.Activated;
-  const isPassDeadline = isBeforeToday(orderMetafields?.warrantyActivationDeadline?.value);
+const OrderConfirmationModal = dynamic(() => import('./order-confirmation-modal'));
+
+const MobileOrderActions = ({ order }: { order: Order }) => {
+  const [isWarrantyOpen, setIsWarrantyOpen] = useState(false);
+  const [isOrderConfirmaionOpen, setIsOrderConfirmationOpen] = useState(false);
+
+  const isWarrantyActivated = order?.warrantyStatus?.value === WarrantyStatus.Activated;
+  const isPassDeadline = isBeforeToday(order?.warrantyActivationDeadline?.value);
+  const isOrderConfirmed = order?.orderConfirmation?.value;
 
   return (
     <>
@@ -56,22 +56,43 @@ const MobileOrderActions = ({
                       focus ? 'bg-gray-100 text-gray-900' : 'text-gray-700',
                       'flex w-full px-4 py-2 text-sm'
                     )}
-                    onClick={() => setIsOpen(true)}
+                    onClick={() => setIsWarrantyOpen(true)}
                   >
                     Activate Warranty
                   </Button>
                 )}
               </MenuItem>
             )}
+            {!isOrderConfirmed && (
+              <MenuItem>
+                {({ focus }) => (
+                  <Button
+                    className={clsx(
+                      focus ? 'bg-gray-100 text-gray-900' : 'text-gray-700',
+                      'flex w-full px-4 py-2 text-sm'
+                    )}
+                    onClick={() => setIsOrderConfirmationOpen(true)}
+                  >
+                    Confirm Order
+                  </Button>
+                )}
+              </MenuItem>
+            )}
           </div>
         </MenuItems>
       </Menu>
       <ActivateWarrantyModal
-        isOpen={isOpen}
-        onClose={() => setIsOpen(false)}
-        orderId={order.id}
-        orderMetafields={orderMetafields}
+        isOpen={isWarrantyOpen}
+        onClose={() => setIsWarrantyOpen(false)}
+        order={order}
       />
+      {!isOrderConfirmed && (
+        <OrderConfirmationModal
+          isOpen={isOrderConfirmaionOpen}
+          onClose={() => setIsOrderConfirmationOpen(false)}
+          order={order}
+        />
+      )}
     </>
   );
 };
diff --git a/components/orders/order-confirmation-modal.tsx b/components/orders/order-confirmation-modal.tsx
new file mode 100644
index 000000000..ff0d1d87b
--- /dev/null
+++ b/components/orders/order-confirmation-modal.tsx
@@ -0,0 +1,292 @@
+import Image from 'next/image';
+import { Dialog, DialogBackdrop, DialogPanel } from '@headlessui/react';
+import { toPrintDate } from 'lib/utils';
+import PaymentsDetails from './payment-details';
+import Price from 'components/price';
+import Divider from 'components/divider';
+import Markdown from 'markdown-to-jsx';
+import { Order, OrderConfirmationContent } from 'lib/shopify/types';
+import { FormEventHandler, useEffect, useRef, useState, useTransition } from 'react';
+import { confirmOrder } from 'components/orders/actions';
+import { Button, Heading, Text, Label, Skeleton, InputLabel, Input } from 'components/ui';
+
+function OrderConfirmationDetails({
+  content,
+  order
+}: {
+  content: OrderConfirmationContent;
+  order: Order;
+}) {
+  return (
+    <div className="space-y-4">
+      <figure>
+        <Image
+          src={content?.logo?.url}
+          alt={content?.logo?.altText || 'Logo'}
+          width={content?.logo?.width || 400}
+          height={content?.logo?.height || 400}
+        />
+      </figure>
+      <Heading className="text-primary" size="sm">
+        ORDER INFORMATION:
+      </Heading>
+      <div>
+        <Text>Order number: {order.name}</Text>
+        <Text>Email: {order.customer?.emailAddress}</Text>
+        <Text>Date: {toPrintDate(order.processedAt)}</Text>
+      </div>
+      <div className="flex">
+        <div className="flex-1 space-y-2">
+          <Label>Shipping Address</Label>
+          <div>
+            <Text>
+              {order.shippingAddress!.firstName} {order.shippingAddress!.lastName}
+            </Text>
+            <Text>{order.shippingAddress!.address1}</Text>
+            {order.shippingAddress!.address2 && <Text>{order.shippingAddress!.address2}</Text>}
+            <Text>
+              {order.shippingAddress!.city} {order.shippingAddress!.provinceCode}{' '}
+              {order.shippingAddress!.zip}
+            </Text>
+            <Text>{order.shippingAddress!.country}</Text>
+          </div>
+        </div>
+        <div className="flex-1 space-y-2">
+          <Label>Billing Address</Label>
+          <div>
+            <Text>
+              {order.billingAddress!.firstName} {order.billingAddress!.lastName}
+            </Text>
+            <Text>{order.billingAddress!.address1}</Text>
+            {order.billingAddress!.address2 && <Text>{order.billingAddress!.address2}</Text>}
+            <Text>
+              {order.billingAddress!.city} {order.billingAddress!.provinceCode}{' '}
+              {order.billingAddress!.zip}
+            </Text>
+            <Text>{order.billingAddress!.country}</Text>
+          </div>
+        </div>
+      </div>
+      <div className="flex flex-col gap-2">
+        <Label>Payment</Label>
+        <PaymentsDetails order={order} hideIcon />
+      </div>
+      <div className="mb-4">
+        <Heading size="sm">Products</Heading>
+        <Divider />
+        <table className="w-full table-auto">
+          <thead>
+            <tr>
+              <th className="text-start">
+                <Label>Product</Label>
+              </th>
+              <th className="text-start">
+                <Label>Quantity</Label>
+              </th>
+              <th className="text-start">
+                <Label>Price</Label>
+              </th>
+            </tr>
+          </thead>
+          <tbody>
+            {order.lineItems.map((lineItem, index) => (
+              <tr key={index}>
+                <td className="py-4 text-start">
+                  <Text className="max-w-sm">{lineItem.title}</Text>
+                </td>
+                <td className="text-start">
+                  <Text>{lineItem.quantity}</Text>
+                </td>
+                <td className="text-start">
+                  <Price
+                    className="text-sm"
+                    amount={lineItem.totalPrice!.amount}
+                    currencyCode={lineItem.totalPrice!.currencyCode}
+                  />
+                </td>
+              </tr>
+            ))}
+          </tbody>
+        </table>
+        <Divider />
+        <div className="ml-auto flex w-60 flex-col gap-4">
+          <div className="flex justify-between">
+            <Text>Subtotal</Text>
+            <Price
+              className="text-sm font-semibold"
+              amount={order.subtotal!.amount}
+              currencyCode={order.subtotal!.currencyCode}
+            />
+          </div>
+          <div className="flex items-center justify-between">
+            <Text>Shipping</Text>
+            {order.shippingMethod.price.amount !== '0.0' ? (
+              <Price
+                className="text-sm font-semibold"
+                amount={order.shippingMethod!.price.amount}
+                currencyCode={order.shippingMethod!.price.currencyCode}
+              />
+            ) : (
+              <Text className="font-semibold">Free</Text>
+            )}
+          </div>
+          <div className="flex items-center justify-between">
+            <Heading as="span" size="sm">
+              Total
+            </Heading>
+            <Price
+              className="font-semibold"
+              amount={order.totalPrice.amount}
+              currencyCode={order.totalPrice.currencyCode}
+            />
+          </div>
+        </div>
+      </div>
+      <Markdown
+        options={{
+          overrides: {
+            h1: {
+              props: {
+                className: 'text-primary font-semibold mt-4 mb-2 text-xl'
+              }
+            },
+            h2: {
+              props: {
+                className: 'text-primary font-semibold mt-4 mb-2'
+              }
+            },
+            h3: {
+              props: {
+                className: 'text-primary text-sm font-semibold mt-4 mb-2'
+              }
+            },
+            p: {
+              props: {
+                className: 'text-sm'
+              }
+            },
+            a: {
+              props: {
+                className: 'text-sm, text-primary underline'
+              }
+            }
+          }
+        }}
+      >
+        {content?.body || ''}
+      </Markdown>
+    </div>
+  );
+}
+export default function OrderConfirmationModal({
+  order,
+  isOpen,
+  onClose
+}: {
+  order: Order;
+  isOpen: boolean;
+  onClose: () => void;
+}) {
+  const [loading, setLoading] = useState(true);
+  const [orderConfirmationContent, setOrderConfirmationContent] =
+    useState<OrderConfirmationContent>();
+  const [, startTransition] = useTransition();
+  const formRef = useRef<HTMLFormElement>(null);
+
+  useEffect(() => {
+    const fetchOrderConfirmationContent = async () => {
+      const res = await fetch('/api/orders/confirmation');
+      const data = await res.json();
+
+      setOrderConfirmationContent(data);
+
+      setLoading(false);
+    };
+
+    // If the order has already been confirmed, don't fetch the content
+    if (order.orderConfirmation) return;
+
+    fetchOrderConfirmationContent();
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, []);
+
+  const handleSubmit: FormEventHandler<HTMLFormElement> = (event) => {
+    event.preventDefault();
+    setLoading(true);
+    const form = formRef.current;
+    if (!form) return;
+    const formData = new FormData(form);
+
+    startTransition(async () => {
+      await confirmOrder({
+        order,
+        content: orderConfirmationContent!,
+        formData
+      });
+      form.reset();
+    });
+  };
+
+  if (!loading && !orderConfirmationContent) return null;
+
+  return (
+    <Dialog open={isOpen} onClose={onClose} className="relative z-50">
+      <DialogBackdrop
+        transition
+        className="fixed inset-0 bg-black/30 duration-300 ease-out data-[closed]:opacity-0"
+      />
+      <div className="fixed inset-0 w-screen overflow-y-auto p-4">
+        <div className="flex min-h-full items-center justify-center">
+          <DialogPanel
+            transition
+            className="max-w-3xl space-y-4 rounded bg-white p-12 duration-300 ease-out data-[closed]:scale-95 data-[closed]:opacity-0"
+          >
+            {loading ? (
+              <Skeleton />
+            ) : (
+              <OrderConfirmationDetails content={orderConfirmationContent!} order={order} />
+            )}
+            <form onSubmit={handleSubmit} ref={formRef} className="space-y-4">
+              <div className="space-y-2">
+                <InputLabel htmlFor="date">Today&apos;s date</InputLabel>
+                <Input
+                  type="date"
+                  id="date"
+                  name="date"
+                  readOnly
+                  value={new Date().toLocaleDateString('en-CA', {
+                    year: 'numeric',
+                    month: '2-digit',
+                    day: '2-digit'
+                  })}
+                />
+              </div>
+              <div className="space-y-2">
+                <InputLabel htmlFor="signature1">Print your name to sign</InputLabel>
+                <Input id="signature1" name="signature1" required />
+              </div>
+              <div className="space-y-2">
+                <InputLabel htmlFor="signature2">
+                  Credit card holder&apos;s electronic signature
+                </InputLabel>
+                <Input id="signature2" name="signature2" required />
+              </div>
+              <div className="flex justify-end gap-2">
+                <Button variant="text">Cancel</Button>
+                <Button
+                  type="submit"
+                  variant="solid"
+                  color="primary"
+                  disabled={loading}
+                  isLoading={loading}
+                >
+                  Submit
+                </Button>
+              </div>
+            </form>
+          </DialogPanel>
+        </div>
+      </div>
+    </Dialog>
+  );
+}
diff --git a/components/orders/order-confirmation-pdf.tsx b/components/orders/order-confirmation-pdf.tsx
new file mode 100644
index 000000000..88f53fd6e
--- /dev/null
+++ b/components/orders/order-confirmation-pdf.tsx
@@ -0,0 +1,298 @@
+import Markdown from 'markdown-to-jsx';
+import { Document, Image, Page, Text, StyleSheet, View, Link } from '@react-pdf/renderer';
+import { Order, OrderConfirmationContent } from 'lib/shopify/types';
+import { toPrintDate } from 'lib/utils';
+
+const PDFPrice = ({
+  style,
+  amount,
+  currencyCode = 'USD'
+}: {
+  style?: any;
+  amount: string;
+  currencyCode: string;
+}) => {
+  const price = parseFloat(amount);
+
+  // Return 'Included' if price is 0
+  if (price === 0) {
+    return <Text style={style}>Free</Text>;
+  }
+
+  return (
+    <Text style={style}>
+      {new Intl.NumberFormat(undefined, {
+        style: 'currency',
+        currency: currencyCode,
+        currencyDisplay: 'narrowSymbol'
+      }).format(price)}
+    </Text>
+  );
+};
+
+export default function OrderConfirmationPdf({
+  content,
+  order,
+  signature1,
+  signature2,
+  date
+}: {
+  content: OrderConfirmationContent;
+  order: Order;
+  signature1: string;
+  signature2: string;
+  date: string;
+}) {
+  const styles = StyleSheet.create({
+    logo: {
+      width: 300,
+      marginHorizontal: 'auto',
+      marginBottom: 24
+    },
+    page: {
+      padding: 48,
+      paddingVertical: 64
+    },
+    h1: {
+      fontSize: 18,
+      fontWeight: 700,
+      marginBottom: 12,
+      color: content.color
+    },
+    h2: {
+      fontSize: 14,
+      fontWeight: 700,
+      marginBottom: 12,
+      color: content.color
+    },
+    h3: {
+      fontSize: 12,
+      fontWeight: 700,
+      marginBottom: 12,
+      color: content.color
+    },
+    p: {
+      fontSize: 10,
+      marginBottom: 12
+    },
+    span: {
+      fontSize: 10
+    },
+    strong: {
+      fontWeight: 700,
+      fontSize: 10
+    },
+    a: {
+      color: content.color,
+      fontSize: 10,
+      textDecoration: 'underline'
+    },
+    label: {
+      fontSize: 10,
+      fontWeight: 'bold',
+      color: '#555'
+    },
+    tableRow: {
+      display: 'flex',
+      flexDirection: 'row',
+      gap: 8
+    },
+    tableCell: {
+      textAlign: 'left',
+      fontSize: 10,
+      paddingVertical: 12
+    }
+  });
+
+  return (
+    <Document>
+      <Page size="A4" style={styles.page}>
+        <View>
+          {/* eslint-disable-next-line jsx-a11y/alt-text */}
+          <Image src={content?.logo?.url} style={styles.logo} />
+          <Text style={styles.h3}>ORDER INFORMATION:</Text>
+          <View>
+            <Text style={styles.span}>Order number: {order.name}</Text>
+            <Text style={styles.span}>Email: {order.customer?.emailAddress}</Text>
+            <Text style={styles.p}>Date: {toPrintDate(order.processedAt)}</Text>
+          </View>
+          <View style={{ display: 'flex', flexDirection: 'row' }}>
+            <View style={{ flex: 1 }}>
+              <Text style={[styles.label, { marginBottom: 6 }]}>Shipping Address</Text>
+              <View>
+                <Text style={styles.span}>
+                  {order.shippingAddress!.firstName} {order.shippingAddress!.lastName}
+                </Text>
+                <Text style={styles.span}>{order.shippingAddress!.address1}</Text>
+                {order.shippingAddress!.address2 && (
+                  <Text style={styles.p}>{order.shippingAddress!.address2}</Text>
+                )}
+                <Text style={styles.span}>
+                  {order.shippingAddress!.city} {order.shippingAddress!.provinceCode}{' '}
+                  {order.shippingAddress!.zip}
+                </Text>
+                <Text style={styles.p}>{order.shippingAddress!.country}</Text>
+              </View>
+            </View>
+            <View style={{ flex: 1 }}>
+              <Text style={[styles.label, { marginBottom: 6 }]}>Billing Address</Text>
+              <View>
+                <Text style={styles.span}>
+                  {order.billingAddress!.firstName} {order.billingAddress!.lastName}
+                </Text>
+                <Text style={styles.span}>{order.billingAddress!.address1}</Text>
+                {order.billingAddress!.address2 && (
+                  <Text style={styles.span}>{order.billingAddress!.address2}</Text>
+                )}
+                <Text style={styles.span}>
+                  {order.billingAddress!.city} {order.billingAddress!.provinceCode}{' '}
+                  {order.billingAddress!.zip}
+                </Text>
+                <Text style={styles.p}>{order.billingAddress!.country}</Text>
+              </View>
+            </View>
+          </View>
+          <View>
+            <Text style={styles.label}>Payment</Text>
+            <View>
+              <Text style={styles.p}>
+                Ending with {order.transactions[0]!.paymentDetails.last4} -
+                <PDFPrice
+                  amount={order.transactions[0]!.transactionAmount.amount}
+                  currencyCode={order.transactions[0]!.transactionAmount.currencyCode}
+                />
+              </Text>
+            </View>
+          </View>
+          <View>
+            <View style={styles.tableRow}>
+              <Text style={[styles.label, { width: '70%' }]}>Products</Text>
+              <Text style={[styles.label, { width: '15%' }]}>Quantity</Text>
+              <Text style={[styles.label, { width: '15%' }]}>Price</Text>
+            </View>
+            <View
+              style={{
+                width: '100%',
+                borderBottom: '1px solid #333',
+                marginTop: 6,
+                marginBottom: 8
+              }}
+            />
+            {order.lineItems.map((lineItem, index) => (
+              <View key={index} style={styles.tableRow}>
+                <Text style={[styles.tableCell, { width: '70%' }]}>{lineItem.title}</Text>
+                <Text style={[styles.tableCell, { width: '15%' }]}>{lineItem.quantity}</Text>
+                <PDFPrice
+                  style={[styles.tableCell, { width: '15%' }]}
+                  amount={lineItem.totalPrice!.amount}
+                  currencyCode={lineItem.totalPrice!.currencyCode}
+                />
+              </View>
+            ))}
+            <View
+              style={{
+                width: '100%',
+                borderBottom: '1px solid black',
+                marginTop: 6,
+                marginBottom: 8
+              }}
+            />
+            <View style={{ width: '150px', marginLeft: 'auto', marginRight: '20' }}>
+              <View
+                style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between' }}
+              >
+                <Text style={styles.span}>Subtotal</Text>
+                <PDFPrice
+                  style={styles.span}
+                  amount={order.subtotal!.amount}
+                  currencyCode={order.subtotal!.currencyCode}
+                />
+              </View>
+              <View
+                style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between' }}
+              >
+                <Text style={styles.span}>Shipping</Text>
+                <PDFPrice
+                  style={styles.span}
+                  amount={order.shippingMethod!.price.amount}
+                  currencyCode={order.shippingMethod!.price.currencyCode}
+                />
+              </View>
+              <View
+                style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between' }}
+              >
+                <Text style={styles.span}>Total</Text>
+                <PDFPrice
+                  style={styles.span}
+                  amount={order.totalPrice!.amount}
+                  currencyCode={order.totalPrice!.currencyCode}
+                />
+              </View>
+            </View>
+          </View>
+        </View>
+      </Page>
+      <Page size="A4" style={styles.page}>
+        <Markdown
+          options={{
+            wrapper: View,
+            overrides: {
+              h1: {
+                component: Text,
+                props: {
+                  style: styles.h1
+                }
+              },
+              h2: {
+                component: Text,
+                props: {
+                  style: styles.h2
+                }
+              },
+              h3: {
+                component: Text,
+                props: {
+                  style: styles.h3
+                }
+              },
+              p: {
+                component: Text,
+                props: {
+                  style: styles.p
+                }
+              },
+              strong: {
+                component: Text,
+                props: {
+                  style: styles.strong
+                }
+              },
+              a: {
+                component: Link,
+                props: {
+                  style: styles.a
+                }
+              }
+            }
+          }}
+        >
+          {content.body}
+        </Markdown>
+        <View style={{ display: 'flex', flexDirection: 'row' }}>
+          <Text style={[styles.p, { flex: 1 }]}>Date:</Text>
+          <Text style={[styles.p, { flex: 1 }]}>{toPrintDate(date)}</Text>
+        </View>
+        <View style={{ display: 'flex', flexDirection: 'row' }}>
+          <Text style={[styles.p, { flex: 1 }]}>Print your name to sign:</Text>
+          <Text style={[styles.p, { flex: 1 }]}>{signature1}</Text>
+        </View>
+        <View style={{ display: 'flex', flexDirection: 'row' }}>
+          <Text style={[styles.p, { flex: 1 }]}>
+            Credit card holder&apos;s electronic signature
+          </Text>
+          <Text style={[styles.p, { flex: 1 }]}>{signature2}</Text>
+        </View>
+      </Page>
+    </Document>
+  );
+}
diff --git a/components/orders/order-confirmation.tsx b/components/orders/order-confirmation.tsx
new file mode 100644
index 000000000..3924b2455
--- /dev/null
+++ b/components/orders/order-confirmation.tsx
@@ -0,0 +1,24 @@
+'use client';
+import { Button } from 'components/ui';
+import { Order } from 'lib/shopify/types';
+import dynamic from 'next/dynamic';
+import { useState } from 'react';
+
+const OrderConfirmationModal = dynamic(() => import('./order-confirmation-modal'));
+
+export default function OrderConfirmation({ order }: { order: Order }) {
+  const [isOpen, setIsOpen] = useState(false);
+
+  if (order.orderConfirmation) return null;
+  return (
+    <>
+      <Button variant="outlined" onClick={() => setIsOpen(true)}>
+        Confirm Order
+      </Button>
+
+      {isOpen && (
+        <OrderConfirmationModal isOpen={isOpen} onClose={() => setIsOpen(false)} order={order} />
+      )}
+    </>
+  );
+}
diff --git a/components/orders/order-summary.tsx b/components/orders/order-summary.tsx
index 4510d0562..3a4f51481 100644
--- a/components/orders/order-summary.tsx
+++ b/components/orders/order-summary.tsx
@@ -54,8 +54,8 @@ export default function OrderSummary({ order }: { order: Order }) {
             <Text>Subtotal</Text>
             <Price
               className="text-sm font-semibold"
-              amount={order.totalPrice!.amount}
-              currencyCode={order.totalPrice!.currencyCode}
+              amount={order.subtotal!.amount}
+              currencyCode={order.subtotal!.currencyCode}
             />
           </div>
           <div className="flex items-center justify-between">
diff --git a/components/orders/payment-details.tsx b/components/orders/payment-details.tsx
new file mode 100644
index 000000000..0284757c5
--- /dev/null
+++ b/components/orders/payment-details.tsx
@@ -0,0 +1,36 @@
+import Text from 'components/ui/text';
+import Label from 'components/ui/label';
+import { Order } from 'lib/shopify/types';
+import Price from 'components/price';
+import { toPrintDate } from 'lib/utils';
+
+export default function PaymentsDetails({ order, hideIcon }: { order: Order; hideIcon?: boolean }) {
+  return (
+    <>
+      {order.transactions.map((transaction, index) => (
+        <div key={index} className="flex items-start gap-2">
+          {!hideIcon && (
+            // eslint-disable-next-line @next/next/no-img-element
+            <img
+              src={transaction.paymentIcon.url}
+              alt={transaction.paymentIcon.altText}
+              width={36}
+            />
+          )}
+
+          <div>
+            <Text>
+              Ending with {transaction.paymentDetails.last4} -
+              <Price
+                as="span"
+                amount={transaction.transactionAmount.amount}
+                currencyCode={transaction.transactionAmount.currencyCode}
+              />
+            </Text>
+            <Label>{toPrintDate(transaction.processedAt)}</Label>
+          </div>
+        </div>
+      ))}
+    </>
+  );
+}
diff --git a/components/profile/popover.tsx b/components/profile/popover.tsx
index 85c4b4c19..c8b605e2b 100644
--- a/components/profile/popover.tsx
+++ b/components/profile/popover.tsx
@@ -1,7 +1,7 @@
 'use client';
 import { CloseButton, Popover, PopoverButton, PopoverPanel, Transition } from '@headlessui/react';
 import { ArrowRightIcon } from '@heroicons/react/16/solid';
-import { Button } from 'components/button';
+import { Button } from 'components/ui';
 import useAuth from 'hooks/use-auth';
 import { Menu } from 'lib/shopify/types';
 import Link from 'next/link';
diff --git a/components/spinner.tsx b/components/spinner.tsx
deleted file mode 100644
index a80fa722b..000000000
--- a/components/spinner.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import clsx from 'clsx';
-import React from 'react';
-
-export default function Spinner({ className }: { className?: string }) {
-  return (
-    <svg
-      xmlns="http://www.w3.org/2000/svg"
-      className={clsx('flex-1 animate-spin stroke-current stroke-[3]', className)}
-      fill="none"
-      viewBox="0 0 24 24"
-    >
-      <path
-        d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"
-        className="stroke-current opacity-25"
-      />
-      <path d="M12 2C6.47715 2 2 6.47715 2 12C2 14.7255 3.09032 17.1962 4.85857 19" />
-    </svg>
-  );
-}
diff --git a/components/ui/badge.tsx b/components/ui/badge.tsx
index a70e349f1..0780b53d9 100644
--- a/components/ui/badge.tsx
+++ b/components/ui/badge.tsx
@@ -19,7 +19,7 @@ const badgeStyles = tv({
   }
 });
 
-interface BadgeProps extends VariantProps<typeof badgeStyles> {
+export interface BadgeProps extends VariantProps<typeof badgeStyles> {
   content: string | number;
   className?: string;
   children: React.ReactNode;
diff --git a/components/button.tsx b/components/ui/button.tsx
similarity index 56%
rename from components/button.tsx
rename to components/ui/button.tsx
index 0750b652f..29e55f81c 100644
--- a/components/button.tsx
+++ b/components/ui/button.tsx
@@ -3,7 +3,8 @@ import React from 'react';
 import { Button as ButtonBase, ButtonProps as ButtonBaseProps } from '@headlessui/react';
 import { tv, type VariantProps } from 'tailwind-variants';
 import clsx from 'clsx';
-import Spinner from './spinner';
+import LoadingDots from './loading-dots';
+import { focusInput } from 'lib/utils';
 
 const buttonVariants = tv({
   slots: {
@@ -15,7 +16,8 @@ const buttonVariants = tv({
       // transition
       'transition-all duration-100 ease-in-out',
       // disabled
-      'disabled:pointer-events-none disabled:shadow-none'
+      'disabled:pointer-events-none disabled:shadow-none',
+      focusInput
     ],
     loading: 'pointer-events-none flex shrink-0 items-center justify-center gap-1.5'
   },
@@ -36,11 +38,15 @@ const buttonVariants = tv({
       content: {}
     },
     variant: {
-      solid: {},
-      outlined: {
-        root: 'border bg-white'
+      solid: {
+        root: 'border border-transparent shadow-sm'
       },
-      text: {}
+      outlined: {
+        root: 'border bg-white shadow-sm'
+      },
+      text: {
+        root: 'border border-transparent'
+      }
     }
   },
   compoundVariants: [
@@ -49,20 +55,35 @@ const buttonVariants = tv({
       variant: 'solid',
       class: {
         root: [
-          // border
-          'border-transparent',
           // text color
           'text-white',
           // background color
           'bg-primary',
           // hover color
-          'hover:bg-primary-empahsis',
+          'hover:bg-primary-emphasis',
           // disabled
           'disabled:bg-primary-muted',
           'pressed:bg-primary-emphasis/80'
         ]
       }
     },
+    {
+      color: 'content',
+      variant: 'solid',
+      class: {
+        root: [
+          // text color
+          'text-white',
+          // background color
+          'bg-content',
+          // hover color
+          'hover:bg-content-emphasis',
+          // disabled
+          'disabled:bg-content-muted',
+          'pressed:bg-content-emphasis/80'
+        ]
+      }
+    },
     {
       color: 'primary',
       variant: 'outlined',
@@ -75,25 +96,62 @@ const buttonVariants = tv({
           // background color
           'bg-white',
           // hover color
-          'hover:bg-primary/10',
+          'hover:bg-primary/5',
           // disabled
           'disabled:border-primary-muted disabled:text-primary-muted'
         ]
       }
+    },
+    {
+      color: 'content',
+      variant: 'outlined',
+      class: {
+        root: [
+          // border
+          'border-content-subtle',
+          // text color
+          'text-content-emphasis',
+          // background color
+          'bg-white',
+          // hover color
+          'hover:bg-content/5',
+          // disabled
+          'disabled:border-content-muted disabled:text-content-muted'
+        ]
+      }
+    },
+    {
+      color: 'content',
+      variant: 'text',
+      class: {
+        root: [
+          // text color
+          'text-content-emphasis',
+          // background color
+          'bg-transparent',
+          // hover color
+          'hover:bg-content/5',
+          // disabled
+          'disabled:text-content-muted'
+        ]
+      }
     }
   ],
   defaultVariants: {
-    variant: 'solid',
-    color: 'primary',
+    variant: 'outlined',
+    color: 'content',
     size: 'md'
   }
 });
 
-interface ButtonProps extends Omit<ButtonBaseProps, 'color'>, VariantProps<typeof buttonVariants> {
+export interface ButtonProps
+  extends Omit<ButtonBaseProps, 'color' | 'as'>,
+    VariantProps<typeof buttonVariants> {
   isLoading?: boolean;
   loadingText?: string;
   className?: string;
   disabled?: boolean;
+  as?: React.ElementType;
 }
 
 const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
@@ -105,14 +163,19 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
       isLoading,
       loadingText = 'Loading',
       size,
+      color,
       variant,
+      as,
       ...props
     }: ButtonProps,
     forwardedRef
   ) => {
-    const { loading, root } = buttonVariants({ variant, size });
+    const { loading, root } = buttonVariants({ variant, size, color });
+
+    const Component = as || 'button';
     return (
       <ButtonBase
+        as={Component}
         ref={forwardedRef}
         className={clsx(root(), className)}
         disabled={disabled || isLoading}
@@ -120,7 +183,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
       >
         {isLoading ? (
           <span className={loading()}>
-            <Spinner />
+            <LoadingDots />
             <span className="sr-only">{loadingText}</span>
             <span>{loadingText}</span>
           </span>
@@ -134,4 +197,4 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
 
 Button.displayName = 'Button';
 
-export { Button, buttonVariants, type ButtonProps };
+export default Button;
diff --git a/components/ui/card.tsx b/components/ui/card.tsx
index 31d263482..bb65e3345 100644
--- a/components/ui/card.tsx
+++ b/components/ui/card.tsx
@@ -21,7 +21,9 @@ const cardStyles = tv({
   }
 });
 
-interface CardProps extends React.ComponentPropsWithoutRef<'div'>, VariantProps<typeof cardStyles> {
+export interface CardProps
+  extends React.ComponentPropsWithoutRef<'div'>,
+    VariantProps<typeof cardStyles> {
   asChild?: boolean;
 }
 
@@ -41,4 +43,4 @@ const Card = React.forwardRef<HTMLDivElement, CardProps>(
 
 Card.displayName = 'Card';
 
-export { Card, type CardProps };
+export default Card;
diff --git a/components/ui/checkbox.tsx b/components/ui/checkbox.tsx
new file mode 100644
index 000000000..48d1c8ed2
--- /dev/null
+++ b/components/ui/checkbox.tsx
@@ -0,0 +1,28 @@
+'use client';
+
+import { CheckIcon } from '@heroicons/react/24/outline';
+import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
+import { cn } from 'lib/utils';
+import { forwardRef } from 'react';
+
+const Checkbox = forwardRef<
+  React.ElementRef<typeof CheckboxPrimitive.Root>,
+  React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
+>(({ className, ...props }, ref) => (
+  <CheckboxPrimitive.Root
+    ref={ref}
+    className={cn(
+      'ring-offset-background focus-visible:ring-ring peer h-4 w-4 shrink-0 rounded-sm border border-dark focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-dark data-[state=checked]:text-white',
+      className
+    )}
+    {...props}
+  >
+    <CheckboxPrimitive.Indicator className={cn('flex items-center justify-center text-current')}>
+      <CheckIcon className="h-4 w-4" />
+    </CheckboxPrimitive.Indicator>
+  </CheckboxPrimitive.Root>
+));
+
+Checkbox.displayName = CheckboxPrimitive.Root.displayName;
+
+export default Checkbox;
diff --git a/components/ui/heading.tsx b/components/ui/heading.tsx
index a73dee028..79ca13f5d 100644
--- a/components/ui/heading.tsx
+++ b/components/ui/heading.tsx
@@ -1,20 +1,25 @@
 import { VariantProps, tv } from 'tailwind-variants';
 
-const heading = tv({
-  base: [''],
-  variants: {
-    size: {
-      sm: 'text-heading-sm',
-      md: 'text-heading-md',
-      lg: 'text-heading-lg'
+const heading = tv(
+  {
+    base: [''],
+    variants: {
+      size: {
+        sm: 'text-heading-sm',
+        md: 'text-heading-md',
+        lg: 'text-heading-lg'
+      }
+    },
+    defaultVariants: {
+      size: 'md'
     }
   },
-  defaultVariants: {
-    size: 'md'
+  {
+    twMerge: false
   }
-});
+);
 
-interface HeadingProps extends VariantProps<typeof heading> {
+export interface HeadingProps extends VariantProps<typeof heading> {
   className?: string;
   children: React.ReactNode;
   as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'span' | 'p';
diff --git a/components/ui/index.ts b/components/ui/index.ts
new file mode 100644
index 000000000..01c268397
--- /dev/null
+++ b/components/ui/index.ts
@@ -0,0 +1,18 @@
+export { default as Badge } from './badge';
+export * from './badge';
+export { default as Button } from './button';
+export * from './button';
+export { default as Card } from './card';
+export * from './card';
+export { default as Checkbox } from './checkbox';
+export { default as Heading } from './heading';
+export { default as InputLabel } from './input-label';
+export * from './input-label';
+export { default as Input } from './input';
+export * from './input';
+export { default as Label } from './label';
+export * from './label';
+export { default as Skeleton } from './skeleton';
+export * from './skeleton';
+export { default as Text } from './text';
+export * from './text';
diff --git a/components/ui/input-label.tsx b/components/ui/input-label.tsx
new file mode 100644
index 000000000..669aaf2f0
--- /dev/null
+++ b/components/ui/input-label.tsx
@@ -0,0 +1,33 @@
+import React from 'react';
+import * as LabelPrimitives from '@radix-ui/react-label';
+
+import { cx } from 'lib/utils';
+
+export interface InputLabelProps
+  extends React.ComponentPropsWithoutRef<typeof LabelPrimitives.Root> {
+  disabled?: boolean;
+}
+
+const InputLabel = React.forwardRef<React.ElementRef<typeof LabelPrimitives.Root>, InputLabelProps>(
+  ({ className, disabled, ...props }, forwardedRef) => (
+    <LabelPrimitives.Root
+      ref={forwardedRef}
+      className={cx(
+        // base
+        'text-sm leading-none',
+        // text color
+        'text-gray-900 dark:text-gray-50',
+        // disabled
+        {
+          'text-gray-400 dark:text-gray-600': disabled
+        },
+        className
+      )}
+      aria-disabled={disabled}
+      {...props}
+    />
+  )
+);
+InputLabel.displayName = 'InputLabel';
+
+export default InputLabel;
diff --git a/components/ui/input.tsx b/components/ui/input.tsx
new file mode 100644
index 000000000..12eae80a1
--- /dev/null
+++ b/components/ui/input.tsx
@@ -0,0 +1,70 @@
+import React from 'react';
+import { tv, type VariantProps } from 'tailwind-variants';
+
+import { cx, focusInput, hasErrorInput } from 'lib/utils';
+
+const inputStyles = tv({
+  base: [
+    // base
+    'relative block w-full appearance-none rounded-md border px-2.5 py-1.5 shadow-sm outline-none transition sm:text-sm',
+    // border color
+    'border-gray-300 dark:border-gray-800',
+    // text color
+    'text-gray-900 dark:text-gray-50',
+    // placeholder color
+    'placeholder-gray-400 dark:placeholder-gray-500',
+    // background color
+    'bg-white dark:bg-gray-950',
+    // disabled
+    'disabled:border-gray-300 disabled:bg-gray-100 disabled:text-gray-400',
+    'disabled:dark:border-gray-700 disabled:dark:bg-gray-800 disabled:dark:text-gray-500',
+    // file
+    [
+      'file:-my-1.5 file:-ml-2.5 file:h-[36px] file:cursor-pointer file:rounded-l-md file:rounded-r-none file:border-0 file:px-3 file:py-1.5 file:outline-none focus:outline-none disabled:pointer-events-none file:disabled:pointer-events-none',
+      'file:border-solid file:border-gray-300 file:bg-gray-50 file:text-gray-500 file:hover:bg-gray-100 file:dark:border-gray-800 file:dark:bg-gray-950 file:hover:dark:bg-gray-900/20 file:disabled:dark:border-gray-700',
+      'file:[border-inline-end-width:1px] file:[margin-inline-end:0.75rem]',
+      'file:disabled:bg-gray-100 file:disabled:text-gray-500 file:disabled:dark:bg-gray-800'
+    ],
+    // focus
+    focusInput,
+    // invalid
+    'aria-[invalid=true]:dark:ring-red-400/20 aria-[invalid=true]:ring-2 aria-[invalid=true]:ring-red-200 aria-[invalid=true]:border-red-500 invalid:ring-2 invalid:ring-red-200 invalid:border-red-500'
+  ],
+  variants: {
+    hasError: {
+      true: hasErrorInput
+    },
+    // number input
+    enableStepper: {
+      true: '[appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none'
+    }
+  }
+});
+
+export interface InputProps
+  extends React.InputHTMLAttributes<HTMLInputElement>,
+    VariantProps<typeof inputStyles> {
+  inputClassName?: string;
+}
+
+const Input = React.forwardRef<HTMLInputElement, InputProps>(
+  (
+    { className, inputClassName, hasError, enableStepper, type, ...props }: InputProps,
+    forwardedRef
+  ) => {
+    return (
+      <div className={cx('relative w-full', className)}>
+        <input
+          ref={forwardedRef}
+          type={type}
+          className={cx(inputStyles({ hasError, enableStepper }), inputClassName)}
+          {...props}
+        />
+      </div>
+    );
+  }
+);
+
+Input.displayName = 'Input';
+
+export default Input;
diff --git a/components/ui/label.tsx b/components/ui/label.tsx
index 1dec14f18..2178321ec 100644
--- a/components/ui/label.tsx
+++ b/components/ui/label.tsx
@@ -19,7 +19,7 @@ const label = tv(
   }
 );
 
-interface LabelProps extends VariantProps<typeof label> {
+export interface LabelProps extends VariantProps<typeof label> {
   className?: string;
   children: React.ReactNode;
   as?: 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'span' | 'p';
diff --git a/components/ui/loading-dots.tsx b/components/ui/loading-dots.tsx
new file mode 100644
index 000000000..0a3fb676e
--- /dev/null
+++ b/components/ui/loading-dots.tsx
@@ -0,0 +1,15 @@
+import clsx from 'clsx';
+
+const dots = 'mx-[1px] inline-block h-1 w-1 animate-blink rounded-md';
+
+const LoadingDots = ({ className }: { className?: string }) => {
+  return (
+    <span className="mx-2 inline-flex items-center">
+      <span className={clsx(dots, className)} />
+      <span className={clsx(dots, 'animation-delay-[200ms]', className)} />
+      <span className={clsx(dots, 'animation-delay-[400ms]', className)} />
+    </span>
+  );
+};
+
+export default LoadingDots;
diff --git a/components/ui/text.tsx b/components/ui/text.tsx
index 7ce0a09b7..ac30a0c8e 100644
--- a/components/ui/text.tsx
+++ b/components/ui/text.tsx
@@ -19,7 +19,7 @@ const text = tv(
   }
 );
 
-interface TextProps extends VariantProps<typeof text> {
+export interface TextProps extends VariantProps<typeof text> {
   className?: string;
   children: React.ReactNode;
   as?: 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'span' | 'p';
diff --git a/lib/shopify/auth.ts b/lib/shopify/auth.ts
index f0a82a52e..4070d6fba 100644
--- a/lib/shopify/auth.ts
+++ b/lib/shopify/auth.ts
@@ -390,6 +390,7 @@ export async function isLoggedIn(request: NextRequest, origin: string) {
   }
 
   newHeaders.set('x-shop-customer-token', `${customerTokenValue}`);
+  console.log('Customer Token', customerTokenValue);
   return NextResponse.next({
     request: {
       // New request headers
diff --git a/lib/shopify/fragments/address.ts b/lib/shopify/fragments/address.ts
new file mode 100644
index 000000000..cf9af22f0
--- /dev/null
+++ b/lib/shopify/fragments/address.ts
@@ -0,0 +1,17 @@
+const addressFragment = /* GraphQL */ `
+  fragment Address on CustomerAddress {
+    id
+    address1
+    address2
+    firstName
+    lastName
+    provinceCode: zoneCode
+    city
+    zip
+    countryCodeV2: territoryCode
+    company
+    phone: phoneNumber
+  }
+`;
+
+export default addressFragment;
diff --git a/lib/shopify/fragments/order-card.ts b/lib/shopify/fragments/order-card.ts
new file mode 100644
index 000000000..e69de29bb
diff --git a/lib/shopify/fragments/order-metafields.ts b/lib/shopify/fragments/order-metafields.ts
new file mode 100644
index 000000000..2488b66d7
--- /dev/null
+++ b/lib/shopify/fragments/order-metafields.ts
@@ -0,0 +1,56 @@
+const orderMetafieldsFragment = /* GraphQL */ `
+  fragment OrderMetafields on Order {
+    warrantyStatus: metafield(namespace: "custom", key: "warranty_status") {
+      value
+      id
+      key
+    }
+    warrantyActivationDeadline: metafield(
+      namespace: "custom"
+      key: "warranty_activation_deadline"
+    ) {
+      value
+      id
+      key
+    }
+    warrantyActivationOdometer: metafield(
+      namespace: "custom"
+      key: "warranty_activation_odometer"
+    ) {
+      value
+      id
+      key
+    }
+    warrantyActivationInstallation: metafield(
+      namespace: "custom"
+      key: "warranty_activation_installation"
+    ) {
+      value
+      id
+      key
+    }
+    warrantyActivationSelfInstall: metafield(
+      namespace: "custom"
+      key: "warranty_activation_self_install"
+    ) {
+      value
+      id
+      key
+    }
+    warrantyActivationVIN: metafield(namespace: "custom", key: "warranty_activation_vin") {
+      value
+      id
+      key
+    }
+    warrantyActivationMileage: metafield(namespace: "custom", key: "warranty_activation_mileage") {
+      value
+      id
+      key
+    }
+    orderConfirmation: metafield(namespace: "custom", key: "customer_confirmation") {
+      value
+    }
+  }
+`;
+
+export default orderMetafieldsFragment;
diff --git a/lib/shopify/fragments/order-transaction.ts b/lib/shopify/fragments/order-transaction.ts
new file mode 100644
index 000000000..4047a7af4
--- /dev/null
+++ b/lib/shopify/fragments/order-transaction.ts
@@ -0,0 +1,38 @@
+const orderTransactionFragment = /* GraphQL */ `
+  fragment OrderTransaction on OrderTransaction {
+    id
+    processedAt
+    paymentIcon {
+      id
+      url
+      altText
+    }
+    paymentDetails {
+      ... on CardPaymentDetails {
+        last4
+        cardBrand
+      }
+    }
+    transactionAmount {
+      presentmentMoney {
+        ...Price
+      }
+    }
+    giftCardDetails {
+      last4
+      balance {
+        ...Price
+      }
+    }
+    status
+    kind
+    transactionParentId
+    type
+    typeDetails {
+      name
+      message
+    }
+  }
+`;
+
+export default orderTransactionFragment;
diff --git a/lib/shopify/fragments/order.ts b/lib/shopify/fragments/order.ts
index d15409862..f5fcf13e4 100644
--- a/lib/shopify/fragments/order.ts
+++ b/lib/shopify/fragments/order.ts
@@ -1,4 +1,8 @@
+import addressFragment from './address';
 import lineItemFragment from './line-item';
+import orderMetafieldsFragment from './order-metafields';
+import orderTrasactionFragment from './order-transaction';
+import priceFragment from './price';
 
 const orderCard = /* GraphQL */ `
   fragment OrderCard on Order {
@@ -16,69 +20,44 @@ const orderCard = /* GraphQL */ `
       }
     }
     totalPrice {
-      amount
-      currencyCode
+      ...Price
+    }
+    subtotal {
+      ...Price
+    }
+    totalShipping {
+      ...Price
+    }
+    totalTax {
+      ...Price
+    }
+    shippingLine {
+      title
+      originalPrice {
+        ...Price
+      }
     }
     lineItems(first: 20) {
       nodes {
         ...LineItem
       }
     }
+    shippingAddress {
+      ...Address
+    }
+    billingAddress {
+      ...Address
+    }
+    transactions {
+      ...OrderTransaction
+    }
+    ...OrderMetafields
   }
   ${lineItemFragment}
-`;
-
-export const orderMetafields = /* GraphQL */ `
-  fragment OrderMetafield on Order {
-    id
-    warrantyStatus: metafield(namespace: "custom", key: "warranty_status") {
-      value
-      id
-      key
-    }
-    warrantyActivationDeadline: metafield(
-      namespace: "custom"
-      key: "warranty_activation_deadline"
-    ) {
-      value
-      id
-      key
-    }
-    warrantyActivationOdometer: metafield(
-      namespace: "custom"
-      key: "warranty_activation_odometer"
-    ) {
-      value
-      id
-      key
-    }
-    warrantyActivationInstallation: metafield(
-      namespace: "custom"
-      key: "warranty_activation_installation"
-    ) {
-      value
-      id
-      key
-    }
-    warrantyActivationSelfInstall: metafield(
-      namespace: "custom"
-      key: "warranty_activation_self_install"
-    ) {
-      value
-      id
-      key
-    }
-    warrantyActivationVIN: metafield(namespace: "custom", key: "warranty_activation_vin") {
-      value
-      id
-      key
-    }
-    warrantyActivationMileage: metafield(namespace: "custom", key: "warranty_activation_mileage") {
-      value
-      id
-      key
-    }
-  }
+  ${addressFragment}
+  ${priceFragment}
+  ${orderTrasactionFragment}
+  ${orderMetafieldsFragment}
 `;
 
 export default orderCard;
diff --git a/lib/shopify/fragments/price.ts b/lib/shopify/fragments/price.ts
new file mode 100644
index 000000000..6b003a6dd
--- /dev/null
+++ b/lib/shopify/fragments/price.ts
@@ -0,0 +1,8 @@
+const priceFragment = /* GraphQL */ `
+  fragment Price on MoneyV2 {
+    amount
+    currencyCode
+  }
+`;
+
+export default priceFragment;
diff --git a/lib/shopify/index.ts b/lib/shopify/index.ts
index 005d70a76..daab9ebed 100644
--- a/lib/shopify/index.ts
+++ b/lib/shopify/index.ts
@@ -38,8 +38,7 @@ import { getCustomerQuery } from './queries/customer';
 import { getMenuQuery } from './queries/menu';
 import { getMetaobjectQuery, getMetaobjectsQuery } from './queries/metaobject';
 import { getFileQuery, getImageQuery, getMetaobjectsByIdsQuery } from './queries/node';
-import { getCustomerOrderQuery, getOrderMetafieldsQuery } from './queries/order';
-import { getCustomerOrderMetafieldsQuery, getCustomerOrdersQuery } from './queries/orders';
+import { getCustomerOrdersQuery } from './queries/orders';
 import { getPageQuery, getPagesQuery } from './queries/page';
 import {
   getProductQuery,
@@ -64,6 +63,7 @@ import {
   Metaobject,
   Money,
   Order,
+  OrderConfirmationContent,
   Page,
   PageInfo,
   Product,
@@ -86,10 +86,10 @@ import {
   ShopifyImageOperation,
   ShopifyMenuOperation,
   ShopifyMetaobject,
+  ShopifyMetaobjectOperation,
   ShopifyMetaobjectsOperation,
   ShopifyMoneyV2,
   ShopifyOrder,
-  ShopifyOrderMetafield,
   ShopifyPage,
   ShopifyPageOperation,
   ShopifyPagesOperation,
@@ -109,6 +109,7 @@ import {
   UploadInput,
   WarrantyStatus
 } from './types';
+import getCustomerOrderQuery from './queries/order';
 
 const domain = process.env.SHOPIFY_STORE_DOMAIN
   ? ensureStartsWith(process.env.SHOPIFY_STORE_DOMAIN, 'https://')
@@ -185,7 +186,7 @@ export async function shopifyFetch<T>({
   }
 }
 
-async function adminFetch<T>({
+async function shopifyAdminFetch<T>({
   headers,
   query,
   variables,
@@ -313,7 +314,7 @@ export async function shopifyCustomerFetch<T>({
   }
 }
 
-const removeEdgesAndNodes = (array: Connection<any>) => {
+const removeEdgesAndNodes = <T = any>(array: Connection<T>) => {
   return array.edges.map((edge) => edge?.node);
 };
 
@@ -439,7 +440,7 @@ const reshapeImages = (images: Connection<Image>, productTitle: string) => {
   const flattened = removeEdgesAndNodes(images);
 
   return flattened.map((image) => {
-    const filename = image.url.match(/.*\/(.*)\..*/)[1];
+    const filename = (image.url.match(/.*\/(.*)\..*/) || [])[1];
     return {
       ...image,
       altText: image.altText || `${productTitle} - ${filename}`
@@ -531,8 +532,7 @@ function reshapeOrders(orders: ShopifyOrder[]): any[] | Promise<Order[]> {
 }
 
 function reshapeOrder(shopifyOrder: ShopifyOrder): Order {
-  const reshapeAddress = (address?: ShopifyAddress): Address | undefined => {
-    if (!address) return undefined;
+  const reshapeAddress = (address: ShopifyAddress): Address => {
     return {
       address1: address.address1,
       address2: address.address2,
@@ -547,8 +547,7 @@ function reshapeOrder(shopifyOrder: ShopifyOrder): Order {
     };
   };
 
-  const reshapeMoney = (money?: ShopifyMoneyV2): Money | undefined => {
-    if (!money) return undefined;
+  const reshapeMoney = (money: ShopifyMoneyV2): Money => {
     return {
       amount: money.amount || '0.00',
       currencyCode: money.currencyCode || 'USD'
@@ -619,23 +618,38 @@ function reshapeOrder(shopifyOrder: ShopifyOrder): Order {
     totalShipping: reshapeMoney(shopifyOrder.totalShipping),
     totalTax: reshapeMoney(shopifyOrder.totalTax),
     totalPrice: reshapeMoney(shopifyOrder.totalPrice),
-    createdAt: shopifyOrder.createdAt
+    createdAt: shopifyOrder.createdAt,
+    shippingMethod: {
+      name: shopifyOrder.shippingLine?.title,
+      price: reshapeMoney(shopifyOrder.shippingLine.originalPrice)!
+    },
+    warrantyActivationDeadline: shopifyOrder.warrantyActivationDeadline,
+    warrantyStatus: shopifyOrder.warrantyStatus,
+    warrantyActivationInstallation: shopifyOrder.warrantyActivationInstallation,
+    warrantyActivationMileage: shopifyOrder.warrantyActivationMileage,
+    warrantyActivationOdometer: shopifyOrder.warrantyActivationOdometer,
+    warrantyActivationSelfInstall: shopifyOrder.warrantyActivationSelfInstall,
+    warrantyActivationVIN: shopifyOrder.warrantyActivationVIN,
+    orderConfirmation: shopifyOrder.orderConfirmation
   };
 
   if (shopifyOrder.customer) {
     order.customer = reshapeCustomer(shopifyOrder.customer);
   }
 
-  if (shopifyOrder.shippingLine) {
-    order.shippingMethod = {
-      name: shopifyOrder.shippingLine?.title,
-      price: reshapeMoney(shopifyOrder.shippingLine.originalPrice)!
-    };
-  }
-
   return order;
 }
 
+export function reshapeOrderConfirmationPdf(
+  metaobject: ShopifyMetaobject
+): OrderConfirmationContent {
+  return {
+    body: metaobject.fields.find((field) => field.key === 'body')?.value || '',
+    logo: metaobject.fields.find((field) => field.key === 'logo')?.reference.image!,
+    color: metaobject.fields.find((field) => field.key === 'color')?.value || '#000000'
+  };
+}
+
 export async function createCart(): Promise<Cart> {
   const res = await shopifyFetch<ShopifyCreateCartOperation>({
     query: createCartMutation,
@@ -874,6 +888,31 @@ export async function getMetaobjects(type: string) {
   return reshapeMetaobjects(removeEdgesAndNodes(res.body.data.metaobjects));
 }
 
+export async function getAllMetaobjects(type: string) {
+  const allMetaobjects: Metaobject[] = [];
+  let hasNextPage = true;
+  let after: string | undefined;
+
+  while (hasNextPage) {
+    const res = await shopifyFetch<ShopifyMetaobjectsOperation>({
+      query: getMetaobjectsQuery,
+      tags: [TAGS.collections, TAGS.products],
+      variables: { type, after }
+    });
+
+    const metaobjects = reshapeMetaobjects(removeEdgesAndNodes(res.body.data.metaobjects));
+
+    for (const metaobject of metaobjects) {
+      allMetaobjects.push(metaobject);
+    }
+
+    hasNextPage = res.body.data.metaobjects.pageInfo?.hasNextPage || false;
+    after = res.body.data.metaobjects.pageInfo?.endCursor;
+  }
+
+  return allMetaobjects;
+}
+
 export async function getMetaobjectsByIds(ids: string[]) {
   if (!ids.length) return [];
 
@@ -895,10 +934,7 @@ export async function getMetaobject({
   id?: string;
   handle?: { handle: string; type: string };
 }) {
-  const res = await shopifyFetch<{
-    data: { metaobject: ShopifyMetaobject };
-    variables: { id?: string; handle?: { handle: string; type: string } };
-  }>({
+  const res = await shopifyFetch<ShopifyMetaobjectOperation>({
     query: getMetaobjectQuery,
     variables: { id, handle }
   });
@@ -906,6 +942,15 @@ export async function getMetaobject({
   return res.body.data.metaobject ? reshapeMetaobjects([res.body.data.metaobject])[0] : null;
 }
 
+export async function getOrderConfirmationContent(): Promise<OrderConfirmationContent> {
+  const res = await shopifyFetch<ShopifyMetaobjectOperation>({
+    query: getMetaobjectQuery,
+    variables: { handle: { handle: 'order-confirmation-pdf', type: 'order_confirmation_pdf' } }
+  });
+
+  return reshapeOrderConfirmationPdf(res.body.data.metaobject);
+}
+
 export async function getPage(handle: string): Promise<Page> {
   const res = await shopifyFetch<ShopifyPageOperation>({
     query: getPageQuery,
@@ -1064,7 +1109,7 @@ export const getImage = async (id: string): Promise<Image> => {
 };
 
 export const stageUploadFile = async (params: UploadInput) => {
-  const res = await adminFetch<ShopifyStagedUploadOperation>({
+  const res = await shopifyAdminFetch<ShopifyStagedUploadOperation>({
     query: createStageUploads,
     variables: { input: [params] }
   });
@@ -1080,7 +1125,7 @@ export const uploadFile = async ({ url, formData }: { url: string; formData: For
 };
 
 export const createFile = async (params: FileCreateInput) => {
-  const res = await adminFetch<ShopifyCreateFileOperation>({
+  const res = await shopifyAdminFetch<ShopifyCreateFileOperation>({
     query: createFileMutation,
     variables: { files: [params] }
   });
@@ -1103,7 +1148,7 @@ export const updateOrderMetafields = async ({
     validMetafields.find(({ key }) => (Array.isArray(field) ? field.includes(key) : key === field))
   );
 
-  const response = await adminFetch<ShopifyUpdateOrderMetafieldsOperation>({
+  const response = await shopifyAdminFetch<ShopifyUpdateOrderMetafieldsOperation>({
     query: updateOrderMetafieldsMutation,
     variables: {
       input: {
@@ -1125,59 +1170,6 @@ export const updateOrderMetafields = async ({
   return response.body.data.orderUpdate.order.id;
 };
 
-export const getOrdersMetafields = async (): Promise<{ [key: string]: ShopifyOrderMetafield }> => {
-  const customer = await getCustomer();
-  const res = await adminFetch<{
-    data: {
-      customer: {
-        orders: {
-          nodes: Array<
-            {
-              id: string;
-            } & ShopifyOrderMetafield
-          >;
-        };
-      };
-    };
-    variables: {
-      id: string;
-    };
-  }>({
-    query: getCustomerOrderMetafieldsQuery,
-    variables: { id: customer.id },
-    tags: [TAGS.orderMetafields]
-  });
-
-  return res.body.data.customer.orders.nodes.reduce(
-    (acc, order) => ({
-      ...acc,
-      [order.id]: order
-    }),
-    {} as { [key: string]: ShopifyOrderMetafield }
-  );
-};
-
-export const getOrderMetafields = async (orderId: string): Promise<ShopifyOrderMetafield> => {
-  const res = await adminFetch<{
-    data: {
-      order: {
-        id: string;
-      } & ShopifyOrderMetafield;
-    };
-    variables: {
-      id: string;
-    };
-  }>({
-    query: getOrderMetafieldsQuery,
-    variables: { id: `gid://shopify/Order/${orderId}` },
-    tags: [TAGS.orderMetafields]
-  });
-
-  const order = res.body.data.order;
-
-  return order;
-};
-
 export const getFile = async (id: string) => {
   const res = await shopifyFetch<{
     data: {
diff --git a/lib/shopify/queries/metaobject.ts b/lib/shopify/queries/metaobject.ts
index 70270821f..2c63e3696 100644
--- a/lib/shopify/queries/metaobject.ts
+++ b/lib/shopify/queries/metaobject.ts
@@ -1,6 +1,6 @@
 export const getMetaobjectsQuery = /* GraphQL */ `
-  query getMetaobjects($type: String!) {
-    metaobjects(type: $type, first: 200) {
+  query getMetaobjects($type: String!, $after: String) {
+    metaobjects(type: $type, first: 200, after: $after) {
       edges {
         node {
           id
@@ -16,6 +16,10 @@ export const getMetaobjectsQuery = /* GraphQL */ `
           }
         }
       }
+      pageInfo {
+        hasNextPage
+        endCursor
+      }
     }
   }
 `;
@@ -30,6 +34,14 @@ export const getMetaobjectQuery = /* GraphQL */ `
           ... on Metaobject {
             id
           }
+          ... on MediaImage {
+            image {
+              url
+              altText
+              height
+              width
+            }
+          }
         }
         key
         value
diff --git a/lib/shopify/queries/order.ts b/lib/shopify/queries/order.ts
index 58b47a282..3680aaa23 100644
--- a/lib/shopify/queries/order.ts
+++ b/lib/shopify/queries/order.ts
@@ -1,8 +1,11 @@
+import addressFragment from '../fragments/address';
 import lineItemFragment from '../fragments/line-item';
-import { orderMetafields } from '../fragments/order';
+import orderMetafieldsFragment from '../fragments/order-metafields';
+import orderTrasactionFragment from '../fragments/order-transaction';
+import priceFragment from '../fragments/price';
 
 // NOTE: https://shopify.dev/docs/api/customer/latest/queries/customer
-export const getCustomerOrderQuery = /* GraphQL */ `
+const getCustomerOrderQuery = /* GraphQL */ `
   query getCustomerOrderQuery($orderId: ID!) {
     customer {
       emailAddress {
@@ -95,60 +98,7 @@ export const getCustomerOrderQuery = /* GraphQL */ `
         ...Price
       }
     }
-  }
-
-  fragment OrderTransaction on OrderTransaction {
-    id
-    processedAt
-    paymentIcon {
-      id
-      url
-      altText
-    }
-    paymentDetails {
-      ... on CardPaymentDetails {
-        last4
-        cardBrand
-      }
-    }
-    transactionAmount {
-      presentmentMoney {
-        ...Price
-      }
-    }
-    giftCardDetails {
-      last4
-      balance {
-        ...Price
-      }
-    }
-    status
-    kind
-    transactionParentId
-    type
-    typeDetails {
-      name
-      message
-    }
-  }
-
-  fragment Price on MoneyV2 {
-    amount
-    currencyCode
-  }
-
-  fragment Address on CustomerAddress {
-    id
-    address1
-    address2
-    firstName
-    lastName
-    provinceCode: zoneCode
-    city
-    zip
-    countryCodeV2: territoryCode
-    company
-    phone: phoneNumber
+    ...OrderMetafields
   }
 
   fragment Fulfillment on Fulfillment {
@@ -220,13 +170,10 @@ export const getCustomerOrderQuery = /* GraphQL */ `
     }
   }
   ${lineItemFragment}
+  ${addressFragment}
+  ${priceFragment}
+  ${orderTrasactionFragment}
+  ${orderMetafieldsFragment}
 `;
 
-export const getOrderMetafieldsQuery = /* GraphQL */ `
-  query getOrderMetafields($id: ID!) {
-    order(id: $id) {
-      ...OrderMetafield
-    }
-  }
-  ${orderMetafields}
-`;
+export default getCustomerOrderQuery;
diff --git a/lib/shopify/queries/orders.ts b/lib/shopify/queries/orders.ts
index 27a840428..1c55a2b9a 100644
--- a/lib/shopify/queries/orders.ts
+++ b/lib/shopify/queries/orders.ts
@@ -1,5 +1,4 @@
 import customerDetailsFragment from '../fragments/customer-details';
-import { orderMetafields } from '../fragments/order';
 
 const customerFragment = `#graphql
 `;
@@ -14,16 +13,3 @@ export const getCustomerOrdersQuery = `#graphql
   ${customerFragment}
   ${customerDetailsFragment}
 `;
-
-export const getCustomerOrderMetafieldsQuery = /* GraphQL */ `
-  query getCustomerOrderMetafields($id: ID!) {
-    customer(id: $id) {
-      orders(first: 20, sortKey: PROCESSED_AT, reverse: true) {
-        nodes {
-          ...OrderMetafield
-        }
-      }
-    }
-  }
-  ${orderMetafields}
-`;
diff --git a/lib/shopify/types.ts b/lib/shopify/types.ts
index 049c7b715..5c63c5669 100644
--- a/lib/shopify/types.ts
+++ b/lib/shopify/types.ts
@@ -3,6 +3,7 @@ export type Maybe<T> = T | null;
 
 export type Connection<T> = {
   edges: Array<Edge<T>>;
+  pageInfo?: PageInfo;
 };
 
 export type Edge<T> = {
@@ -141,18 +142,18 @@ export type Order = {
   fulfillments: Fulfillment[];
   transactions: Transaction[];
   lineItems: LineItem[];
-  shippingAddress?: Address;
-  billingAddress?: Address;
+  shippingAddress: Address;
+  billingAddress: Address;
   /** the price of all line items, excluding taxes and surcharges */
-  subtotal?: Money;
-  totalShipping?: Money;
-  totalTax?: Money;
-  totalPrice?: Money;
-  shippingMethod?: {
+  subtotal: Money;
+  totalShipping: Money;
+  totalTax: Money;
+  totalPrice: Money;
+  shippingMethod: {
     name: string;
     price: Money;
   };
-};
+} & ShopifyOrderMetafield;
 
 export type ShopifyOrder = {
   id: string;
@@ -181,7 +182,7 @@ export type ShopifyOrder = {
   requiresShipping: boolean;
   shippingLine: ShopifyShippingLine;
   note: string | null;
-};
+} & ShopifyOrderMetafield;
 
 type ShopifyShippingLine = {
   title: string;
@@ -372,16 +373,30 @@ export type ShopifyMetaobject = {
     value: string;
     reference: {
       id: string;
+      image?: Image;
     };
   }>;
 };
 
+export type ShopifyMetafield = {
+  id: string;
+  namespace: string;
+  key: string;
+  value: string;
+};
+
 export type Metaobject = {
   id: string;
   type: string;
   [key: string]: string;
 };
 
+export type OrderConfirmationContent = {
+  logo: Image;
+  body: string;
+  color: string;
+};
+
 export type TransmissionType = 'Automatic' | 'Manual';
 
 export type Product = Omit<
@@ -665,7 +680,7 @@ export type ShopifyImageOperation = {
 
 export type ShopifyMetaobjectsOperation = {
   data: { metaobjects: Connection<ShopifyMetaobject> };
-  variables: { type: string };
+  variables: { type: string; after?: string };
 };
 
 export type ShopifyPagesOperation = {
@@ -675,8 +690,8 @@ export type ShopifyPagesOperation = {
 };
 
 export type ShopifyMetaobjectOperation = {
-  data: { nodes: ShopifyMetaobject[] };
-  variables: { ids: string[] };
+  data: { metaobject: ShopifyMetaobject };
+  variables: { id?: string; handle?: { handle: string; type: string } };
 };
 
 export type ShopifyProductOperation = {
@@ -858,20 +873,15 @@ export enum WarrantyStatus {
   LimitedActivated = 'Limited Activation'
 }
 
-export type OrderMetafieldValue<T = string> = {
-  value: T;
-  id: string;
-  key: string;
-};
-
 export type ShopifyOrderMetafield = {
-  warrantyStatus: OrderMetafieldValue | null;
-  warrantyActivationDeadline: OrderMetafieldValue | null;
-  warrantyActivationOdometer: OrderMetafieldValue | null;
-  warrantyActivationInstallation: OrderMetafieldValue | null;
-  warrantyActivationSelfInstall: OrderMetafieldValue | null;
-  warrantyActivationVIN: OrderMetafieldValue | null;
-  warrantyActivationMileage: OrderMetafieldValue | null;
+  orderConfirmation: ShopifyMetafield | null;
+  warrantyStatus: ShopifyMetafield | null;
+  warrantyActivationDeadline: ShopifyMetafield | null;
+  warrantyActivationOdometer: ShopifyMetafield | null;
+  warrantyActivationInstallation: ShopifyMetafield | null;
+  warrantyActivationSelfInstall: ShopifyMetafield | null;
+  warrantyActivationVIN: ShopifyMetafield | null;
+  warrantyActivationMileage: ShopifyMetafield | null;
 };
 
 export type File = {
diff --git a/lib/styles.ts b/lib/styles.ts
index 6c6a67e86..d24035282 100644
--- a/lib/styles.ts
+++ b/lib/styles.ts
@@ -5,7 +5,7 @@ export const carPartPlanetColor = {
     muted: '#E6CCB7'
   },
   content: {
-    subtle: '#9ca3af', // gray-400
+    subtle: '#d1d5db', // gray-300
     DEFAULT: '#6b7280', // gray-500
     emphasis: '#374151', // gray-700
     strong: '#111827', // gray-900
diff --git a/lib/utils.ts b/lib/utils.ts
index 8e03f335a..b5715b9d3 100644
--- a/lib/utils.ts
+++ b/lib/utils.ts
@@ -3,6 +3,34 @@ import { ReadonlyURLSearchParams } from 'next/navigation';
 import { twMerge } from 'tailwind-merge';
 import { Menu } from './shopify/types';
 
+export function cx(...args: ClassValue[]) {
+  return twMerge(clsx(...args));
+}
+export const focusInput = [
+  // base
+  'focus:ring-2',
+  // ring color
+  'focus:ring-blue-200 focus:dark:ring-blue-700/30',
+  // border color
+  'focus:border-blue-500 focus:dark:border-blue-700'
+];
+
+export const hasErrorInput = [
+  // base
+  'ring-2',
+  // border color
+  'border-red-500 dark:border-red-700',
+  // ring color
+  'ring-red-200 dark:ring-red-700/30'
+];
+
+export const focusRing = [
+  // base
+  'outline outline-offset-2 outline-0 focus-visible:outline-2',
+  // outline color
+  'outline-blue-500 dark:outline-blue-500'
+];
+
 export const createUrl = (pathname: string, params: URLSearchParams | ReadonlyURLSearchParams) => {
   const paramsString = params.toString();
   const queryString = `${paramsString.length ? '?' : ''}${paramsString}`;
diff --git a/package.json b/package.json
index 5251cbf2b..f9ef027d5 100644
--- a/package.json
+++ b/package.json
@@ -25,12 +25,17 @@
     "@headlessui/react": "^2.1.0",
     "@heroicons/react": "^2.1.3",
     "@hookform/resolvers": "^3.6.0",
+    "@radix-ui/react-checkbox": "^1.0.4",
+    "@radix-ui/react-label": "^2.1.0",
+    "@radix-ui/react-popover": "^1.1.1",
     "@radix-ui/react-slot": "^1.0.2",
+    "@react-pdf/renderer": "^3.4.4",
     "clsx": "^2.1.0",
     "geist": "^1.3.0",
     "lodash.get": "^4.4.2",
     "lodash.kebabcase": "^4.1.1",
     "lodash.startcase": "^4.4.0",
+    "markdown-to-jsx": "^7.4.7",
     "next": "14.2.4",
     "react": "18.2.0",
     "react-dom": "18.2.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index eedcb4fc1..601c223d1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -17,9 +17,21 @@ importers:
       '@hookform/resolvers':
         specifier: ^3.6.0
         version: 3.6.0(react-hook-form@7.51.5(react@18.2.0))
+      '@radix-ui/react-checkbox':
+        specifier: ^1.0.4
+        version: 1.1.1(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-label':
+        specifier: ^2.1.0
+        version: 2.1.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-popover':
+        specifier: ^1.1.1
+        version: 1.1.1(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
       '@radix-ui/react-slot':
         specifier: ^1.0.2
         version: 1.0.2(@types/react@18.2.72)(react@18.2.0)
+      '@react-pdf/renderer':
+        specifier: ^3.4.4
+        version: 3.4.4(react@18.2.0)
       clsx:
         specifier: ^2.1.0
         version: 2.1.0
@@ -35,6 +47,9 @@ importers:
       lodash.startcase:
         specifier: ^4.4.0
         version: 4.4.0
+      markdown-to-jsx:
+        specifier: ^7.4.7
+        version: 7.4.7(react@18.2.0)
       next:
         specifier: 14.2.4
         version: 14.2.4(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
@@ -318,6 +333,35 @@ packages:
     resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
     engines: {node: '>=14'}
 
+  '@radix-ui/primitive@1.1.0':
+    resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==}
+
+  '@radix-ui/react-arrow@1.1.0':
+    resolution: {integrity: sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==}
+    peerDependencies:
+      '@types/react': '*'
+      '@types/react-dom': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+      '@types/react-dom':
+        optional: true
+
+  '@radix-ui/react-checkbox@1.1.1':
+    resolution: {integrity: sha512-0i/EKJ222Afa1FE0C6pNJxDq1itzcl3HChE9DwskA4th4KRse8ojx8a1nVcOjwJdbpDLcz7uol77yYnQNMHdKw==}
+    peerDependencies:
+      '@types/react': '*'
+      '@types/react-dom': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+      '@types/react-dom':
+        optional: true
+
   '@radix-ui/react-compose-refs@1.0.1':
     resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==}
     peerDependencies:
@@ -327,6 +371,146 @@ packages:
       '@types/react':
         optional: true
 
+  '@radix-ui/react-compose-refs@1.1.0':
+    resolution: {integrity: sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==}
+    peerDependencies:
+      '@types/react': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
+  '@radix-ui/react-context@1.1.0':
+    resolution: {integrity: sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==}
+    peerDependencies:
+      '@types/react': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
+  '@radix-ui/react-dismissable-layer@1.1.0':
+    resolution: {integrity: sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==}
+    peerDependencies:
+      '@types/react': '*'
+      '@types/react-dom': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+      '@types/react-dom':
+        optional: true
+
+  '@radix-ui/react-focus-guards@1.1.0':
+    resolution: {integrity: sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==}
+    peerDependencies:
+      '@types/react': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
+  '@radix-ui/react-focus-scope@1.1.0':
+    resolution: {integrity: sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==}
+    peerDependencies:
+      '@types/react': '*'
+      '@types/react-dom': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+      '@types/react-dom':
+        optional: true
+
+  '@radix-ui/react-id@1.1.0':
+    resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==}
+    peerDependencies:
+      '@types/react': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
+  '@radix-ui/react-label@2.1.0':
+    resolution: {integrity: sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==}
+    peerDependencies:
+      '@types/react': '*'
+      '@types/react-dom': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+      '@types/react-dom':
+        optional: true
+
+  '@radix-ui/react-popover@1.1.1':
+    resolution: {integrity: sha512-3y1A3isulwnWhvTTwmIreiB8CF4L+qRjZnK1wYLO7pplddzXKby/GnZ2M7OZY3qgnl6p9AodUIHRYGXNah8Y7g==}
+    peerDependencies:
+      '@types/react': '*'
+      '@types/react-dom': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+      '@types/react-dom':
+        optional: true
+
+  '@radix-ui/react-popper@1.2.0':
+    resolution: {integrity: sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==}
+    peerDependencies:
+      '@types/react': '*'
+      '@types/react-dom': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+      '@types/react-dom':
+        optional: true
+
+  '@radix-ui/react-portal@1.1.1':
+    resolution: {integrity: sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g==}
+    peerDependencies:
+      '@types/react': '*'
+      '@types/react-dom': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+      '@types/react-dom':
+        optional: true
+
+  '@radix-ui/react-presence@1.1.0':
+    resolution: {integrity: sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==}
+    peerDependencies:
+      '@types/react': '*'
+      '@types/react-dom': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+      '@types/react-dom':
+        optional: true
+
+  '@radix-ui/react-primitive@2.0.0':
+    resolution: {integrity: sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==}
+    peerDependencies:
+      '@types/react': '*'
+      '@types/react-dom': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+      react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+      '@types/react-dom':
+        optional: true
+
   '@radix-ui/react-slot@1.0.2':
     resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==}
     peerDependencies:
@@ -336,6 +520,81 @@ packages:
       '@types/react':
         optional: true
 
+  '@radix-ui/react-slot@1.1.0':
+    resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==}
+    peerDependencies:
+      '@types/react': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
+  '@radix-ui/react-use-callback-ref@1.1.0':
+    resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==}
+    peerDependencies:
+      '@types/react': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
+  '@radix-ui/react-use-controllable-state@1.1.0':
+    resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==}
+    peerDependencies:
+      '@types/react': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
+  '@radix-ui/react-use-escape-keydown@1.1.0':
+    resolution: {integrity: sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==}
+    peerDependencies:
+      '@types/react': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
+  '@radix-ui/react-use-layout-effect@1.1.0':
+    resolution: {integrity: sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==}
+    peerDependencies:
+      '@types/react': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
+  '@radix-ui/react-use-previous@1.1.0':
+    resolution: {integrity: sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==}
+    peerDependencies:
+      '@types/react': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
+  '@radix-ui/react-use-rect@1.1.0':
+    resolution: {integrity: sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==}
+    peerDependencies:
+      '@types/react': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
+  '@radix-ui/react-use-size@1.1.0':
+    resolution: {integrity: sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==}
+    peerDependencies:
+      '@types/react': '*'
+      react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
+  '@radix-ui/rect@1.1.0':
+    resolution: {integrity: sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==}
+
   '@react-aria/focus@3.17.1':
     resolution: {integrity: sha512-FLTySoSNqX++u0nWZJPPN5etXY0WBxaIe/YuL/GTEeuqUIuC/2bJSaw5hlsM6T2yjy6Y/VAxBcKSdAFUlU6njQ==}
     peerDependencies:
@@ -357,6 +616,44 @@ packages:
     peerDependencies:
       react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0
 
+  '@react-pdf/fns@2.2.1':
+    resolution: {integrity: sha512-s78aDg0vDYaijU5lLOCsUD+qinQbfOvcNeaoX9AiE7+kZzzCo6B/nX+l48cmt9OosJmvZvE9DWR9cLhrhOi2pA==}
+
+  '@react-pdf/font@2.5.1':
+    resolution: {integrity: sha512-Hyb2zBb92Glc3lvhmJfy4dO2Mj29KB26Uk12Ua9EhKAdiuCTLBqgP8Oe1cGwrvDI7xA4OOcwvBMdYh0vhOUHzA==}
+
+  '@react-pdf/image@2.3.6':
+    resolution: {integrity: sha512-7iZDYZrZlJqNzS6huNl2XdMcLFUo68e6mOdzQeJ63d5eApdthhSHBnkGzHfLhH5t8DCpZNtClmklzuLL63ADfw==}
+
+  '@react-pdf/layout@3.12.1':
+    resolution: {integrity: sha512-BxSeykDxvADlpe4OGtQ7NH46QXq3uImAYsTHOPLCwbXMniQ1O3uCBx7H+HthxkCNshgYVPp9qS3KyvQv/oIZwg==}
+
+  '@react-pdf/pdfkit@3.1.10':
+    resolution: {integrity: sha512-P/qPBtCFo2HDJD0i6NfbmoBRrsOVO8CIogYsefwG4fklTo50zNgnMM5U1WLckTuX8Qt1ThiQuokmTG5arheblA==}
+
+  '@react-pdf/png-js@2.3.1':
+    resolution: {integrity: sha512-pEZ18I4t1vAUS4lmhvXPmXYP4PHeblpWP/pAlMMRkEyP7tdAeHUN7taQl9sf9OPq7YITMY3lWpYpJU6t4CZgZg==}
+
+  '@react-pdf/primitives@3.1.1':
+    resolution: {integrity: sha512-miwjxLwTnO3IjoqkTVeTI+9CdyDggwekmSLhVCw+a/7FoQc+gF3J2dSKwsHvAcVFM0gvU8mzCeTofgw0zPDq0w==}
+
+  '@react-pdf/render@3.4.4':
+    resolution: {integrity: sha512-CfGxWmVgrY3JgmB1iMnz2W6Ck+8pisZeFt8vGlxP+JfT+0onr208pQvGSV5KwA9LGhAdABxqc/+y17V3vtKdFA==}
+
+  '@react-pdf/renderer@3.4.4':
+    resolution: {integrity: sha512-j1TWMHHXDeHdoQE3xjhBh0MZ2rn7wHIlP/uglr/EJZXqnPbfg6bfLzRJCM6bs+XJV3d8+zLQjHf6sF/fWcBDfg==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0 || ^18.0.0
+
+  '@react-pdf/stylesheet@4.2.5':
+    resolution: {integrity: sha512-XnmapeCW+hDuNdVwpuvO04WKv71wAs8aH+saIq29Bo2fp1SxznHTcQArTZtK6Wgr/E9BHXeB2iAPpUZuI6G+xA==}
+
+  '@react-pdf/textkit@4.4.1':
+    resolution: {integrity: sha512-Jl9wdTqIvJ5pX+vAGz0EOhP7ut5Two9H6CzTKo/YYPeD79cM2yTXF3JzTERBC28y7LR0Waq9D2LHQjI+b/EYUQ==}
+
+  '@react-pdf/types@2.5.0':
+    resolution: {integrity: sha512-XsVRkt0hQ60I4e3leAVt+aZR3KJCaJd179BfJHAv4F4x6Vq3yqkry8lcbUWKGKDw1j3/8sW4FsgGR41SFvsG9A==}
+
   '@react-stately/utils@3.10.1':
     resolution: {integrity: sha512-VS/EHRyicef25zDZcM/ClpzYMC5i2YGN6uegOeQawmgfGjb02yaCX0F0zR69Pod9m2Hr3wunTbtpgVXvYbZItg==}
     peerDependencies:
@@ -373,6 +670,12 @@ packages:
   '@swc/counter@0.1.3':
     resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
 
+  '@swc/helpers@0.4.14':
+    resolution: {integrity: sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==}
+
+  '@swc/helpers@0.4.36':
+    resolution: {integrity: sha512-5lxnyLEYFskErRPenYItLRSge5DjrJngYKdVjRSrWfza9G6KkgHEXi0vUZiyUeMU5JfXH1YnvXZzSp8ul88o2Q==}
+
   '@swc/helpers@0.5.5':
     resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==}
 
@@ -472,6 +775,9 @@ packages:
   '@vercel/git-hooks@1.0.0':
     resolution: {integrity: sha512-OxDFAAdyiJ/H0b8zR9rFCu3BIb78LekBXOphOYG3snV4ULhKFX387pBPpqZ9HLiRTejBWBxYEahkw79tuIgdAA==}
 
+  abs-svg-path@0.1.1:
+    resolution: {integrity: sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==}
+
   acorn-jsx@5.3.2:
     resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
     peerDependencies:
@@ -522,6 +828,10 @@ packages:
   argparse@2.0.1:
     resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
 
+  aria-hidden@1.2.4:
+    resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==}
+    engines: {node: '>=10'}
+
   aria-query@5.3.0:
     resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
 
@@ -587,6 +897,12 @@ packages:
   balanced-match@1.0.2:
     resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
 
+  base64-js@1.5.1:
+    resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+
+  bidi-js@1.0.3:
+    resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==}
+
   binary-extensions@2.3.0:
     resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
     engines: {node: '>=8'}
@@ -601,6 +917,12 @@ packages:
     resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
     engines: {node: '>=8'}
 
+  brotli@1.3.3:
+    resolution: {integrity: sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==}
+
+  browserify-zlib@0.2.0:
+    resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==}
+
   browserslist@4.23.0:
     resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==}
     engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
@@ -667,6 +989,10 @@ packages:
   client-only@0.0.1:
     resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
 
+  clone@2.1.2:
+    resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==}
+    engines: {node: '>=0.8'}
+
   clsx@2.1.0:
     resolution: {integrity: sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==}
     engines: {node: '>=6'}
@@ -684,6 +1010,9 @@ packages:
   color-name@1.1.4:
     resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
 
+  color-string@1.9.1:
+    resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
+
   colorette@2.0.20:
     resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
 
@@ -701,10 +1030,16 @@ packages:
   core-js-compat@3.36.1:
     resolution: {integrity: sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==}
 
+  cross-fetch@3.1.8:
+    resolution: {integrity: sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==}
+
   cross-spawn@7.0.3:
     resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
     engines: {node: '>= 8'}
 
+  crypto-js@4.2.0:
+    resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
+
   cssesc@3.0.0:
     resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
     engines: {node: '>=4'}
@@ -760,6 +1095,12 @@ packages:
     resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
     engines: {node: '>=6'}
 
+  detect-node-es@1.1.0:
+    resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
+
+  dfa@1.2.0:
+    resolution: {integrity: sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==}
+
   didyoumean@1.2.2:
     resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
 
@@ -959,6 +1300,10 @@ packages:
   eventemitter3@5.0.1:
     resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==}
 
+  events@3.3.0:
+    resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==}
+    engines: {node: '>=0.8.x'}
+
   execa@8.0.1:
     resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
     engines: {node: '>=16.17'}
@@ -1002,6 +1347,9 @@ packages:
   flatted@3.3.1:
     resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
 
+  fontkit@2.0.2:
+    resolution: {integrity: sha512-jc4k5Yr8iov8QfS6u8w2CnHWVmbOGtdBtOXMze5Y+QD966Rx6PEVWXSEGwXlsDlKtu1G12cJjcsybnqhSk/+LA==}
+
   for-each@0.3.3:
     resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
 
@@ -1043,6 +1391,10 @@ packages:
     resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==}
     engines: {node: '>= 0.4'}
 
+  get-nonce@1.0.1:
+    resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==}
+    engines: {node: '>=6'}
+
   get-stream@8.0.1:
     resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
     engines: {node: '>=16'}
@@ -1124,10 +1476,19 @@ packages:
   hosted-git-info@2.8.9:
     resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
 
+  hsl-to-hex@1.0.0:
+    resolution: {integrity: sha512-K6GVpucS5wFf44X0h2bLVRDsycgJmf9FF2elg+CrqD8GcFU8c6vYhgXn8NjUkFCwj+xDFb70qgLbTUm6sxwPmA==}
+
+  hsl-to-rgb-for-reals@1.1.1:
+    resolution: {integrity: sha512-LgOWAkrN0rFaQpfdWBQlv/VhkOxb5AsBjk6NQVx4yEzWS923T07X0M1Y0VNko2H52HeSpZrZNNMJ0aFqsdVzQg==}
+
   human-signals@5.0.0:
     resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
     engines: {node: '>=16.17.0'}
 
+  hyphen@1.10.4:
+    resolution: {integrity: sha512-SejXzIpv9gOVdDWXd4suM1fdF1k2dxZGvuTdkOVLoazYfK7O4DykIQbdrvuyG+EaTNlXAGhMndtKrhykgbt0gg==}
+
   ignore@5.3.1:
     resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
     engines: {node: '>= 4'}
@@ -1154,6 +1515,9 @@ packages:
     resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==}
     engines: {node: '>= 0.4'}
 
+  invariant@2.2.4:
+    resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==}
+
   is-array-buffer@3.0.4:
     resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==}
     engines: {node: '>= 0.4'}
@@ -1161,6 +1525,9 @@ packages:
   is-arrayish@0.2.1:
     resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
 
+  is-arrayish@0.3.2:
+    resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
+
   is-async-function@2.0.0:
     resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==}
     engines: {node: '>= 0.4'}
@@ -1270,6 +1637,9 @@ packages:
     resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==}
     engines: {node: '>= 0.4'}
 
+  is-url@1.2.4:
+    resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==}
+
   is-weakmap@2.0.2:
     resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
     engines: {node: '>= 0.4'}
@@ -1294,6 +1664,9 @@ packages:
     resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
     engines: {node: '>=14'}
 
+  jay-peg@1.0.2:
+    resolution: {integrity: sha512-fyV3NVvv6pTys/3BTapBUGAWAuU9rM2gRcgijZHzptd5KKL+s+S7hESFN+wOsbDH1MzFwdlRAXi0aGxS6uiMKg==}
+
   jiti@1.21.0:
     resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==}
     hasBin: true
@@ -1414,6 +1787,15 @@ packages:
     resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
     engines: {node: '>=10'}
 
+  markdown-to-jsx@7.4.7:
+    resolution: {integrity: sha512-0+ls1IQZdU6cwM1yu0ZjjiVWYtkbExSyUIFU2ZeDIFuZM1W42Mh4OlJ4nb4apX4H8smxDHRdFaoIVJGwfv5hkg==}
+    engines: {node: '>= 10'}
+    peerDependencies:
+      react: '>= 0.14.0'
+
+  media-engine@1.0.3:
+    resolution: {integrity: sha512-aa5tG6sDoK+k70B9iEX1NeyfT8ObCKhNDs6lJVpwF6r8vhUfuKMslIcirq6HIUYuuUYLefcEQOn9bSBOvawtwg==}
+
   merge-stream@2.0.0:
     resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
 
@@ -1490,6 +1872,15 @@ packages:
       sass:
         optional: true
 
+  node-fetch@2.7.0:
+    resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
+    engines: {node: 4.x || >=6.0.0}
+    peerDependencies:
+      encoding: ^0.1.0
+    peerDependenciesMeta:
+      encoding:
+        optional: true
+
   node-releases@2.0.14:
     resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
 
@@ -1504,6 +1895,9 @@ packages:
     resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
     engines: {node: '>=0.10.0'}
 
+  normalize-svg-path@1.1.0:
+    resolution: {integrity: sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg==}
+
   npm-run-path@5.3.0:
     resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -1582,6 +1976,12 @@ packages:
     resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
     engines: {node: '>=6'}
 
+  pako@0.2.9:
+    resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==}
+
+  pako@1.0.11:
+    resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
+
   parent-module@1.0.1:
     resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
     engines: {node: '>=6'}
@@ -1590,6 +1990,9 @@ packages:
     resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
     engines: {node: '>=8'}
 
+  parse-svg-path@0.1.2:
+    resolution: {integrity: sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==}
+
   path-exists@4.0.0:
     resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
     engines: {node: '>=8'}
@@ -1765,6 +2168,9 @@ packages:
   queue-microtask@1.2.3:
     resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
 
+  queue@6.0.2:
+    resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==}
+
   react-dom@18.2.0:
     resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
     peerDependencies:
@@ -1779,6 +2185,36 @@ packages:
   react-is@16.13.1:
     resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
 
+  react-remove-scroll-bar@2.3.6:
+    resolution: {integrity: sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==}
+    engines: {node: '>=10'}
+    peerDependencies:
+      '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
+      react: ^16.8.0 || ^17.0.0 || ^18.0.0
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
+  react-remove-scroll@2.5.7:
+    resolution: {integrity: sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==}
+    engines: {node: '>=10'}
+    peerDependencies:
+      '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
+      react: ^16.8.0 || ^17.0.0 || ^18.0.0
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
+  react-style-singleton@2.2.1:
+    resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==}
+    engines: {node: '>=10'}
+    peerDependencies:
+      '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
+      react: ^16.8.0 || ^17.0.0 || ^18.0.0
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
   react-tooltip@5.26.3:
     resolution: {integrity: sha512-MpYAws8CEHUd/RC4GaDCdoceph/T4KHM5vS5Dbk8FOmLMvvIht2ymP2htWdrke7K6lqPO8rz8+bnwWUIXeDlzg==}
     peerDependencies:
@@ -1823,6 +2259,10 @@ packages:
     resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==}
     hasBin: true
 
+  require-from-string@2.0.2:
+    resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
+    engines: {node: '>=0.10.0'}
+
   resolve-from@4.0.0:
     resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
     engines: {node: '>=4'}
@@ -1842,6 +2282,9 @@ packages:
     resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==}
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
 
+  restructure@3.0.2:
+    resolution: {integrity: sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==}
+
   reusify@1.0.4:
     resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
     engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
@@ -1860,10 +2303,16 @@ packages:
     resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==}
     engines: {node: '>=0.4'}
 
+  safe-buffer@5.2.1:
+    resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+
   safe-regex-test@1.0.3:
     resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==}
     engines: {node: '>= 0.4'}
 
+  scheduler@0.17.0:
+    resolution: {integrity: sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA==}
+
   scheduler@0.23.0:
     resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
 
@@ -1907,6 +2356,9 @@ packages:
     resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
     engines: {node: '>=14'}
 
+  simple-swizzle@0.2.2:
+    resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
+
   slash@3.0.0:
     resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
     engines: {node: '>=8'}
@@ -1970,6 +2422,9 @@ packages:
     resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
     engines: {node: '>= 0.4'}
 
+  string_decoder@1.3.0:
+    resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+
   strip-ansi@6.0.1:
     resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
     engines: {node: '>=8'}
@@ -2024,6 +2479,9 @@ packages:
     resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
     engines: {node: '>= 0.4'}
 
+  svg-arc-to-cubic-bezier@3.2.0:
+    resolution: {integrity: sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==}
+
   tabbable@6.2.0:
     resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
 
@@ -2055,10 +2513,16 @@ packages:
   thenify@3.3.1:
     resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
 
+  tiny-inflate@1.0.3:
+    resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==}
+
   to-regex-range@5.0.1:
     resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
     engines: {node: '>=8.0'}
 
+  tr46@0.0.3:
+    resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
+
   ts-api-utils@1.3.0:
     resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==}
     engines: {node: '>=16'}
@@ -2117,6 +2581,12 @@ packages:
   undici-types@5.26.5:
     resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
 
+  unicode-properties@1.4.1:
+    resolution: {integrity: sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==}
+
+  unicode-trie@2.0.0:
+    resolution: {integrity: sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==}
+
   update-browserslist-db@1.0.13:
     resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==}
     hasBin: true
@@ -2126,12 +2596,42 @@ packages:
   uri-js@4.4.1:
     resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
 
+  use-callback-ref@1.3.2:
+    resolution: {integrity: sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==}
+    engines: {node: '>=10'}
+    peerDependencies:
+      '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0
+      react: ^16.8.0 || ^17.0.0 || ^18.0.0
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
+  use-sidecar@1.1.2:
+    resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==}
+    engines: {node: '>=10'}
+    peerDependencies:
+      '@types/react': ^16.9.0 || ^17.0.0 || ^18.0.0
+      react: ^16.8.0 || ^17.0.0 || ^18.0.0
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+
   util-deprecate@1.0.2:
     resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
 
   validate-npm-package-license@3.0.4:
     resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
 
+  vite-compatible-readable-stream@3.6.1:
+    resolution: {integrity: sha512-t20zYkrSf868+j/p31cRIGN28Phrjm3nRSLR2fyc2tiWi4cZGVdv68yNlwnIINTkMTmPoMiSlc0OadaO7DXZaQ==}
+    engines: {node: '>= 6'}
+
+  webidl-conversions@3.0.1:
+    resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
+
+  whatwg-url@5.0.0:
+    resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
+
   which-boxed-primitive@1.0.2:
     resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
 
@@ -2183,6 +2683,9 @@ packages:
     resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
     engines: {node: '>=10'}
 
+  yoga-layout@2.0.1:
+    resolution: {integrity: sha512-tT/oChyDXelLo2A+UVnlW9GU7CsvFMaEnd9kVFsaiCQonFAXd3xrHhkLYu+suwwosrAEQ746xBU+HvYtm1Zs2Q==}
+
   zod@3.23.8:
     resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
 
@@ -2361,6 +2864,33 @@ snapshots:
   '@pkgjs/parseargs@0.11.0':
     optional: true
 
+  '@radix-ui/primitive@1.1.0': {}
+
+  '@radix-ui/react-arrow@1.1.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+    dependencies:
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      react: 18.2.0
+      react-dom: 18.2.0(react@18.2.0)
+    optionalDependencies:
+      '@types/react': 18.2.72
+      '@types/react-dom': 18.2.22
+
+  '@radix-ui/react-checkbox@1.1.1(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+    dependencies:
+      '@radix-ui/primitive': 1.1.0
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-context': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-use-previous': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-use-size': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      react: 18.2.0
+      react-dom: 18.2.0(react@18.2.0)
+    optionalDependencies:
+      '@types/react': 18.2.72
+      '@types/react-dom': 18.2.22
+
   '@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.72)(react@18.2.0)':
     dependencies:
       '@babel/runtime': 7.24.1
@@ -2368,6 +2898,134 @@ snapshots:
     optionalDependencies:
       '@types/react': 18.2.72
 
+  '@radix-ui/react-compose-refs@1.1.0(@types/react@18.2.72)(react@18.2.0)':
+    dependencies:
+      react: 18.2.0
+    optionalDependencies:
+      '@types/react': 18.2.72
+
+  '@radix-ui/react-context@1.1.0(@types/react@18.2.72)(react@18.2.0)':
+    dependencies:
+      react: 18.2.0
+    optionalDependencies:
+      '@types/react': 18.2.72
+
+  '@radix-ui/react-dismissable-layer@1.1.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+    dependencies:
+      '@radix-ui/primitive': 1.1.0
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      react: 18.2.0
+      react-dom: 18.2.0(react@18.2.0)
+    optionalDependencies:
+      '@types/react': 18.2.72
+      '@types/react-dom': 18.2.22
+
+  '@radix-ui/react-focus-guards@1.1.0(@types/react@18.2.72)(react@18.2.0)':
+    dependencies:
+      react: 18.2.0
+    optionalDependencies:
+      '@types/react': 18.2.72
+
+  '@radix-ui/react-focus-scope@1.1.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+    dependencies:
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      react: 18.2.0
+      react-dom: 18.2.0(react@18.2.0)
+    optionalDependencies:
+      '@types/react': 18.2.72
+      '@types/react-dom': 18.2.22
+
+  '@radix-ui/react-id@1.1.0(@types/react@18.2.72)(react@18.2.0)':
+    dependencies:
+      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      react: 18.2.0
+    optionalDependencies:
+      '@types/react': 18.2.72
+
+  '@radix-ui/react-label@2.1.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+    dependencies:
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      react: 18.2.0
+      react-dom: 18.2.0(react@18.2.0)
+    optionalDependencies:
+      '@types/react': 18.2.72
+      '@types/react-dom': 18.2.22
+
+  '@radix-ui/react-popover@1.1.1(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+    dependencies:
+      '@radix-ui/primitive': 1.1.0
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-context': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-id': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-slot': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      aria-hidden: 1.2.4
+      react: 18.2.0
+      react-dom: 18.2.0(react@18.2.0)
+      react-remove-scroll: 2.5.7(@types/react@18.2.72)(react@18.2.0)
+    optionalDependencies:
+      '@types/react': 18.2.72
+      '@types/react-dom': 18.2.22
+
+  '@radix-ui/react-popper@1.2.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+    dependencies:
+      '@floating-ui/react-dom': 2.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-arrow': 1.1.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-context': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-use-rect': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-use-size': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/rect': 1.1.0
+      react: 18.2.0
+      react-dom: 18.2.0(react@18.2.0)
+    optionalDependencies:
+      '@types/react': 18.2.72
+      '@types/react-dom': 18.2.22
+
+  '@radix-ui/react-portal@1.1.1(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+    dependencies:
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
+      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      react: 18.2.0
+      react-dom: 18.2.0(react@18.2.0)
+    optionalDependencies:
+      '@types/react': 18.2.72
+      '@types/react-dom': 18.2.22
+
+  '@radix-ui/react-presence@1.1.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+    dependencies:
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      react: 18.2.0
+      react-dom: 18.2.0(react@18.2.0)
+    optionalDependencies:
+      '@types/react': 18.2.72
+      '@types/react-dom': 18.2.22
+
+  '@radix-ui/react-primitive@2.0.0(@types/react-dom@18.2.22)(@types/react@18.2.72)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)':
+    dependencies:
+      '@radix-ui/react-slot': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      react: 18.2.0
+      react-dom: 18.2.0(react@18.2.0)
+    optionalDependencies:
+      '@types/react': 18.2.72
+      '@types/react-dom': 18.2.22
+
   '@radix-ui/react-slot@1.0.2(@types/react@18.2.72)(react@18.2.0)':
     dependencies:
       '@babel/runtime': 7.24.1
@@ -2376,6 +3034,61 @@ snapshots:
     optionalDependencies:
       '@types/react': 18.2.72
 
+  '@radix-ui/react-slot@1.1.0(@types/react@18.2.72)(react@18.2.0)':
+    dependencies:
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      react: 18.2.0
+    optionalDependencies:
+      '@types/react': 18.2.72
+
+  '@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.2.72)(react@18.2.0)':
+    dependencies:
+      react: 18.2.0
+    optionalDependencies:
+      '@types/react': 18.2.72
+
+  '@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.2.72)(react@18.2.0)':
+    dependencies:
+      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      react: 18.2.0
+    optionalDependencies:
+      '@types/react': 18.2.72
+
+  '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.2.72)(react@18.2.0)':
+    dependencies:
+      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      react: 18.2.0
+    optionalDependencies:
+      '@types/react': 18.2.72
+
+  '@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.2.72)(react@18.2.0)':
+    dependencies:
+      react: 18.2.0
+    optionalDependencies:
+      '@types/react': 18.2.72
+
+  '@radix-ui/react-use-previous@1.1.0(@types/react@18.2.72)(react@18.2.0)':
+    dependencies:
+      react: 18.2.0
+    optionalDependencies:
+      '@types/react': 18.2.72
+
+  '@radix-ui/react-use-rect@1.1.0(@types/react@18.2.72)(react@18.2.0)':
+    dependencies:
+      '@radix-ui/rect': 1.1.0
+      react: 18.2.0
+    optionalDependencies:
+      '@types/react': 18.2.72
+
+  '@radix-ui/react-use-size@1.1.0(@types/react@18.2.72)(react@18.2.0)':
+    dependencies:
+      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.2.72)(react@18.2.0)
+      react: 18.2.0
+    optionalDependencies:
+      '@types/react': 18.2.72
+
+  '@radix-ui/rect@1.1.0': {}
+
   '@react-aria/focus@3.17.1(react@18.2.0)':
     dependencies:
       '@react-aria/interactions': 3.21.3(react@18.2.0)
@@ -2407,6 +3120,113 @@ snapshots:
       clsx: 2.1.0
       react: 18.2.0
 
+  '@react-pdf/fns@2.2.1':
+    dependencies:
+      '@babel/runtime': 7.24.1
+
+  '@react-pdf/font@2.5.1':
+    dependencies:
+      '@babel/runtime': 7.24.1
+      '@react-pdf/types': 2.5.0
+      cross-fetch: 3.1.8
+      fontkit: 2.0.2
+      is-url: 1.2.4
+    transitivePeerDependencies:
+      - encoding
+
+  '@react-pdf/image@2.3.6':
+    dependencies:
+      '@babel/runtime': 7.24.1
+      '@react-pdf/png-js': 2.3.1
+      cross-fetch: 3.1.8
+      jay-peg: 1.0.2
+    transitivePeerDependencies:
+      - encoding
+
+  '@react-pdf/layout@3.12.1':
+    dependencies:
+      '@babel/runtime': 7.24.1
+      '@react-pdf/fns': 2.2.1
+      '@react-pdf/image': 2.3.6
+      '@react-pdf/pdfkit': 3.1.10
+      '@react-pdf/primitives': 3.1.1
+      '@react-pdf/stylesheet': 4.2.5
+      '@react-pdf/textkit': 4.4.1
+      '@react-pdf/types': 2.5.0
+      cross-fetch: 3.1.8
+      emoji-regex: 10.3.0
+      queue: 6.0.2
+      yoga-layout: 2.0.1
+    transitivePeerDependencies:
+      - encoding
+
+  '@react-pdf/pdfkit@3.1.10':
+    dependencies:
+      '@babel/runtime': 7.24.1
+      '@react-pdf/png-js': 2.3.1
+      browserify-zlib: 0.2.0
+      crypto-js: 4.2.0
+      fontkit: 2.0.2
+      jay-peg: 1.0.2
+      vite-compatible-readable-stream: 3.6.1
+
+  '@react-pdf/png-js@2.3.1':
+    dependencies:
+      browserify-zlib: 0.2.0
+
+  '@react-pdf/primitives@3.1.1': {}
+
+  '@react-pdf/render@3.4.4':
+    dependencies:
+      '@babel/runtime': 7.24.1
+      '@react-pdf/fns': 2.2.1
+      '@react-pdf/primitives': 3.1.1
+      '@react-pdf/textkit': 4.4.1
+      '@react-pdf/types': 2.5.0
+      abs-svg-path: 0.1.1
+      color-string: 1.9.1
+      normalize-svg-path: 1.1.0
+      parse-svg-path: 0.1.2
+      svg-arc-to-cubic-bezier: 3.2.0
+
+  '@react-pdf/renderer@3.4.4(react@18.2.0)':
+    dependencies:
+      '@babel/runtime': 7.24.1
+      '@react-pdf/font': 2.5.1
+      '@react-pdf/layout': 3.12.1
+      '@react-pdf/pdfkit': 3.1.10
+      '@react-pdf/primitives': 3.1.1
+      '@react-pdf/render': 3.4.4
+      '@react-pdf/types': 2.5.0
+      events: 3.3.0
+      object-assign: 4.1.1
+      prop-types: 15.8.1
+      queue: 6.0.2
+      react: 18.2.0
+      scheduler: 0.17.0
+    transitivePeerDependencies:
+      - encoding
+
+  '@react-pdf/stylesheet@4.2.5':
+    dependencies:
+      '@babel/runtime': 7.24.1
+      '@react-pdf/fns': 2.2.1
+      '@react-pdf/types': 2.5.0
+      color-string: 1.9.1
+      hsl-to-hex: 1.0.0
+      media-engine: 1.0.3
+      postcss-value-parser: 4.2.0
+
+  '@react-pdf/textkit@4.4.1':
+    dependencies:
+      '@babel/runtime': 7.24.1
+      '@react-pdf/fns': 2.2.1
+      bidi-js: 1.0.3
+      hyphen: 1.10.4
+      unicode-properties: 1.4.1
+
+  '@react-pdf/types@2.5.0': {}
+
   '@react-stately/utils@3.10.1(react@18.2.0)':
     dependencies:
       '@swc/helpers': 0.5.5
@@ -2420,6 +3240,15 @@ snapshots:
 
   '@swc/counter@0.1.3': {}
 
+  '@swc/helpers@0.4.14':
+    dependencies:
+      tslib: 2.6.2
+
+  '@swc/helpers@0.4.36':
+    dependencies:
+      legacy-swc-helpers: '@swc/helpers@0.4.14'
+      tslib: 2.6.2
+
   '@swc/helpers@0.5.5':
     dependencies:
       '@swc/counter': 0.1.3
@@ -2531,6 +3360,8 @@ snapshots:
 
   '@vercel/git-hooks@1.0.0': {}
 
+  abs-svg-path@0.1.1: {}
+
   acorn-jsx@5.3.2(acorn@8.11.3):
     dependencies:
       acorn: 8.11.3
@@ -2571,6 +3402,10 @@ snapshots:
 
   argparse@2.0.1: {}
 
+  aria-hidden@1.2.4:
+    dependencies:
+      tslib: 2.6.2
+
   aria-query@5.3.0:
     dependencies:
       dequal: 2.0.3
@@ -2673,6 +3508,12 @@ snapshots:
 
   balanced-match@1.0.2: {}
 
+  base64-js@1.5.1: {}
+
+  bidi-js@1.0.3:
+    dependencies:
+      require-from-string: 2.0.2
+
   binary-extensions@2.3.0: {}
 
   brace-expansion@1.1.11:
@@ -2688,6 +3529,14 @@ snapshots:
     dependencies:
       fill-range: 7.0.1
 
+  brotli@1.3.3:
+    dependencies:
+      base64-js: 1.5.1
+
+  browserify-zlib@0.2.0:
+    dependencies:
+      pako: 1.0.11
+
   browserslist@4.23.0:
     dependencies:
       caniuse-lite: 1.0.30001600
@@ -2759,6 +3608,8 @@ snapshots:
 
   client-only@0.0.1: {}
 
+  clone@2.1.2: {}
+
   clsx@2.1.0: {}
 
   color-convert@1.9.3:
@@ -2773,6 +3624,11 @@ snapshots:
 
   color-name@1.1.4: {}
 
+  color-string@1.9.1:
+    dependencies:
+      color-name: 1.1.4
+      simple-swizzle: 0.2.2
+
   colorette@2.0.20: {}
 
   commander@11.1.0: {}
@@ -2785,12 +3641,20 @@ snapshots:
     dependencies:
       browserslist: 4.23.0
 
+  cross-fetch@3.1.8:
+    dependencies:
+      node-fetch: 2.7.0
+    transitivePeerDependencies:
+      - encoding
+
   cross-spawn@7.0.3:
     dependencies:
       path-key: 3.1.1
       shebang-command: 2.0.0
       which: 2.0.2
 
+  crypto-js@4.2.0: {}
+
   cssesc@3.0.0: {}
 
   csstype@3.1.3: {}
@@ -2839,6 +3703,10 @@ snapshots:
 
   dequal@2.0.3: {}
 
+  detect-node-es@1.1.0: {}
+
+  dfa@1.2.0: {}
+
   didyoumean@1.2.2: {}
 
   dir-glob@3.0.1:
@@ -3195,6 +4063,8 @@ snapshots:
 
   eventemitter3@5.0.1: {}
 
+  events@3.3.0: {}
+
   execa@8.0.1:
     dependencies:
       cross-spawn: 7.0.3
@@ -3251,6 +4121,18 @@ snapshots:
 
   flatted@3.3.1: {}
 
+  fontkit@2.0.2:
+    dependencies:
+      '@swc/helpers': 0.4.36
+      brotli: 1.3.3
+      clone: 2.1.2
+      dfa: 1.2.0
+      fast-deep-equal: 3.1.3
+      restructure: 3.0.2
+      tiny-inflate: 1.0.3
+      unicode-properties: 1.4.1
+      unicode-trie: 2.0.0
+
   for-each@0.3.3:
     dependencies:
       is-callable: 1.2.7
@@ -3292,6 +4174,8 @@ snapshots:
       has-symbols: 1.0.3
       hasown: 2.0.2
 
+  get-nonce@1.0.1: {}
+
   get-stream@8.0.1: {}
 
   get-symbol-description@1.0.2:
@@ -3378,8 +4262,16 @@ snapshots:
 
   hosted-git-info@2.8.9: {}
 
+  hsl-to-hex@1.0.0:
+    dependencies:
+      hsl-to-rgb-for-reals: 1.1.1
+
+  hsl-to-rgb-for-reals@1.1.1: {}
+
   human-signals@5.0.0: {}
 
+  hyphen@1.10.4: {}
+
   ignore@5.3.1: {}
 
   import-fresh@3.3.0:
@@ -3404,6 +4296,10 @@ snapshots:
       hasown: 2.0.2
       side-channel: 1.0.6
 
+  invariant@2.2.4:
+    dependencies:
+      loose-envify: 1.4.0
+
   is-array-buffer@3.0.4:
     dependencies:
       call-bind: 1.0.7
@@ -3411,6 +4307,8 @@ snapshots:
 
   is-arrayish@0.2.1: {}
 
+  is-arrayish@0.3.2: {}
+
   is-async-function@2.0.0:
     dependencies:
       has-tostringtag: 1.0.2
@@ -3505,6 +4403,8 @@ snapshots:
     dependencies:
       which-typed-array: 1.1.15
 
+  is-url@1.2.4: {}
+
   is-weakmap@2.0.2: {}
 
   is-weakref@1.0.2:
@@ -3534,6 +4434,10 @@ snapshots:
     optionalDependencies:
       '@pkgjs/parseargs': 0.11.0
 
+  jay-peg@1.0.2:
+    dependencies:
+      restructure: 3.0.2
+
   jiti@1.21.0: {}
 
   js-tokens@4.0.0: {}
@@ -3650,6 +4554,12 @@ snapshots:
     dependencies:
       yallist: 4.0.0
 
+  markdown-to-jsx@7.4.7(react@18.2.0):
+    dependencies:
+      react: 18.2.0
+
+  media-engine@1.0.3: {}
+
   merge-stream@2.0.0: {}
 
   merge2@1.4.1: {}
@@ -3718,6 +4628,10 @@ snapshots:
       - '@babel/core'
       - babel-plugin-macros
 
+  node-fetch@2.7.0:
+    dependencies:
+      whatwg-url: 5.0.0
+
   node-releases@2.0.14: {}
 
   normalize-package-data@2.5.0:
@@ -3731,6 +4645,10 @@ snapshots:
 
   normalize-range@0.1.2: {}
 
+  normalize-svg-path@1.1.0:
+    dependencies:
+      svg-arc-to-cubic-bezier: 3.2.0
+
   npm-run-path@5.3.0:
     dependencies:
       path-key: 4.0.0
@@ -3820,6 +4738,10 @@ snapshots:
 
   p-try@2.2.0: {}
 
+  pako@0.2.9: {}
+
+  pako@1.0.11: {}
+
   parent-module@1.0.1:
     dependencies:
       callsites: 3.1.0
@@ -3831,6 +4753,8 @@ snapshots:
       json-parse-even-better-errors: 2.3.1
       lines-and-columns: 1.2.4
 
+  parse-svg-path@0.1.2: {}
+
   path-exists@4.0.0: {}
 
   path-is-absolute@1.0.1: {}
@@ -3928,6 +4852,10 @@ snapshots:
 
   queue-microtask@1.2.3: {}
 
+  queue@6.0.2:
+    dependencies:
+      inherits: 2.0.4
+
   react-dom@18.2.0(react@18.2.0):
     dependencies:
       loose-envify: 1.4.0
@@ -3940,6 +4868,34 @@ snapshots:
 
   react-is@16.13.1: {}
 
+  react-remove-scroll-bar@2.3.6(@types/react@18.2.72)(react@18.2.0):
+    dependencies:
+      react: 18.2.0
+      react-style-singleton: 2.2.1(@types/react@18.2.72)(react@18.2.0)
+      tslib: 2.6.2
+    optionalDependencies:
+      '@types/react': 18.2.72
+
+  react-remove-scroll@2.5.7(@types/react@18.2.72)(react@18.2.0):
+    dependencies:
+      react: 18.2.0
+      react-remove-scroll-bar: 2.3.6(@types/react@18.2.72)(react@18.2.0)
+      react-style-singleton: 2.2.1(@types/react@18.2.72)(react@18.2.0)
+      tslib: 2.6.2
+      use-callback-ref: 1.3.2(@types/react@18.2.72)(react@18.2.0)
+      use-sidecar: 1.1.2(@types/react@18.2.72)(react@18.2.0)
+    optionalDependencies:
+      '@types/react': 18.2.72
+
+  react-style-singleton@2.2.1(@types/react@18.2.72)(react@18.2.0):
+    dependencies:
+      get-nonce: 1.0.1
+      invariant: 2.2.4
+      react: 18.2.0
+      tslib: 2.6.2
+    optionalDependencies:
+      '@types/react': 18.2.72
+
   react-tooltip@5.26.3(react-dom@18.2.0(react@18.2.0))(react@18.2.0):
     dependencies:
       '@floating-ui/dom': 1.6.3
@@ -3997,6 +4953,8 @@ snapshots:
     dependencies:
       jsesc: 0.5.0
 
+  require-from-string@2.0.2: {}
+
   resolve-from@4.0.0: {}
 
   resolve-pkg-maps@1.0.0: {}
@@ -4018,6 +4976,8 @@ snapshots:
       onetime: 5.1.2
       signal-exit: 3.0.7
 
+  restructure@3.0.2: {}
+
   reusify@1.0.4: {}
 
   rfdc@1.3.1: {}
@@ -4037,12 +4997,19 @@ snapshots:
       has-symbols: 1.0.3
       isarray: 2.0.5
 
+  safe-buffer@5.2.1: {}
+
   safe-regex-test@1.0.3:
     dependencies:
       call-bind: 1.0.7
       es-errors: 1.3.0
       is-regex: 1.1.4
 
+  scheduler@0.17.0:
+    dependencies:
+      loose-envify: 1.4.0
+      object-assign: 4.1.1
+
   scheduler@0.23.0:
     dependencies:
       loose-envify: 1.4.0
@@ -4088,6 +5055,10 @@ snapshots:
 
   signal-exit@4.1.0: {}
 
+  simple-swizzle@0.2.2:
+    dependencies:
+      is-arrayish: 0.3.2
+
   slash@3.0.0: {}
 
   slice-ansi@5.0.0:
@@ -4172,6 +5143,10 @@ snapshots:
       define-properties: 1.2.1
       es-object-atoms: 1.0.0
 
+  string_decoder@1.3.0:
+    dependencies:
+      safe-buffer: 5.2.1
+
   strip-ansi@6.0.1:
     dependencies:
       ansi-regex: 5.0.1
@@ -4215,6 +5190,8 @@ snapshots:
 
   supports-preserve-symlinks-flag@1.0.0: {}
 
+  svg-arc-to-cubic-bezier@3.2.0: {}
+
   tabbable@6.2.0: {}
 
   tailwind-merge@2.2.2:
@@ -4265,10 +5242,14 @@ snapshots:
     dependencies:
       any-promise: 1.3.0
 
+  tiny-inflate@1.0.3: {}
+
   to-regex-range@5.0.1:
     dependencies:
       is-number: 7.0.0
 
+  tr46@0.0.3: {}
+
   ts-api-utils@1.3.0(typescript@5.4.3):
     dependencies:
       typescript: 5.4.3
@@ -4337,6 +5318,16 @@ snapshots:
 
   undici-types@5.26.5: {}
 
+  unicode-properties@1.4.1:
+    dependencies:
+      base64-js: 1.5.1
+      unicode-trie: 2.0.0
+
+  unicode-trie@2.0.0:
+    dependencies:
+      pako: 0.2.9
+      tiny-inflate: 1.0.3
+
   update-browserslist-db@1.0.13(browserslist@4.23.0):
     dependencies:
       browserslist: 4.23.0
@@ -4347,6 +5338,21 @@ snapshots:
     dependencies:
       punycode: 2.3.1
 
+  use-callback-ref@1.3.2(@types/react@18.2.72)(react@18.2.0):
+    dependencies:
+      react: 18.2.0
+      tslib: 2.6.2
+    optionalDependencies:
+      '@types/react': 18.2.72
+
+  use-sidecar@1.1.2(@types/react@18.2.72)(react@18.2.0):
+    dependencies:
+      detect-node-es: 1.1.0
+      react: 18.2.0
+      tslib: 2.6.2
+    optionalDependencies:
+      '@types/react': 18.2.72
+
   util-deprecate@1.0.2: {}
 
   validate-npm-package-license@3.0.4:
@@ -4354,6 +5360,19 @@ snapshots:
       spdx-correct: 3.2.0
       spdx-expression-parse: 3.0.1
 
+  vite-compatible-readable-stream@3.6.1:
+    dependencies:
+      inherits: 2.0.4
+      string_decoder: 1.3.0
+      util-deprecate: 1.0.2
+
+  webidl-conversions@3.0.1: {}
+
+  whatwg-url@5.0.0:
+    dependencies:
+      tr46: 0.0.3
+      webidl-conversions: 3.0.1
+
   which-boxed-primitive@1.0.2:
     dependencies:
       is-bigint: 1.0.4
@@ -4424,4 +5443,6 @@ snapshots:
 
   yocto-queue@0.1.0: {}
 
+  yoga-layout@2.0.1: {}
+
   zod@3.23.8: {}