diff --git a/frontend/apps/artcraft-website/src/app/app.tsx b/frontend/apps/artcraft-website/src/app/app.tsx
index 7a301b7e5e..d0a6aca1c7 100644
--- a/frontend/apps/artcraft-website/src/app/app.tsx
+++ b/frontend/apps/artcraft-website/src/app/app.tsx
@@ -17,6 +17,7 @@ import CreateVideo from "../pages/create-video";
import CreateVFX from "../pages/create-vfx";
//import Landing2 from "../pages/landing2";
import Landing3 from "../pages/landing3";
+import Landing4 from "../pages/landing4";
import LandingSD2 from "../pages/landing-sd2";
import LandingSD25 from "../pages/landing-sd25";
import TutorialsPage from "../pages/tutorials";
@@ -59,14 +60,19 @@ function appOrWebapp(localElement: ReactNode, webappPath: string): ReactNode {
}
export function App() {
+ // Landing4 renders its own scoped navbar/footer; hide the global chrome.
+ const { pathname } = useLocation();
+ const hideGlobalChrome = pathname === "/landing4";
+
return (
-
+ {!hideGlobalChrome && }
} />
} />
+ } />
} />
} />
} />
diff --git a/frontend/apps/artcraft-website/src/pages/landing4/components/brut-footer.tsx b/frontend/apps/artcraft-website/src/pages/landing4/components/brut-footer.tsx
new file mode 100644
index 0000000000..88060082c3
--- /dev/null
+++ b/frontend/apps/artcraft-website/src/pages/landing4/components/brut-footer.tsx
@@ -0,0 +1,104 @@
+import { Link } from "react-router-dom";
+import { SOCIAL_LINKS, SUPPORT_EMAIL } from "../../../config/links";
+import { MonoLabel } from "./ui";
+
+const SITEMAP: ReadonlyArray<{ label: string; to: string }> = [
+ { label: "Home", to: "/" },
+ { label: "Download", to: "/download" },
+ { label: "Pricing", to: "/pricing" },
+ { label: "Tutorials", to: "/tutorials" },
+ { label: "FAQ", to: "/faq" },
+ { label: "News", to: "/news" },
+ { label: "Press Kit", to: "/press-kit" },
+ { label: "Support", to: "/support" },
+];
+
+const SOCIALS: ReadonlyArray<{ label: string; href: string }> = [
+ { label: "GitHub", href: SOCIAL_LINKS.GITHUB },
+ { label: "Discord", href: SOCIAL_LINKS.DISCORD },
+ { label: "YouTube", href: SOCIAL_LINKS.YOUTUBE },
+ { label: "Instagram", href: SOCIAL_LINKS.INSTAGRAM },
+ { label: "TikTok", href: SOCIAL_LINKS.TIKTOK },
+ { label: "Reddit", href: SOCIAL_LINKS.REDDIT },
+];
+
+// Landing4-only footer. Dark chapter: mono column grid over a hairline, then
+// a giant clipped wordmark bleeding off the bottom edge.
+export const BrutFooter = () => (
+
+);
diff --git a/frontend/apps/artcraft-website/src/pages/landing4/components/brut-navbar.tsx b/frontend/apps/artcraft-website/src/pages/landing4/components/brut-navbar.tsx
new file mode 100644
index 0000000000..8e81b516d8
--- /dev/null
+++ b/frontend/apps/artcraft-website/src/pages/landing4/components/brut-navbar.tsx
@@ -0,0 +1,141 @@
+import { useEffect, useState } from "react";
+import { Link } from "react-router-dom";
+import { SOCIAL_LINKS } from "../../../config/links";
+import { MonoLabel } from "./ui";
+
+const NAV_LINKS: ReadonlyArray<{
+ label: string;
+ index: string;
+ to?: string;
+ href?: string;
+}> = [
+ { label: "PRICING", index: "01", to: "/pricing" },
+ { label: "TUTORIALS", index: "02", to: "/tutorials" },
+ { label: "NEWS", index: "03", to: "/news" },
+ { label: "GITHUB ↗", index: "04", href: SOCIAL_LINKS.GITHUB },
+];
+
+// Landing4-only fixed navbar. Chapter-aware: text and hairlines read the
+// --l4-* vars so the bar recolors as the page scrubs between ink and paper.
+// A backdrop tinted with the current --l4-bg keeps links legible over content.
+// Mobile: a full-screen ink overlay with numbered index-style rows.
+export const BrutNavbar = ({
+ onDownloadClick,
+}: {
+ onDownloadClick: () => void;
+}) => {
+ const [menuOpen, setMenuOpen] = useState(false);
+
+ // Lock page scroll behind the full-screen menu.
+ useEffect(() => {
+ if (!menuOpen) return;
+ const previous = document.body.style.overflow;
+ document.body.style.overflow = "hidden";
+ return () => {
+ document.body.style.overflow = previous;
+ };
+ }, [menuOpen]);
+
+ return (
+ <>
+
+
+
+ ArtCraft®
+
+
+
+
+
+
+
+
+
+
+
+ {/* Mobile full-screen index */}
+ {menuOpen && (
+
+
+
+ ARTCRAFT — IMG / VID / 3D — OPEN SOURCE
+
+
+ )}
+ >
+ );
+};
diff --git a/frontend/apps/artcraft-website/src/pages/landing4/components/section-community.tsx b/frontend/apps/artcraft-website/src/pages/landing4/components/section-community.tsx
new file mode 100644
index 0000000000..4bd6993dcd
--- /dev/null
+++ b/frontend/apps/artcraft-website/src/pages/landing4/components/section-community.tsx
@@ -0,0 +1,58 @@
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faDiscord, faGithub } from "@fortawesome/free-brands-svg-icons";
+import { SOCIAL_LINKS } from "../../../config/links";
+import { LineMaskHeading, MonoLabel, SectionHeader } from "./ui";
+
+// /07 — Community. Back to the dark chapter (the boundary sentinel before
+// this section scrubs the root vars). Two 50/50 hairline cells; the whole
+// cell is the anchor and inverts to flare on hover.
+export const SectionCommunity = () => (
+ <>
+ {/* Chapter boundary: paper → dark */}
+
+
+
+
+
+ >
+);
diff --git a/frontend/apps/artcraft-website/src/pages/landing4/components/section-features.tsx b/frontend/apps/artcraft-website/src/pages/landing4/components/section-features.tsx
new file mode 100644
index 0000000000..1f5f90a895
--- /dev/null
+++ b/frontend/apps/artcraft-website/src/pages/landing4/components/section-features.tsx
@@ -0,0 +1,127 @@
+import { useEffect, useRef, useState } from "react";
+import { FEATURES } from "../data";
+import {
+ HairlineFrame,
+ LazyAutoplayVideo,
+ LineMaskHeading,
+ MonoLabel,
+ SectionHeader,
+} from "./ui";
+
+// /03 — Features. Paper chapter. Desktop: an index list on the left with a
+// sticky hairline-framed preview on the right; an IntersectionObserver with a
+// center-band root margin marks the row crossing mid-viewport as active,
+// which drives the preview video swap. Mobile: each row embeds its own video
+// and the observer never activates (rows are hidden from it via lg gating in
+// markup, and the sticky preview is display:none).
+export const SectionFeatures = () => {
+ const [activeIndex, setActiveIndex] = useState(0);
+ const listRef = useRef(null);
+ const active = FEATURES[activeIndex];
+
+ useEffect(() => {
+ const list = listRef.current;
+ if (!list) return;
+ const rows = Array.from(
+ list.querySelectorAll("[data-l4-feature-row]"),
+ );
+ // Center band: a row becomes active while it overlaps the middle 20% of
+ // the viewport. Cheap, and unlike per-row ScrollTriggers it needs no
+ // cleanup coordination with the GSAP context.
+ const observer = new IntersectionObserver(
+ (entries) => {
+ for (const entry of entries) {
+ if (entry.isIntersecting) {
+ const index = Number(
+ (entry.target as HTMLElement).dataset.l4FeatureRow,
+ );
+ if (!Number.isNaN(index)) setActiveIndex(index);
+ }
+ }
+ },
+ { rootMargin: "-40% 0px -40% 0px" },
+ );
+ rows.forEach((row) => observer.observe(row));
+ return () => observer.disconnect();
+ }, []);
+
+ return (
+
+
+
+ THE TOOLKIT>]}
+ />
+
+
+
+ {/* Index list */}
+
+ {FEATURES.map((feature, i) => (
+
+
+
+ {String(i + 1).padStart(2, "0")}
+
+
+ {feature.label}
+
+ {feature.title}
+
+
+ {feature.description}
+
+
+
+ +
+
+
+ {/* Mobile-only inline video */}
+
+
+
+
+
+
+ ))}
+
+
+ {/* Sticky preview (desktop) */}
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/frontend/apps/artcraft-website/src/pages/landing4/components/section-final-cta.tsx b/frontend/apps/artcraft-website/src/pages/landing4/components/section-final-cta.tsx
new file mode 100644
index 0000000000..c8b9483e22
--- /dev/null
+++ b/frontend/apps/artcraft-website/src/pages/landing4/components/section-final-cta.tsx
@@ -0,0 +1,61 @@
+import { Link } from "react-router-dom";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import {
+ faApple,
+ faWindows,
+ faLinux,
+} from "@fortawesome/free-brands-svg-icons";
+import { LineMaskHeading, MonoLabel } from "./ui";
+
+// /08 — Final CTA. Dark chapter, near-full-viewport, giant type with the last
+// line clipped at the section edge.
+export const SectionFinalCta = ({
+ onDownloadClick,
+}: {
+ onDownloadClick: () => void;
+}) => (
+
+
+
+);
diff --git a/frontend/apps/artcraft-website/src/pages/landing4/components/section-hero.tsx b/frontend/apps/artcraft-website/src/pages/landing4/components/section-hero.tsx
new file mode 100644
index 0000000000..63385aae12
--- /dev/null
+++ b/frontend/apps/artcraft-website/src/pages/landing4/components/section-hero.tsx
@@ -0,0 +1,121 @@
+import { Link } from "react-router-dom";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import {
+ faApple,
+ faWindows,
+ faLinux,
+} from "@fortawesome/free-brands-svg-icons";
+import { HairlineFrame, LineMaskHeading, MonoLabel, PlusCorners } from "./ui";
+
+// /01 — Hero. Dark chapter. Swiss grid with visible column rules, stacked
+// oversized display type, mono metadata at the corners, and a hairline-framed
+// canvas video in the right column.
+export const SectionHero = ({
+ onDownloadClick,
+}: {
+ onDownloadClick: () => void;
+}) => (
+
+ {/* Vertical gridlines (desktop only) */}
+
+ {[25, 50, 75].map((left) => (
+
+ ))}
+
+
+
+ {/* Top metadata row */}
+
+ EST. 2024 — OPEN SOURCE
+
+ IMG / VID / 3D
+
+ N 37°46′ — W 122°25′
+
+
+ {/* Headline */}
+
+ CONTROLLABLE>,
+ <>
+ AI FOR
+ >,
+ ARTISTS,
+ ]}
+ />
+
+ ArtCraft is an open desktop app for AI image, video, and 3D. Every
+ model, one canvas, zero prompt-wrestling.
+
+
+ {/* CTAs */}
+
+
+
+ Use on Web
+
+
+ MAC OS — WINDOWS — LINUX
+
+
+
+
+ {/* Bottom row: figure video right, mono coordinates left */}
+
+
+ ARTCRAFT — DESKTOP + WEB
+ V2.X — PUBLIC BUILD
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
diff --git a/frontend/apps/artcraft-website/src/pages/landing4/components/section-made-with.tsx b/frontend/apps/artcraft-website/src/pages/landing4/components/section-made-with.tsx
new file mode 100644
index 0000000000..8dd489b02f
--- /dev/null
+++ b/frontend/apps/artcraft-website/src/pages/landing4/components/section-made-with.tsx
@@ -0,0 +1,50 @@
+import { MADE_WITH_VIDEOS } from "../data";
+import { HairlineFrame, LineMaskHeading, SectionHeader } from "./ui";
+
+// /06 — Output. Paper chapter. Asymmetric editorial grid: one large frame plus
+// two stacked small frames, all lazy YouTube embeds with mono figure captions.
+export const SectionMadeWith = () => {
+ const [featureFilm, ...smallFilms] = MADE_WITH_VIDEOS;
+ return (
+
+
+
+ MADE WITH>, <>ARTCRAFT>]}
+ />
+
+
+
+
+
+
+
+
+
+ {smallFilms.map((film, i) => (
+
+
+
+
+
+ ))}
+
+
+
+ );
+};
diff --git a/frontend/apps/artcraft-website/src/pages/landing4/components/section-manifesto.tsx b/frontend/apps/artcraft-website/src/pages/landing4/components/section-manifesto.tsx
new file mode 100644
index 0000000000..cb29a88fcc
--- /dev/null
+++ b/frontend/apps/artcraft-website/src/pages/landing4/components/section-manifesto.tsx
@@ -0,0 +1,45 @@
+import { Fragment } from "react";
+import { MANIFESTO_ACCENT_WORDS, MANIFESTO_WORDS } from "../data";
+import { MonoLabel } from "./ui";
+
+// /02 — Statement. Dark chapter. On desktop the outer section is tall and the
+// inner viewport sticks, while a scrubbed ScrollTrigger raises each word from
+// 18% opacity to full as the user scrolls. Words tagged as accents also flip
+// to flare. On mobile the section is static (no pin) and gets a simple fade.
+// The [data-l4-boundary="paper"] spacer after the text drives the dark→paper
+// chapter transition.
+export const SectionManifesto = () => (
+ <>
+
+
+
+ {/* Chapter boundary: scrubbing through this spacer tweens the root CSS
+ vars from the dark palette to paper. */}
+
+ >
+);
diff --git a/frontend/apps/artcraft-website/src/pages/landing4/components/section-model-wall.tsx b/frontend/apps/artcraft-website/src/pages/landing4/components/section-model-wall.tsx
new file mode 100644
index 0000000000..f330a64863
--- /dev/null
+++ b/frontend/apps/artcraft-website/src/pages/landing4/components/section-model-wall.tsx
@@ -0,0 +1,61 @@
+import { PROVIDERS } from "../data";
+import { LineMaskHeading, MonoLabel, SectionHeader } from "./ui";
+
+// /04 — Model wall. Paper chapter. Collapsed-border grid of provider marks
+// (the service SVGs are dark-on-transparent, so they read natively on paper).
+// Counters tick up once via the [data-l4-counter] hooks in the animations
+// module.
+export const SectionModelWall = () => (
+
+
+ PROVIDERS — 19 / MODELS —{" "}
+ 60+
+ >
+ }
+ />
+
+ EVERY MODEL.>, ONE CANVAS.]}
+ />
+
+ Text prompting is neat, but artists crave control. Use every frontier
+ model from one desktop canvas — no tab-hopping, no per-site
+ subscriptions.
+
+
+
+
+ {PROVIDERS.map((provider) => (
+
+
+
+ {provider.name}
+
+
+ ))}
+
+
+ +
+
+ MORE EVERY WEEK
+
+
+
+);
diff --git a/frontend/apps/artcraft-website/src/pages/landing4/components/section-ownership.tsx b/frontend/apps/artcraft-website/src/pages/landing4/components/section-ownership.tsx
new file mode 100644
index 0000000000..dc5d7f4f38
--- /dev/null
+++ b/frontend/apps/artcraft-website/src/pages/landing4/components/section-ownership.tsx
@@ -0,0 +1,75 @@
+import { OWNERSHIP_ROWS, RENTAL_ROWS } from "../data";
+import { LineMaskHeading, MonoLabel, SectionHeader } from "./ui";
+
+// /05 — Ownership. Paper chapter with the page's strongest hit: a full ink
+// panel for the ArtCraft column against a paper ledger of rental grievances.
+export const SectionOwnership = () => (
+
+
+
+ STOP RENTING>, YOUR TOOLS]}
+ />
+
+ ArtCraft is yours to own and keep, forever. No subscriptions needed, no
+ aggregator middleman, no rent payments.
+
+
+
+
+ {/* The subscription web — ledger of grievances */}
+