+ Bluefin is an operating system for your computer. The best of
+ both worlds: the reliability and ease of use of a Chromebook,
+ with the power of a GNOME desktop.
+
+
+ {userBenefits.map((benefit) => (
+
{benefit}
+ ))}
+
+
+
+
+
+
+
+
+ For
+
Developers
+
+ Bluefin comes with an optional "developer mode" that
+ transforms your device into a powerful workstation. It features
+ container-focused workflows to get you started depending on
+ where you're coming from, or bring your own.
+
+
+ {developerBenefits.map((benefit) => (
+
{benefit}
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Our
+
Mission
+
+ Bluefin is not just software, she is a new breed of animal,
+ adapted to survive the rigors of an ecosystem dominated by giants
+ while protecting her family.
+
+
+ Technology begins with the local computer, the device that you
+ touch, and it should be as essential as the rest of the Linux
+ ecosystem.
+
+
+ Bluefin is about sustainability, encompassing the software, the
+ hardware, and the people.
+
+
+
+
+
+ );
+}
diff --git a/src/components/portal/portalModel.ts b/src/components/portal/portalModel.ts
new file mode 100644
index 00000000..493146ef
--- /dev/null
+++ b/src/components/portal/portalModel.ts
@@ -0,0 +1,119 @@
+export const PORTAL_BREAKPOINT_PX = 956;
+export const MOBILE_LAYER_SRC = "/img/portal/mobile-parallax.webp";
+export const TRANSITION_SRC = "/img/portal/layer-transition.webp";
+
+export type PortalDrift = "left" | "right";
+
+export type PortalLayer = {
+ key: string;
+ src: string;
+ top: number;
+ rate: number;
+ drift?: PortalDrift;
+ priority?: boolean;
+};
+
+const evening = (file: string): string => `/img/portal/evening/${file}`;
+const clouds = evening("BlueFinSite_2_Clouds-min.webp");
+
+export const PORTAL_LAYERS: readonly PortalLayer[] = [
+ {
+ key: "sky",
+ src: evening("BlueFinSite_1_Sky-min.webp"),
+ top: 0,
+ rate: 0,
+ priority: true,
+ },
+ { key: "clouds-right", src: clouds, top: -60, rate: 0, drift: "right" },
+ {
+ key: "sun",
+ src: evening("BlueFinSite_2_Sun-min.webp"),
+ top: -90,
+ rate: 0.05,
+ },
+ { key: "clouds-left", src: clouds, top: 0, rate: 0, drift: "left" },
+ {
+ key: "mountains",
+ src: evening("BlueFinSite_4_Mountains-min.webp"),
+ top: 0,
+ rate: 0,
+ },
+ {
+ key: "fog-a",
+ src: evening("BlueFinSite_5_FogA-min.webp"),
+ top: 0,
+ rate: 0,
+ },
+ {
+ key: "background-a",
+ src: evening("BlueFinSite_6_BackgroundA-min.webp"),
+ top: 165,
+ rate: 0,
+ },
+ {
+ key: "fog-b",
+ src: evening("BlueFinSite_7_FogB-min.webp"),
+ top: 200,
+ rate: 0,
+ },
+ {
+ key: "background-b",
+ src: evening("BlueFinSite_8_BackgroundB-min.webp"),
+ top: 175,
+ rate: -0.01,
+ },
+ {
+ key: "midground-a",
+ src: evening("BlueFinSite_9_MidGroundA-min.webp"),
+ top: 210,
+ rate: -0.03,
+ },
+ {
+ key: "midground-b",
+ src: evening("BlueFinSite_10_MidgroundB-min.webp"),
+ top: 250,
+ rate: -0.05,
+ },
+ {
+ key: "midground-c",
+ src: evening("BlueFinSite_11_MidGroundC-min.webp"),
+ top: 300,
+ rate: -0.07,
+ },
+ {
+ key: "foreground-a",
+ src: evening("BlueFinSite_12_ForeGroundA-min.webp"),
+ top: 320,
+ rate: -0.09,
+ },
+ {
+ key: "foreground-b",
+ src: evening("BlueFinSite_13_ForegroundB-min.webp"),
+ top: 340,
+ rate: -0.11,
+ },
+ {
+ key: "foreground-c",
+ src: evening("BlueFinSite_14_ForegroundC-min.webp"),
+ top: 360,
+ rate: -0.13,
+ },
+];
+
+const clamp = (value: number, min: number, max: number): number =>
+ Math.max(min, Math.min(max, value));
+
+export function overlayOpacity(
+ scrollY: number,
+ viewportHeight: number,
+): number {
+ return clamp((scrollY - viewportHeight * 0.25) / 650, 0, 1);
+}
+
+export function layerTransform(scrollY: number, rate: number): string {
+ return `translate3d(0, ${scrollY * rate}px, 0)`;
+}
+
+export function isParallaxVisible(scrollY: number, sceneEnd: number): boolean {
+ return scrollY <= sceneEnd;
+}
diff --git a/src/pages/portal-prototype.tsx b/src/pages/portal-prototype.tsx
new file mode 100644
index 00000000..eaa779eb
--- /dev/null
+++ b/src/pages/portal-prototype.tsx
@@ -0,0 +1,14 @@
+import React from "react";
+import Layout from "@theme/Layout";
+import PortalPrototype from "../components/portal/PortalPrototype";
+
+const description =
+ "The next generation Linux workstation, designed for reliability, performance, and sustainability.";
+
+export default function PortalPrototypePage(): React.JSX.Element {
+ return (
+
+
+
+ );
+}
diff --git a/static/img/portal/characters/bluefin.webp b/static/img/portal/characters/bluefin.webp
new file mode 100644
index 00000000..4b1fee2a
Binary files /dev/null and b/static/img/portal/characters/bluefin.webp differ
diff --git a/static/img/portal/characters/karl.webp b/static/img/portal/characters/karl.webp
new file mode 100644
index 00000000..249d0206
Binary files /dev/null and b/static/img/portal/characters/karl.webp differ
diff --git a/static/img/portal/characters/nest.webp b/static/img/portal/characters/nest.webp
new file mode 100644
index 00000000..dabc9993
Binary files /dev/null and b/static/img/portal/characters/nest.webp differ
diff --git a/static/img/portal/evening/BlueFinSite_10_MidgroundB-min.webp b/static/img/portal/evening/BlueFinSite_10_MidgroundB-min.webp
new file mode 100644
index 00000000..af525682
Binary files /dev/null and b/static/img/portal/evening/BlueFinSite_10_MidgroundB-min.webp differ
diff --git a/static/img/portal/evening/BlueFinSite_11_MidGroundC-min.webp b/static/img/portal/evening/BlueFinSite_11_MidGroundC-min.webp
new file mode 100644
index 00000000..26e6d57b
Binary files /dev/null and b/static/img/portal/evening/BlueFinSite_11_MidGroundC-min.webp differ
diff --git a/static/img/portal/evening/BlueFinSite_12_ForeGroundA-min.webp b/static/img/portal/evening/BlueFinSite_12_ForeGroundA-min.webp
new file mode 100644
index 00000000..7d3f9752
Binary files /dev/null and b/static/img/portal/evening/BlueFinSite_12_ForeGroundA-min.webp differ
diff --git a/static/img/portal/evening/BlueFinSite_13_ForegroundB-min.webp b/static/img/portal/evening/BlueFinSite_13_ForegroundB-min.webp
new file mode 100644
index 00000000..38fef185
Binary files /dev/null and b/static/img/portal/evening/BlueFinSite_13_ForegroundB-min.webp differ
diff --git a/static/img/portal/evening/BlueFinSite_14_ForegroundC-min.webp b/static/img/portal/evening/BlueFinSite_14_ForegroundC-min.webp
new file mode 100644
index 00000000..67478b8b
Binary files /dev/null and b/static/img/portal/evening/BlueFinSite_14_ForegroundC-min.webp differ
diff --git a/static/img/portal/evening/BlueFinSite_1_Sky-min.webp b/static/img/portal/evening/BlueFinSite_1_Sky-min.webp
new file mode 100644
index 00000000..bcbc23f8
Binary files /dev/null and b/static/img/portal/evening/BlueFinSite_1_Sky-min.webp differ
diff --git a/static/img/portal/evening/BlueFinSite_2_Clouds-min.webp b/static/img/portal/evening/BlueFinSite_2_Clouds-min.webp
new file mode 100644
index 00000000..fe7e96f8
Binary files /dev/null and b/static/img/portal/evening/BlueFinSite_2_Clouds-min.webp differ
diff --git a/static/img/portal/evening/BlueFinSite_2_Sun-min.webp b/static/img/portal/evening/BlueFinSite_2_Sun-min.webp
new file mode 100644
index 00000000..2b883f3d
Binary files /dev/null and b/static/img/portal/evening/BlueFinSite_2_Sun-min.webp differ
diff --git a/static/img/portal/evening/BlueFinSite_4_Mountains-min.webp b/static/img/portal/evening/BlueFinSite_4_Mountains-min.webp
new file mode 100644
index 00000000..61b87136
Binary files /dev/null and b/static/img/portal/evening/BlueFinSite_4_Mountains-min.webp differ
diff --git a/static/img/portal/evening/BlueFinSite_5_FogA-min.webp b/static/img/portal/evening/BlueFinSite_5_FogA-min.webp
new file mode 100644
index 00000000..5765ef29
Binary files /dev/null and b/static/img/portal/evening/BlueFinSite_5_FogA-min.webp differ
diff --git a/static/img/portal/evening/BlueFinSite_6_BackgroundA-min.webp b/static/img/portal/evening/BlueFinSite_6_BackgroundA-min.webp
new file mode 100644
index 00000000..bf4efbad
Binary files /dev/null and b/static/img/portal/evening/BlueFinSite_6_BackgroundA-min.webp differ
diff --git a/static/img/portal/evening/BlueFinSite_7_FogB-min.webp b/static/img/portal/evening/BlueFinSite_7_FogB-min.webp
new file mode 100644
index 00000000..d2bf1643
Binary files /dev/null and b/static/img/portal/evening/BlueFinSite_7_FogB-min.webp differ
diff --git a/static/img/portal/evening/BlueFinSite_8_BackgroundB-min.webp b/static/img/portal/evening/BlueFinSite_8_BackgroundB-min.webp
new file mode 100644
index 00000000..b076caaf
Binary files /dev/null and b/static/img/portal/evening/BlueFinSite_8_BackgroundB-min.webp differ
diff --git a/static/img/portal/evening/BlueFinSite_9_MidGroundA-min.webp b/static/img/portal/evening/BlueFinSite_9_MidGroundA-min.webp
new file mode 100644
index 00000000..d53e47df
Binary files /dev/null and b/static/img/portal/evening/BlueFinSite_9_MidGroundA-min.webp differ
diff --git a/static/img/portal/layer-transition.webp b/static/img/portal/layer-transition.webp
new file mode 100644
index 00000000..6c049b83
Binary files /dev/null and b/static/img/portal/layer-transition.webp differ
diff --git a/static/img/portal/mobile-parallax.webp b/static/img/portal/mobile-parallax.webp
new file mode 100644
index 00000000..c1b88924
Binary files /dev/null and b/static/img/portal/mobile-parallax.webp differ