diff --git a/apps/insights/.env.development b/apps/insights/.env.development
new file mode 100644
index 0000000000..addc9dd5a0
--- /dev/null
+++ b/apps/insights/.env.development
@@ -0,0 +1 @@
+DISABLE_ACCESSIBILITY_REPORTING=true
\ No newline at end of file
diff --git a/apps/insights/.gitignore b/apps/insights/.gitignore
index 9d2ee2a739..e6fc78b8ba 100644
--- a/apps/insights/.gitignore
+++ b/apps/insights/.gitignore
@@ -1 +1,2 @@
 .env*.local
+.env*.development
\ No newline at end of file
diff --git a/apps/insights/src/components/CardTitle/index.module.scss b/apps/insights/src/components/CardTitle/index.module.scss
new file mode 100644
index 0000000000..ccb19f4b02
--- /dev/null
+++ b/apps/insights/src/components/CardTitle/index.module.scss
@@ -0,0 +1,25 @@
+@use "@pythnetwork/component-library/theme";
+
+.cardTitle {
+    display: flex;
+    flex-flow: row nowrap;
+    gap: theme.spacing(3);
+    align-items: center;
+    justify-content: flex-start;
+    .title {
+        color: theme.color("heading");
+        display: flex;
+        flex-flow: row nowrap;
+        gap: theme.spacing(3);
+        align-items: center;
+        @include theme.text("base", "semibold");
+        @include theme.breakpoint("md") {
+            @include theme.text("lg", "semibold");
+        }
+    }
+    .icon {
+        font-size: theme.spacing(6);
+        height: theme.spacing(6);
+        color: theme.color("button", "primary", "background", "normal");
+    }
+}
diff --git a/apps/insights/src/components/CardTitle/index.tsx b/apps/insights/src/components/CardTitle/index.tsx
new file mode 100644
index 0000000000..902235689e
--- /dev/null
+++ b/apps/insights/src/components/CardTitle/index.tsx
@@ -0,0 +1,20 @@
+import clsx from "clsx";
+import type { ComponentProps, ReactNode } from "react";
+
+import styles from "./index.module.scss";
+
+type CardTitleProps = {
+    children: ReactNode;
+    icon?: ReactNode | undefined;
+    badge?: ReactNode;
+} & ComponentProps<"div">;
+
+export const CardTitle = ({ children, icon, badge, ...props }: CardTitleProps) => {
+    return (
+        <div className={clsx(styles.cardTitle, props.className)} {...props}>
+            {icon && <div className={styles.icon}>{icon}</div>}
+            <h2 className={styles.title}>{children}</h2>
+            {badge}
+        </div>
+    )
+}
\ No newline at end of file
diff --git a/apps/insights/src/components/CopyButton/index.tsx b/apps/insights/src/components/CopyButton/index.tsx
index f002ccbbbc..53de57de10 100644
--- a/apps/insights/src/components/CopyButton/index.tsx
+++ b/apps/insights/src/components/CopyButton/index.tsx
@@ -27,7 +27,6 @@ export const CopyButton = ({ text, children, className, ...props }: Props) => {
   const [isCopied, setIsCopied] = useState(false);
   const logger = useLogger();
   const copy = useCallback(() => {
-    // eslint-disable-next-line n/no-unsupported-features/node-builtins
     navigator.clipboard
       .writeText(text)
       .then(() => {
diff --git a/apps/insights/src/components/MobileMenu/mobile-menu.module.scss b/apps/insights/src/components/MobileMenu/mobile-menu.module.scss
new file mode 100644
index 0000000000..ae47132655
--- /dev/null
+++ b/apps/insights/src/components/MobileMenu/mobile-menu.module.scss
@@ -0,0 +1,54 @@
+@use "@pythnetwork/component-library/theme";
+
+.mobileMenuTrigger {
+  display: block;
+
+  @include theme.breakpoint("md") {
+    display: none;
+  }
+}
+
+.mobileMenuOverlay {
+  background: rgb(0 0 0 / 40%);
+  position: fixed;
+  inset: 0;
+  z-index: 999;
+}
+
+.mobileMenuContainer {
+  border-top-left-radius: theme.border-radius("2xl");
+  border-top-right-radius: theme.border-radius("2xl");
+  background: theme.color("background", "modal");
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  padding: 1rem;
+  display: flex;
+  flex-flow: column nowrap;
+  gap: theme.spacing(4);
+}
+
+.mobileMenuHandle {
+  background: theme.color("background", "secondary");
+  width: 33%;
+  height: 6px;
+  border-radius: theme.border-radius("full");
+  align-self: center;
+}
+
+.mobileThemeSwitcher {
+  display: flex;
+  flex-flow: row nowrap;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.mobileThemeSwitcherFeedback {
+  display: flex;
+  flex-flow: row nowrap;
+  align-items: center;
+  gap: theme.spacing(3);
+  text-transform: capitalize;
+  font-weight: theme.font-weight("medium");
+}
diff --git a/apps/insights/src/components/MobileMenu/mobile-menu.tsx b/apps/insights/src/components/MobileMenu/mobile-menu.tsx
new file mode 100644
index 0000000000..4e5932b425
--- /dev/null
+++ b/apps/insights/src/components/MobileMenu/mobile-menu.tsx
@@ -0,0 +1,29 @@
+"use client";
+import { List } from "@phosphor-icons/react/dist/ssr/List";
+import { Button } from "@pythnetwork/component-library/Button";
+import clsx from "clsx";
+import { useState, type ComponentProps } from "react";
+
+import styles from "./mobile-menu.module.scss";
+
+export const MobileMenu = ({ className, ...props }: ComponentProps<"div">) => {
+  const [isOpen, setIsOpen] = useState(false);
+
+  const toggleMenu = () => {
+    setIsOpen(!isOpen);
+  };
+
+  return (
+    <div className={clsx(styles.mobileMenuTrigger, className)} {...props}>
+      <Button
+        variant="ghost"
+        size="sm"
+        afterIcon={List}
+        rounded
+        onPress={toggleMenu}
+      >
+        Menu
+      </Button>
+    </div>
+  );
+};
diff --git a/apps/insights/src/components/MobileNavigation/mobile-navigation.module.scss b/apps/insights/src/components/MobileNavigation/mobile-navigation.module.scss
new file mode 100644
index 0000000000..00e1c7ceec
--- /dev/null
+++ b/apps/insights/src/components/MobileNavigation/mobile-navigation.module.scss
@@ -0,0 +1,12 @@
+@use "@pythnetwork/component-library/theme";
+
+.mobileNavigation {
+  display: block;
+  padding: theme.spacing(2);
+  background: theme.color("background", "primary");
+  border-top: 1px solid theme.color("background", "secondary");
+
+  @include theme.breakpoint("md") {
+    display: none;
+  }
+}
diff --git a/apps/insights/src/components/MobileNavigation/mobile-navigation.tsx b/apps/insights/src/components/MobileNavigation/mobile-navigation.tsx
new file mode 100644
index 0000000000..0ee7773a4b
--- /dev/null
+++ b/apps/insights/src/components/MobileNavigation/mobile-navigation.tsx
@@ -0,0 +1,9 @@
+import styles from "./mobile-navigation.module.scss";
+import { MainNavTabs } from "../Root/tabs";
+export const MobileNavigation = () => {
+  return (
+    <div className={styles.mobileNavigation}>
+      <MainNavTabs />
+    </div>
+  );
+};
diff --git a/apps/insights/src/components/Overview/index.tsx b/apps/insights/src/components/Overview/index.tsx
index 3185cbd16d..1d9bf083d2 100644
--- a/apps/insights/src/components/Overview/index.tsx
+++ b/apps/insights/src/components/Overview/index.tsx
@@ -1,7 +1,9 @@
-import styles from "./index.module.scss";
+import { Card } from "@pythnetwork/component-library/Card";
+
+import { PageLayout } from "../PageLayout/page-layout";
 
 export const Overview = () => (
-  <div className={styles.overview}>
-    <h1 className={styles.header}>Overview</h1>
-  </div>
+  <PageLayout title={"Overview"}>
+    <Card title="Overview"></Card>
+  </PageLayout>
 );
diff --git a/apps/insights/src/components/PageLayout/page-layout.module.scss b/apps/insights/src/components/PageLayout/page-layout.module.scss
new file mode 100644
index 0000000000..442bb61b8e
--- /dev/null
+++ b/apps/insights/src/components/PageLayout/page-layout.module.scss
@@ -0,0 +1,24 @@
+@use "@pythnetwork/component-library/theme";
+
+.pageLayout {
+    @include theme.max-width;
+    display: flex;
+    gap: theme.spacing(6);
+    flex-direction: column;
+
+    .pageTitleContainer {
+        display: flex;
+        flex-flow: row nowrap;
+        gap: theme.spacing(3);
+        width: 100%;
+        align-items: center;
+        justify-content: space-between;
+
+        .pageTitle {
+            @include theme.h3;
+            color: theme.color("heading");
+            font-weight: theme.font-weight("semibold");
+            flex-grow: 1;
+        }
+    }
+}
diff --git a/apps/insights/src/components/PageLayout/page-layout.tsx b/apps/insights/src/components/PageLayout/page-layout.tsx
new file mode 100644
index 0000000000..b70e04c255
--- /dev/null
+++ b/apps/insights/src/components/PageLayout/page-layout.tsx
@@ -0,0 +1,15 @@
+import type { ReactNode } from "react";
+
+import styles from "./page-layout.module.scss";
+
+export const PageLayout = ({ children, title, actions }: { children: ReactNode; title: ReactNode, actions?: ReactNode }) => {
+    return (
+        <div className={styles.pageLayout}>
+            <div className={styles.pageTitleContainer}>
+                <h1 className={styles.pageTitle}>{title}</h1>
+                {actions && <div className={styles.actions}>{actions}</div>}
+            </div>
+            {children}
+        </div>
+    )
+}
\ No newline at end of file
diff --git a/apps/insights/src/components/PriceFeedTag/index.module.scss b/apps/insights/src/components/PriceFeedTag/index.module.scss
index 0ca6b99f12..fc92baf48e 100644
--- a/apps/insights/src/components/PriceFeedTag/index.module.scss
+++ b/apps/insights/src/components/PriceFeedTag/index.module.scss
@@ -1,8 +1,8 @@
 @use "@pythnetwork/component-library/theme";
 
 .priceFeedTag {
-  display: flex;
-  flex-flow: row nowrap;
+  display: grid;
+  grid-template-columns: theme.spacing(10) 1fr;
   gap: theme.spacing(3);
   align-items: center;
 
@@ -13,6 +13,8 @@
   }
 
   .nameAndDescription {
+    width: 100%;
+    position: relative;
     display: flex;
     flex-flow: column nowrap;
     gap: theme.spacing(1.5);
@@ -52,6 +54,8 @@
       color: theme.color("muted");
       overflow: hidden;
       text-overflow: ellipsis;
+      white-space: nowrap; // Add this line
+      width: 100%;
 
       @include theme.text("xs", "medium");
     }
diff --git a/apps/insights/src/components/PriceFeeds/index.module.scss b/apps/insights/src/components/PriceFeeds/index.module.scss
index d5927a894b..dd081b90e7 100644
--- a/apps/insights/src/components/PriceFeeds/index.module.scss
+++ b/apps/insights/src/components/PriceFeeds/index.module.scss
@@ -1,66 +1,53 @@
 @use "@pythnetwork/component-library/theme";
 
-.priceFeeds {
-  @include theme.max-width;
+.toolbarContainer {
+  display: flex;
+  flex-flow: row nowrap;
+  gap: theme.spacing(2);
+}
+
+.feedKey {
+  margin: 0 -#{theme.button-padding("xs", true)};
+}
 
-  .header {
-    @include theme.h3;
+.featuredFeeds {
+  display: flex;
+  flex-flow: column nowrap;
+  align-items: stretch;
 
-    color: theme.color("heading");
-    font-weight: theme.font-weight("semibold");
+  @include theme.breakpoint("md") {
+    flex-flow: row nowrap;
+
+    & > * {
+      flex: 1 1 0px;
+      width: 0;
+    }
   }
+}
+
+.featuredFeeds {
+  gap: theme.spacing(1);
 
-  .body {
+  .feedCardContents {
     display: flex;
     flex-flow: column nowrap;
+    justify-content: space-between;
+    align-items: stretch;
+    padding: theme.spacing(3);
     gap: theme.spacing(6);
-    margin-top: theme.spacing(6);
-
-    .feedKey {
-      margin: 0 -#{theme.button-padding("xs", true)};
-    }
 
-    .featuredFeeds,
-    .stats {
+    .prices {
       display: flex;
       flex-flow: row nowrap;
+      justify-content: space-between;
       align-items: center;
+      color: theme.color("heading");
+      font-weight: theme.font-weight("medium");
+      line-height: 1;
+      font-size: theme.font-size("base");
 
-      & > * {
-        flex: 1 1 0px;
-        width: 0;
-      }
-    }
-
-    .stats {
-      gap: theme.spacing(6);
-    }
-
-    .featuredFeeds {
-      gap: theme.spacing(1);
-
-      .feedCardContents {
-        display: flex;
-        flex-flow: column nowrap;
-        justify-content: space-between;
-        align-items: stretch;
-        padding: theme.spacing(3);
-        gap: theme.spacing(6);
-
-        .prices {
-          display: flex;
-          flex-flow: row nowrap;
-          justify-content: space-between;
-          align-items: center;
-          color: theme.color("heading");
-          font-weight: theme.font-weight("medium");
-          line-height: 1;
-          font-size: theme.font-size("base");
-
-          .changePercent {
-            font-size: theme.font-size("sm");
-          }
-        }
+      .changePercent {
+        font-size: theme.font-size("sm");
       }
     }
   }
diff --git a/apps/insights/src/components/PriceFeeds/index.tsx b/apps/insights/src/components/PriceFeeds/index.tsx
index 16691c0844..05f5d1f35a 100644
--- a/apps/insights/src/components/PriceFeeds/index.tsx
+++ b/apps/insights/src/components/PriceFeeds/index.tsx
@@ -19,10 +19,13 @@ import styles from "./index.module.scss";
 import { PriceFeedsCard } from "./price-feeds-card";
 import { Cluster, getData } from "../../services/pyth";
 import { priceFeeds as priceFeedsStaticConfig } from "../../static-data/price-feeds";
+import { CardTitle } from "../CardTitle";
 import { YesterdaysPricesProvider, ChangePercent } from "../ChangePercent";
 import { LivePrice } from "../LivePrices";
+import { PageLayout } from "../PageLayout/page-layout";
 import { PriceFeedIcon } from "../PriceFeedIcon";
 import { PriceFeedTag } from "../PriceFeedTag";
+import { Stats } from "../Stats";
 
 const PRICE_FEEDS_ANCHOR = "priceFeeds";
 
@@ -45,99 +48,94 @@ export const PriceFeeds = async () => {
   );
 
   return (
-    <div className={styles.priceFeeds}>
-      <h1 className={styles.header}>Price Feeds</h1>
-      <div className={styles.body}>
-        <section className={styles.stats}>
-          <StatCard
-            variant="primary"
-            header="Active Feeds"
-            stat={priceFeeds.activeFeeds.length}
-            href={`#${PRICE_FEEDS_ANCHOR}`}
-            corner={<ArrowLineDown />}
-          />
-          <StatCard
-            header="Frequency"
-            stat={priceFeedsStaticConfig.updateFrequency}
-          />
+    <PageLayout title={"Price Feeds"}>
+      <Stats>
+        <StatCard
+          variant="primary"
+          header="Active Feeds"
+          stat={priceFeeds.activeFeeds.length}
+          href={`#${PRICE_FEEDS_ANCHOR}`}
+          corner={<ArrowLineDown />}
+        />
+        <StatCard
+          header="Frequency"
+          stat={priceFeedsStaticConfig.updateFrequency}
+        />
+        <StatCard
+          header="Active Chains"
+          stat={priceFeedsStaticConfig.activeChains}
+          href="https://docs.pyth.network/price-feeds/contract-addresses"
+          target="_blank"
+          corner={<ArrowSquareOut weight="fill" />}
+        />
+        <AssetClassesDrawer numFeedsByAssetClass={numFeedsByAssetClass}>
           <StatCard
-            header="Active Chains"
-            stat={priceFeedsStaticConfig.activeChains}
-            href="https://docs.pyth.network/price-feeds/contract-addresses"
-            target="_blank"
-            corner={<ArrowSquareOut weight="fill" />}
+            header="Asset Classes"
+            stat={Object.keys(numFeedsByAssetClass).length}
+            corner={<Info weight="fill" />}
           />
-          <AssetClassesDrawer numFeedsByAssetClass={numFeedsByAssetClass}>
-            <StatCard
-              header="Asset Classes"
-              stat={Object.keys(numFeedsByAssetClass).length}
-              corner={<Info weight="fill" />}
-            />
-          </AssetClassesDrawer>
-        </section>
-        <YesterdaysPricesProvider
-          feeds={Object.fromEntries(
-            featuredRecentlyAdded.map(({ symbol, product }) => [
-              symbol,
-              product.price_account,
-            ]),
-          )}
-        >
-          <FeaturedFeedsCard
-            title="Recently Added"
-            icon={<StackPlus />}
-            feeds={featuredRecentlyAdded}
-            showPrices
-            linkFeeds
-          />
-        </YesterdaysPricesProvider>
+        </AssetClassesDrawer>
+      </Stats>
+      <YesterdaysPricesProvider
+        feeds={Object.fromEntries(
+          featuredRecentlyAdded.map(({ symbol, product }) => [
+            symbol,
+            product.price_account,
+          ]),
+        )}
+      >
         <FeaturedFeedsCard
-          title="Coming Soon"
-          icon={<ClockCountdown />}
-          feeds={featuredComingSoon}
-          toolbar={
-            <DrawerTrigger>
-              <Button size="xs" variant="outline">
-                Show all
-              </Button>
-              <Drawer
-                fill
-                className={styles.comingSoonCard ?? ""}
-                title={
-                  <>
-                    <span>Coming Soon</span>
-                    <Badge>{priceFeeds.comingSoon.length}</Badge>
-                  </>
-                }
-              >
-                <ComingSoonList
-                  comingSoonFeeds={priceFeeds.comingSoon.map((feed) => ({
-                    id: feed.product.price_account,
-                    displaySymbol: feed.product.display_symbol,
-                    assetClass: feed.product.asset_type,
-                    icon: (
-                      <PriceFeedIcon symbol={feed.product.display_symbol} />
-                    ),
-                  }))}
-                />
-              </Drawer>
-            </DrawerTrigger>
-          }
-        />
-        <PriceFeedsCard
-          id={PRICE_FEEDS_ANCHOR}
-          priceFeeds={priceFeeds.activeFeeds.map((feed) => ({
-            symbol: feed.symbol,
-            icon: <PriceFeedIcon symbol={feed.product.display_symbol} />,
-            id: feed.product.price_account,
-            displaySymbol: feed.product.display_symbol,
-            assetClass: feed.product.asset_type,
-            exponent: feed.price.exponent,
-            numQuoters: feed.price.numQuoters,
-          }))}
+          title={<CardTitle icon={<StackPlus />}>Recently added</CardTitle>}
+          feeds={featuredRecentlyAdded}
+          showPrices
+          linkFeeds
         />
-      </div>
-    </div>
+      </YesterdaysPricesProvider>
+      <FeaturedFeedsCard
+        title={<CardTitle icon={<ClockCountdown />}>Coming soon</CardTitle>}
+        feeds={featuredComingSoon}
+        action={
+          <DrawerTrigger>
+            <Button size="sm" variant="outline">
+              Show all
+            </Button>
+            <Drawer
+              fill
+              className={styles.comingSoonCard ?? ""}
+              title={
+                <>
+                  <span>Coming Soon</span>
+                  <Badge>{priceFeeds.comingSoon.length}</Badge>
+                </>
+              }
+            >
+              <ComingSoonList
+                comingSoonFeeds={priceFeeds.comingSoon.map((feed) => ({
+                  id: feed.product.price_account,
+                  displaySymbol: feed.product.display_symbol,
+                  assetClass: feed.product.asset_type,
+                  icon: (
+                    <PriceFeedIcon symbol={feed.product.display_symbol} />
+                  ),
+                }))}
+              />
+            </Drawer>
+          </DrawerTrigger>
+        }
+      />
+      <PriceFeedsCard
+        id={PRICE_FEEDS_ANCHOR}
+        priceFeeds={priceFeeds.activeFeeds.map((feed) => ({
+          symbol: feed.symbol,
+          icon: <PriceFeedIcon symbol={feed.product.display_symbol} />,
+          id: feed.product.price_account,
+          displaySymbol: feed.product.display_symbol,
+          assetClass: feed.product.asset_type,
+          exponent: feed.price.exponent,
+          numQuoters: feed.price.numQuoters,
+        }))}
+      />
+    </PageLayout>
   );
 };
 
diff --git a/apps/insights/src/components/PriceFeeds/price-feed-items.module.scss b/apps/insights/src/components/PriceFeeds/price-feed-items.module.scss
new file mode 100644
index 0000000000..9825c9e6e4
--- /dev/null
+++ b/apps/insights/src/components/PriceFeeds/price-feed-items.module.scss
@@ -0,0 +1,22 @@
+@use "@pythnetwork/component-library/theme";
+
+.priceFeedItemsWrapper {
+  display: flex;
+  flex-flow: column nowrap;
+  gap: 0;
+  border-radius: theme.border-radius("xl");
+  background: theme.color("background", "card-secondary");
+
+  @include theme.breakpoint("md") {
+    display: none;
+  }
+}
+
+.priceFeedItem {
+  padding: theme.spacing(4);
+  position: relative;
+
+  &:not(:last-child) {
+    border-bottom: 1px solid theme.color("background", "secondary");
+  }
+}
diff --git a/apps/insights/src/components/PriceFeeds/price-feed-items.tsx b/apps/insights/src/components/PriceFeeds/price-feed-items.tsx
new file mode 100644
index 0000000000..3759311ca7
--- /dev/null
+++ b/apps/insights/src/components/PriceFeeds/price-feed-items.tsx
@@ -0,0 +1,32 @@
+import styles from "./price-feed-items.module.scss";
+import { PriceFeedTag } from "../PriceFeedTag";
+import { StructuredList } from "../StructuredList";
+
+export const PriceFeedItems = () => {
+  return (
+    <div className={styles.priceFeedItemsWrapper}>
+      {Array.from({ length: 20 }).map((_, index) => {
+        return (
+          <div className={styles.priceFeedItem} key={index}>
+            <StructuredList
+              items={[
+                {
+                  label: <PriceFeedTag compact isLoading />,
+                  value: "$32,323.22",
+                },
+                {
+                  label: "Last Price",
+                  value: "$10,000.00",
+                },
+                {
+                  label: "Last Updated",
+                  value: "2022-01-01",
+                },
+              ]}
+            />
+          </div>
+        );
+      })}
+    </div>
+  );
+};
diff --git a/apps/insights/src/components/PriceFeeds/price-feeds-card.tsx b/apps/insights/src/components/PriceFeeds/price-feeds-card.tsx
index 0fe94882fd..3d632740ed 100644
--- a/apps/insights/src/components/PriceFeeds/price-feeds-card.tsx
+++ b/apps/insights/src/components/PriceFeeds/price-feeds-card.tsx
@@ -16,7 +16,9 @@ import { useQueryState, parseAsString } from "nuqs";
 import { type ReactNode, Suspense, useCallback, useMemo } from "react";
 import { useFilter, useCollator } from "react-aria";
 
+import { PriceFeedItems } from "./price-feed-items";
 import { useQueryParamFilterPagination } from "../../use-query-param-filter-pagination";
+import { CardTitle } from "../CardTitle";
 import { FeedKey } from "../FeedKey";
 import {
   SKELETON_WIDTH,
@@ -195,49 +197,56 @@ type PriceFeedsCardContents = Pick<Props, "id"> &
   (
     | { isLoading: true }
     | {
-        isLoading?: false;
-        numResults: number;
-        search: string;
-        sortDescriptor: SortDescriptor;
-        onSortChange: (newSort: SortDescriptor) => void;
-        assetClass: string;
-        assetClasses: string[];
-        numPages: number;
-        page: number;
-        pageSize: number;
-        onSearchChange: (newSearch: string) => void;
-        onAssetClassChange: (newAssetClass: string) => void;
-        onPageSizeChange: (newPageSize: number) => void;
-        onPageChange: (newPage: number) => void;
-        mkPageLink: (page: number) => string;
-        rows: RowConfig<
-          | "priceFeedName"
-          | "assetClass"
-          | "priceFeedId"
-          | "price"
-          | "confidenceInterval"
-          | "exponent"
-          | "numPublishers"
-        >[];
-      }
+      isLoading?: false;
+      numResults: number;
+      search: string;
+      sortDescriptor: SortDescriptor;
+      onSortChange: (newSort: SortDescriptor) => void;
+      assetClass: string;
+      assetClasses: string[];
+      numPages: number;
+      page: number;
+      pageSize: number;
+      onSearchChange: (newSearch: string) => void;
+      onAssetClassChange: (newAssetClass: string) => void;
+      onPageSizeChange: (newPageSize: number) => void;
+      onPageChange: (newPage: number) => void;
+      mkPageLink: (page: number) => string;
+      rows: RowConfig<
+        | "priceFeedName"
+        | "assetClass"
+        | "priceFeedId"
+        | "price"
+        | "confidenceInterval"
+        | "exponent"
+        | "numPublishers"
+      >[];
+    }
   );
 
 const PriceFeedsCardContents = ({ id, ...props }: PriceFeedsCardContents) => (
   <Card
     id={id}
-    icon={<ChartLine />}
     title={
-      <>
-        <span>Price Feeds</span>
-        {!props.isLoading && (
-          <Badge style="filled" variant="neutral" size="md">
-            {props.numResults}
-          </Badge>
-        )}
-      </>
+      <CardTitle icon={<ChartLine />} badge={!props.isLoading && (
+        <Badge style="filled" variant="neutral" size="md">
+          {props.numResults}
+        </Badge>
+      )}>Price Feeds</CardTitle>
     }
     toolbar={
       <>
+        <SearchInput
+          size="sm"
+          width={50}
+          placeholder="Feed symbol"
+          {...(props.isLoading
+            ? { isPending: true, isDisabled: true }
+            : {
+              value: props.search,
+              onChange: props.onSearchChange,
+            })}
+        />
         <Select<string>
           label="Asset Class"
           size="sm"
@@ -246,29 +255,18 @@ const PriceFeedsCardContents = ({ id, ...props }: PriceFeedsCardContents) => (
           {...(props.isLoading
             ? { isPending: true, options: [], buttonLabel: "Asset Class" }
             : {
-                optionGroups: [
-                  { name: "All", options: [""] },
-                  { name: "Asset classes", options: props.assetClasses },
-                ],
-                hideGroupLabel: true,
-                show: (value) => (value === "" ? "All" : value),
-                placement: "bottom end",
-                buttonLabel:
-                  props.assetClass === "" ? "Asset Class" : props.assetClass,
-                selectedKey: props.assetClass,
-                onSelectionChange: props.onAssetClassChange,
-              })}
-        />
-        <SearchInput
-          size="sm"
-          width={50}
-          placeholder="Feed symbol"
-          {...(props.isLoading
-            ? { isPending: true, isDisabled: true }
-            : {
-                value: props.search,
-                onChange: props.onSearchChange,
-              })}
+              optionGroups: [
+                { name: "All", options: [""] },
+                { name: "Asset classes", options: props.assetClasses },
+              ],
+              hideGroupLabel: true,
+              show: (value) => (value === "" ? "All" : value),
+              placement: "bottom end",
+              buttonLabel:
+                props.assetClass === "" ? "Asset Class" : props.assetClass,
+              selectedKey: props.assetClass,
+              onSelectionChange: props.onAssetClassChange,
+            })}
         />
       </>
     }
@@ -286,6 +284,8 @@ const PriceFeedsCardContents = ({ id, ...props }: PriceFeedsCardContents) => (
       ),
     })}
   >
+    <PriceFeedItems />
+
     <Table
       rounded
       fill
@@ -344,21 +344,21 @@ const PriceFeedsCardContents = ({ id, ...props }: PriceFeedsCardContents) => (
       ]}
       {...(props.isLoading
         ? {
-            isLoading: true,
-          }
+          isLoading: true,
+        }
         : {
-            rows: props.rows,
-            sortDescriptor: props.sortDescriptor,
-            onSortChange: props.onSortChange,
-            emptyState: (
-              <NoResults
-                query={props.search}
-                onClearSearch={() => {
-                  props.onSearchChange("");
-                }}
-              />
-            ),
-          })}
+          rows: props.rows,
+          sortDescriptor: props.sortDescriptor,
+          onSortChange: props.onSortChange,
+          emptyState: (
+            <NoResults
+              query={props.search}
+              onClearSearch={() => {
+                props.onSearchChange("");
+              }}
+            />
+          ),
+        })}
     />
   </Card>
 );
diff --git a/apps/insights/src/components/Publisher/layout.module.scss b/apps/insights/src/components/Publisher/layout.module.scss
index 81697a4ec2..be96824372 100644
--- a/apps/insights/src/components/Publisher/layout.module.scss
+++ b/apps/insights/src/components/Publisher/layout.module.scss
@@ -84,8 +84,7 @@
 
   .body {
     @include theme.max-width;
-
-    padding-top: theme.spacing(6);
+    margin-top: theme.spacing(6);
   }
 }
 
