(null);
+
+ useEffect(() => {
+ if (videoRef.current && prefersReducedMotion) {
+ videoRef.current.pause();
+ }
+ }, [prefersReducedMotion]);
+
+ return (
+
+
+
+ {eyebrow && (
+
+ {eyebrow}
+
+ )}
+
+
+ {title}
+
+
+ {subtitle && (
+
+ {subtitle}
+
+ )}
+
+ {buttons && (
+
+
+ {buttons?.map((button, index) => (
+
+ ))}
+
+
+ )}
+
+
+
+
+
+
+
+ );
+};
+
+export default VideoBgHero;
diff --git a/src/components/solutions/blinks-and-actions/BlinksHero.jsx b/src/components/solutions/blinks-and-actions/BlinksHero.jsx
new file mode 100644
index 00000000..2e40bbbb
--- /dev/null
+++ b/src/components/solutions/blinks-and-actions/BlinksHero.jsx
@@ -0,0 +1,83 @@
+import { useEffect, useRef } from "react";
+import { useTranslation } from "next-i18next";
+import classNames from "classnames";
+import Image from "next/image";
+
+import useReducedMotion from "@/hooks/useReducedMotion";
+
+import Button from "@/components/solutions/Button";
+import { OpacityInText } from "@/components/shared/Text";
+import { MotionSlideIn } from "@/components/shared/Motions";
+
+import styles from "./BlinksHero.module.scss";
+
+const BlinksHero = () => {
+ const { t } = useTranslation();
+
+ const videoRef = useRef(null);
+ const [prefersReducedMotion] = useReducedMotion();
+
+ useEffect(() => {
+ prefersReducedMotion && videoRef.current.pause();
+ }, [prefersReducedMotion]);
+
+ return (
+
+
+
+ {t("solutions-blinks-and-actions.hero.kicker")}
+
+
+
+ {t("solutions-blinks-and-actions.hero.title")}
+
+
+
+ {t("solutions-blinks-and-actions.hero.subtitle")}
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default BlinksHero;
diff --git a/src/components/solutions/blinks-and-actions/BlinksHero.module.scss b/src/components/solutions/blinks-and-actions/BlinksHero.module.scss
new file mode 100644
index 00000000..c8b9c057
--- /dev/null
+++ b/src/components/solutions/blinks-and-actions/BlinksHero.module.scss
@@ -0,0 +1,124 @@
+@import "../../../scss/solutions/_variables.scss";
+
+.BlinksHero {
+ padding: 64px 24px;
+ display: flex;
+ flex-direction: column;
+ gap: 40px;
+
+ .ContentWrapper {
+ display: flex;
+ flex-direction: column;
+ gap: 24px;
+
+ p,
+ h1 {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+ }
+
+ .Kicker {
+ font-size: 16px;
+ font-weight: 800;
+ line-height: 1.25;
+ letter-spacing: -0.02em;
+ text-align: center;
+ color: var(--blue);
+ }
+
+ .Title {
+ font-size: 36px;
+ font-weight: 700;
+ line-height: 1.14;
+ letter-spacing: -0.01em;
+ text-align: center;
+ }
+
+ .Subtitle {
+ font-size: 20px;
+ font-weight: 700;
+ line-height: 1.2;
+ text-align: center;
+ color: var(--grey-250);
+ }
+
+ .Buttons {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ width: max-content;
+ margin: 0 auto;
+ }
+
+ .ImageWrapper {
+ display: flex;
+ justify-content: center;
+ }
+}
+
+@include breakpoint(md) {
+ .BlinksHero {
+ padding: 80px 24px;
+
+ .ContentWrapper {
+ @include max-width(650px);
+ }
+
+ .Title {
+ font-size: 64px;
+ }
+
+ .Subtitle {
+ font-size: 24px;
+ }
+ }
+}
+
+@include breakpoint(xl) {
+ .BlinksHero {
+ padding: 92px 24px;
+ flex-direction: row;
+ justify-content: space-between;
+ gap: 128px;
+
+ .ContentWrapper {
+ max-width: 520px;
+ justify-content: center;
+ flex: 1;
+
+ * {
+ text-align: left;
+ }
+ }
+
+ .Kicker {
+ margin-left: 0;
+ font-size: 22px;
+ }
+
+ .Title {
+ font-size: 64px;
+ line-height: 1;
+ letter-spacing: -0.02em;
+ max-width: 422px;
+ }
+
+ .Subtitle {
+ font-size: 32px;
+ line-height: 1.15;
+ letter-spacing: -0.02em;
+ max-width: 100%;
+ }
+
+ .Buttons {
+ margin-left: 0;
+ min-width: 328px;
+
+ a {
+ padding: 12px;
+ width: 100%;
+ }
+ }
+ }
+}
diff --git a/src/components/solutions/gaming/GamesKit.jsx b/src/components/solutions/gaming/GamesKit.jsx
new file mode 100644
index 00000000..04ae56d6
--- /dev/null
+++ b/src/components/solutions/gaming/GamesKit.jsx
@@ -0,0 +1,89 @@
+import Link from "next/link";
+import classNames from "classnames";
+import { useTranslation, Trans } from "next-i18next";
+
+import Button from "@/components/solutions/Button";
+import CaretIcon from "@/components/icons/Caret";
+import { AnimatedText, GradientText } from "@/components/shared/Text";
+import { MotionSlideIn } from "@/components/shared/Motions";
+
+import styles from "./GamesKit.module.scss";
+
+const GamesKit = () => {
+ const { t } = useTranslation();
+
+ const ListItem = ({ title, text, url }) => (
+
+
+
+ {title}
+
+
+
+
{text}
+
+ );
+
+ return (
+
+
+
+
+
+
+ Start with the
+
+ Solana Games Kit
+
+
+
+
+
+
+ {t("solutions-gaming.games-kit.subtitle")}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default GamesKit;
diff --git a/src/components/solutions/gaming/GamesKit.module.scss b/src/components/solutions/gaming/GamesKit.module.scss
new file mode 100644
index 00000000..605182d1
--- /dev/null
+++ b/src/components/solutions/gaming/GamesKit.module.scss
@@ -0,0 +1,172 @@
+@import "~@/scss/solutions/_variables.scss";
+
+.GamesKit {
+ background: var(--grey-500);
+ border-top: 1px solid var(--grey-450);
+
+ @include breakpoint(sm) {
+ padding: 0 40px;
+ }
+}
+
+.Container {
+ @include breakpoint(xl) {
+ display: flex;
+ padding: 128px 40px;
+ gap: 225px;
+
+ .TextBlock,
+ .ListItems {
+ padding: 0;
+ }
+ }
+}
+
+.TextBlock {
+ padding: 64px 24px;
+
+ h2 {
+ font-size: 32px;
+ font-weight: 700;
+ line-height: 1.11;
+ letter-spacing: -0.01em;
+ text-align: center;
+ margin: 0;
+
+ strong {
+ @include gradient-text(
+ linear-gradient(90deg, #64a8f2 0%, #9945ff 49.61%, #eb54bc 100%)
+ );
+ }
+ }
+
+ p {
+ font-size: 18px;
+ font-weight: 700;
+ line-height: 1.16;
+ letter-spacing: -0.01em;
+ text-align: center;
+ color: var(--grey-250);
+ margin: 24px 0 40px;
+ max-width: 100%;
+ }
+
+ a {
+ width: max-content;
+ font-size: 15px;
+ font-weight: 700;
+ line-height: 1.32;
+ margin: 0 auto;
+ }
+}
+
+.ListItems {
+ padding: 0 24px 64px;
+ display: flex;
+ flex-direction: column;
+ gap: 32px;
+
+ .ListItem {
+ h5 {
+ font-size: 18px;
+ font-weight: 700;
+ line-height: 1.16;
+ letter-spacing: -0.01em;
+ text-align: center;
+ margin: 0;
+
+ a {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 4px;
+ color: var(--grey-100);
+
+ svg {
+ width: 22px;
+ transition: 0.2s ease-in;
+
+ @include breakpoint(xl) {
+ width: 24px;
+ }
+ }
+
+ &:hover {
+ svg {
+ transform: translateX(4px);
+ }
+ }
+ }
+ }
+
+ p {
+ font-size: 18px;
+ font-weight: 700;
+ line-height: 1.16;
+ letter-spacing: -0.01em;
+ text-align: center;
+ color: var(--grey-300);
+ margin: 8px 0 0;
+ }
+ }
+}
+
+@include breakpoint(sm) {
+ .TextBlock {
+ h2 {
+ font-size: 40px;
+ }
+ }
+}
+
+@include breakpoint(md) {
+ .TextBlock {
+ h2 {
+ font-size: 56px;
+ }
+ }
+}
+
+@include breakpoint(xl) {
+ .TextBlock {
+ h2 {
+ font-weight: 700;
+ line-height: 1;
+ letter-spacing: -0.02em;
+ text-align: left;
+ }
+
+ p {
+ font-size: 20px;
+ font-weight: 700;
+ line-height: 1.12;
+ letter-spacing: -0.02em;
+ text-align: left;
+ }
+
+ a {
+ font-size: 18px;
+ font-weight: 700;
+ line-height: 1.1;
+ margin-left: 0;
+ }
+ }
+
+ .ListItems {
+ .ListItem {
+ h5 a,
+ p {
+ text-align: left;
+ justify-content: flex-start;
+ }
+
+ h5,
+ p {
+ font-size: 20px;
+ font-weight: 700;
+ line-height: 1.12;
+ letter-spacing: -0.02em;
+ }
+ }
+ }
+}
diff --git a/src/components/solutions/gaming/GamingSlider.module.scss b/src/components/solutions/gaming/GamingSlider.module.scss
new file mode 100644
index 00000000..00cd1167
--- /dev/null
+++ b/src/components/solutions/gaming/GamingSlider.module.scss
@@ -0,0 +1,186 @@
+@import "~@/scss/solutions/_variables.scss";
+
+.Container {
+ position: relative;
+
+ h5,
+ p {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ }
+
+ h5 {
+ font-size: 18px;
+ font-weight: 700;
+ line-height: 1.16;
+ letter-spacing: -0.01em;
+ text-align: left;
+ color: var(--grey-100);
+ margin: 24px 0 0;
+ display: flex;
+ gap: 4px;
+ align-items: center;
+
+ svg {
+ width: 22px;
+
+ @include breakpoint(md) {
+ width: 24px;
+ }
+ }
+
+ &:hover {
+ svg {
+ transform: translateX(4px);
+ }
+ }
+ }
+
+ p {
+ color: #6c6a81;
+ font-size: 14px;
+ line-height: 1.3;
+
+ @include breakpoint(md) {
+ font-size: 18px;
+ }
+ }
+
+ a {
+ color: var(--white);
+ }
+
+ @include breakpoint(lg) {
+ padding: 0;
+ }
+}
+
+.Slider {
+ max-width: 1024px;
+ margin: 0 auto;
+ position: relative;
+ padding-bottom: 80px;
+
+ @include breakpoint(lg) {
+ padding: 0;
+
+ & > div {
+ padding-top: 48px !important;
+ padding-bottom: 168px !important;
+ }
+
+ &:before {
+ content: "";
+ width: 200px;
+ height: 100%;
+ position: absolute;
+ left: -2px;
+ top: 0;
+ background: linear-gradient(
+ 90deg,
+ #0d0817 20%,
+ rgba(15, 10, 22, 0) 99.21%
+ );
+ z-index: 10;
+ pointer-events: none;
+ }
+
+ &:after {
+ content: "";
+ width: 200px;
+ height: 100%;
+ position: absolute;
+ right: -2px;
+ top: 0;
+ background: linear-gradient(
+ 272deg,
+ #0d0817 20%,
+ rgba(15, 10, 22, 0) 99.21%
+ );
+ z-index: 10;
+ pointer-events: none;
+ }
+ }
+}
+
+.Card {
+ $height: 320px;
+
+ position: relative;
+ padding: 8px;
+ min-height: $height;
+
+ @include breakpoint(lg) {
+ min-height: auto;
+ }
+
+ img {
+ border-radius: 16px;
+ }
+
+ .CardInner {
+ padding: 24px;
+ display: block;
+ border-radius: 8px;
+ border: 1px solid var(--gradient-6, #504d61);
+ background: var(--Neutrals-Grey-500, #1d1a23);
+ min-height: 300px;
+ position: relative;
+
+ @include breakpoint(sm) {
+ min-height: 320px;
+ }
+
+ @include breakpoint(md) {
+ min-height: 350px;
+ }
+
+ @include breakpoint(lg) {
+ padding: 0;
+ border-radius: 16px;
+ box-shadow: none !important;
+ min-height: 0;
+ }
+ }
+
+ .CardImageWrapper {
+ position: relative;
+ aspect-ratio: 14 / 9;
+ width: 100%;
+ height: auto;
+ }
+
+ .CardContent {
+ @include breakpoint(lg) {
+ display: none;
+ }
+ }
+}
+
+.TooltipContainer {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: calc(100%);
+ z-index: 12;
+}
+
+.Tooltip {
+ display: none !important;
+
+ @include breakpoint(lg) {
+ display: block !important;
+ }
+
+ position: absolute;
+ top: -24px;
+ left: -24px;
+ width: calc(100% + 48px);
+ padding: 24px;
+ border-radius: 16px;
+ z-index: 10 !important;
+ border-radius: 8px;
+ border: 1px solid var(--gradient-6, #504d61);
+ background: var(--Neutrals-Grey-500, #1d1a23);
+}
diff --git a/src/components/solutions/gaming/GamingSlider.tsx b/src/components/solutions/gaming/GamingSlider.tsx
new file mode 100644
index 00000000..5bcc5a0f
--- /dev/null
+++ b/src/components/solutions/gaming/GamingSlider.tsx
@@ -0,0 +1,202 @@
+"use client";
+
+import { useState } from "react";
+import Link from "next/link";
+import { useTranslation } from "next-i18next";
+import Image from "next/image";
+import Slider from "react-slick";
+import "slick-carousel/slick/slick.css";
+import "slick-carousel/slick/slick-theme.css";
+
+import styles from "./GamingSlider.module.scss";
+import CaretIcon from "@/components/icons/Caret";
+
+const GamingSlider = () => {
+ const { t } = useTranslation();
+ const [tooltip, setTooltip] = useState<{
+ title: string;
+ content: string;
+ img: string;
+ url: string;
+ boxShadow: string;
+ } | null>(null);
+
+ const handleMouseEnter = (card: {
+ title: string;
+ content: string;
+ img: string;
+ url: string;
+ boxShadow: string;
+ }) => {
+ console.log("Hovering over card:", card);
+ setTooltip(card);
+ };
+
+ const handleMouseLeave = () => {
+ console.log("Mouse left card");
+ setTooltip(null);
+ };
+
+ const cards = [
+ {
+ title: t("solutions-gaming.cards.star-atlas.title"),
+ content: t("solutions-gaming.cards.star-atlas.content"),
+ img: "/solutions/gaming/slider/row1-card1.jpg",
+ url: "https://play.staratlas.com/",
+ boxShadow: "#3079A6B2",
+ },
+ {
+ title: t("solutions-gaming.cards.aurory.title"),
+ content: t("solutions-gaming.cards.aurory.content"),
+ img: "/solutions/gaming/slider/row1-card2.jpg",
+ url: "https://aurory.io/",
+ boxShadow: "#AE7272B2",
+ },
+ {
+ title: t("solutions-gaming.cards.stepn-go.title"),
+ content: t("solutions-gaming.cards.stepn-go.content"),
+ img: "/solutions/gaming/slider/row1-card3.jpg",
+ url: "https://stepngo.com/",
+ boxShadow: "#7E5CDCB2",
+ },
+ {
+ title: t("solutions-gaming.cards.br1.title"),
+ content: t("solutions-gaming.cards.br1.content"),
+ img: "/solutions/gaming/slider/row1-card4.jpg",
+ url: "https://www.br1game.com/",
+ boxShadow: "#22ABC1B2",
+ },
+ {
+ title: t("solutions-gaming.cards.nyan-heros.title"),
+ content: t("solutions-gaming.cards.nyan-heros.content"),
+ img: "/solutions/gaming/slider/row1-card5.jpg",
+ url: "https://nyanheroes.com/",
+ boxShadow: "#3079A6B2",
+ },
+ {
+ title: t("solutions-gaming.cards.photo-finish-live.title"),
+ content: t("solutions-gaming.cards.photo-finish-live.content"),
+ img: "/solutions/gaming/slider/row2-card1.jpg",
+ url: "https://photofinish.live/",
+ boxShadow: "#206E72B2",
+ },
+ {
+ title: t("solutions-gaming.cards.genopets.title"),
+ content: t("solutions-gaming.cards.genopets.content"),
+ img: "/solutions/gaming/slider/row2-card2.jpg",
+ url: "https://www.genopets.me/",
+ boxShadow: "#A1937DB2",
+ },
+ {
+ title: t("solutions-gaming.cards.portals.title"),
+ content: t("solutions-gaming.cards.portals.content"),
+ img: "/solutions/gaming/slider/row2-card3.jpg",
+ url: "https://theportal.to/",
+ boxShadow: "#29729FB2",
+ },
+ {
+ title: t("solutions-gaming.cards.low-life-forms.title"),
+ content: t("solutions-gaming.cards.low-life-forms.content"),
+ img: "/solutions/gaming/slider/row2-card4.jpg",
+ url: "https://www.rtrigger.com/#lowlifeforms",
+ boxShadow: "#9F51EBB2",
+ },
+ {
+ title: t("solutions-gaming.cards.mixmob.title"),
+ content: t("solutions-gaming.cards.mixmob.content"),
+ img: "/solutions/gaming/slider/row2-card5.jpg",
+ url: "https://uprising.mixmob.io/",
+ boxShadow: "#2D42C3B2",
+ },
+ ];
+
+ const settings = {
+ className: "center",
+ centerMode: true,
+ infinite: true,
+ centerPadding: "140px",
+ arrows: true,
+ slidesToShow: 3,
+ speed: 500,
+ rows: 2,
+ slidesPerRow: 1,
+ responsive: [
+ {
+ breakpoint: 992,
+ settings: {
+ slidesToShow: 2,
+ centerPadding: "48px",
+ },
+ },
+ {
+ breakpoint: 639,
+ settings: {
+ slidesToShow: 1,
+ centerPadding: "56px",
+ },
+ },
+ {
+ breakpoint: 480,
+ settings: {
+ slidesToShow: 1,
+ centerPadding: "32px",
+ },
+ },
+ ],
+ };
+
+ return (
+
+
+ {cards.map((card, index) => (
+ handleMouseEnter(card)}
+ onMouseLeave={handleMouseLeave}
+ >
+
+
+
+
+
+
+ {card.title}
+
+
+
{card.content}
+
+
+
+ {tooltip && tooltip.title === card.title && (
+
+
+
+
+
+
+ {tooltip.title}
+
+
+
{tooltip.content}
+
+
+ )}
+
+ ))}
+
+
+ );
+};
+
+export default GamingSlider;
diff --git a/src/components/solutions/gaming/GamingVideoHero.jsx b/src/components/solutions/gaming/GamingVideoHero.jsx
new file mode 100644
index 00000000..8e02d42a
--- /dev/null
+++ b/src/components/solutions/gaming/GamingVideoHero.jsx
@@ -0,0 +1,119 @@
+import { useRef, useEffect } from "react";
+import { useTranslation } from "next-i18next";
+import useReducedMotion from "../../../hooks/useReducedMotion";
+
+import Button from "@/components/solutions/Button";
+import { OpacityInText } from "@/components/shared/Text";
+import { MotionSlideIn } from "@/components/shared/Motions";
+
+import styles from "./GamingVideoHero.module.scss";
+
+const GamingVideoHero = () => {
+ const { t } = useTranslation();
+ const video1Ref = useRef(null);
+ const video2Ref = useRef(null);
+ const [prefersReducedMotion] = useReducedMotion();
+
+ const videos = [
+ {
+ src_720:
+ "https://player.vimeo.com/progressive_redirect/playback/1009457872/rendition/720p/file.mp4?loc=external&signature=9c3fab67abf9c4a84a9db0c3cc16ffaeab06ad83e2c8100aa5b524d0184f9954",
+ src_1080:
+ "https://player.vimeo.com/progressive_redirect/playback/1009457872/rendition/1080p/file.mp4?loc=external&signature=86bd2ccd9bc532bff002c5e4eeb2cd892842aba7ac17b8f06936c5bfeab95012",
+ poster: "/solutions/gaming/hero-video-1.webp",
+ },
+ {
+ src_720:
+ "https://player.vimeo.com/progressive_redirect/playback/1009457866/rendition/720p/file.mp4?loc=external&signature=f945644cad9795580cb0b90ce6d3ca744fdd13a5faf7eeafd1fb35b46739a7bd",
+ src_1080:
+ "https://player.vimeo.com/progressive_redirect/playback/1009457866/rendition/1080p/file.mp4?loc=external&signature=f77cc386fce4caa083968ed91504145a93b448a51d4b8e22b2d444484722d128",
+ poster: "/solutions/gaming/hero-video-2.webp",
+ },
+ ];
+
+ const handleVideoEnd = () => {
+ video1Ref.current.style.opacity = 0;
+ video2Ref.current.style.opacity = 1;
+ };
+
+ useEffect(() => {
+ if (video1Ref.current && prefersReducedMotion) {
+ video1Ref.current.pause();
+ }
+ }, [prefersReducedMotion]);
+
+ useEffect(() => {
+ if (video1Ref.current && video2Ref.current) {
+ video1Ref.current.play();
+ video2Ref.current.play();
+ }
+ }, [video1Ref, video2Ref]);
+
+ return (
+
+
+
+
+
+ {t("solutions-gaming.hero.kicker")}
+
+
+ {t("solutions-gaming.hero.title")}
+
+
+ {t("solutions-gaming.hero.subtitle")}
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default GamingVideoHero;
diff --git a/src/components/solutions/gaming/GamingVideoHero.module.scss b/src/components/solutions/gaming/GamingVideoHero.module.scss
new file mode 100644
index 00000000..fdde4f21
--- /dev/null
+++ b/src/components/solutions/gaming/GamingVideoHero.module.scss
@@ -0,0 +1,116 @@
+@import "~@/scss/solutions/_variables.scss";
+
+.GamingVideoHero {
+ height: calc(100vh - 76px);
+ position: relative;
+
+ video {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ object-position: center;
+ }
+
+ .Video2 {
+ opacity: 0;
+ }
+}
+
+.VideoWrapper {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+
+ .VideoOverlay {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.4);
+ z-index: 1;
+ }
+}
+
+.TextBlock {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ z-index: 2;
+ text-align: center;
+ width: 100%;
+ padding: 24px;
+
+ .Kicker {
+ font-size: 16px;
+ font-weight: 800;
+ line-height: 1.25;
+ letter-spacing: -0.02em;
+ text-align: center;
+ text-transform: uppercase;
+ margin: 0 0 24px;
+ display: block;
+
+ @include breakpoint(lg) {
+ font-size: 22px;
+ font-weight: 800;
+ line-height: 1.25;
+ letter-spacing: -0.02em;
+ }
+ }
+
+ h1 {
+ font-size: 48px;
+ font-weight: 700;
+ line-height: 1;
+ letter-spacing: -0.02em;
+ }
+
+ p {
+ font-size: 20px;
+ font-weight: 700;
+ line-height: 1.2;
+ margin: 24px auto 0;
+ max-width: 702px;
+ }
+}
+
+.Buttons {
+ display: flex;
+ flex-direction: column;
+ width: max-content;
+ margin: 24px auto 0;
+ gap: 16px;
+
+ @media (max-width: #{$screen-md-min - 1}) {
+ a {
+ font-size: 15px;
+ line-height: 1.32;
+ }
+ }
+
+ @include breakpoint(lg) {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ }
+}
+
+@include breakpoint(xl) {
+ .TextBlock {
+ h1 {
+ font-size: 96px;
+ }
+
+ p {
+ font-size: 28px;
+ line-height: 1.15;
+ letter-spacing: -0.02em;
+ }
+ }
+}
diff --git a/src/components/solutions/gaming/TVMert.module.scss b/src/components/solutions/gaming/TVMert.module.scss
new file mode 100644
index 00000000..2281efca
--- /dev/null
+++ b/src/components/solutions/gaming/TVMert.module.scss
@@ -0,0 +1,79 @@
+@import "../../../scss/solutions/_variables.scss";
+
+.TVMert {
+ position: relative;
+ padding: 64px 0;
+
+ .Title {
+ font-size: 40px;
+ font-weight: 700;
+ line-height: 1.06;
+ letter-spacing: -0.01em;
+ text-align: center;
+ padding: 0 24px;
+ margin: 0 auto 24px;
+ position: relative;
+ z-index: 2;
+
+ --gradient: linear-gradient(
+ 90deg,
+ #3f37c9 4.6%,
+ #46dcf8 31.37%,
+ #ffffff 50.45%
+ );
+ }
+}
+
+.VideoWrapper {
+ position: relative;
+ width: 100vw;
+ height: calc(100vw * 0.5);
+ transform: scale(1.25);
+
+ @include breakpoint(sm) {
+ transform: scale(1);
+ }
+
+ @include breakpoint(md) {
+ margin-top: -5%;
+ position: relative;
+ z-index: 1;
+ }
+
+ video {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 100%;
+ height: 100%;
+ object-fit: contain;
+ object-position: center;
+ opacity: 0;
+ transition: opacity $duration-standard;
+
+ &.Active {
+ opacity: 1;
+ }
+ }
+}
+
+@include breakpoint(md) {
+ .TVMert {
+ .Title {
+ font-size: 80px;
+ margin-bottom: 0;
+ letter-spacing: -0.03em;
+ }
+ }
+
+ .VideoWrapper {
+ width: 100%;
+ }
+}
+
+@include breakpoint(xl) {
+ .TVMert {
+ padding: 128px 0 0;
+ }
+}
diff --git a/src/components/solutions/gaming/TVMert.tsx b/src/components/solutions/gaming/TVMert.tsx
new file mode 100644
index 00000000..c03f0e74
--- /dev/null
+++ b/src/components/solutions/gaming/TVMert.tsx
@@ -0,0 +1,106 @@
+import { useRef, useEffect } from "react";
+import { Trans } from "next-i18next";
+import classNames from "classnames";
+
+import { AnimatedText, GradientText } from "@/components/shared/Text";
+
+import useReducedMotion from "@/hooks/useReducedMotion";
+
+import styles from "./TVMert.module.scss";
+
+const TVMert = () => {
+ const video1Ref = useRef(null);
+ const video2Ref = useRef(null);
+ const [prefersReducedMotion] = useReducedMotion();
+
+ const videos = [
+ {
+ src_720:
+ "https://player.vimeo.com/progressive_redirect/playback/1009649838/rendition/720p/file.mp4?loc=external&signature=0c0ffaab9ea401d986555187c28100a88594ccc69d8317f295f06cb618815e4c",
+ src_1080:
+ "https://player.vimeo.com/progressive_redirect/playback/1009649838/rendition/1080p/file.mp4?loc=external&signature=8769962746274f024137d46578b7ee5630fe33ea5d845d5ee8e342697ab82dac",
+ poster: "/solutions/gaming/mert-tv-1.jpeg",
+ },
+ {
+ src_720:
+ "https://player.vimeo.com/progressive_redirect/playback/1009649823/rendition/720p/file.mp4?loc=external&signature=9917c37382359cac1733ee757060f86b07cff29c8d646842962d56321c52d544",
+ src_1080:
+ "https://player.vimeo.com/progressive_redirect/playback/1009649823/rendition/1080p/file.mp4?loc=external&signature=b8f8a4574f9ee500b74e63279e83c0da87258c7c306f0ba879d051f264f85f10",
+ poster: "/solutions/gaming/mert-tv-2.jpeg",
+ },
+ ];
+
+ const handleVideoEnd = () => {
+ video1Ref.current.style.opacity = 0;
+ video2Ref.current.style.opacity = 1;
+ };
+
+ useEffect(() => {
+ if (video1Ref.current && prefersReducedMotion) {
+ video1Ref.current.pause();
+ }
+ }, [prefersReducedMotion, video1Ref]);
+
+ useEffect(() => {
+ if (video1Ref.current && video2Ref.current) {
+ video1Ref.current.play();
+ video2Ref.current.play();
+ setTimeout(() => {
+ video1Ref.current?.classList.add(styles.Active);
+ }, 500);
+ }
+ }, [video1Ref, video2Ref]);
+
+ return (
+
+
+ ,
+ }}
+ />
+
+
+
+
+
+
+
+
+ );
+};
+
+export default TVMert;
diff --git a/src/components/solutions/layout.tsx b/src/components/solutions/layout.tsx
new file mode 100644
index 00000000..f8a7406e
--- /dev/null
+++ b/src/components/solutions/layout.tsx
@@ -0,0 +1,21 @@
+import { ReactNode } from "react";
+import classNames from "classnames";
+import Header from "../Header";
+import Footer from "../Footer";
+import styles from "./Layout.module.scss";
+
+interface LayoutProps {
+ headerClassName?: string;
+ children: ReactNode;
+}
+
+const Layout = ({ headerClassName, children }: LayoutProps) => {
+ return (
+
+
+ {children}
+
+
+ );
+};
+export default Layout;
diff --git a/src/components/solutions/loyalty/LoyaltyHero.jsx b/src/components/solutions/loyalty/LoyaltyHero.jsx
new file mode 100644
index 00000000..e7a81283
--- /dev/null
+++ b/src/components/solutions/loyalty/LoyaltyHero.jsx
@@ -0,0 +1,53 @@
+import Lottie from "react-lottie";
+import { useTranslation } from "next-i18next";
+
+import Text from "@/components/shared/Text";
+import Button from "@/components/solutions/Button";
+import { MotionSlideIn } from "@/components/shared/Motions";
+
+import styles from "./LoyaltyHero.module.scss";
+
+const LoyaltyHero = ({ heroLottie }) => {
+ const { t } = useTranslation();
+
+ return (
+
+
+
+ {t("solutions-loyalty.hero.eyebrow")}
+
+
+ {t("solutions-loyalty.hero.title")}
+
+
+ {t("solutions-loyalty.hero.subtitle")}
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default LoyaltyHero;
diff --git a/src/components/solutions/loyalty/LoyaltyHero.module.scss b/src/components/solutions/loyalty/LoyaltyHero.module.scss
new file mode 100644
index 00000000..53b4078f
--- /dev/null
+++ b/src/components/solutions/loyalty/LoyaltyHero.module.scss
@@ -0,0 +1,114 @@
+@import "@/scss/solutions/_variables.scss";
+
+.Hero {
+ padding: 64px 24px;
+
+ .HeroTitle {
+ font-size: 36px;
+ font-weight: 700;
+ line-height: 1.14;
+ letter-spacing: -0.01em;
+ text-align: center;
+ text-wrap: initial;
+ }
+
+ .HeroSubtitle {
+ font-size: 20px;
+ font-weight: 700;
+ line-height: 1.12;
+ text-align: center;
+ color: #a2a1b2;
+ margin: 24px 0 40px;
+ max-width: 100%;
+ }
+
+ .Eyebrow {
+ color: #64a8f2;
+ text-align: center;
+ margin-bottom: 24px;
+ text-transform: uppercase;
+ font-size: 16px;
+ font-weight: 800;
+ line-height: 1.25;
+ letter-spacing: -0.02em;
+ }
+
+ .ButtonWrapper {
+ display: flex;
+ flex-direction: column;
+ width: max-content;
+ margin: 24px auto 40px;
+ gap: 16px;
+
+ @media (max-width: #{$screen-xl-min - 1}) {
+ a {
+ font-size: 15px;
+ line-height: 1.32;
+ }
+ }
+
+ @include breakpoint(lg) {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ margin-left: 0;
+
+ a {
+ width: 100%;
+ flex-direction: column;
+ }
+ }
+ }
+
+ @include breakpoint(lg) {
+ display: flex;
+ gap: 80px;
+ max-width: 1080px;
+ margin: 0 auto;
+ align-items: center;
+ padding: 128px 40px;
+ box-sizing: content-box;
+
+ * {
+ flex-basis: 50%;
+ }
+
+ .HeroTitle {
+ font-size: 64px;
+ text-align: left;
+ }
+
+ .HeroSubtitle {
+ font-size: 24px;
+ text-align: left;
+ }
+
+ .Eyebrow {
+ text-align: left;
+ }
+ }
+
+ @include breakpoint(xl) {
+ .HeroTitle {
+ font-size: 64px;
+ font-weight: 700;
+ line-height: 1.04;
+ letter-spacing: -0.02em;
+ text-align: left;
+ max-width: 400px;
+ }
+
+ .HeroSubtitle {
+ font-size: 24px;
+ font-weight: 700;
+ line-height: 1.15;
+ letter-spacing: -0.02em;
+ }
+
+ .Eyebrow {
+ font-size: 20px;
+ font-weight: 800;
+ line-height: 1.25;
+ letter-spacing: -0.44px;
+ }
+ }
+}
diff --git a/src/components/solutions/token-extensions/EcosystemToggle.module.scss b/src/components/solutions/token-extensions/EcosystemToggle.module.scss
new file mode 100644
index 00000000..060c700b
--- /dev/null
+++ b/src/components/solutions/token-extensions/EcosystemToggle.module.scss
@@ -0,0 +1,326 @@
+@import "~@/scss/solutions/_variables.scss";
+
+.TitleBlock {
+ padding-top: 64px;
+
+ @include breakpoint(lg) {
+ padding-top: 80px;
+ }
+}
+
+.Title {
+ font-size: 40px;
+ font-weight: 700;
+ line-height: 1.15;
+ letter-spacing: -0.03em;
+ text-align: center;
+ color: var(--white);
+ text-transform: capitalize;
+ margin: 0;
+ padding: 0 24px;
+
+ strong {
+ background: var(--gradient-2);
+ -webkit-background-clip: text;
+ background-clip: text;
+ -webkit-text-fill-color: transparent;
+ }
+
+ @include breakpoint(lg) {
+ font-size: 72px;
+ line-height: 1.08;
+ letter-spacing: -0.03em;
+ margin-bottom: 24px;
+ }
+}
+
+.Text {
+ font-size: 20px;
+ font-weight: 700;
+ line-height: 1.12;
+ letter-spacing: -0.02em;
+ text-align: center;
+ color: var(--grey-250);
+ max-width: 698px;
+ padding: 0 24px;
+ margin: 24px auto 0;
+
+ @include breakpoint(md) {
+ font-size: 24px;
+ }
+
+ @include breakpoint(lg) {
+ font-size: 32px;
+ font-weight: 500;
+ line-height: 1.25;
+ text-align: center;
+ max-width: 886px;
+ }
+}
+
+.MainCollapsible {
+ & > button[data-state="open"] {
+ animation: hide 300ms ease;
+ visibility: hidden;
+ transition: visibility 300ms ease;
+ }
+}
+
+.CollapsibleContentWrapper {
+ margin-top: 64px;
+ margin-bottom: 64px;
+
+ @include breakpoint(lg) {
+ margin-top: 124px;
+ margin-bottom: 80px;
+ }
+
+ .ToggleBtn {
+ background: var(--grey-450);
+ font-size: 15px;
+ color: white;
+ line-height: 1.3;
+ font-weight: 700;
+ padding: 12px;
+ border-radius: 8px;
+ margin-bottom: 24px;
+
+ svg path {
+ stroke: var(--white);
+ }
+
+ @include breakpoint(md) {
+ font-size: 16px;
+ justify-content: center;
+ }
+
+ @include breakpoint(lg) {
+ justify-content: center;
+ }
+ }
+
+ .EcosystemPreviewContent {
+ position: relative;
+ // overflow: hidden;
+
+ &:after {
+ content: "";
+ display: block;
+ height: 100%;
+ width: 100%;
+ position: absolute;
+ top: 0;
+ opacity: 1;
+ background: linear-gradient(0deg, #0f0a16 0%, rgba(15, 10, 22, 0.6) 100%);
+ transform: translateY(0%);
+ transition:
+ opacity 0.3s ease-in-out,
+ background 0.5s ease-in-out,
+ transform 0s ease-in-out;
+ }
+ }
+
+ div[data-state="closed"] {
+ .EcosystemPreviewContent {
+ &:after {
+ opacity: 1;
+ background: linear-gradient(
+ 0deg,
+ #0f0a16 0%,
+ rgba(15, 10, 22, 0.6) 100%
+ );
+ transform: translateY(0%);
+ }
+ }
+ }
+
+ div[data-state="open"] {
+ .EcosystemPreviewContent {
+ &:after {
+ opacity: 0;
+ background: transparent;
+ transform: translateY(-100%);
+ }
+ }
+ }
+
+ .EcosystemItem {
+ position: relative;
+ // .AccordionContent {
+ // opacity: 0;
+ // }
+
+ .AccordionContent[data-state="closed"] {
+ animation: slideUp 300ms cubic-bezier(0.87, 0, 0.13, 1);
+ }
+
+ .AccordionContent[data-state="open"] {
+ animation: slideDown 300ms cubic-bezier(0.87, 0, 0.13, 1) forwards;
+
+ @include breakpoint(lg) {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: auto;
+ }
+ }
+
+ h3 {
+ margin: 0;
+ line-height: 1;
+ display: flex;
+ }
+
+ button {
+ color: var(--grey-400);
+ letter-spacing: -0.01em;
+ font-size: 18px;
+ line-height: 1.16;
+ padding: 6px 0;
+ width: 100%;
+
+ @include breakpoint(md) {
+ font-size: 20px;
+ }
+
+ @include breakpoint(lg) {
+ font-size: 28px;
+ }
+
+ svg {
+ display: none;
+ }
+
+ &[data-state="open"] {
+ color: var(--white);
+ }
+ }
+
+ .ItemToggleBtn {
+ display: flex;
+ justify-content: center;
+
+ &:hover {
+ color: var(--white);
+ transition: color 0.1s ease-in;
+ }
+
+ @include breakpoint(lg) {
+ justify-content: flex-start;
+ }
+ }
+
+ .EcosystemItemContent {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ gap: 8px;
+ text-align: center;
+ padding: 6px;
+ position: relative;
+
+ @include breakpoint(lg) {
+ align-items: flex-end;
+ text-align: left;
+ }
+
+ .EcosystemItemContentInner {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+
+ @include breakpoint(lg) {
+ width: 329px;
+ gap: 40px;
+ position: relative;
+ }
+ }
+
+ h4 {
+ font-size: 13px;
+ line-height: 1.32;
+ color: var(--grey-100);
+ margin: 0;
+ font-weight: bold;
+
+ @include breakpoint(md) {
+ font-size: 15px;
+ }
+
+ @include breakpoint(lg) {
+ font-size: 18px;
+ }
+ }
+
+ p {
+ font-size: 13px;
+ line-height: 1.32;
+ color: var(--grey-300);
+ margin: 0;
+ font-weight: bold;
+ width: 75%;
+ max-width: 500px;
+ margin: 0 auto;
+
+ @include breakpoint(md) {
+ font-size: 15px;
+ }
+
+ @include breakpoint(lg) {
+ max-width: 100%;
+ width: 100%;
+ margin: 0 auto;
+ font-size: 18px;
+ }
+ }
+
+ a {
+ font-size: 13px;
+ line-height: 1.1;
+ color: var(--white);
+ max-width: 75%;
+ margin: 8px auto;
+
+ @include breakpoint(md) {
+ font-size: 15px;
+ }
+
+ @include breakpoint(lg) {
+ max-width: 100%;
+ width: 100%;
+ margin: 0 auto;
+ }
+ }
+ }
+ }
+}
+
+@keyframes hide {
+ from {
+ opacity: 1;
+ }
+ to {
+ opacity: 0;
+ }
+}
+
+@keyframes slideDown {
+ from {
+ height: 0;
+ opacity: 0;
+ }
+ to {
+ height: var(--radix-accordion-content-height);
+ opacity: 1;
+ }
+}
+
+@keyframes slideUp {
+ from {
+ height: var(--radix-accordion-content-height);
+ }
+ to {
+ height: 0;
+ }
+}
diff --git a/src/components/solutions/token-extensions/EcosystemToggle.tsx b/src/components/solutions/token-extensions/EcosystemToggle.tsx
new file mode 100644
index 00000000..3330d7aa
--- /dev/null
+++ b/src/components/solutions/token-extensions/EcosystemToggle.tsx
@@ -0,0 +1,133 @@
+import { ReactNode, Fragment } from "react";
+import classNames from "classnames";
+import { Trans } from "next-i18next";
+import * as Accordion from "@radix-ui/react-accordion";
+
+import Text, { AnimatedText, GradientText } from "@/components/shared/Text";
+import CollapsibleContent from "@/components/shared/CollapsibleContent";
+
+import styles from "./EcosystemToggle.module.scss";
+
+interface EcosystemItem {
+ label: string;
+ content: ReactNode;
+}
+
+const AccordionItem = ({ value, label, content }) => {
+ return (
+
+
+
+ {label}
+
+
+
+
+ {content}
+
+
+ );
+};
+
+const EcosystemToggle = ({ titleKey, textKey, toggleLabel, items }) => {
+ return (
+
+
+ {titleKey && (
+
+
+ ),
+ }}
+ />
+
+ )}
+
+ {textKey && (
+
+
+
+ )}
+
+
+
+
+
+ {items.slice(0, 3).map((item: EcosystemItem, index: number) => (
+
+
+
+ ))}
+
+ }
+ >
+ {items
+ .slice(3)
+ .map(
+ (
+ item: { label: string; content?: ReactNode },
+ index: number,
+ ) => (
+
+
+
+ ),
+ )}
+ {/* {items
+ .slice(3)
+ .map(
+ (
+ item: { label: string; content?: ReactNode },
+ index: number,
+ ) => (
+
+
+
+ ),
+ )} */}
+
+
+
+
+ );
+};
+
+export const EcosystemItemContentWrap = ({
+ children,
+}: {
+ children: ReactNode;
+}) => (
+
+);
+
+export const EcosystemItemContentTitle = ({ text }: { text: string }) => (
+ {text}
+);
+
+export const EcosystemItemContentText = ({ text }: { text: string }) => (
+ {text}
+);
+
+export default EcosystemToggle;
diff --git a/src/components/solutions/wallets-explorer/CollapsibleContent.jsx b/src/components/solutions/wallets-explorer/CollapsibleContent.jsx
new file mode 100644
index 00000000..4f6da03c
--- /dev/null
+++ b/src/components/solutions/wallets-explorer/CollapsibleContent.jsx
@@ -0,0 +1,43 @@
+import { useState } from "react";
+import * as Collapsible from "@radix-ui/react-collapsible";
+import classNames from "classnames";
+
+import CaretIcon from "@/components/icons/Caret";
+
+import styles from "./CollapsibleContent.module.scss";
+
+const CollapsibleContent = ({
+ label,
+ defaultOpen,
+ children,
+ icon,
+ classes,
+}) => {
+ const [open, setOpen] = useState(defaultOpen || false);
+
+ return (
+
+ {label && (
+
+
+
+ )}
+
+ {children}
+
+ );
+};
+
+export default CollapsibleContent;
diff --git a/src/components/solutions/wallets-explorer/CollapsibleContent.module.scss b/src/components/solutions/wallets-explorer/CollapsibleContent.module.scss
new file mode 100644
index 00000000..0e473028
--- /dev/null
+++ b/src/components/solutions/wallets-explorer/CollapsibleContent.module.scss
@@ -0,0 +1,23 @@
+.CollapsibleTrigger {
+ border-bottom: 1px solid var(--grey-400);
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ width: 100%;
+}
+
+.Label {
+ font-size: 13px;
+ font-weight: 400;
+ line-height: 1.4;
+ letter-spacing: 0.02em;
+ color: var(--blue);
+ text-transform: uppercase;
+ padding: 19px 0;
+ margin: 0;
+ text-align: left;
+}
+
+.IconArrowDown {
+ transform: rotate(180deg);
+}
diff --git a/src/components/solutions/wallets-explorer/Filters.jsx b/src/components/solutions/wallets-explorer/Filters.jsx
new file mode 100644
index 00000000..da66b5f6
--- /dev/null
+++ b/src/components/solutions/wallets-explorer/Filters.jsx
@@ -0,0 +1,433 @@
+import { useState } from "react";
+import Image from "next/image";
+import { useTranslation } from "next-i18next";
+
+import CollapsibleContent from "@/components/solutions/wallets-explorer/CollapsibleContent";
+
+import XIcon from "../../../../assets/wallets/x.inline.svg";
+
+import styles from "./Filters.module.scss";
+
+const CloseButton = ({ onClick }) => {
+ return (
+
+ );
+};
+
+const ToggleFormField = ({ key, label, id, checked, onChange }) => (
+
+
+ {label}
+
+
+
+
+
+
+);
+
+export const MobileFilters = ({
+ filterState,
+ toggleFilterActiveState,
+ resetWalletsAndFilters,
+}) => {
+ const { t } = useTranslation();
+
+ const [open, setOpen] = useState(false);
+
+ // Active filters count
+ const activeFiltersCount = filterState.filter(
+ (filter) => filter.checked,
+ ).length;
+
+ // Categories
+ const beginnerFilters = filterState.filter(
+ (filter) => filter.category === "beginner",
+ );
+ const advancedFilters = filterState.filter(
+ (filter) => filter.category === "advanced",
+ );
+
+ // Advanced filters are further categorized into subcategories
+ const walletTypeFilters = advancedFilters.filter(
+ (filter) => filter.subCategory === "wallet_type",
+ );
+ const financialTransactionFilters = advancedFilters.filter(
+ (filter) => filter.subCategory === "financial_transaction",
+ );
+ const assetManagementFilters = advancedFilters.filter(
+ (filter) => filter.subCategory === "asset_management",
+ );
+ const securityRecoveryFilters = advancedFilters.filter(
+ (filter) => filter.subCategory === "security_recovery",
+ );
+ const toolingFilters = advancedFilters.filter(
+ (filter) => filter.subCategory === "tooling",
+ );
+
+ const handleMenuToggle = () => {
+ !open
+ ? (document.body.style.overflow = "hidden")
+ : (document.body.style.overflow = "auto");
+ setOpen(!open);
+ };
+
+ return (
+
+
+
+
+
+
+ {t("solutions-wallets-explorer.filters")}
+
+
+
+
+
+
+
+
+ {beginnerFilters.length &&
+ beginnerFilters.map((filter, index) => (
+ toggleFilterActiveState(filter.id)}
+ />
+ ))}
+
+
+
+
+
+
+ {walletTypeFilters.length &&
+ walletTypeFilters.map((filter, index) => (
+ toggleFilterActiveState(filter.id)}
+ />
+ ))}
+
+
+
+ {financialTransactionFilters.length &&
+ financialTransactionFilters.map((filter, index) => (
+ toggleFilterActiveState(filter.id)}
+ />
+ ))}
+
+
+
+ {assetManagementFilters.length &&
+ assetManagementFilters.map((filter, index) => (
+ toggleFilterActiveState(filter.id)}
+ />
+ ))}
+
+
+
+ {securityRecoveryFilters.length &&
+ securityRecoveryFilters.map((filter, index) => (
+ toggleFilterActiveState(filter.id)}
+ />
+ ))}
+
+
+
+ {toolingFilters.length &&
+ toolingFilters.map((filter, index) => (
+ toggleFilterActiveState(filter.id)}
+ />
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export const DesktopFilters = ({
+ filterState,
+ toggleFilterActiveState,
+ resetWalletsAndFilters,
+}) => {
+ const { t } = useTranslation();
+
+ // Active filters count
+ const activeFiltersCount = filterState.filter(
+ (filter) => filter.checked,
+ ).length;
+
+ // Categories
+ const beginnerFilters = filterState.filter(
+ (filter) => filter.category === "beginner",
+ );
+ const advancedFilters = filterState.filter(
+ (filter) => filter.category === "advanced",
+ );
+
+ // Advanced filters are further categorized into subcategories
+ const walletTypeFilters = advancedFilters.filter(
+ (filter) => filter.subCategory === "wallet_type",
+ );
+ const financialTransactionFilters = advancedFilters.filter(
+ (filter) => filter.subCategory === "financial_transaction",
+ );
+ const assetManagementFilters = advancedFilters.filter(
+ (filter) => filter.subCategory === "asset_management",
+ );
+ const securityRecoveryFilters = advancedFilters.filter(
+ (filter) => filter.subCategory === "security_recovery",
+ );
+ const toolingFilters = advancedFilters.filter(
+ (filter) => filter.subCategory === "tooling",
+ );
+
+ return (
+
+
+
+
+
+
+
+
+ {beginnerFilters.length &&
+ beginnerFilters.map((filter, index) => (
+ toggleFilterActiveState(filter.id)}
+ />
+ ))}
+
+
+
+
+
+
+ }
+ classes={styles.FirstChild}
+ >
+ {walletTypeFilters.length &&
+ walletTypeFilters.map((filter, index) => (
+ toggleFilterActiveState(filter.id)}
+ />
+ ))}
+
+
+
+ }
+ classes={styles.Child}
+ >
+ {financialTransactionFilters.length &&
+ financialTransactionFilters.map((filter, index) => (
+ toggleFilterActiveState(filter.id)}
+ />
+ ))}
+
+
+
+ }
+ classes={styles.Child}
+ >
+ {assetManagementFilters.length &&
+ assetManagementFilters.map((filter, index) => (
+ toggleFilterActiveState(filter.id)}
+ />
+ ))}
+
+
+
+ }
+ classes={styles.Child}
+ >
+ {securityRecoveryFilters.length &&
+ securityRecoveryFilters.map((filter, index) => (
+ toggleFilterActiveState(filter.id)}
+ />
+ ))}
+
+
+
+ }
+ classes={styles.Child}
+ >
+ {toolingFilters.length &&
+ toolingFilters.map((filter, index) => (
+ toggleFilterActiveState(filter.id)}
+ />
+ ))}
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/components/solutions/wallets-explorer/Filters.module.scss b/src/components/solutions/wallets-explorer/Filters.module.scss
new file mode 100644
index 00000000..04ded05b
--- /dev/null
+++ b/src/components/solutions/wallets-explorer/Filters.module.scss
@@ -0,0 +1,346 @@
+@import "~@/scss/solutions/_variables.scss";
+
+.Fieldsets {
+ display: flex;
+ flex-direction: column;
+ gap: 15px;
+ padding-bottom: 24px;
+}
+
+.FieldsetsInner {
+ padding-bottom: 96px;
+ padding-top: 105px;
+}
+
+.FormField {
+ display: grid;
+ grid-template-columns: 1fr auto;
+ align-items: center;
+ width: 100%;
+ gap: 5px;
+ padding: 19px 0;
+ position: relative;
+}
+
+.FormFieldLabel {
+ font-size: 13px;
+ font-weight: 400;
+ line-height: 1.13;
+ letter-spacing: 0.02em;
+ text-align: left;
+ color: #a2a1b2;
+ text-transform: uppercase;
+ margin: 0;
+}
+
+.LabelChecked {
+ color: #fff !important;
+}
+
+.SwitchWrapper {
+ display: flex;
+ align-items: center;
+ position: relative;
+}
+.Switch {
+ position: relative;
+ display: inline-block;
+ width: 44px;
+ height: 24px;
+ background-color: transparent;
+ border-radius: 20px;
+ transition:
+ background 0.3s,
+ border 0.3s,
+ left 0.3s;
+ border: 1px solid #6c6a81;
+ cursor: pointer;
+
+ &:after {
+ content: "";
+ position: absolute;
+ width: 20px;
+ height: 20px;
+ border-radius: 50%;
+ background-color: transparent;
+ top: 1px;
+ left: 1px;
+ transition: all 0.3s;
+ border: 1px solid #a2a1b2;
+ }
+}
+
+.Checkbox:checked + .Switch::after {
+ left: 21px;
+ background-color: #14f195;
+ border: 1px solid #14f195;
+}
+.Checkbox:checked + .Switch {
+ border: 1px solid #14f195;
+}
+.Checkbox {
+ appearance: none;
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ top: 0;
+ z-index: 2;
+ cursor: pointer;
+}
+
+// Mobile
+.MobileFiltersMenuToggle {
+ background: #322f43;
+ width: 100%;
+ padding: 8px;
+ border-radius: 8px;
+ font-size: 15px;
+ font-weight: 700;
+ line-height: 1.32;
+}
+
+.MobileFiltersMenu {
+ display: none;
+ height: 100%;
+ min-height: 100vh;
+ overflow: scroll; // TODO: body overflow hidden to prevent double scrollbar
+ box-sizing: content-box;
+
+ // Menu Open State
+ &[data-open="true"] {
+ display: block;
+ position: fixed;
+ top: 0;
+ left: 0;
+ background: #1d1a23;
+ z-index: 1021;
+ padding: 0 24px;
+ width: calc(100% - 48px); // 48px = x-axis padding
+ }
+
+ header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 56px 0 24px;
+ position: fixed;
+ top: 0;
+ width: calc(100% - 48px);
+ background: #1d1a23;
+ z-index: 2;
+ }
+
+ .HeaderTitle {
+ font-size: 18px;
+ font-weight: 700;
+ line-height: 1.16;
+ letter-spacing: -0.01em;
+ text-align: left;
+ margin: 0;
+ }
+
+ .Actions {
+ padding: 24px 0;
+ position: fixed;
+ bottom: 0;
+ width: 100%;
+ left: 0;
+ background: #1d1a23;
+
+ .ActionsInner {
+ padding: 0 24px;
+ display: flex;
+ gap: 8px;
+ }
+ }
+
+ .ActionButton {
+ width: 100%;
+ cursor: pointer;
+ background: #322f43;
+ border-radius: 8px;
+ font-size: 15px;
+ font-weight: 700;
+ line-height: 1.32;
+ text-align: center;
+ padding: 14px;
+ }
+}
+
+.MobileFilters {
+ margin-bottom: 40px;
+
+ @include breakpoint(lg) {
+ display: none;
+ margin-bottom: 0;
+ }
+}
+
+.DesktopFilters {
+ display: none;
+
+ @include breakpoint(lg) {
+ display: block;
+ }
+
+ .FormField {
+ padding: 16px 0;
+ }
+ .DesktopFieldsetOne {
+ background: var(--grey-500);
+ }
+
+ button {
+ p {
+ align-items: center;
+ padding-top: 24px;
+ }
+ }
+}
+
+.DesktopFiltersHeader {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding-left: 16px;
+ padding-bottom: 16px;
+}
+
+.DesktopActionButton {
+ font-family: "ABC Mono";
+ color: #a2a1b2;
+ font-size: 15px;
+ line-height: 1.15;
+ letter-spacing: 0.3px;
+ text-transform: uppercase;
+ border-bottom: 1px solid #a2a1b2;
+ margin: 0;
+ padding: 0;
+ transition: color 0.2s ease;
+
+ &:hover {
+ color: #9945ff;
+ }
+}
+
+.DesktopFiltersCount {
+ font-size: 18px;
+ font-weight: 700;
+ line-height: 1.16;
+ letter-spacing: -0.18px;
+ margin: 0;
+ padding: 0;
+}
+
+.DesktopFieldsets {
+ margin-top: 24px;
+
+ p {
+ color: #a2a1b2;
+ font-family: var(--font-mono);
+ font-size: 15px;
+ font-weight: 400;
+ line-height: 1.15;
+ letter-spacing: 0.02em;
+ text-transform: uppercase;
+ }
+
+ button {
+ padding-top: 8px;
+ }
+}
+
+.DesktopFieldsetOne {
+ border-radius: 8px;
+ background: #1d1a23;
+ padding: 16px;
+
+ p {
+ padding: 0;
+ }
+}
+
+.DesktopFieldsetTwo {
+ border-radius: 8px;
+ background: #1d1a23;
+ padding: 0;
+ margin-top: 24px;
+
+ button {
+ border: none;
+ }
+}
+
+.Parent {
+ & > button {
+ padding: 0 16px;
+ p,
+ svg {
+ color: #64a8f2;
+ }
+ svg path {
+ stroke: #64a8f2;
+ }
+ svg {
+ padding: 6px;
+ box-sizing: content-box;
+ }
+ }
+}
+
+.FirstChild {
+ border-top: 1px solid #504d61;
+ padding-bottom: 8px;
+
+ button {
+ p,
+ svg {
+ color: #80ecff;
+ }
+ }
+
+ svg path {
+ stroke: #80ecff;
+ }
+
+ p {
+ display: flex;
+ align-items: flex-start;
+ gap: 6px;
+
+ svg {
+ margin-bottom: 4px;
+ }
+ }
+
+ & > div,
+ button {
+ padding: 0 32px;
+ }
+}
+
+.Child {
+ padding: 0 16px;
+ padding-bottom: 8px;
+
+ > * {
+ padding: 0 16px;
+ }
+
+ svg path {
+ stroke: #80ecff;
+ }
+
+ button {
+ border-top: 1px solid #504d61;
+ p,
+ svg {
+ color: #80ecff;
+ }
+
+ p {
+ display: flex;
+ gap: 6px;
+ }
+ }
+}
diff --git a/src/components/solutions/wallets-explorer/WalletCard.jsx b/src/components/solutions/wallets-explorer/WalletCard.jsx
new file mode 100644
index 00000000..d8d2d375
--- /dev/null
+++ b/src/components/solutions/wallets-explorer/WalletCard.jsx
@@ -0,0 +1,307 @@
+import classNames from "classnames";
+import { useState } from "react";
+import Link from "next/link";
+import * as Collapsible from "@radix-ui/react-collapsible";
+import Image from "next/image";
+import { useTranslation } from "next-i18next";
+
+import CaretIcon from "@/components/icons/Caret";
+
+import styles from "./WalletCard.module.scss";
+
+import ArrowUpRightIcon from "../../../../assets/wallets/arrow-up-right.inline.svg";
+
+// Function to group keys into categories
+const groupWalletData = (content) => {
+ const groups = {
+ "Wallet Type": ["custodial", "non_custodial", "hardware", "mpc"],
+ "Financial Transactions": ["buy_crypto", "sell_crypto", "staking"],
+ "Asset Management": ["hold_nfts", "gas_abstraction", "spending_limits"],
+ "Security and Recovery": [
+ "social_recovery",
+ "open_source",
+ "private_key_infrastructure",
+ ],
+ "Solana Tooling": ["te", "blinks_and_actions", "solana_pay"],
+ };
+
+ // Generate content for each group by filtering true values
+ const groupedContent = Object.entries(groups).map(([groupName, keys]) => {
+ const filteredKeys = keys.filter((key) => content[key] === true);
+ return {
+ groupName,
+ values: filteredKeys,
+ };
+ });
+
+ return groupedContent;
+};
+
+const Tag = ({ text }) => (
+
+ {text}
+
+);
+
+const Dot = () => •;
+
+const WalletCard = ({
+ index,
+ walletImage,
+ name,
+ websiteUrl,
+ newToCrypto,
+ developer,
+ content,
+}) => {
+ const { t } = useTranslation();
+ const [open, setOpen] = useState(true);
+
+ const tags = [];
+ if (newToCrypto) tags.push(t("solutions-wallets-explorer.tags.beginner"));
+ if (developer) tags.push(t("solutions-wallets-explorer.tags.developer"));
+
+ const groupedContent = groupWalletData(content);
+
+ const localize = (value) =>
+ t(`solutions-wallets-explorer.wallet-filters.${value}`);
+
+ // Map of group names to their corresponding icons
+ const groupIcons = {
+ "Wallet Type": (
+
+ ),
+ "Financial Transactions": (
+
+ ),
+ "Asset Management": (
+
+ ),
+ "Security and Recovery": (
+
+ ),
+ "Solana Tooling": (
+
+ ),
+ };
+
+ const MobileCollapsibleContentRow = ({
+ groupName,
+ values,
+ maxValuesShown,
+ }) => {
+ if (values.length === 0) return null;
+
+ if (values.length === maxValuesShown) {
+ return (
+
+ {groupIcons[groupName]}
+
+ {values.map((value, index) => (
+
+ {localize(value)}
+ {index === values.length - 1 ? null : }
+
+ ))}
+
+
+ );
+ }
+
+ if (values.length > maxValuesShown - 1) {
+ return (
+
+ {groupIcons[groupName]}
+
+ {values.slice(0, maxValuesShown).map((value, index) => (
+
+ {localize(value)}
+
+
+ ))}
+ +{values.length - maxValuesShown}
+
+
+ );
+ }
+
+ return (
+
+ {groupIcons[groupName]}
+
{localize(values[0])}
+
+ );
+ };
+
+ const MobileTags = () => (
+
+ {tags.length > 0 && (
+
+
+ {tags.length > 1 && (
+ +{tags.length - 1}
+ )}
+
+ )}
+
+ );
+
+ const DesktopTags = () => (
+
+ {tags.length > 0 && (
+
+ {tags.map((tag, index) => (
+
+ ))}
+
+ )}
+
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {name}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {groupedContent.map((group, index) => {
+ if (group.values.length === 0) return null;
+ return (
+
+ {groupIcons[group.groupName]}
+
+ {group.values.map((value, index) => (
+
+ {localize(value)}
+ {index === group.values.length - 1 ? null : }
+
+ ))}
+
+
+ );
+ })}
+
+
+
+
+ {t("solutions-wallets-explorer.visit-website")}
+
+
+
+
+
+
+ );
+};
+
+export default WalletCard;
diff --git a/src/components/solutions/wallets-explorer/WalletCard.module.scss b/src/components/solutions/wallets-explorer/WalletCard.module.scss
new file mode 100644
index 00000000..eccf50f1
--- /dev/null
+++ b/src/components/solutions/wallets-explorer/WalletCard.module.scss
@@ -0,0 +1,176 @@
+@import "~@/scss/solutions/_variables.scss";
+
+.WalletCard {
+ border-bottom: 1px solid #322f43;
+ padding: 20px 0;
+ position: relative;
+
+ @include breakpoint(lg) {
+ padding: 40px 0;
+ }
+}
+
+.WalletCardContainer {
+ display: flex;
+ gap: 15px;
+}
+
+.CollapsibleTrigger {
+ position: absolute;
+ right: 0;
+ top: 50%;
+ transform: translateY(-50%);
+}
+
+.WalletCardImage {
+ width: 64px;
+ min-width: 64px;
+ overflow: hidden;
+ border-radius: 8px;
+
+ img {
+ width: 100%;
+ }
+}
+
+.WalletCardContent {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.WalletCardTitle {
+ font-size: 18px;
+ font-weight: 700;
+ line-height: 1.1;
+ margin-bottom: 0;
+ color: #fff;
+ transition: 0.2s all ease;
+
+ @include breakpoint(lg) {
+ font-size: 24px;
+ }
+}
+
+.TagsWrapper {
+ display: flex;
+ gap: 10px;
+}
+
+.Tags {
+ display: flex;
+ gap: 12px;
+ align-items: center;
+ font-family: var(--font-mono);
+}
+
+.Tag {
+ font-size: 13px;
+ font-weight: 400;
+ line-height: 1.4;
+ letter-spacing: 0.02em;
+ text-transform: uppercase;
+ color: #a2a1b2;
+ padding: 8px 12px;
+ border-radius: 40px;
+ background: #322f43;
+
+ @include breakpoint(lg) {
+ line-height: 1.15;
+ }
+}
+
+.ExtraTagsCount {
+ font-size: 13px;
+ font-weight: 400;
+ line-height: 1.4;
+ letter-spacing: 0.02em;
+}
+
+.WalletCardLink {
+ color: #fff;
+ font-family: "ABC Mono";
+ font-size: 13px;
+ font-weight: 400;
+ line-height: 1.4;
+ letter-spacing: 0.26px;
+ text-transform: uppercase;
+ margin-top: 12px;
+ transition: color 0.2s ease;
+ display: flex;
+ align-items: center;
+ gap: 4px;
+
+ @media (min-width: 768px) {
+ font-size: 15px;
+ line-height: 1.15;
+ letter-spacing: 0.3px;
+ margin-top: 28px;
+ }
+}
+
+.MobileContent {
+ @include breakpoint(lg) {
+ display: none;
+ }
+}
+
+.DesktopContent {
+ display: none;
+ @include breakpoint(lg) {
+ display: block;
+ }
+}
+
+.GroupedContent {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+
+ & + .GroupedContent {
+ margin-top: 12px;
+ }
+
+ .GroupedContentText {
+ margin-bottom: 0;
+ color: #a2a1b2;
+ font-size: 13px;
+ font-weight: 700;
+ line-height: 1.32;
+
+ &,
+ .ValueGroup {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ }
+
+ @include breakpoint(lg) {
+ font-size: 15px;
+ line-height: 1.32;
+ }
+ }
+
+ svg {
+ width: 17px;
+ height: 17px;
+ }
+}
+
+.Dot {
+ font-size: 6px;
+}
+
+.MobileTags {
+ @include breakpoint(lg) {
+ display: none;
+ }
+}
+
+.DesktopTags {
+ display: none;
+
+ @include breakpoint(lg) {
+ display: block;
+ }
+}
diff --git a/src/components/solutions/wallets-explorer/WalletFilters.jsx b/src/components/solutions/wallets-explorer/WalletFilters.jsx
new file mode 100644
index 00000000..3e8da024
--- /dev/null
+++ b/src/components/solutions/wallets-explorer/WalletFilters.jsx
@@ -0,0 +1,115 @@
+import { useState } from "react";
+
+import { MobileFilters, DesktopFilters } from "./Filters";
+
+import Wallets from "./Wallets";
+
+import styles from "./WalletFilters.module.scss";
+
+const WalletFilters = ({
+ filterData,
+ currentFilters,
+ setFilters,
+ updateWallets,
+ walletData,
+}) => {
+ /**
+ * Returns all filter data with an extra key named `checked` set to false as the initial state of a filter
+ * @returns Object
+ */
+ const setFilterInitialState = () => {
+ return filterData.map((filter) => ({ ...filter, checked: false }));
+ };
+
+ const [filterState, setFilterState] = useState(setFilterInitialState());
+
+ // Accepts the index of the filter and changes its checked state,
+ // then updates filterState to use the updated state
+ const toggleFilterActiveState = (index) => {
+ console.log({ index });
+ const filters = [...filterState];
+ filters[index].checked = !filters[index].checked;
+
+ setFilterState(filters);
+
+ const activeFilters = { ...currentFilters };
+ const filterKey = filters[index].filterKey;
+
+ // Add the filter as true to the filters state or remove the filter if its been unchecked
+ if (filters[index].checked) {
+ if (!(filterKey in activeFilters)) {
+ activeFilters[filterKey] = true;
+ }
+ } else {
+ if (filterKey in activeFilters) {
+ delete activeFilters[filterKey];
+ }
+ }
+
+ const showAllButton = document.querySelector(
+ 'button[data-role="show-all"]',
+ );
+
+ setFilters(activeFilters);
+
+ // Handle case where a user checks a filter and then unchecks that same filter. If we have no filters active,
+ // show all wallets and set the "All wallets" button as active. If we have filters at least one filter active,
+ // remove active state from "All wallets" and show filtered wallets
+ if (Object.keys(activeFilters).length > 0) {
+ if (
+ showAllButton &&
+ showAllButton.classList.contains(`${styles["wallet-filter--active"]}`)
+ ) {
+ showAllButton.classList.remove(`${styles["wallet-filter--active"]}`);
+ }
+
+ // Filters are active - show filtered results
+ updateWallets(activeFilters);
+ } else {
+ if (
+ showAllButton &&
+ !showAllButton.classList.contains(`${styles["wallet-filter--active"]}`)
+ ) {
+ showAllButton.classList.add(`${styles["wallet-filter--active"]}`);
+ }
+
+ // No filters are active - show all
+ updateWallets({});
+ }
+ };
+
+ const resetWalletsAndFilters = () => {
+ setFilterState(setFilterInitialState()); // Reset all filters to unchecked
+ setFilters({}); // Remove all current filters
+ updateWallets({}); // Pass empty filters object to show all wallets
+
+ const showAllButton = document.querySelector(
+ 'button[data-role="show-all"]',
+ );
+
+ if (
+ showAllButton &&
+ !showAllButton.classList.contains(`${styles["wallet-filter--active"]}`)
+ ) {
+ showAllButton.classList.add(`${styles["wallet-filter--active"]}`);
+ }
+ };
+
+ return (
+
+
+
+
+
+ );
+};
+
+export default WalletFilters;
diff --git a/src/components/solutions/wallets-explorer/WalletFilters.module.scss b/src/components/solutions/wallets-explorer/WalletFilters.module.scss
new file mode 100644
index 00000000..7bd6538b
--- /dev/null
+++ b/src/components/solutions/wallets-explorer/WalletFilters.module.scss
@@ -0,0 +1,65 @@
+@import "~@/scss/solutions/_variables.scss";
+
+.WalletFilters {
+ padding: 0 24px 64px;
+ max-width: 1068px;
+ margin: 0 auto;
+
+ @include breakpoint(lg) {
+ display: grid;
+ grid-template-columns: 330px 1fr;
+ gap: 40px;
+ }
+}
+
+.wallet-filter-section {
+ display: flex;
+ flex-flow: row wrap;
+ justify-content: flex-start;
+ align-items: center;
+ gap: 5px;
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 0 20px;
+ position: relative;
+ z-index: 10;
+}
+
+.wallet-filter {
+ display: inline-block;
+ background-color: #504d61;
+ color: #fff;
+ transition: all 0.3s ease;
+ border-radius: 30px;
+ padding: 7px 12px;
+ font-size: 12px;
+ text-transform: uppercase;
+ min-width: 50px;
+ text-align: center;
+ font-family: "Diatype", monotype;
+ line-height: 13px;
+ border: 1px solid #504d61;
+
+ &:hover {
+ background-color: #1d1a23;
+ cursor: pointer;
+ }
+}
+
+.wallet-filter--active {
+ background-color: #1d1a23;
+ color: #fff;
+}
+
+.wallet-filter + .wallet-filter-input:checked {
+ background-color: #1d1a23;
+}
+
+.wallet-filter.active {
+ background-color: #1d1a23;
+ color: #fff;
+}
+
+.wallet-filter-input {
+ appearance: none;
+}
diff --git a/src/components/solutions/wallets-explorer/Wallets.jsx b/src/components/solutions/wallets-explorer/Wallets.jsx
new file mode 100644
index 00000000..63c89bbd
--- /dev/null
+++ b/src/components/solutions/wallets-explorer/Wallets.jsx
@@ -0,0 +1,61 @@
+import { useTranslation } from "next-i18next";
+
+import { walletData } from "../../../data/wallets/wallet-data";
+
+import WalletCard from "./WalletCard";
+import { MotionSlideIn } from "@/components/shared/Motions";
+
+import styles from "./Wallets.module.scss";
+
+const Wallets = ({ filteredWalletData }) => {
+ const { t } = useTranslation();
+
+ return (
+ <>
+
+
+
+ {t("solutions-wallets-explorer.showing")}{" "}
+
+ {filteredWalletData.length} / {walletData.length}
+ {" "}
+ {t("solutions-wallets-explorer.wallets")}
+
+
+
+
+ {filteredWalletData.length ? (
+ filteredWalletData.map((wallet, key) => {
+ const { ...walletDataContent } = wallet;
+
+ return (
+
+
+
+ );
+ })
+ ) : (
+
+
+ {t("solutions-wallets-explorer.no-results")}
+
+
+ )}
+
+
+ >
+ );
+};
+
+export default Wallets;
diff --git a/src/components/solutions/wallets-explorer/Wallets.module.scss b/src/components/solutions/wallets-explorer/Wallets.module.scss
new file mode 100644
index 00000000..3f351fb4
--- /dev/null
+++ b/src/components/solutions/wallets-explorer/Wallets.module.scss
@@ -0,0 +1,13 @@
+.WalletsCount {
+ font-size: 15px;
+ font-weight: 700;
+ line-height: 1.32;
+ text-align: left;
+ padding: 0 0 20px;
+ color: #6c6a81;
+ margin-bottom: 0;
+
+ .Count {
+ color: white;
+ }
+}
diff --git a/src/components/solutions/wallets-explorer/WalletsLayout.jsx b/src/components/solutions/wallets-explorer/WalletsLayout.jsx
new file mode 100644
index 00000000..f5564537
--- /dev/null
+++ b/src/components/solutions/wallets-explorer/WalletsLayout.jsx
@@ -0,0 +1,72 @@
+import { useState } from "react";
+import { useTranslation } from "next-i18next";
+import Lottie from "react-lottie";
+
+import { walletData } from "../../../data/wallets/wallet-data";
+import { walletFiltersData } from "../../../data/wallets/wallet-filters";
+
+import WalletFilters from "./WalletFilters";
+import { OpacityInText } from "@/components/shared/Text";
+
+import styles from "./WalletsLayout.module.scss";
+
+import * as walletHeroLottie from "../../../../assets/wallets/wallet-finder.json";
+
+const WalletsLayout = () => {
+ const { t } = useTranslation();
+
+ const [filters, setFilters] = useState({});
+ const [wallets, setWallets] = useState(walletData);
+
+ const updateWalletsBasedOnFilters = (filters) => {
+ if (Object.keys(filters).length !== 0) {
+ // Only return wallets that match every key/value pair inside the filters object
+ const updatedWallets = walletData.filter((obj) =>
+ Object.keys(filters).every((key) => obj[key] === filters[key]),
+ );
+
+ setWallets(updatedWallets);
+ } else {
+ setWallets(walletData);
+ }
+ };
+
+ return (
+
+
+
+
+
+ {t("solutions-wallets-explorer.hero.title")}
+
+
+
+ {t("solutions-wallets-explorer.hero.text")}
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default WalletsLayout;
diff --git a/src/components/solutions/wallets-explorer/WalletsLayout.module.scss b/src/components/solutions/wallets-explorer/WalletsLayout.module.scss
new file mode 100644
index 00000000..0a8d7167
--- /dev/null
+++ b/src/components/solutions/wallets-explorer/WalletsLayout.module.scss
@@ -0,0 +1,92 @@
+@import "~@/scss/solutions/_variables.scss";
+
+.WalletLayout {
+ background: #0f0a16;
+}
+
+.Hero {
+ padding: 64px 0;
+ position: relative;
+ background-image: url("/src/img/solana-wallets/hero-mb.svg");
+ background-size: cover;
+ background-repeat: no-repeat;
+ background-position: center;
+
+ @media (min-width: 640px) {
+ padding: 128px 0;
+ background-image: url("/src/img/solana-wallets/hero-dt.svg");
+ background-position: right center;
+ }
+
+ .HeroContainer {
+ padding: 0 24px;
+ display: grid;
+ grid-template-columns: 1fr;
+ grid-gap: 40px;
+ align-items: center;
+ justify-content: center;
+ max-width: 1080px;
+ margin: 0 auto;
+
+ @include breakpoint(md) {
+ grid-template-columns: 0.8fr 1fr;
+ }
+
+ @include breakpoint(lg) {
+ padding: 40px;
+ }
+ }
+
+ h2 {
+ font-size: 36px;
+ font-weight: 700;
+ line-height: 1.14;
+ letter-spacing: -0.01em;
+ text-align: center;
+ margin: 0;
+ }
+
+ p {
+ font-size: 20px;
+ font-weight: 700;
+ line-height: 1.2;
+ text-align: center;
+ color: #a2a1b2;
+ margin: 24px 0 0;
+ max-width: 100%;
+ }
+
+ @include breakpoint(md) {
+ h2,
+ p {
+ text-align: left;
+ }
+ h2 {
+ font-size: 48px;
+ }
+ }
+
+ @include breakpoint(lg) {
+ h2 {
+ font-size: 64px;
+ font-weight: 700;
+ line-height: 1.04;
+ letter-spacing: -0.02em;
+ text-align: left;
+ }
+ p {
+ font-size: 24px;
+ font-weight: 700;
+ line-height: 1.15;
+ letter-spacing: -0.02em;
+ text-align: left;
+ }
+ }
+}
+
+.LottieContainer {
+ height: 407px;
+ [role="button"] {
+ cursor: initial;
+ }
+}
diff --git a/src/components/solutions/wallets/WalletTitle.jsx b/src/components/solutions/wallets/WalletTitle.jsx
new file mode 100644
index 00000000..3c3fd1f0
--- /dev/null
+++ b/src/components/solutions/wallets/WalletTitle.jsx
@@ -0,0 +1,35 @@
+import classNames from "classnames";
+import { Trans } from "next-i18next";
+
+import { motion } from "framer-motion";
+import { useInView } from "react-intersection-observer";
+
+import { animations, easeFunctions, durations } from "@/constants/animations";
+
+const transition = {
+ duration: durations.slower,
+ ease: easeFunctions.easeInQuart,
+};
+
+const WalletTitle = ({ styleName, text }) => {
+ const { ref, inView } = useInView({
+ triggerOnce: true,
+ threshold: 0.25,
+ });
+
+ return (
+
+
+
+
+
+ );
+};
+
+export default WalletTitle;
diff --git a/src/components/solutions/wallets/WalletsDetails.jsx b/src/components/solutions/wallets/WalletsDetails.jsx
new file mode 100644
index 00000000..8b28458b
--- /dev/null
+++ b/src/components/solutions/wallets/WalletsDetails.jsx
@@ -0,0 +1,65 @@
+import classNames from "classnames";
+import DetailsSection, { Detail } from "@/components/solutions/DetailsSection";
+import { useTranslation, Trans } from "next-i18next";
+import { useInView } from "react-intersection-observer";
+import { MotionSlideIn } from "@/components/shared/Motions";
+
+const WalletsDetails = ({ styles }) => {
+ const { t } = useTranslation();
+ const { ref: inViewRef, inView } = useInView({
+ triggerOnce: true,
+ threshold: 0.5,
+ });
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default WalletsDetails;
diff --git a/src/components/solutions/wallets/WalletsExploreSolutions.jsx b/src/components/solutions/wallets/WalletsExploreSolutions.jsx
new file mode 100644
index 00000000..444df853
--- /dev/null
+++ b/src/components/solutions/wallets/WalletsExploreSolutions.jsx
@@ -0,0 +1,62 @@
+import classNames from "classnames";
+import { useTranslation, Trans } from "next-i18next";
+import Button from "@/components/solutions/Button";
+import { MotionSlideIn } from "@/components/shared/Motions";
+import Text, { AnimatedText, GradientText } from "@/components/shared/Text";
+
+const WalletsExploreSolutions = ({ styles }) => {
+ const { t } = useTranslation();
+
+ return (
+
+
+
+ ),
+ }}
+ />
+
+
+
+ {t("solutions-wallets.explore.subtitle")}
+
+
+
+
+ {t("solutions-wallets.explore.cards.new.title")}
+ {t("solutions-wallets.explore.cards.new.subtitle")}
+
+
+
+
+ {t("solutions-wallets.explore.cards.embed.title")}
+
+
+ {t("solutions-wallets.explore.cards.embed.subtitle")}
+
+
+
+
+
+
+
+
+ );
+};
+
+export default WalletsExploreSolutions;
diff --git a/src/components/solutions/wallets/WalletsHero.jsx b/src/components/solutions/wallets/WalletsHero.jsx
new file mode 100644
index 00000000..0379e75e
--- /dev/null
+++ b/src/components/solutions/wallets/WalletsHero.jsx
@@ -0,0 +1,103 @@
+import { useEffect, useRef, useState } from "react";
+import { useTranslation } from "next-i18next";
+import classNames from "classnames";
+
+import useReducedMotion from "@/hooks/useReducedMotion";
+
+import Button from "@/components/solutions/Button";
+import { OpacityInText } from "@/components/shared/Text";
+
+import styles from "./WalletsHero.module.scss";
+
+import { MotionSlideIn } from "@/components/shared/Motions";
+
+const WalletsHero = () => {
+ const { t } = useTranslation();
+
+ const [active, setActive] = useState(false);
+ const videoRef = useRef(null);
+ const [prefersReducedMotion] = useReducedMotion();
+
+ useEffect(() => {
+ setTimeout(() => setActive(true), 500);
+ }, []);
+
+ useEffect(() => {
+ prefersReducedMotion && videoRef.current.pause();
+ }, [prefersReducedMotion]);
+
+ return (
+
+
+
+ {t("solutions-wallets.hero.kicker")}
+
+
+
+ {t("solutions-wallets.hero.title")}
+
+
+
+ {t("solutions-wallets.hero.subtitle")}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default WalletsHero;
diff --git a/src/components/solutions/wallets/WalletsHero.module.scss b/src/components/solutions/wallets/WalletsHero.module.scss
new file mode 100644
index 00000000..56bceb42
--- /dev/null
+++ b/src/components/solutions/wallets/WalletsHero.module.scss
@@ -0,0 +1,147 @@
+@import "~@/scss/solutions/_variables.scss";
+
+.WalletsHero {
+ padding: 64px 24px;
+ display: flex;
+ flex-direction: column;
+ gap: 40px;
+
+ .ContentWrapper {
+ display: flex;
+ flex-direction: column;
+ gap: 24px;
+
+ p,
+ h1 {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+ }
+
+ .Kicker {
+ font-size: 16px;
+ font-weight: 800;
+ line-height: 1.25;
+ letter-spacing: -0.02em;
+ text-align: center;
+ color: var(--blue);
+ }
+
+ .Title {
+ font-size: 36px;
+ font-weight: 700;
+ line-height: 1.14;
+ letter-spacing: -0.01em;
+ text-align: center;
+ }
+
+ .Subtitle {
+ font-size: 20px;
+ font-weight: 700;
+ line-height: 1.2;
+ text-align: center;
+ color: var(--grey-250);
+ }
+
+ .Buttons {
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ width: max-content;
+ margin: 0 auto;
+ }
+}
+
+.VideoWrapper {
+ display: flex;
+ align-items: center;
+ opacity: 0;
+ transition: opacity $duration-standard $easeInQuart;
+ transition-delay: 300ms;
+
+ &.Active {
+ opacity: 1;
+ }
+
+ video {
+ width: 100%;
+ height: 100%;
+ object-fit: contain;
+ max-width: 600px;
+ margin: 0 auto;
+ }
+}
+
+@include breakpoint(md) {
+ .WalletsHero {
+ padding: 80px 24px;
+
+ .ContentWrapper {
+ @include max-width(650px);
+ }
+
+ .Title {
+ font-size: 64px;
+ }
+
+ .Subtitle {
+ font-size: 24px;
+ }
+
+ .Buttons {
+ flex-direction: row;
+ }
+ }
+}
+
+@include breakpoint(xl) {
+ .WalletsHero {
+ padding: 92px 24px;
+ flex-direction: row;
+ justify-content: space-between;
+ gap: 128px;
+
+ .ContentWrapper {
+ max-width: 520px;
+ justify-content: center;
+ flex: 1;
+
+ * {
+ text-align: left;
+ }
+ }
+
+ .VideoWrapper {
+ flex: 2;
+ height: 670px;
+ max-width: 500px;
+ }
+
+ .Kicker {
+ margin-left: 0;
+ font-size: 22px;
+ }
+
+ .Title {
+ line-height: 1;
+ letter-spacing: -0.02em;
+ max-width: 422px;
+ }
+
+ .Subtitle {
+ font-size: 28px;
+ line-height: 1.15;
+ letter-spacing: -0.02em;
+ max-width: 100%;
+ }
+
+ .Buttons {
+ flex-direction: row;
+ margin-left: 0;
+
+ a {
+ padding: 12px;
+ }
+ }
+ }
+}