+
{/* Right: illustration */}
-
diff --git a/docs/app/(home)/components/CompatibilitySection/CompatibilitySection.module.css b/docs/app/(home)/components/CompatibilitySection/CompatibilitySection.module.css
new file mode 100644
index 000000000..e087df6a3
--- /dev/null
+++ b/docs/app/(home)/components/CompatibilitySection/CompatibilitySection.module.css
@@ -0,0 +1,109 @@
+.section {
+ width: 100%;
+ padding-inline: 1.25rem;
+}
+
+.container {
+ max-width: 75rem;
+ margin-inline: auto;
+}
+
+.stack {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+}
+
+.row {
+ display: flex;
+ flex-direction: column;
+ gap: 0.75rem;
+}
+
+.label {
+ flex-shrink: 0;
+ font-family: "Inter", sans-serif;
+ font-size: 13px;
+ font-weight: 500;
+ line-height: 1;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ color: rgb(0 0 0 / 30%);
+}
+
+.chips {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.chip {
+ display: flex;
+ align-items: center;
+ gap: 0.375rem;
+ padding: 0.375rem 0.625rem;
+ border: 1px solid rgb(0 0 0 / 8%);
+ border-radius: 999px;
+ background: #fff;
+ box-shadow: 0 2px 8px -2px rgb(22 34 51 / 8%);
+}
+
+.badge {
+ display: flex;
+ height: 1.375rem;
+ width: 1.375rem;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+ border-radius: 5px;
+}
+
+.badgeWithBorder {
+ border: 1px solid rgb(0 0 0 / 10%);
+}
+
+.badgeImage {
+ height: 0.875rem;
+ width: 0.875rem;
+ object-fit: contain;
+}
+
+.chipLabel,
+.more {
+ font-family: "Inter", sans-serif;
+ font-size: 13px;
+ line-height: 1;
+ white-space: nowrap;
+ color: rgb(0 0 0 / 60%);
+}
+
+.chipLabel {
+ font-weight: 500;
+}
+
+.more {
+ margin-left: 0.25rem;
+ color: rgb(0 0 0 / 30%);
+}
+
+.divider {
+ height: 1px;
+ background: rgb(0 0 0 / 6%);
+}
+
+@media (min-width: 1024px) {
+ .section {
+ padding-inline: 2rem;
+ }
+
+ .stack {
+ gap: 1.25rem;
+ }
+
+ .row {
+ flex-direction: row;
+ align-items: center;
+ }
+}
diff --git a/docs/app/(home)/components/CompatibilitySection.tsx b/docs/app/(home)/components/CompatibilitySection/CompatibilitySection.tsx
similarity index 60%
rename from docs/app/(home)/components/CompatibilitySection.tsx
rename to docs/app/(home)/components/CompatibilitySection/CompatibilitySection.tsx
index 7685a73c8..b2717d257 100644
--- a/docs/app/(home)/components/CompatibilitySection.tsx
+++ b/docs/app/(home)/components/CompatibilitySection/CompatibilitySection.tsx
@@ -2,6 +2,8 @@
// Data
// ---------------------------------------------------------------------------
+import styles from "./CompatibilitySection.module.css";
+
interface CompatibilityItem {
name: string;
slug?: string;
@@ -16,27 +18,27 @@ const LLMS: CompatibilityItem[] = [
name: "OpenAI",
localSrc: "/brand-icons/openai.svg",
iconColor: "000000",
- badgeBg: "bg-white",
+ badgeBg: "#ffffff",
border: true,
},
- { name: "Anthropic", slug: "anthropic", iconColor: "ffffff", badgeBg: "bg-[#D4A574]" },
- { name: "Gemini", slug: "googlegemini", iconColor: "000000", badgeBg: "bg-white", border: true },
- { name: "Mistral", slug: "mistralai", iconColor: "ffffff", badgeBg: "bg-[#FF7000]" },
+ { name: "Anthropic", slug: "anthropic", iconColor: "ffffff", badgeBg: "#D4A574" },
+ { name: "Gemini", slug: "googlegemini", iconColor: "000000", badgeBg: "#ffffff", border: true },
+ { name: "Mistral", slug: "mistralai", iconColor: "ffffff", badgeBg: "#FF7000" },
];
const FRAMEWORKS: CompatibilityItem[] = [
- { name: "Vercel AI SDK", slug: "vercel", iconColor: "ffffff", badgeBg: "bg-black" },
- { name: "LangChain", slug: "langchain", iconColor: "ffffff", badgeBg: "bg-[#1C3144]" },
- { name: "CrewAI", slug: "crewai", iconColor: "ffffff", badgeBg: "bg-[#FF4B4B]" },
+ { name: "Vercel AI SDK", slug: "vercel", iconColor: "ffffff", badgeBg: "#000000" },
+ { name: "LangChain", slug: "langchain", iconColor: "ffffff", badgeBg: "#1C3144" },
+ { name: "CrewAI", slug: "crewai", iconColor: "ffffff", badgeBg: "#FF4B4B" },
{
name: "OpenAI Agents SDK",
localSrc: "/brand-icons/openai.svg",
iconColor: "000000",
- badgeBg: "bg-white",
+ badgeBg: "#ffffff",
border: true,
},
- { name: "Anthropic Agents SDK", slug: "anthropic", iconColor: "ffffff", badgeBg: "bg-[#D4A574]" },
- { name: "Google ADK", slug: "google", iconColor: "ffffff", badgeBg: "bg-[#4285F4]" },
+ { name: "Anthropic Agents SDK", slug: "anthropic", iconColor: "ffffff", badgeBg: "#D4A574" },
+ { name: "Google ADK", slug: "google", iconColor: "ffffff", badgeBg: "#4285F4" },
];
// ---------------------------------------------------------------------------
@@ -44,12 +46,12 @@ const FRAMEWORKS: CompatibilityItem[] = [
// ---------------------------------------------------------------------------
function Chip({ item }: { item: CompatibilityItem }) {
- const borderClass = item.border ? "border border-black/10" : "";
const imgSrc = item.localSrc ?? `https://cdn.simpleicons.org/${item.slug}/${item.iconColor}`;
return (
-
+
{/* eslint-disable-next-line @next/next/no-img-element */}
-
+
{item.name}
@@ -73,37 +75,37 @@ function Chip({ item }: { item: CompatibilityItem }) {
export function CompatibilitySection() {
return (
-
-
-
+
+
+
{/* LLMs row */}
-
-
+
+
Any LLM
-
+
{LLMS.map((item) => (
))}
-
+
+ more
{/* Divider */}
-
+
{/* Frameworks row */}
-
-
+
+
Any Framework
-
+
{FRAMEWORKS.map((item) => (
))}
-
+
+ more
diff --git a/docs/app/(home)/components/FadeInSection.tsx b/docs/app/(home)/components/FadeInSection.tsx
deleted file mode 100644
index 16f76130d..000000000
--- a/docs/app/(home)/components/FadeInSection.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-"use client";
-
-import { motion, useInView } from "motion/react";
-import { useRef, type ReactNode } from "react";
-
-interface FadeInSectionProps {
- children: ReactNode;
- className?: string;
-}
-
-export function FadeInSection({ children, className = "" }: FadeInSectionProps) {
- const ref = useRef
(null);
- const isInView = useInView(ref, { once: true, margin: "-100px 0px" });
-
- return (
-
- {children}
-
- );
-}
diff --git a/docs/app/(home)/components/FadeInSection/FadeInSection.module.css b/docs/app/(home)/components/FadeInSection/FadeInSection.module.css
new file mode 100644
index 000000000..88de80d08
--- /dev/null
+++ b/docs/app/(home)/components/FadeInSection/FadeInSection.module.css
@@ -0,0 +1,3 @@
+.root {
+ width: 100%;
+}
diff --git a/docs/app/(home)/components/FadeInSection/FadeInSection.tsx b/docs/app/(home)/components/FadeInSection/FadeInSection.tsx
new file mode 100644
index 000000000..adf65cea7
--- /dev/null
+++ b/docs/app/(home)/components/FadeInSection/FadeInSection.tsx
@@ -0,0 +1,17 @@
+"use client";
+
+import type { ReactNode } from "react";
+import styles from "./FadeInSection.module.css";
+
+interface FadeInSectionProps {
+ children: ReactNode;
+ className?: string;
+}
+
+export function FadeInSection({ children, className = "" }: FadeInSectionProps) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/docs/app/(home)/components/FeaturesSection.tsx b/docs/app/(home)/components/FeaturesSection.tsx
deleted file mode 100644
index d7ed2ae90..000000000
--- a/docs/app/(home)/components/FeaturesSection.tsx
+++ /dev/null
@@ -1,233 +0,0 @@
-"use client";
-
-import svgPaths from "@/imports/svg-urruvoh2be";
-import { motion, useInView } from "motion/react";
-import Link from "next/link";
-import { useRef } from "react";
-import { BUTTON_SHADOW } from "./shared";
-
-// ---------------------------------------------------------------------------
-// Data
-// ---------------------------------------------------------------------------
-
-interface Feature {
- title: string;
- description: string;
- iconPath: string;
-}
-
-const FEATURES: Feature[] = [
- {
- title: "Performance Optimized",
- description: "Up to 3.0x faster rendering than json-render",
- iconPath: svgPaths.p7658f00,
- },
- {
- title: "Token efficient",
- description: "Up to 67.1% lesser tokens than json-render",
- iconPath: svgPaths.p2a8ddd80,
- },
- {
- title: "Native Types",
- description: "Performant and memory safe",
- iconPath: svgPaths.p10e86100,
- },
- {
- title: "Works across platforms",
- description: "JS Runtime. Native support for iOS & Android coming soon",
- iconPath: svgPaths.p2cbb5d00,
- },
- {
- title: "Streaming Native",
- description: "Streaming and partial responses",
- iconPath: svgPaths.p33780400,
- },
- {
- title: "Interactive",
- description: "Handles inputs and interactive flows",
- iconPath: svgPaths.p17c7f700,
- },
- {
- title: "Safe by Default",
- description: "No arbitrary code execution",
- iconPath: svgPaths.p16eec200,
- },
-];
-
-const LAST_FEATURE_INDEX = FEATURES.length - 1;
-
-// ---------------------------------------------------------------------------
-// Sub-components
-// ---------------------------------------------------------------------------
-
-function FeatureIcon({ path, index }: { path: string; index: number }) {
- const clipId = `clip_feat_${index}`;
- return (
-
- );
-}
-
-// Stagger timing: each row starts after the previous; within a row, icon → title → description
-const ROW_STAGGER = 0.12; // seconds between rows
-const ELEMENT_STAGGER = 0.14; // seconds between icon, title, description within a row
-const FADE_DURATION = 0.55;
-
-function DesktopFeatureRow({ feature, index }: { feature: Feature; index: number }) {
- const rowRef = useRef(null);
- const isInView = useInView(rowRef, { once: true, margin: "-100px 0px" });
-
- const baseDelay = index * ROW_STAGGER;
- const iconDelay = baseDelay;
- const titleDelay = baseDelay + ELEMENT_STAGGER;
- const descDelay = baseDelay + ELEMENT_STAGGER * 2;
-
- return (
-
-
-
-
-
-
- {feature.title}
-
-
-
- {feature.description}
-
-
- );
-}
-
-function MobileFeatureRow({ feature, index }: { feature: Feature; index: number }) {
- const rowRef = useRef(null);
- const isInView = useInView(rowRef, { once: true, margin: "-60px 0px" });
-
- const baseDelay = index * ROW_STAGGER;
- const titleDelay = baseDelay;
- const descDelay = baseDelay + ELEMENT_STAGGER;
- const iconDelay = baseDelay + ELEMENT_STAGGER * 2;
-
- return (
-
-
-
- {feature.title}
-
-
- {feature.description}
-
-
-
-
-
-
- );
-}
-
-function Divider({ className = "" }: { className?: string }) {
- return (
-
- );
-}
-
-// ---------------------------------------------------------------------------
-// Main component
-// ---------------------------------------------------------------------------
-
-export function FeaturesSection() {
- const lastRowDesktopRef = useRef(null);
- const lastRowMobileRef = useRef(null);
- const lastRowDesktopInView = useInView(lastRowDesktopRef, { once: true, margin: "-100px 0px" });
- const lastRowMobileInView = useInView(lastRowMobileRef, { once: true, margin: "-60px 0px" });
-
- const lastRowInView = lastRowDesktopInView || lastRowMobileInView;
-
- // Button appears after the last row's elements finish animating
- const lastRowTotalDelay =
- (FEATURES.length - 1) * ROW_STAGGER + ELEMENT_STAGGER * 2 + FADE_DURATION;
- const buttonDelay = lastRowTotalDelay * 0.6; // overlap slightly so it feels connected
-
- return (
-
-
- {/* Desktop */}
-
- {FEATURES.map((f, i) => (
-
-
- {i < LAST_FEATURE_INDEX &&
}
-
- ))}
-
-
- {/* Mobile */}
-
- {FEATURES.map((f, i) => (
-
-
- {i < LAST_FEATURE_INDEX &&
}
-
- ))}
-
-
- {/* CTA button */}
-
-
-
- Detailed comparison
- View Comparison
-
-
-
-
-
- );
-}
diff --git a/docs/app/(home)/components/FeaturesSection/FeaturesSection.module.css b/docs/app/(home)/components/FeaturesSection/FeaturesSection.module.css
new file mode 100644
index 000000000..8dac57417
--- /dev/null
+++ b/docs/app/(home)/components/FeaturesSection/FeaturesSection.module.css
@@ -0,0 +1,191 @@
+.section {
+ width: 100%;
+ padding-inline: 1.25rem;
+}
+
+.container {
+ max-width: 75rem;
+ margin-inline: auto;
+}
+
+.featureIcon {
+ display: flex;
+ height: 2.25rem;
+ width: 2.25rem;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ border: 1px solid rgb(0 0 0 / 10%);
+ border-radius: 999px;
+ background: #fff;
+}
+
+.featureIconSvg {
+ height: 18px;
+ width: 18px;
+}
+
+.desktopList {
+ display: none;
+}
+
+.mobileList {
+ display: block;
+}
+
+.desktopRow {
+ display: flex;
+ height: 72px;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.desktopRowLead {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+}
+
+.desktopTitle,
+.desktopDescription {
+ font-family: "Inter Display", sans-serif;
+ font-size: 22px;
+ line-height: 1.4;
+}
+
+.desktopTitle {
+ color: #000;
+}
+
+.desktopDescription {
+ text-align: right;
+ color: rgb(0 0 0 / 40%);
+}
+
+.mobileRow {
+ display: flex;
+ align-items: center;
+ gap: 0.375rem;
+ padding-block: 1rem;
+}
+
+.mobileCopy {
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ gap: 0.25rem;
+}
+
+.mobileTitle,
+.mobileDescription {
+ font-family: "Inter", sans-serif;
+ font-size: 16px;
+}
+
+.mobileTitle {
+ font-weight: 500;
+ line-height: 1.25;
+ color: #000;
+}
+
+.mobileDescription {
+ line-height: 1.4;
+ color: rgb(0 0 0 / 40%);
+}
+
+.divider {
+ height: 1px;
+ width: 100vw;
+ margin-left: calc(-50vw + 50%);
+}
+
+.desktopDivider {
+ background: rgb(0 0 0 / 10%);
+}
+
+.mobileDivider {
+ background: rgb(0 0 0 / 8%);
+}
+
+.ctaWrap {
+ display: flex;
+ justify-content: center;
+ margin-top: 2.5rem;
+}
+
+.ctaLink {
+ width: 100%;
+ max-width: 280px;
+ text-decoration: none;
+}
+
+.ctaButton {
+ display: flex;
+ height: 3rem;
+ width: 100%;
+ align-items: center;
+ justify-content: center;
+ padding-inline: 1rem;
+ border: 1.25px solid rgb(0 0 0 / 8%);
+ border-radius: 999px;
+ background: #fff;
+ box-shadow: var(--features-cta-shadow, none);
+ color: #000;
+ cursor: pointer;
+ transition:
+ transform 0.2s ease,
+ box-shadow 0.2s ease;
+ font-family: "Inter", sans-serif;
+ font-size: 16px;
+ font-weight: 500;
+ line-height: 1.5rem;
+}
+
+.ctaButton:hover {
+ transform: scale(0.99);
+ box-shadow: none;
+}
+
+.mobileLabel {
+ display: inline;
+}
+
+.desktopLabel {
+ display: none;
+}
+
+@media (min-width: 1024px) {
+ .section {
+ padding-inline: 2rem;
+ }
+
+ .desktopList {
+ display: block;
+ }
+
+ .mobileList {
+ display: none;
+ }
+
+ .ctaWrap {
+ margin-top: 5rem;
+ }
+
+ .ctaLink {
+ width: auto;
+ max-width: none;
+ }
+
+ .ctaButton {
+ width: auto;
+ font-size: 18px;
+ }
+
+ .mobileLabel {
+ display: none;
+ }
+
+ .desktopLabel {
+ display: inline;
+ }
+}
diff --git a/docs/app/(home)/components/FeaturesSection/FeaturesSection.tsx b/docs/app/(home)/components/FeaturesSection/FeaturesSection.tsx
new file mode 100644
index 000000000..c64d53872
--- /dev/null
+++ b/docs/app/(home)/components/FeaturesSection/FeaturesSection.tsx
@@ -0,0 +1,164 @@
+"use client";
+
+import svgPaths from "@/imports/svg-urruvoh2be";
+import Link from "next/link";
+import type { CSSProperties } from "react";
+import { BUTTON_SHADOW } from "../shared/shared";
+import styles from "./FeaturesSection.module.css";
+
+// ---------------------------------------------------------------------------
+// Data
+// ---------------------------------------------------------------------------
+
+interface Feature {
+ title: string;
+ description: string;
+ iconPath: string;
+}
+
+const FEATURES: Feature[] = [
+ {
+ title: "Performance Optimized",
+ description: "Up to 3.0x faster rendering than json-render",
+ iconPath: svgPaths.p7658f00,
+ },
+ {
+ title: "Token efficient",
+ description: "Up to 67.1% lesser tokens than json-render",
+ iconPath: svgPaths.p2a8ddd80,
+ },
+ {
+ title: "Native Types",
+ description: "Performant and memory safe",
+ iconPath: svgPaths.p10e86100,
+ },
+ {
+ title: "Works across platforms",
+ description: "JS Runtime. Native support for iOS & Android coming soon",
+ iconPath: svgPaths.p2cbb5d00,
+ },
+ {
+ title: "Streaming Native",
+ description: "Streaming and partial responses",
+ iconPath: svgPaths.p33780400,
+ },
+ {
+ title: "Interactive",
+ description: "Handles inputs and interactive flows",
+ iconPath: svgPaths.p17c7f700,
+ },
+ {
+ title: "Safe by Default",
+ description: "No arbitrary code execution",
+ iconPath: svgPaths.p16eec200,
+ },
+];
+
+const LAST_FEATURE_INDEX = FEATURES.length - 1;
+const FEATURES_CTA_STYLE = {
+ "--features-cta-shadow": BUTTON_SHADOW,
+} as CSSProperties;
+
+// ---------------------------------------------------------------------------
+// Sub-components
+// ---------------------------------------------------------------------------
+
+function FeatureIcon({ path, index }: { path: string; index: number }) {
+ const clipId = `clip_feat_${index}`;
+ return (
+
+ );
+}
+
+function DesktopFeatureRow({ feature, index }: { feature: Feature; index: number }) {
+ return (
+
+
+
+
+
+
+ {feature.title}
+
+
+
+ {feature.description}
+
+
+ );
+}
+
+function MobileFeatureRow({ feature, index }: { feature: Feature; index: number }) {
+ return (
+
+
+
+ {feature.title}
+
+
+ {feature.description}
+
+
+
+
+
+
+ );
+}
+
+function Divider({ className = "" }: { className?: string }) {
+ return ;
+}
+
+// ---------------------------------------------------------------------------
+// Main component
+// ---------------------------------------------------------------------------
+
+export function FeaturesSection() {
+ return (
+
+
+ {/* Desktop */}
+
+ {FEATURES.map((f, i) => (
+
+
+ {i < LAST_FEATURE_INDEX &&
}
+
+ ))}
+
+
+ {/* Mobile */}
+
+ {FEATURES.map((f, i) => (
+
+
+ {i < LAST_FEATURE_INDEX &&
}
+
+ ))}
+
+
+ {/* CTA button */}
+
+
+
+ Detailed comparison
+ View Comparison
+
+
+
+
+
+ );
+}
diff --git a/docs/app/(home)/components/Footer/Footer.module.css b/docs/app/(home)/components/Footer/Footer.module.css
new file mode 100644
index 000000000..9dc6d9e0d
--- /dev/null
+++ b/docs/app/(home)/components/Footer/Footer.module.css
@@ -0,0 +1,167 @@
+.footer {
+ width: 100%;
+}
+
+.absoluteSvg {
+ position: absolute;
+ display: block;
+ height: 100%;
+ width: 100%;
+}
+
+.handcraftedSection {
+ width: 100%;
+ padding-inline: 1.25rem;
+}
+
+.handcraftedContainer {
+ display: flex;
+ max-width: 75rem;
+ margin-inline: auto;
+ flex-direction: column;
+ align-items: center;
+ gap: 0.625rem;
+ padding-block: 4rem;
+}
+
+.mascotWrap {
+ position: relative;
+ height: 140px;
+ width: 140px;
+ flex-shrink: 0;
+}
+
+.handcraftedMascot {
+ position: absolute;
+ inset: 9.29% 0 10% 0;
+ display: block;
+}
+
+.handcraftedCopy {
+ text-align: center;
+ font-family: "Playwrite US Trad", serif;
+ font-size: 16px;
+ line-height: 1.2;
+ color: #000;
+}
+
+.contentSection {
+ padding: 60px 1.25rem 1rem;
+ background: #fff;
+}
+
+.contentContainer {
+ max-width: 75rem;
+ margin-inline: auto;
+}
+
+.desktopLogoRow {
+ display: none;
+}
+
+.mobileLogoRow {
+ display: flex;
+ width: 100%;
+ flex-direction: column;
+ align-items: center;
+}
+
+.logoWrap {
+ position: relative;
+ height: 3rem;
+ width: 124px;
+}
+
+.bottomBar {
+ margin-top: 2.5rem;
+ padding-block: 1rem;
+ border-top: 1px solid rgb(0 0 0 / 4%);
+}
+
+.desktopBottomBar {
+ display: none;
+}
+
+.desktopMetaLeft,
+.desktopMetaRight {
+ font-family: "Inter", sans-serif;
+ font-size: 15px;
+ line-height: 1.5;
+ color: rgb(0 0 0 / 40%);
+}
+
+.desktopMetaLeft {
+ text-align: left;
+}
+
+.desktopMetaRight {
+ text-align: right;
+}
+
+.mobileBottomBar {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: flex-start;
+ padding: 2.5rem 0 1.25rem;
+}
+
+.socialIcons {
+ display: flex;
+ gap: 1.5rem;
+}
+
+.socialLink {
+ position: relative;
+ height: 1.5rem;
+ width: 1.5rem;
+}
+
+.socialIconWrap {
+ position: absolute;
+}
+
+.mobileMeta {
+ margin-top: 2.5rem;
+ text-align: center;
+}
+
+.mobileMetaText {
+ font-family: "Inter", sans-serif;
+ font-size: 12px;
+ line-height: 1.5;
+ color: rgb(0 0 0 / 40%);
+}
+
+@media (min-width: 1024px) {
+ .handcraftedSection,
+ .contentSection {
+ padding-inline: 2rem;
+ }
+
+ .handcraftedCopy {
+ font-size: 22px;
+ }
+
+ .desktopLogoRow {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ }
+
+ .mobileLogoRow,
+ .mobileBottomBar {
+ display: none;
+ }
+
+ .bottomBar {
+ margin-top: 60px;
+ }
+
+ .desktopBottomBar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 0.5rem;
+ }
+}
diff --git a/docs/app/(home)/components/Footer.tsx b/docs/app/(home)/components/Footer/Footer.tsx
similarity index 67%
rename from docs/app/(home)/components/Footer.tsx
rename to docs/app/(home)/components/Footer/Footer.tsx
index 5e830d6b5..af87b02c9 100644
--- a/docs/app/(home)/components/Footer.tsx
+++ b/docs/app/(home)/components/Footer/Footer.tsx
@@ -1,7 +1,9 @@
"use client";
+import type { CSSProperties } from "react";
import svgPaths from "@/imports/svg-urruvoh2be";
import mascotSvgPaths from "@/imports/svg-xeurqn3j1r";
+import styles from "./Footer.module.css";
// ---------------------------------------------------------------------------
// Data
@@ -12,8 +14,7 @@ interface SocialLink {
href: string;
viewBox: string;
path: string;
- /** Optional wrapper for icons that need precise positioning */
- wrapperClass?: string;
+ wrapperStyle?: CSSProperties;
clipId?: string;
clipSize?: { width: string; height: string };
}
@@ -24,7 +25,7 @@ const SOCIAL_LINKS: SocialLink[] = [
href: "https://x.com/thesysdev",
viewBox: "0 0 24 24",
path: svgPaths.pa1e7100,
- wrapperClass: "inset-[10.82%_4.33%_18.35%_4.17%]",
+ wrapperStyle: { inset: "10.82% 4.33% 18.35% 4.17%" },
},
{
label: "Discord",
@@ -37,7 +38,13 @@ const SOCIAL_LINKS: SocialLink[] = [
href: "https://www.youtube.com/@thesysdev",
viewBox: "0 0 22 15.4688",
path: svgPaths.p23dbbd00,
- wrapperClass: "-translate-x-1/2 -translate-y-1/2 left-1/2 top-1/2 h-[15.469px] w-[22px]",
+ wrapperStyle: {
+ left: "50%",
+ top: "50%",
+ width: "22px",
+ height: "15.469px",
+ transform: "translate(-50%, -50%)",
+ },
clipId: "clip_yt",
clipSize: { width: "22", height: "15.4688" },
},
@@ -46,7 +53,13 @@ const SOCIAL_LINKS: SocialLink[] = [
href: "https://www.linkedin.com/company/thesysdev/",
viewBox: "0 0 19 19",
path: svgPaths.p26fc3100,
- wrapperClass: "-translate-x-1/2 -translate-y-1/2 left-1/2 top-1/2 size-[19px]",
+ wrapperStyle: {
+ left: "50%",
+ top: "50%",
+ width: "19px",
+ height: "19px",
+ transform: "translate(-50%, -50%)",
+ },
clipId: "clip_li",
clipSize: { width: "19", height: "19" },
},
@@ -58,7 +71,7 @@ const SOCIAL_LINKS: SocialLink[] = [
function SocialIcon({ link }: { link: SocialLink }) {
const svgContent = link.clipId ? (
-