diff --git a/apps/insights/src/components/Publisher/layout.tsx b/apps/insights/src/components/Publisher/layout.tsx
index fc7cfc7bae..55df87dd79 100644
--- a/apps/insights/src/components/Publisher/layout.tsx
+++ b/apps/insights/src/components/Publisher/layout.tsx
@@ -40,6 +40,7 @@ import { PublisherKey } from "../PublisherKey";
 import { PublisherTag } from "../PublisherTag";
 import { ScoreHistory } from "../ScoreHistory";
 import { SemicircleMeter } from "../SemicircleMeter";
+import { Stats } from "../Stats";
 import { TabPanel, TabRoot, Tabs } from "../Tabs";
 import { TokenIcon } from "../TokenIcon";
 
@@ -110,264 +111,266 @@ export const PublishersLayout = async ({ children, params }: Props) => {
             />
           </div>
           <section className={styles.stats}>
-            <ChartCard
-              variant="primary"
-              header="Publisher Ranking"
-              lineClassName={styles.primarySparkChartLine}
-              corner={
-                <AlertTrigger>
-                  <Button
-                    variant="ghost"
-                    size="xs"
-                    beforeIcon={(props) => <Info weight="fill" {...props} />}
-                    rounded
-                    hideText
-                    className={styles.publisherRankingExplainButton ?? ""}
-                  >
-                    Explain Publisher Ranking
-                  </Button>
-                  <Alert title="Publisher Ranking" icon={<Lightbulb />}>
-                    <p className={styles.publisherRankingExplainDescription}>
-                      Each <b>Publisher</b> receives a <b>Ranking</b> which is
-                      derived from the number of price feeds the{" "}
-                      <b>Publisher</b> is actively publishing.
-                    </p>
-                  </Alert>
-                </AlertTrigger>
-              }
-              data={rankingHistory.map(({ timestamp, rank }) => ({
-                x: timestamp,
-                y: rank,
-                displayX: (
-                  <span className={styles.activeDate}>
-                    <FormattedDate value={timestamp} />
-                  </span>
-                ),
-              }))}
-              stat={currentRanking.rank}
-              {...(previousRanking && {
-                miniStat: (
-                  <ChangeValue
-                    direction={getChangeDirection(
-                      currentRanking.rank,
-                      previousRanking.rank,
-                    )}
-                  >
-                    {Math.abs(currentRanking.rank - previousRanking.rank)}
-                  </ChangeValue>
-                ),
-              })}
-            />
-            <DrawerTrigger>
+            <Stats>
               <ChartCard
-                header="Median Score"
-                chartClassName={styles.medianScoreChart}
-                lineClassName={styles.secondarySparkChartLine}
-                corner={<Info weight="fill" />}
-                data={medianScoreHistory.map(({ time, score }) => ({
-                  x: time,
-                  y: score,
+                variant="primary"
+                header="Publisher Ranking"
+                lineClassName={styles.primarySparkChartLine}
+                corner={
+                  <AlertTrigger>
+                    <Button
+                      variant="ghost"
+                      size="xs"
+                      beforeIcon={(props) => <Info weight="fill" {...props} />}
+                      rounded
+                      hideText
+                      className={styles.publisherRankingExplainButton ?? ""}
+                    >
+                      Explain Publisher Ranking
+                    </Button>
+                    <Alert title="Publisher Ranking" icon={<Lightbulb />}>
+                      <p className={styles.publisherRankingExplainDescription}>
+                        Each <b>Publisher</b> receives a <b>Ranking</b> which is
+                        derived from the number of price feeds the{" "}
+                        <b>Publisher</b> is actively publishing.
+                      </p>
+                    </Alert>
+                  </AlertTrigger>
+                }
+                data={rankingHistory.map(({ timestamp, rank }) => ({
+                  x: timestamp,
+                  y: rank,
                   displayX: (
                     <span className={styles.activeDate}>
-                      <FormattedDate value={time} />
+                      <FormattedDate value={timestamp} />
                     </span>
                   ),
-                  displayY: (
-                    <FormattedNumber
-                      maximumSignificantDigits={5}
-                      value={score}
-                    />
-                  ),
                 }))}
-                stat={
-                  <FormattedNumber
-                    maximumSignificantDigits={5}
-                    value={currentMedianScore.score}
-                  />
-                }
-                {...(previousMedianScore && {
+                stat={currentRanking.rank}
+                {...(previousRanking && {
                   miniStat: (
                     <ChangeValue
                       direction={getChangeDirection(
-                        previousMedianScore.score,
-                        currentMedianScore.score,
+                        currentRanking.rank,
+                        previousRanking.rank,
                       )}
                     >
-                      <FormattedNumber
-                        maximumSignificantDigits={2}
-                        value={
-                          (100 *
-                            Math.abs(
-                              currentMedianScore.score -
-                                previousMedianScore.score,
-                            )) /
-                          previousMedianScore.score
-                        }
-                      />
-                      %
+                      {Math.abs(currentRanking.rank - previousRanking.rank)}
                     </ChangeValue>
                   ),
                 })}
               />
-              <Drawer
-                title="Median Score"
-                className={styles.medianScoreDrawer ?? ""}
-                bodyClassName={styles.medianScoreDrawerBody}
-                footerClassName={styles.medianScoreDrawerFooter}
-                footer={
-                  <Button
-                    variant="outline"
-                    size="sm"
-                    href="https://docs.pyth.network/home/oracle-integrity-staking/publisher-quality-ranking"
-                    target="_blank"
-                    beforeIcon={BookOpenText}
-                  >
-                    Documentation
-                  </Button>
-                }
-              >
-                <ScoreHistory isMedian scoreHistory={medianScoreHistory} />
-                <InfoBox icon={<Ranking />} header="Publisher Score">
-                  Each price feed a publisher provides has an associated score,
-                  which is determined by the component{"'"}s uptime, price
-                  deviation, and staleness. This panel shows the median for each
-                  score across all price feeds published by this publisher, as
-                  well as the overall median score across all those feeds.
-                </InfoBox>
-              </Drawer>
-            </DrawerTrigger>
-            <ActiveFeedsCard
-              publisherKey={key}
-              activeFeeds={
-                priceFeeds.filter((feed) => feed.status === Status.Active)
-                  .length
-              }
-              totalFeeds={totalFeedsCount}
-            />
-            <DrawerTrigger>
-              <StatCard
-                header="OIS Pool Allocation"
-                stat={
-                  <span
-                    className={styles.oisAllocation}
-                    data-is-overallocated={
-                      Number(oisStats.poolUtilization) > oisStats.maxPoolSize
-                        ? ""
-                        : undefined
-                    }
-                  >
+              <DrawerTrigger>
+                <ChartCard
+                  header="Median Score"
+                  chartClassName={styles.medianScoreChart}
+                  lineClassName={styles.secondarySparkChartLine}
+                  corner={<Info weight="fill" />}
+                  data={medianScoreHistory.map(({ time, score }) => ({
+                    x: time,
+                    y: score,
+                    displayX: (
+                      <span className={styles.activeDate}>
+                        <FormattedDate value={time} />
+                      </span>
+                    ),
+                    displayY: (
+                      <FormattedNumber
+                        maximumSignificantDigits={5}
+                        value={score}
+                      />
+                    ),
+                  }))}
+                  stat={
                     <FormattedNumber
-                      maximumFractionDigits={2}
-                      value={
-                        (100 * Number(oisStats.poolUtilization)) /
-                        oisStats.maxPoolSize
-                      }
+                      maximumSignificantDigits={5}
+                      value={currentMedianScore.score}
                     />
-                    %
-                  </span>
-                }
-                corner={<Info weight="fill" />}
-              >
-                <Meter
-                  value={Number(oisStats.poolUtilization)}
-                  maxValue={oisStats.maxPoolSize}
-                  label="OIS Pool"
-                  startLabel={
-                    <span className={styles.tokens}>
-                      <TokenIcon />
-                      <span>
-                        <FormattedTokens tokens={oisStats.poolUtilization} />
-                      </span>
-                    </span>
                   }
-                  endLabel={
-                    <span className={styles.tokens}>
-                      <TokenIcon />
-                      <span>
-                        <FormattedTokens
-                          tokens={BigInt(oisStats.maxPoolSize)}
+                  {...(previousMedianScore && {
+                    miniStat: (
+                      <ChangeValue
+                        direction={getChangeDirection(
+                          previousMedianScore.score,
+                          currentMedianScore.score,
+                        )}
+                      >
+                        <FormattedNumber
+                          maximumSignificantDigits={2}
+                          value={
+                            (100 *
+                              Math.abs(
+                                currentMedianScore.score -
+                                previousMedianScore.score,
+                              )) /
+                            previousMedianScore.score
+                          }
                         />
-                      </span>
-                    </span>
-                  }
+                        %
+                      </ChangeValue>
+                    ),
+                  })}
                 />
-              </StatCard>
-              <Drawer
-                title="OIS Pool Allocation"
-                className={styles.oisDrawer ?? ""}
-                bodyClassName={styles.oisDrawerBody}
-                footerClassName={styles.oisDrawerFooter}
-                footer={
-                  <>
-                    <Button
-                      variant="solid"
-                      size="sm"
-                      href="https://staking.pyth.network"
-                      target="_blank"
-                      beforeIcon={Browsers}
-                    >
-                      Open Staking App
-                    </Button>
+                <Drawer
+                  title="Median Score"
+                  className={styles.medianScoreDrawer ?? ""}
+                  bodyClassName={styles.medianScoreDrawerBody}
+                  footerClassName={styles.medianScoreDrawerFooter}
+                  footer={
                     <Button
                       variant="outline"
                       size="sm"
-                      href="https://docs.pyth.network/home/oracle-integrity-staking"
+                      href="https://docs.pyth.network/home/oracle-integrity-staking/publisher-quality-ranking"
                       target="_blank"
                       beforeIcon={BookOpenText}
                     >
                       Documentation
                     </Button>
-                  </>
-                }
-              >
-                <SemicircleMeter
-                  width={420}
-                  height={420}
-                  value={Number(oisStats.poolUtilization)}
-                  maxValue={oisStats.maxPoolSize}
-                  className={styles.oisMeter ?? ""}
-                  aria-label="OIS Pool Utilization"
+                  }
                 >
-                  <TokenIcon className={styles.oisMeterIcon} />
-                  <div className={styles.oisMeterLabel}>OIS Pool</div>
-                </SemicircleMeter>
+                  <ScoreHistory isMedian scoreHistory={medianScoreHistory} />
+                  <InfoBox icon={<Ranking />} header="Publisher Score">
+                    Each price feed a publisher provides has an associated score,
+                    which is determined by the component{"'"}s uptime, price
+                    deviation, and staleness. This panel shows the median for each
+                    score across all price feeds published by this publisher, as
+                    well as the overall median score across all those feeds.
+                  </InfoBox>
+                </Drawer>
+              </DrawerTrigger>
+              <ActiveFeedsCard
+                publisherKey={key}
+                activeFeeds={
+                  priceFeeds.filter((feed) => feed.status === Status.Active)
+                    .length
+                }
+                totalFeeds={totalFeedsCount}
+              />
+              <DrawerTrigger>
                 <StatCard
-                  header="Total Staked"
-                  variant="secondary"
-                  nonInteractive
+                  header="OIS Pool Allocation"
                   stat={
-                    <>
-                      <TokenIcon />
-                      <FormattedTokens tokens={oisStats.poolUtilization} />
-                    </>
+                    <span
+                      className={styles.oisAllocation}
+                      data-is-overallocated={
+                        Number(oisStats.poolUtilization) > oisStats.maxPoolSize
+                          ? ""
+                          : undefined
+                      }
+                    >
+                      <FormattedNumber
+                        maximumFractionDigits={2}
+                        value={
+                          (100 * Number(oisStats.poolUtilization)) /
+                          oisStats.maxPoolSize
+                        }
+                      />
+                      %
+                    </span>
                   }
-                />
-                <StatCard
-                  header="Pool Capacity"
-                  variant="secondary"
-                  nonInteractive
-                  stat={
+                  corner={<Info weight="fill" />}
+                >
+                  <Meter
+                    value={Number(oisStats.poolUtilization)}
+                    maxValue={oisStats.maxPoolSize}
+                    label="OIS Pool"
+                    startLabel={
+                      <span className={styles.tokens}>
+                        <TokenIcon />
+                        <span>
+                          <FormattedTokens tokens={oisStats.poolUtilization} />
+                        </span>
+                      </span>
+                    }
+                    endLabel={
+                      <span className={styles.tokens}>
+                        <TokenIcon />
+                        <span>
+                          <FormattedTokens
+                            tokens={BigInt(oisStats.maxPoolSize)}
+                          />
+                        </span>
+                      </span>
+                    }
+                  />
+                </StatCard>
+                <Drawer
+                  title="OIS Pool Allocation"
+                  className={styles.oisDrawer ?? ""}
+                  bodyClassName={styles.oisDrawerBody}
+                  footerClassName={styles.oisDrawerFooter}
+                  footer={
                     <>
-                      <TokenIcon />
-                      <FormattedTokens tokens={BigInt(oisStats.maxPoolSize)} />
+                      <Button
+                        variant="solid"
+                        size="sm"
+                        href="https://staking.pyth.network"
+                        target="_blank"
+                        beforeIcon={Browsers}
+                      >
+                        Open Staking App
+                      </Button>
+                      <Button
+                        variant="outline"
+                        size="sm"
+                        href="https://docs.pyth.network/home/oracle-integrity-staking"
+                        target="_blank"
+                        beforeIcon={BookOpenText}
+                      >
+                        Documentation
+                      </Button>
                     </>
                   }
-                />
-                <OisApyHistory apyHistory={oisStats.apyHistory ?? []} />
-                <InfoBox
-                  icon={<ShieldChevron />}
-                  header="Oracle Integrity Staking (OIS)"
                 >
-                  OIS allows anyone to help secure Pyth and protect DeFi.
-                  Through decentralized staking rewards and slashing, OIS
-                  incentivizes Pyth publishers to maintain high-quality data
-                  contributions. PYTH holders can stake to publishers to further
-                  reinforce oracle security. Rewards are programmatically
-                  distributed to high quality publishers and the stakers
-                  supporting them to strengthen oracle integrity.
-                </InfoBox>
-              </Drawer>
-            </DrawerTrigger>
+                  <SemicircleMeter
+                    width={420}
+                    height={420}
+                    value={Number(oisStats.poolUtilization)}
+                    maxValue={oisStats.maxPoolSize}
+                    className={styles.oisMeter ?? ""}
+                    aria-label="OIS Pool Utilization"
+                  >
+                    <TokenIcon className={styles.oisMeterIcon} />
+                    <div className={styles.oisMeterLabel}>OIS Pool</div>
+                  </SemicircleMeter>
+                  <StatCard
+                    header="Total Staked"
+                    variant="secondary"
+                    nonInteractive
+                    stat={
+                      <>
+                        <TokenIcon />
+                        <FormattedTokens tokens={oisStats.poolUtilization} />
+                      </>
+                    }
+                  />
+                  <StatCard
+                    header="Pool Capacity"
+                    variant="secondary"
+                    nonInteractive
+                    stat={
+                      <>
+                        <TokenIcon />
+                        <FormattedTokens tokens={BigInt(oisStats.maxPoolSize)} />
+                      </>
+                    }
+                  />
+                  <OisApyHistory apyHistory={oisStats.apyHistory ?? []} />
+                  <InfoBox
+                    icon={<ShieldChevron />}
+                    header="Oracle Integrity Staking (OIS)"
+                  >
+                    OIS allows anyone to help secure Pyth and protect DeFi.
+                    Through decentralized staking rewards and slashing, OIS
+                    incentivizes Pyth publishers to maintain high-quality data
+                    contributions. PYTH holders can stake to publishers to further
+                    reinforce oracle security. Rewards are programmatically
+                    distributed to high quality publishers and the stakers
+                    supporting them to strengthen oracle integrity.
+                  </InfoBox>
+                </Drawer>
+              </DrawerTrigger>
+            </Stats>
           </section>
         </section>
         <TabRoot>
diff --git a/apps/insights/src/components/Publisher/performance.module.scss b/apps/insights/src/components/Publisher/performance.module.scss
index e5e5fd6bad..32ef3b26f9 100644
--- a/apps/insights/src/components/Publisher/performance.module.scss
+++ b/apps/insights/src/components/Publisher/performance.module.scss
@@ -2,11 +2,14 @@
 
 .performance {
   display: grid;
-  grid-template-columns: 1fr 1fr;
-  gap: theme.spacing(12) theme.spacing(6);
+  grid-template-columns: 1fr;
+  gap: theme.spacing(6);
   align-items: flex-start;
 
-  > *:first-child {
-    grid-column: span 2 / span 2;
+  @include theme.breakpoint("md") {
+    grid-template-columns: 1fr 1fr;
+    > *:first-child {
+      grid-column: span 2 / span 2;
+    }
   }
 }
diff --git a/apps/insights/src/components/Publisher/performance.tsx b/apps/insights/src/components/Publisher/performance.tsx
index 37a629f23c..1d70171bf8 100644
--- a/apps/insights/src/components/Publisher/performance.tsx
+++ b/apps/insights/src/components/Publisher/performance.tsx
@@ -14,6 +14,7 @@ import { TopFeedsTable } from "./top-feeds-table";
 import { getPublishers } from "../../services/clickhouse";
 import { Cluster, getTotalFeedCount } from "../../services/pyth";
 import { Status } from "../../status";
+import { CardTitle } from "../CardTitle";
 import { NoResults } from "../NoResults";
 import { PriceFeedIcon } from "../PriceFeedIcon";
 import { PriceFeedTag } from "../PriceFeedTag";
@@ -47,7 +48,7 @@ export const Performance = async ({ params }: Props) => {
     notFound()
   ) : (
     <div className={styles.performance}>
-      <Card icon={<Broadcast />} title="Publishers Ranking">
+      <Card icon={<Broadcast />} title={<CardTitle>Publisher Ranking</CardTitle>}>
         <Table
           rounded
           fill
@@ -118,7 +119,7 @@ export const Performance = async ({ params }: Props) => {
           })}
         />
       </Card>
-      <Card icon={<Network />} title="High-Performing Feeds">
+      <Card title={<CardTitle icon={<Network />}>High-performing Feeds</CardTitle>}>
         <TopFeedsTable
           label="High-Performing Feeds"
           publisherScoreWidth={PUBLISHER_SCORE_WIDTH}
@@ -138,7 +139,7 @@ export const Performance = async ({ params }: Props) => {
           )}
         />
       </Card>
-      <Card icon={<Network />} title="Low-Performing Feeds">
+      <Card title={<CardTitle icon={<Network />}>Low-performing Feeds</CardTitle>}>
         <TopFeedsTable
           label="Low-Performing Feeds"
           publisherScoreWidth={PUBLISHER_SCORE_WIDTH}
diff --git a/apps/insights/src/components/Publishers/index.module.scss b/apps/insights/src/components/Publishers/index.module.scss
index a7568592a6..8e5871e68b 100644
--- a/apps/insights/src/components/Publishers/index.module.scss
+++ b/apps/insights/src/components/Publishers/index.module.scss
@@ -1,74 +1,74 @@
 @use "@pythnetwork/component-library/theme";
 @use "../Root/index.module.scss" as root;
 
-.publishers {
-  @include theme.max-width;
+.body {
+  display: flex;
+  flex-flow: column nowrap;
+  width: 100%;
 
-  .header {
-    @include theme.h3;
-
-    color: theme.color("heading");
-    font-weight: theme.font-weight("semibold");
+  @include theme.breakpoint("lg") {
+    flex-flow: row nowrap;
+    align-items: flex-start;
+    gap: theme.spacing(6);
   }
 
-  .body {
+  .stats {
     display: flex;
-    flex-flow: row nowrap;
-    gap: theme.spacing(12);
-    align-items: flex-start;
-    margin-top: theme.spacing(6);
+    flex-flow: column;
+    gap: theme.spacing(6);
+    align-items: stretch;
+    flex-grow: 1;
 
-    .stats {
-      display: grid;
-      grid-template-columns: repeat(2, minmax(0, 1fr));
-      gap: theme.spacing(4);
-      align-items: center;
-      width: 40%;
+    @include theme.breakpoint("lg") {
       position: sticky;
       top: root.$header-height;
+    }
 
-      .averageMedianScoreExplainButton {
-        margin-top: -#{theme.button-padding("xs", false)};
-        margin-right: -#{theme.button-padding("xs", false)};
-      }
-
-      .oisCard {
-        grid-column: span 2 / span 2;
+    .averageMedianScoreExplainButton {
+      margin-top: -#{theme.button-padding("xs", false)};
+      margin-right: -#{theme.button-padding("xs", false)};
+    }
 
-        .oisPool {
-          .title {
-            font-size: theme.font-size("sm");
-            font-weight: theme.font-weight("normal");
-            color: theme.color("heading");
-            margin: 0;
-          }
+    .oisCard {
+      .oisPool {
+        .title {
+          font-size: theme.font-size("sm");
+          font-weight: theme.font-weight("normal");
+          color: theme.color("heading");
+          margin: 0;
+        }
 
-          .poolUsed {
-            margin: 0;
-            color: theme.color("heading");
+        .poolUsed {
+          margin: 0;
+          color: theme.color("heading");
 
-            @include theme.h3;
-          }
+          @include theme.h3;
+        }
 
-          .poolTotal {
-            margin: 0;
-            color: theme.color("muted");
-            font-size: theme.font-size("sm");
-            font-weight: theme.font-weight("normal");
-          }
+        .poolTotal {
+          margin: 0;
+          color: theme.color("muted");
+          font-size: theme.font-size("sm");
+          font-weight: theme.font-weight("normal");
         }
+      }
+
+      .oisStats {
+        display: flex;
+        flex-flow: column;
+        gap: theme.spacing(1);
 
-        .oisStats {
+        @include theme.breakpoint("lg") {
+          column-span: 2;
           display: grid;
           grid-template-columns: repeat(2, minmax(0, 1fr));
-          gap: theme.spacing(1);
         }
       }
     }
+  }
 
-    .publishersCard {
-      width: 60%;
-    }
+  .publishersCard {
+    width: 60%;
   }
 }
 
diff --git a/apps/insights/src/components/Publishers/index.tsx b/apps/insights/src/components/Publishers/index.tsx
index 1d53cc051c..c84b8655c6 100644
--- a/apps/insights/src/components/Publishers/index.tsx
+++ b/apps/insights/src/components/Publishers/index.tsx
@@ -17,10 +17,13 @@ import {
   getClaimableRewards,
   getDistributedRewards,
 } from "../../services/staking";
+import { CardTitle } from "../CardTitle";
 import { FormattedTokens } from "../FormattedTokens";
+import { PageLayout } from "../PageLayout/page-layout";
 import { PublisherIcon } from "../PublisherIcon";
 import { PublisherTag } from "../PublisherTag";
 import { SemicircleMeter, Label } from "../SemicircleMeter";
+import { Stats } from "../Stats";
 import { TokenIcon } from "../TokenIcon";
 
 const INITIAL_REWARD_POOL_SIZE = 60_000_000_000_000n;
@@ -33,64 +36,65 @@ export const Publishers = async () => {
   ]);
 
   return (
-    <div className={styles.publishers}>
-      <h1 className={styles.header}>Publishers</h1>
+    <PageLayout title={"Publishers"}>
       <div className={styles.body}>
         <section className={styles.stats}>
-          <StatCard
-            variant="primary"
-            header="Active Publishers"
-            stat={publishers.length}
-          />
-          <StatCard
-            header="Avg. Median Score"
-            corner={
-              <AlertTrigger>
-                <Button
-                  variant="ghost"
-                  size="xs"
-                  beforeIcon={(props) => <Info weight="fill" {...props} />}
-                  rounded
-                  hideText
-                  className={styles.averageMedianScoreExplainButton ?? ""}
-                >
-                  Explain Average Median Score
-                </Button>
-                <Alert title="Average Median Score" icon={<Lightbulb />}>
-                  <p className={styles.averageMedianScoreDescription}>
-                    Each <b>Price Feed Component</b> that a <b>Publisher</b>{" "}
-                    provides has an associated <b>Score</b>, which is determined
-                    by that component{"'"}s <b>Uptime</b>,{" "}
-                    <b>Price Deviation</b>, and <b>Staleness</b>. The publisher
-                    {"'"}s <b>Median Score</b> measures the 50th percentile of
-                    the <b>Score</b> across all of that publisher{"'"}s{" "}
-                    <b>Price Feed Components</b>. The{" "}
-                    <b>Average Median Score</b> is the average of the{" "}
-                    <b>Median Scores</b> of all publishers who contribute to the
-                    Pyth Network.
-                  </p>
+          <Stats>
+            <StatCard
+              variant="primary"
+              header="Active Publishers"
+              stat={publishers.length}
+            />
+            <StatCard
+              header="Avg. Median Score"
+              corner={
+                <AlertTrigger>
                   <Button
+                    variant="ghost"
                     size="xs"
-                    variant="solid"
-                    href="https://docs.pyth.network/home/oracle-integrity-staking/publisher-quality-ranking"
-                    target="_blank"
+                    beforeIcon={(props) => <Info weight="fill" {...props} />}
+                    rounded
+                    hideText
+                    className={styles.averageMedianScoreExplainButton ?? ""}
                   >
-                    Learn more
+                    Explain Average Median Score
                   </Button>
-                </Alert>
-              </AlertTrigger>
-            }
-            stat={(
-              publishers.reduce(
-                (sum, publisher) => sum + publisher.medianScore,
-                0,
-              ) / publishers.length
-            ).toFixed(2)}
-          />
+                  <Alert title="Average Median Score" icon={<Lightbulb />}>
+                    <p className={styles.averageMedianScoreDescription}>
+                      Each <b>Price Feed Component</b> that a <b>Publisher</b>{" "}
+                      provides has an associated <b>Score</b>, which is determined
+                      by that component{"'"}s <b>Uptime</b>,{" "}
+                      <b>Price Deviation</b>, and <b>Staleness</b>. The publisher
+                      {"'"}s <b>Median Score</b> measures the 50th percentile of
+                      the <b>Score</b> across all of that publisher{"'"}s{" "}
+                      <b>Price Feed Components</b>. The{" "}
+                      <b>Average Median Score</b> is the average of the{" "}
+                      <b>Median Scores</b> of all publishers who contribute to the
+                      Pyth Network.
+                    </p>
+                    <Button
+                      size="xs"
+                      variant="solid"
+                      href="https://docs.pyth.network/home/oracle-integrity-staking/publisher-quality-ranking"
+                      target="_blank"
+                    >
+                      Learn more
+                    </Button>
+                  </Alert>
+                </AlertTrigger>
+              }
+              stat={(
+                publishers.reduce(
+                  (sum, publisher) => sum + publisher.medianScore,
+                  0,
+                ) / publishers.length
+              ).toFixed(2)}
+            />
+          </Stats>
           <Card
-            title="Oracle Integrity Staking (OIS)"
+            title={<CardTitle>OIS</CardTitle>}
             className={styles.oisCard}
-            toolbar={
+            action={
               <Button
                 href="https://staking.pyth.network"
                 target="_blank"
@@ -169,7 +173,7 @@ export const Publishers = async () => {
           )}
         />
       </div>
-    </div>
+    </PageLayout >
   );
 };
 
diff --git a/apps/insights/src/components/Publishers/publishers-card.tsx b/apps/insights/src/components/Publishers/publishers-card.tsx
index 0d421575d3..b0fa44b758 100644
--- a/apps/insights/src/components/Publishers/publishers-card.tsx
+++ b/apps/insights/src/components/Publishers/publishers-card.tsx
@@ -14,6 +14,7 @@ import { type ReactNode, Suspense, useMemo } from "react";
 import { useFilter, useCollator } from "react-aria";
 
 import { useQueryParamFilterPagination } from "../../use-query-param-filter-pagination";
+import { CardTitle } from "../CardTitle";
 import { NoResults } from "../NoResults";
 import { PublisherTag } from "../PublisherTag";
 import { Ranking } from "../Ranking";
@@ -35,9 +36,9 @@ type Publisher = {
   inactiveFeeds: number;
   medianScore: number;
 } & (
-  | { name: string; icon: ReactNode }
-  | { name?: undefined; icon?: undefined }
-);
+    | { name: string; icon: ReactNode }
+    | { name?: undefined; icon?: undefined }
+  );
 
 export const PublishersCard = ({ publishers, ...props }: Props) => (
   <Suspense fallback={<PublishersCardContents isLoading {...props} />}>
@@ -155,22 +156,22 @@ type PublishersCardContentsProps = Pick<
   (
     | { isLoading: true }
     | {
-        isLoading?: false;
-        numResults: number;
-        search: string;
-        sortDescriptor: SortDescriptor;
-        numPages: number;
-        page: number;
-        pageSize: number;
-        onSearchChange: (newSearch: string) => void;
-        onSortChange: (newSort: SortDescriptor) => void;
-        onPageSizeChange: (newPageSize: number) => void;
-        onPageChange: (newPage: number) => void;
-        mkPageLink: (page: number) => string;
-        rows: RowConfig<
-          "ranking" | "name" | "activeFeeds" | "inactiveFeeds" | "medianScore"
-        >[];
-      }
+      isLoading?: false;
+      numResults: number;
+      search: string;
+      sortDescriptor: SortDescriptor;
+      numPages: number;
+      page: number;
+      pageSize: number;
+      onSearchChange: (newSearch: string) => void;
+      onSortChange: (newSort: SortDescriptor) => void;
+      onPageSizeChange: (newPageSize: number) => void;
+      onPageChange: (newPage: number) => void;
+      mkPageLink: (page: number) => string;
+      rows: RowConfig<
+        "ranking" | "name" | "activeFeeds" | "inactiveFeeds" | "medianScore"
+      >[];
+    }
   );
 
 const PublishersCardContents = ({
@@ -180,16 +181,12 @@ const PublishersCardContents = ({
 }: PublishersCardContentsProps) => (
   <Card
     className={className}
-    icon={<Broadcast />}
     title={
-      <>
-        <span>Publishers</span>
-        {!props.isLoading && (
-          <Badge style="filled" variant="neutral" size="md">
-            {props.numResults}
-          </Badge>
-        )}
-      </>
+      <CardTitle badge={!props.isLoading && (
+        <Badge style="filled" variant="neutral" size="md">
+          {props.numResults}
+        </Badge>
+      )} icon={<Broadcast />}>Publishers</CardTitle>
     }
     toolbar={
       <SearchInput
@@ -199,9 +196,9 @@ const PublishersCardContents = ({
         {...(props.isLoading
           ? { isPending: true, isDisabled: true }
           : {
-              value: props.search,
-              onChange: props.onSearchChange,
-            })}
+            value: props.search,
+            onChange: props.onSearchChange,
+          })}
       />
     }
     {...(!props.isLoading && {
@@ -264,21 +261,21 @@ const PublishersCardContents = ({
       ]}
       {...(props.isLoading
         ? {
-            isLoading: true,
-          }
+          isLoading: true,
+        }
         : {
-            rows: props.rows,
-            sortDescriptor: props.sortDescriptor,
-            onSortChange: props.onSortChange,
-            emptyState: (
-              <NoResults
-                query={props.search}
-                onClearSearch={() => {
-                  props.onSearchChange("");
-                }}
-              />
-            ),
-          })}
+          rows: props.rows,
+          sortDescriptor: props.sortDescriptor,
+          onSortChange: props.onSortChange,
+          emptyState: (
+            <NoResults
+              query={props.search}
+              onClearSearch={() => {
+                props.onSearchChange("");
+              }}
+            />
+          ),
+        })}
     />
   </Card>
 );
diff --git a/apps/insights/src/components/Root/footer.module.scss b/apps/insights/src/components/Root/footer.module.scss
index f6799a3bf8..d28c839e48 100644
--- a/apps/insights/src/components/Root/footer.module.scss
+++ b/apps/insights/src/components/Root/footer.module.scss
@@ -2,41 +2,32 @@
 
 .footer {
   // SM
-  background: theme.color("background", "primary");
-
-  // XL
+  margin-top: theme.spacing(8);
   padding: theme.spacing(8) 0;
-
-  // bg-beige-100 sm:border-t sm:border-stone-300
+  background: theme.color("background", "primary");
 
   .topContent {
     display: flex;
     gap: theme.spacing(6);
-
-    // SM
-    flex-flow: row nowrap;
-    align-items: center;
+    flex-flow: column nowrap;
+    align-items: flex-start;
     justify-content: space-between;
 
     @include theme.max-width;
 
-    // XL
-    margin-bottom: theme.spacing(12);
-
-    // py-6
+    margin-bottom: theme.spacing(6);
 
-    // flex-col
+    @include theme.breakpoint("sm") {
+      flex-flow: row nowrap;
+      align-items: center;
+    }
 
     .left {
       display: flex;
       align-items: stretch;
       justify-content: space-between;
-
-      // SM
       gap: theme.spacing(6);
 
-      // gap-8
-
       .logoLink {
         height: theme.spacing(5);
         box-sizing: content-box;
@@ -86,10 +77,12 @@
   .bottomContent {
     display: flex;
     gap: theme.spacing(6);
+    flex-flow: column;
 
-    // SM
-    flex-flow: row nowrap;
-    justify-content: space-between;
+    @include theme.breakpoint("sm") {
+      flex-flow: row nowrap;
+      justify-content: space-between;
+    }
 
     // "flex-col
 
diff --git a/apps/insights/src/components/Root/footer.tsx b/apps/insights/src/components/Root/footer.tsx
index 343d49e678..04fa9b773b 100644
--- a/apps/insights/src/components/Root/footer.tsx
+++ b/apps/insights/src/components/Root/footer.tsx
@@ -1,3 +1,4 @@
+import { ArrowSquareOut } from "@phosphor-icons/react/dist/ssr/ArrowSquareOut";
 import {
   type Props as ButtonProps,
   Button,
@@ -21,10 +22,10 @@ export const Footer = () => (
         <div className={styles.divider} />
         <div className={styles.help}>
           <SupportDrawer>
-            <Link>Help</Link>
+            <Link>Support</Link>
           </SupportDrawer>
           <Link href="https://docs.pyth.network" target="_blank">
-            Documentation
+            Documentation <ArrowSquareOut />
           </Link>
         </div>
       </div>
diff --git a/apps/insights/src/components/Root/header.module.scss b/apps/insights/src/components/Root/header.module.scss
index 65a3ff8506..fea43a9ca9 100644
--- a/apps/insights/src/components/Root/header.module.scss
+++ b/apps/insights/src/components/Root/header.module.scss
@@ -4,8 +4,9 @@
   position: sticky;
   top: 0;
   width: 100%;
-  background-color: theme.color("background", "nav-blur");
-  backdrop-filter: blur(32px);
+  background-color: theme.color("background", "primary");
+  // TODO: This causes that navigation is not fixed
+  // backdrop-filter: blur(32px);
 
   .content {
     height: 100%;
@@ -16,18 +17,24 @@
 
     .leftMenu {
       flex: none;
-      gap: theme.spacing(6);
+      gap: theme.spacing(4);
+      position: relative;
 
       @include theme.row;
 
       .logoLink {
         padding: theme.spacing(3);
-        margin: -#{theme.spacing(3)};
         color: theme.color("foreground");
+        position: relative;
+
+        @include theme.breakpoint("3xl") {
+          position: absolute;
+          left: -#{theme.spacing(16)};
+        }
 
         .logoWrapper {
-          width: theme.spacing(9);
-          height: theme.spacing(9);
+          width: theme.spacing(8);
+          height: theme.spacing(8);
           position: relative;
 
           .logo {
@@ -52,33 +59,34 @@
 
     .rightMenu {
       flex: none;
+      position: relative;
       gap: theme.spacing(2);
 
       @include theme.row;
 
-      margin-right: -#{theme.button-padding("sm", false)};
-
       .themeSwitch {
-        margin-left: theme.spacing(1);
-      }
-    }
-
-    @media screen and (min-width: theme.$max-width + (2 * (theme.spacing(9) + theme.spacing(8) + theme.spacing(7)))) {
-      .leftMenu {
-        margin-left: -#{theme.spacing(9) + theme.spacing(7)};
+        display: none;
 
-        .logoLink {
-          margin-right: -#{theme.spacing(2)};
+        @include theme.breakpoint("md") {
+          position: relative;
+          display: block;
         }
-      }
-
-      .rightMenu {
-        margin-right: -#{theme.spacing(9) + theme.spacing(7)};
 
-        .themeSwitch {
-          margin-left: theme.spacing(5);
+        @include theme.breakpoint("3xl") {
+          display: block;
+          position: absolute;
+          right: -#{theme.spacing(16)};
         }
       }
     }
   }
+
+  .desktopNavigation,
+  .desktopSupport,
+  .desktopDocs {
+    display: none;
+    @include theme.breakpoint("md") {
+      display: block;
+    }
+  }
 }
diff --git a/apps/insights/src/components/Root/header.tsx b/apps/insights/src/components/Root/header.tsx
index d83d733ccb..d1f54e6294 100644
--- a/apps/insights/src/components/Root/header.tsx
+++ b/apps/insights/src/components/Root/header.tsx
@@ -1,3 +1,5 @@
+"use client";
+
 import { Lifebuoy } from "@phosphor-icons/react/dist/ssr/Lifebuoy";
 import { Button } from "@pythnetwork/component-library/Button";
 import { Link } from "@pythnetwork/component-library/Link";
@@ -10,6 +12,7 @@ import { SearchButton } from "./search-button";
 import { SupportDrawer } from "./support-drawer";
 import { MainNavTabs } from "./tabs";
 import { ThemeSwitch } from "./theme-switch";
+import { MobileMenu } from "../MobileMenu/mobile-menu";
 
 export const Header = ({ className, ...props }: ComponentProps<"header">) => (
   <header className={clsx(styles.header, className)} {...props}>
@@ -22,24 +25,31 @@ export const Header = ({ className, ...props }: ComponentProps<"header">) => (
           <div className={styles.logoLabel}>Pyth Homepage</div>
         </Link>
         <div className={styles.appName}>Insights</div>
-        <MainNavTabs />
+        <div className={styles.desktopNavigation}>
+          <MainNavTabs />
+        </div>
       </div>
       <div className={styles.rightMenu}>
-        <SupportDrawer>
-          <Button beforeIcon={Lifebuoy} variant="ghost" size="sm" rounded>
-            Support
-          </Button>
-        </SupportDrawer>
+        <div className={styles.desktopSupport}>
+          <SupportDrawer>
+            <Button beforeIcon={Lifebuoy} variant="ghost" size="sm" rounded>
+              Support
+            </Button>
+          </SupportDrawer>
+        </div>
         <SearchButton />
-        <Button
-          href="https://docs.pyth.network"
-          size="sm"
-          rounded
-          target="_blank"
-        >
-          Dev Docs
-        </Button>
+        <div className={styles.desktopDocs}>
+          <Button
+            href="https://docs.pyth.network"
+            size="sm"
+            rounded
+            target="_blank"
+          >
+            Dev Docs
+          </Button>
+        </div>
         <ThemeSwitch className={styles.themeSwitch ?? ""} />
+        <MobileMenu />
       </div>
     </div>
   </header>
diff --git a/apps/insights/src/components/Root/index.tsx b/apps/insights/src/components/Root/index.tsx
index e3fb96107d..b2fd1e2a88 100644
--- a/apps/insights/src/components/Root/index.tsx
+++ b/apps/insights/src/components/Root/index.tsx
@@ -18,6 +18,7 @@ import { toHex } from "../../hex";
 import { getPublishers } from "../../services/clickhouse";
 import { Cluster, getData } from "../../services/pyth";
 import { LivePricesProvider } from "../LivePrices";
+import { MobileNavigation } from "../MobileNavigation/mobile-navigation";
 import { PriceFeedIcon } from "../PriceFeedIcon";
 import { PublisherIcon } from "../PublisherIcon";
 
@@ -65,6 +66,7 @@ export const Root = async ({ children }: Props) => {
             <TabPanel>{children}</TabPanel>
           </main>
           <Footer />
+          <MobileNavigation />
         </TabRoot>
       </SearchDialogProvider>
     </BaseRoot>
diff --git a/apps/insights/src/components/Root/search-button.tsx b/apps/insights/src/components/Root/search-button.tsx
index d099ba7431..0f421acb4f 100644
--- a/apps/insights/src/components/Root/search-button.tsx
+++ b/apps/insights/src/components/Root/search-button.tsx
@@ -31,7 +31,7 @@ const SearchText = () => {
 const SearchTextImpl = () => {
   // This component can only ever render in the client so we can safely ignore
   // this eslint rule.
-  // eslint-disable-next-line n/no-unsupported-features/node-builtins
+
   const isMac = useMemo(() => navigator.userAgent.includes("Mac"), []);
   return isMac ? "⌘ K" : "Ctrl K";
 };
diff --git a/apps/insights/src/components/Root/support-drawer.module.scss b/apps/insights/src/components/Root/support-drawer.module.scss
index f6152c85d3..9ef4761f9a 100644
--- a/apps/insights/src/components/Root/support-drawer.module.scss
+++ b/apps/insights/src/components/Root/support-drawer.module.scss
@@ -34,12 +34,12 @@
         grid-template-columns: max-content 1fr max-content;
         grid-template-rows: max-content max-content;
         text-align: left;
-        gap: theme.spacing(2) theme.spacing(4);
-        align-items: center;
+        gap: theme.spacing(1) theme.spacing(4);
+        align-items: start;
         width: 100%;
 
         .icon {
-          font-size: theme.spacing(8);
+          font-size: theme.spacing(6);
           color: theme.color("states", "data", "normal");
           grid-row: span 2 / span 2;
           display: grid;
@@ -47,17 +47,22 @@
         }
 
         .header {
-          @include theme.text("sm", "medium");
+          @include theme.h6;
 
+          line-height: 1.5;
           color: theme.color("heading");
         }
 
         .description {
-          @include theme.text("xs", "normal");
+          @include theme.text("sm", "normal");
 
+          line-height: 1.5;
           color: theme.color("muted");
           grid-column: 2;
           grid-row: 2;
+          word-wrap: break-word;
+          overflow: hidden;
+          max-width: 100%;
         }
 
         .caret {
diff --git a/apps/insights/src/components/Stats/index.module.scss b/apps/insights/src/components/Stats/index.module.scss
new file mode 100644
index 0000000000..8cecc3044f
--- /dev/null
+++ b/apps/insights/src/components/Stats/index.module.scss
@@ -0,0 +1,60 @@
+@use "@pythnetwork/component-library/theme";
+
+.statsContainer {
+  .statScrollWrapper {
+    width: 100dvw; // Extend the width beyond the root padding
+    margin-left: -#{theme.spacing(4)};
+    margin-right: -#{theme.spacing(4)};
+    white-space: nowrap;
+    overflow: auto hidden;
+    -webkit-overflow-scrolling: touch;
+    scroll-snap-type: x mandatory;
+    scroll-padding: theme.spacing(4);
+    left: 0;
+    right: 0;
+
+    // Optional: Hide scrollbars
+    scrollbar-width: none;
+
+    &::-webkit-scrollbar {
+      display: none;
+    }
+
+    @include theme.breakpoint("md") {
+      width: 100%;
+      position: relative;
+      display: flex;
+      flex-flow: row nowrap;
+      overflow: visible;
+      margin: 0;
+    }
+
+    .statsItemsContainer {
+      display: flex;
+      flex-flow: row nowrap;
+      width: max-content;
+      gap: theme.spacing(3);
+      padding: 0 theme.spacing(4);
+
+      > * {
+        width: 280px;
+        scroll-snap-align: start;
+      }
+
+      @include theme.breakpoint("md") {
+        gap: theme.spacing(6);
+        width: 100%;
+        padding: 0;
+
+        > * {
+          display: flex;
+          width: 100%;
+          flex: 1 0 0;
+          min-width: 0;
+          max-width: 100%;
+          min-height: 0;
+        }
+      }
+    }
+  }
+}
diff --git a/apps/insights/src/components/Stats/index.tsx b/apps/insights/src/components/Stats/index.tsx
new file mode 100644
index 0000000000..1a379e913e
--- /dev/null
+++ b/apps/insights/src/components/Stats/index.tsx
@@ -0,0 +1,18 @@
+import clsx from "clsx";
+import type { ComponentProps } from "react";
+
+import styles from "./index.module.scss";
+
+type StatsProps = {
+  children: React.ReactNode;
+} & ComponentProps<"div">;
+
+export const Stats = ({ children, ...props }: StatsProps) => {
+  return (
+    <div className={clsx(styles.statsContainer, props.className)} {...props}>
+      <div className={styles.statScrollWrapper}>
+        <div className={styles.statsItemsContainer}>{children}</div>
+      </div>
+    </div>
+  );
+};
diff --git a/apps/insights/src/components/StructuredList/index.module.scss b/apps/insights/src/components/StructuredList/index.module.scss
new file mode 100644
index 0000000000..150d791f45
--- /dev/null
+++ b/apps/insights/src/components/StructuredList/index.module.scss
@@ -0,0 +1,27 @@
+@use "@pythnetwork/component-library/theme";
+
+.structuredList {
+  display: flex;
+  flex-flow: column nowrap;
+  gap: theme.spacing(4);
+
+  .structuredListItem {
+    display: grid;
+    grid-template-columns: repeat(2, 1fr);
+    gap: theme.spacing(2);
+    align-items: center;
+    justify-content: space-between;
+
+    // font-size: theme.font-size("sm");
+    .structuredListItemLabel {
+      color: theme.color("muted");
+    }
+
+    .structuredListItemValue {
+      text-align: right;
+      place-items: end;
+      font-weight: theme.font-weight("medium");
+      color: theme.color("heading");
+    }
+  }
+}
diff --git a/apps/insights/src/components/StructuredList/index.tsx b/apps/insights/src/components/StructuredList/index.tsx
new file mode 100644
index 0000000000..6ac09802b2
--- /dev/null
+++ b/apps/insights/src/components/StructuredList/index.tsx
@@ -0,0 +1,41 @@
+import clsx from "clsx";
+import type { ComponentProps } from "react";
+
+import styles from "./index.module.scss";
+
+type StructuredListProps = {
+  items: StructureListItemProps[];
+} & ComponentProps<"div">;
+
+type StructureListItemProps = {
+  label: React.ReactNode;
+  value: React.ReactNode;
+} & ComponentProps<"div">;
+
+export const StructuredList = ({ items, ...props }: StructuredListProps) => {
+  return (
+    items.length > 0 && (
+      <div className={clsx(styles.structuredList, props.className)} {...props}>
+        {items.map((item, index) => (
+          <StructuredListItem key={index} {...item} />
+        ))}
+      </div>
+    )
+  );
+};
+
+export const StructuredListItem = ({
+  label,
+  value,
+  ...props
+}: StructureListItemProps) => {
+  return (
+    <div
+      className={clsx(styles.structuredListItem, props.className)}
+      {...props}
+    >
+      <div className={styles.structuredListItemLabel}>{label}</div>
+      <div className={styles.structuredListItemValue}>{value}</div>
+    </div>
+  );
+};
diff --git a/packages/component-library/src/Badge/index.module.scss b/packages/component-library/src/Badge/index.module.scss
index 8ce2c49fe9..891a98dbfd 100644
--- a/packages/component-library/src/Badge/index.module.scss
+++ b/packages/component-library/src/Badge/index.module.scss
@@ -1,7 +1,9 @@
 @use "../theme";
 
 .badge {
-  display: inline flow-root;
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
   border-radius: theme.border-radius("3xl");
   transition-property: color, background-color, border-color;
   transition-duration: 100ms;
@@ -9,6 +11,7 @@
   white-space: nowrap;
   border-width: 1px;
   border-style: solid;
+  flex-shrink: 1;
 
   &[data-size="xs"] {
     line-height: theme.spacing(4);
diff --git a/packages/component-library/src/Button/index.module.scss b/packages/component-library/src/Button/index.module.scss
index 6de1e6fc7a..57379baeaa 100644
--- a/packages/component-library/src/Button/index.module.scss
+++ b/packages/component-library/src/Button/index.module.scss
@@ -1,7 +1,7 @@
 @use "../theme";
 
 .button {
-  display: inline flow-root;
+  display: flex;
   cursor: pointer;
   white-space: nowrap;
   font-weight: theme.font-weight("medium");
@@ -12,6 +12,9 @@
   text-decoration: none;
   outline-offset: 0;
   outline: theme.spacing(1) solid transparent;
+  text-align: center;
+  justify-content: center;
+  align-items: center;
 
   .iconWrapper {
     display: inline-grid;
diff --git a/packages/component-library/src/Card/index.module.scss b/packages/component-library/src/Card/index.module.scss
index 2f127ce2a6..dd79ee1e76 100644
--- a/packages/component-library/src/Card/index.module.scss
+++ b/packages/component-library/src/Card/index.module.scss
@@ -33,35 +33,43 @@
   }
 
   .header {
-    display: flex;
-    padding: theme.spacing(3) theme.spacing(4);
     position: relative;
-
-    .title {
-      color: theme.color("heading");
-      display: inline-flex;
+    display: flex;
+    padding: theme.spacing(3);
+    gap: theme.spacing(3);
+    flex-direction: column;
+    justify-content: flex-start;
+
+    @include theme.breakpoint("lg") {
+      padding: 0 theme.spacing(2);
+      height: theme.spacing(12);
+      justify-content: space-between;
       flex-flow: row nowrap;
-      gap: theme.spacing(3);
       align-items: center;
+    }
 
-      @include theme.text("lg", "medium");
-
-      .icon {
-        font-size: theme.spacing(6);
-        height: theme.spacing(6);
-        color: theme.color("button", "primary", "background", "normal");
+    .toolbar {
+      &:empty {
+        display: none;
       }
+      gap: theme.spacing(2);
+      display: flex;
     }
 
-    .toolbar {
+    .action {
+      align-self: center;
+      grid-area: action;
+      // display: grid;
+      // place-items: center;
+      // height: 100%;
+      // padding: 0 theme.spacing(2);
       position: absolute;
-      right: theme.spacing(3);
-      top: 0;
-      bottom: theme.spacing(0);
-      display: flex;
-      flex-flow: row nowrap;
-      gap: theme.spacing(2);
-      align-items: center;
+      top: theme.spacing(1.5);
+      right: theme.spacing(1.5);
+      @include theme.breakpoint("md") {
+        position: static;
+        padding: 0;
+      }
     }
   }
 
diff --git a/packages/component-library/src/Card/index.tsx b/packages/component-library/src/Card/index.tsx
index de33b1c4cd..2d1b646552 100644
--- a/packages/component-library/src/Card/index.tsx
+++ b/packages/component-library/src/Card/index.tsx
@@ -20,6 +20,7 @@ type OwnProps = {
   icon?: ReactNode | undefined;
   title?: ReactNode | undefined;
   toolbar?: ReactNode | ReactNode[] | undefined;
+  action?: ReactNode | undefined;
   footer?: ReactNode | undefined;
   nonInteractive?: boolean | undefined;
 };
@@ -59,6 +60,7 @@ const cardProps = <T extends ElementType>({
   title,
   toolbar,
   footer,
+  action,
   ...props
 }: Props<T>) => ({
   ...props,
@@ -69,11 +71,9 @@ const cardProps = <T extends ElementType>({
       <div className={styles.cardHoverBackground} />
       {(Boolean(icon) || Boolean(title) || Boolean(toolbar)) && (
         <div className={styles.header}>
-          <h2 className={styles.title}>
-            {icon && <div className={styles.icon}>{icon}</div>}
-            {title}
-          </h2>
-          <div className={styles.toolbar}>{toolbar}</div>
+          <div className={styles.title}>{title}</div>
+          {toolbar && <div className={styles.toolbar}>{toolbar}</div>}
+          {action && <div className={styles.action}>{action}</div>}
         </div>
       )}
       {children}
diff --git a/packages/component-library/src/Drawer/index.module.scss b/packages/component-library/src/Drawer/index.module.scss
index 3840e4b28e..039a26e6d5 100644
--- a/packages/component-library/src/Drawer/index.module.scss
+++ b/packages/component-library/src/Drawer/index.module.scss
@@ -7,31 +7,46 @@
   z-index: 1;
 
   .drawer {
-    position: fixed;
-    top: theme.spacing(4);
-    bottom: theme.spacing(4);
-    right: theme.spacing(4);
-    width: 60%;
-    max-width: theme.spacing(160);
-    outline: none;
+    width: 100%;
+    border-radius: 0;
+    border: none;
+    padding-bottom: 0;
     background: theme.color("background", "primary");
-    border: 1px solid theme.color("border");
-    border-radius: theme.border-radius("3xl");
-    display: flex;
-    flex-flow: column nowrap;
-    overflow-y: hidden;
-    padding-bottom: theme.border-radius("3xl");
+
+    @include theme.breakpoint("sm") {
+      position: fixed;
+      top: theme.spacing(4);
+      bottom: theme.spacing(4);
+      right: theme.spacing(4);
+      width: 80%;
+      max-width: theme.spacing(160);
+      outline: none;
+      border: 1px solid theme.color("background", "secondary");
+      border-radius: theme.border-radius("3xl");
+      display: flex;
+      flex-flow: column nowrap;
+      overflow-y: hidden;
+    }
+
+    @include theme.breakpoint("lg") {
+      width: 60%;
+    }
 
     .heading {
-      padding: theme.spacing(4);
-      padding-left: theme.spacing(6);
+      padding: theme.spacing(3);
+      padding-left: theme.spacing(4);
       display: flex;
       flex-flow: row nowrap;
       justify-content: space-between;
       align-items: center;
       color: theme.color("heading");
       flex: none;
-      border-bottom: 1px solid theme.color("border");
+      border-bottom: 1px solid theme.color("background", "secondary");
+
+      @include theme.breakpoint("sm") {
+        padding: theme.spacing(4);
+        padding-left: theme.spacing(6);
+      }
 
       .title {
         @include theme.h4;
@@ -51,8 +66,12 @@
 
     .body {
       flex: 1;
-      overflow-y: auto;
-      padding: theme.spacing(6);
+      overflow: hidden auto;
+      padding: theme.spacing(4);
+
+      @include theme.breakpoint("sm") {
+        padding: theme.spacing(6);
+      }
     }
 
     &[data-fill] {
diff --git a/packages/component-library/src/MainNavTabs/index.module.scss b/packages/component-library/src/MainNavTabs/index.module.scss
index 0d6e7573ef..c82cc45c65 100644
--- a/packages/component-library/src/MainNavTabs/index.module.scss
+++ b/packages/component-library/src/MainNavTabs/index.module.scss
@@ -2,12 +2,18 @@
 
 .mainNavTabs {
   gap: theme.spacing(2);
+  z-index: 1;
 
   @include theme.row;
 
   .tab {
+    width: 100%;
     position: relative;
     outline: none;
+    z-index: 1;
+    @include theme.breakpoint("md") {
+      width: auto;
+    }
 
     .bubble {
       position: absolute;
@@ -39,21 +45,11 @@
         pointer-events: auto;
 
         &[data-hovered] .bubble {
-          background-color: theme.color(
-            "button",
-            "solid",
-            "background",
-            "hover"
-          );
+          background-color: theme.color("button", "solid", "background", "hover");
         }
 
         &[data-pressed] .bubble {
-          background-color: theme.color(
-            "button",
-            "solid",
-            "background",
-            "active"
-          );
+          background-color: theme.color("button", "solid", "background", "active");
         }
       }
     }
diff --git a/packages/component-library/src/Paginator/index.module.scss b/packages/component-library/src/Paginator/index.module.scss
index 5679663437..cd49af2658 100644
--- a/packages/component-library/src/Paginator/index.module.scss
+++ b/packages/component-library/src/Paginator/index.module.scss
@@ -3,14 +3,22 @@
 .paginator {
   display: flex;
   flex-flow: row nowrap;
-  justify-content: space-between;
+  justify-content: center;
+
+  @include theme.breakpoint("lg") {
+    justify-content: space-between;
+  }
 
   .pageSizeSelect {
-    display: flex;
+    display: none;
     flex-flow: row nowrap;
     align-items: center;
     gap: theme.spacing(1);
 
+    @include theme.breakpoint("lg") {
+      display: flex;
+    }
+
     .loadingIndicator {
       width: theme.spacing(4);
       height: theme.spacing(4);
diff --git a/packages/component-library/src/SingleToggleGroup/index.module.scss b/packages/component-library/src/SingleToggleGroup/index.module.scss
index 5bc1f0d035..64a0400d7d 100644
--- a/packages/component-library/src/SingleToggleGroup/index.module.scss
+++ b/packages/component-library/src/SingleToggleGroup/index.module.scss
@@ -1,7 +1,7 @@
 @use "../theme";
 
 .singleToggleGroup {
-  gap: theme.spacing(2);
+  gap: theme.spacing(1);
 
   @include theme.row;
 
diff --git a/packages/component-library/src/Table/index.module.scss b/packages/component-library/src/Table/index.module.scss
index 6e96da9c1f..0b2d17abd8 100644
--- a/packages/component-library/src/Table/index.module.scss
+++ b/packages/component-library/src/Table/index.module.scss
@@ -1,9 +1,14 @@
 @use "../theme";
 
 .tableContainer {
+  display: none;
   background-color: theme.color("background", "primary");
   position: relative;
 
+  @include theme.breakpoint("md") {
+    display: block;
+  }
+
   .loaderWrapper {
     position: absolute;
     top: theme.spacing(10);
@@ -83,7 +88,7 @@
 
       .cell {
         position: relative;
-        border-bottom: 1px solid theme.color("border");
+        border-bottom: 1px solid theme.color("background", "secondary");
         font-weight: theme.font-weight("medium");
 
         .divider {
@@ -164,21 +169,11 @@
         }
 
         &[data-hovered] .cell {
-          background-color: theme.color(
-            "button",
-            "outline",
-            "background",
-            "hover"
-          );
+          background-color: theme.color("button", "outline", "background", "hover");
         }
 
         &[data-pressed] .cell {
-          background-color: theme.color(
-            "button",
-            "outline",
-            "background",
-            "active"
-          );
+          background-color: theme.color("button", "outline", "background", "active");
         }
       }
     }
diff --git a/packages/component-library/src/theme.scss b/packages/component-library/src/theme.scss
index 0cfb0b6f9b..1f12d81998 100644
--- a/packages/component-library/src/theme.scss
+++ b/packages/component-library/src/theme.scss
@@ -80,6 +80,50 @@ $border-radius: (
   @return map-get-strict($border-radius, $radius);
 }
 
+$breakpoints: (
+  "xs": 480px,
+  "sm": 720px,
+  "md": 960px,
+  "lg": 1024px,
+  "xl": 1280px,
+  "2xl": 1536px,
+  "3xl": 1720px,
+);
+
+@function breakpoint-old($breakpoint) {
+  @return map-get-strict($breakpoints, $breakpoint);
+}
+
+@mixin breakpoint($point) {
+  @media (min-width: map-get-strict($breakpoints, $point)) {
+    @content;
+  }
+}
+
+@mixin mobile() {
+  @media screen and (max-width: breakpoint-old("md")) {
+    @content;
+
+    background: cyan;
+  }
+}
+
+@mixin tablet() {
+  @media screen and (min-width: breakpoint-old("md")) {
+    @content;
+
+    background: orange;
+  }
+}
+
+@mixin desktop() {
+  @media screen and (min-width: breakpoint-old("3xl")) {
+    @content;
+
+    background: pink;
+  }
+}
+
 $color-pallette: (
   "black": #000,
   "white": #fff,
@@ -433,7 +477,7 @@ $color: (
   "highlight":
     light-dark(pallette-color("violet", 600), pallette-color("violet", 500)),
   "muted":
-    light-dark(pallette-color("stone", 700), pallette-color("steel", 300)),
+    light-dark(pallette-color("stone", 500), pallette-color("steel", 400)),
   "border":
     light-dark(pallette-color("stone", 300), pallette-color("steel", 600)),
   "selection": (
@@ -724,8 +768,12 @@ $max-width: 96rem;
 @mixin max-width {
   margin: 0 auto;
   max-width: $max-width;
-  padding: 0 spacing(6);
+  padding: 0 spacing(4);
   box-sizing: content-box;
+
+  @include breakpoint("xl") {
+    padding: 0 spacing(6);
+  }
 }
 
 @mixin row {
@@ -784,6 +832,24 @@ $elevations: (
   margin: 0;
 }
 
+@mixin h5 {
+  font-size: font-size("lg");
+  font-style: normal;
+  font-weight: font-weight("medium");
+  line-height: 125%;
+  letter-spacing: letter-spacing("tight");
+  margin: 0;
+}
+
+@mixin h6 {
+  font-size: font-size("base");
+  font-style: normal;
+  font-weight: font-weight("medium");
+  line-height: 125%;
+  letter-spacing: letter-spacing("tight");
+  margin: 0;
+}
+
 @mixin text($size: "base", $weight: "normal") {
   font-size: font-size($size);
   font-weight: font-weight($weight);