(null);
+ const heroVideoUrl = useBaseUrl(
+ "https://static.oomol.com/assets/homepage/oomol-flow-en.webm"
+ );
+ const heroVideoPosterUrl = useBaseUrl(
+ "/img/pages/home/homepage-first-screen-workflow-poster.png"
+ );
+
+ const handlePlay = async () => {
+ if (!videoRef.current) {
+ return;
+ }
+
+ try {
+ await videoRef.current.play();
+ setIsPlaying(true);
+ } catch {
+ setIsPlaying(false);
+ }
+ };
+
+ return (
+
+
+
+
+
+ {copy.ownershipNote}
+
+ {copy.ownershipHighlight}
+
+
+
{copy.slogan}
+
{copy.overview}
+
+
+
+ {copy.secondaryCta}
+
+
+
+
+
+
+
+ {!isPlaying && (
+
+ )}
+
+
+
+
+
+ );
+}
diff --git a/src/components/CloudPageFirstScreen/styles.module.scss b/src/components/CloudPageFirstScreen/styles.module.scss
new file mode 100644
index 0000000..ebc293c
--- /dev/null
+++ b/src/components/CloudPageFirstScreen/styles.module.scss
@@ -0,0 +1,454 @@
+@use "../../css/custom.scss" as *;
+
+.section {
+ position: relative;
+ overflow: clip;
+ padding: clamp(4.75rem, 7.6vw, 6.6rem) 0 0;
+}
+
+.background {
+ position: absolute;
+ inset: 0;
+ background:
+ radial-gradient(
+ circle at top left,
+ rgba(161, 191, 235, 0.16) 0%,
+ rgba(161, 191, 235, 0) 34%
+ ),
+ radial-gradient(
+ circle at 80% 18%,
+ rgba(127, 138, 231, 0.08) 0%,
+ rgba(127, 138, 231, 0) 26%
+ ),
+ linear-gradient(
+ 180deg,
+ rgba(252, 253, 255, 0.96) 0%,
+ rgba(246, 248, 251, 0.9) 100%
+ );
+
+ &::after {
+ content: "";
+ position: absolute;
+ inset: 0;
+ background:
+ linear-gradient(rgba(92, 108, 141, 0.06) 1px, transparent 1px),
+ linear-gradient(90deg, rgba(92, 108, 141, 0.06) 1px, transparent 1px);
+ background-size: 9.5rem 9.5rem;
+ mask-image: linear-gradient(180deg, rgba(0, 0, 0, 0.75), transparent 90%);
+ opacity: 0.52;
+ pointer-events: none;
+ }
+}
+
+.container {
+ position: relative;
+ z-index: 1;
+ max-width: 1160px;
+ margin: 0 auto;
+ padding: 0 32px;
+ display: grid;
+ gap: clamp(1.1rem, 2.2vw, 1.85rem);
+}
+
+.titleGroup {
+ display: grid;
+ gap: 1rem;
+ max-width: 52rem;
+ margin: 0 auto;
+ justify-items: center;
+ text-align: center;
+}
+
+.slogan {
+ margin: 0;
+ max-width: 100%;
+ font-family: var(--oomol-font-display);
+ font-size: clamp(2.72rem, 4.7vw, 4.15rem);
+ line-height: 1.1;
+ font-weight: 700;
+ letter-spacing: -0.04em;
+ white-space: pre-line;
+ word-break: keep-all;
+ overflow-wrap: normal;
+ color: var(--oomol-text-primary);
+}
+
+.overview {
+ margin: 0;
+ max-width: 44rem;
+ font-size: 1.0625rem;
+ line-height: 1.7;
+ white-space: pre-line;
+ color: var(--oomol-text-secondary);
+}
+
+.ownershipNote {
+ margin: 0;
+ max-width: 48rem;
+ display: inline-flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: center;
+ gap: 0.3rem;
+ padding: 0.55rem 1rem 0.58rem;
+ border-radius: 999px;
+ border: 1px solid color-mix(in srgb, var(--oomol-primary) 12%, white);
+ background: color-mix(in srgb, var(--oomol-primary-bg) 52%, white);
+ box-shadow:
+ inset 0 1px 0 rgba(255, 255, 255, 0.72),
+ 0 10px 24px rgba(124, 138, 190, 0.08);
+ font-size: 0.92rem;
+ line-height: 1.55;
+ color: color-mix(in srgb, var(--oomol-text-secondary) 88%, white 12%);
+}
+
+.ownershipHighlight {
+ font-weight: 700;
+ color: var(--oomol-primary-text);
+}
+
+.actions {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ align-items: flex-start;
+ justify-content: center;
+ gap: 0.95rem;
+ padding-top: 0.4rem;
+}
+
+.secondaryCta {
+ align-self: flex-start;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ min-height: 3rem;
+ padding: 0 1.1rem;
+ border-radius: 999px;
+ border: 1px solid color-mix(in srgb, var(--oomol-border-default) 86%, white);
+ background: color-mix(
+ in srgb,
+ var(--ifm-background-surface-color) 88%,
+ white
+ );
+ color: var(--oomol-text-primary);
+ font-size: 1rem;
+ font-weight: 700;
+ letter-spacing: 0.01em;
+ text-decoration: none;
+ box-shadow: 0 12px 24px rgba(105, 120, 159, 0.09);
+ transition:
+ transform 0.2s ease,
+ box-shadow 0.2s ease,
+ border-color 0.2s ease;
+
+ &:hover {
+ transform: translateY(-1px);
+ text-decoration: none;
+ border-color: color-mix(in srgb, var(--oomol-primary) 28%, white);
+ box-shadow: 0 16px 30px rgba(105, 120, 159, 0.13);
+ }
+}
+
+/* ── Video Showcase: full-width dark container ── */
+
+.videoShowcase {
+ position: relative;
+ z-index: 1;
+ width: 100%;
+ margin-top: clamp(2rem, 3.5vw, 3rem);
+ padding: 0;
+}
+
+.videoShowcaseInner {
+ width: min(1480px, calc(100% - 24px));
+ margin: 0 auto;
+}
+
+.videoFrame {
+ width: 100%;
+ overflow: clip;
+ background: transparent;
+ box-shadow: 0 20px 40px rgba(83, 92, 132, 0.12);
+ position: relative;
+}
+
+.playOverlay {
+ position: absolute;
+ inset: 0;
+ z-index: 2;
+ display: grid;
+ place-items: center;
+ background: rgba(0, 0, 0, 0.2);
+ border: 0;
+ padding: 0;
+ cursor: pointer;
+ transition: background 0.25s ease;
+
+ &:hover {
+ background: rgba(0, 0, 0, 0.1);
+ }
+
+ &:hover .playButton {
+ transform: scale(1.08);
+ box-shadow:
+ 0 0 0 12px rgba(255, 255, 255, 0.08),
+ 0 20px 40px rgba(0, 0, 0, 0.3);
+ }
+}
+
+.playButton {
+ width: 5.5rem;
+ height: 5.5rem;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 999px;
+ background: rgba(255, 255, 255, 0.95);
+ box-shadow:
+ 0 0 0 8px rgba(255, 255, 255, 0.1),
+ 0 16px 32px rgba(0, 0, 0, 0.25);
+ transition:
+ transform 0.25s ease,
+ box-shadow 0.25s ease;
+}
+
+.playTriangle {
+ width: 0;
+ height: 0;
+ margin-left: 0.3rem;
+ border-top: 0.85rem solid transparent;
+ border-bottom: 0.85rem solid transparent;
+ border-left: 1.3rem solid #1a1b28;
+}
+
+.heroVideo {
+ width: 100%;
+ aspect-ratio: 16 / 9;
+ display: block;
+ object-fit: cover;
+ background: transparent;
+}
+
+/* ── English overrides ── */
+
+:global(html[lang="en"]) .container {
+ max-width: 1200px;
+}
+
+:global(html[lang="en"]) .titleGroup {
+ gap: 1rem;
+ max-width: 56rem;
+}
+
+:global(html[lang="en"]) .slogan {
+ max-width: 15em;
+ font-size: clamp(2.55rem, 4.2vw, 3.95rem);
+ line-height: 1.08;
+ letter-spacing: -0.038em;
+ text-wrap: pretty;
+}
+
+:global(html[lang="en"]) .overview {
+ max-width: 46rem;
+}
+
+:global(html[lang="en"]) .ownershipNote {
+ max-width: 42rem;
+ font-size: clamp(0.88rem, 0.95vw, 0.98rem);
+}
+
+/* ── Tablet ── */
+
+@media (max-width: 996px) {
+ .container {
+ gap: clamp(1.35rem, 3vw, 1.9rem);
+ }
+
+ :global(html[lang="en"]) .container {
+ gap: clamp(1.35rem, 3vw, 1.9rem);
+ }
+
+ .section {
+ padding-top: 4.5rem;
+ }
+
+ .container {
+ padding: 0 24px;
+ }
+
+ .slogan {
+ max-width: 100%;
+ }
+
+ .overview {
+ max-width: 100%;
+ }
+}
+
+/* ── Mobile ── */
+
+@media (max-width: 768px) {
+ .section {
+ padding: 3.8rem 0 0;
+ }
+
+ .container {
+ padding: 0 20px;
+ }
+
+ .slogan {
+ font-size: clamp(2.18rem, 8.5vw, 3rem);
+ line-height: 1.12;
+ letter-spacing: -0.03em;
+ max-width: 100%;
+ }
+
+ .titleGroup {
+ gap: 0.75rem;
+ }
+
+ .overview {
+ font-size: 1rem;
+ line-height: 1.6;
+ }
+
+ .ownershipNote {
+ max-width: 100%;
+ border-radius: 1rem;
+ padding: 0.55rem 0.85rem 0.58rem;
+ font-size: 0.88rem;
+ line-height: 1.58;
+ }
+
+ .actions {
+ flex-direction: column;
+ align-items: center;
+ }
+
+ .secondaryCta {
+ align-self: center;
+ }
+
+ .videoShowcase {
+ margin-top: clamp(1.5rem, 3vw, 2rem);
+ }
+
+ .playButton {
+ width: 4rem;
+ height: 4rem;
+ }
+
+ .playTriangle {
+ border-top-width: 0.65rem;
+ border-bottom-width: 0.65rem;
+ border-left-width: 1rem;
+ }
+}
+
+/* ── Dark mode ── */
+
+[data-theme="dark"] {
+ .section {
+ box-shadow: inset 0 -1px 0 var(--oomol-divider-subtle);
+ }
+
+ .background {
+ background:
+ radial-gradient(
+ circle at top left,
+ rgba(155, 146, 208, 0.16) 0%,
+ rgba(155, 146, 208, 0) 38%
+ ),
+ radial-gradient(
+ circle at 80% 18%,
+ rgba(132, 138, 208, 0.1) 0%,
+ rgba(132, 138, 208, 0) 26%
+ ),
+ linear-gradient(
+ 180deg,
+ color-mix(
+ in srgb,
+ var(--oomol-bg-container) 78%,
+ var(--oomol-bg-spotlight) 22%
+ )
+ 0%,
+ color-mix(in srgb, var(--oomol-bg-base) 76%, var(--oomol-bg-layout) 24%)
+ 100%
+ );
+ }
+
+ .background::after {
+ background:
+ linear-gradient(rgba(204, 196, 223, 0.07) 1px, transparent 1px),
+ linear-gradient(90deg, rgba(204, 196, 223, 0.07) 1px, transparent 1px);
+ }
+
+ .overview {
+ color: color-mix(in srgb, var(--oomol-text-secondary) 92%, white 8%);
+ }
+
+ .ownershipNote {
+ border-color: color-mix(
+ in srgb,
+ var(--oomol-primary) 18%,
+ var(--oomol-border-default)
+ );
+ background: color-mix(
+ in srgb,
+ var(--oomol-bg-elevated) 74%,
+ var(--oomol-primary-bg) 26%
+ );
+ box-shadow:
+ inset 0 1px 0 rgba(255, 255, 255, 0.06),
+ 0 12px 28px rgba(0, 0, 0, 0.12);
+ color: color-mix(in srgb, var(--oomol-text-secondary) 90%, white 10%);
+ }
+
+ .ownershipHighlight {
+ color: color-mix(in srgb, var(--oomol-primary-text) 86%, white 14%);
+ }
+
+ .secondaryCta {
+ border-color: color-mix(
+ in srgb,
+ var(--oomol-border-default) 72%,
+ var(--oomol-divider)
+ );
+ background: color-mix(
+ in srgb,
+ var(--oomol-bg-elevated) 80%,
+ var(--oomol-bg-container) 20%
+ );
+ box-shadow: 0 14px 28px rgba(0, 0, 0, 0.18);
+
+ &:hover {
+ border-color: color-mix(
+ in srgb,
+ var(--oomol-primary) 24%,
+ var(--oomol-divider)
+ );
+ box-shadow: 0 18px 32px rgba(0, 0, 0, 0.22);
+ }
+ }
+
+ .videoShowcase {
+ background: transparent;
+ }
+
+ .videoFrame {
+ box-shadow: 0 20px 44px rgba(0, 0, 0, 0.22);
+ }
+
+ .playButton {
+ background: rgba(255, 255, 255, 0.9);
+ }
+
+ .playOverlay {
+ background: rgba(0, 0, 0, 0.3);
+
+ &:hover {
+ background: rgba(0, 0, 0, 0.15);
+ }
+ }
+}
diff --git a/src/components/CloudPageIntro/index.tsx b/src/components/CloudPageIntro/index.tsx
new file mode 100644
index 0000000..797373e
--- /dev/null
+++ b/src/components/CloudPageIntro/index.tsx
@@ -0,0 +1,16 @@
+import CloudPageBrandBreak from "@site/src/components/CloudPageBrandBreak";
+import CloudPageFirstScreen from "@site/src/components/CloudPageFirstScreen";
+import CloudPageLinearFlow from "@site/src/components/CloudPageLinearFlow";
+import CloudPagePainPoints from "@site/src/components/CloudPagePainPoints";
+import React from "react";
+
+export default function CloudPageIntro() {
+ return (
+ <>
+
+
+
+
+ >
+ );
+}
diff --git a/src/components/CloudPageLinearFlow/index.tsx b/src/components/CloudPageLinearFlow/index.tsx
new file mode 100644
index 0000000..0a1cba9
--- /dev/null
+++ b/src/components/CloudPageLinearFlow/index.tsx
@@ -0,0 +1,457 @@
+import styles from "./styles.module.scss";
+
+import type { DocusaurusContext } from "@docusaurus/types";
+
+import Link from "@docusaurus/Link";
+import useBaseUrl from "@docusaurus/useBaseUrl";
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import CloudPageDeveloperBenefits from "@site/src/components/CloudPageDeveloperBenefits";
+import { DownloadButton } from "@site/src/components/DownloadButton";
+import { clsx } from "clsx";
+import React from "react";
+
+const homepageMediaUrls = {
+ cli: "https://static.oomol.com/assets/homepage/oomol-oo-cli-en.webm",
+ studio:
+ "https://static.oomol.com/assets/homepage/OOMOL-Studio-gen-use-skils-en.webm",
+ agent: "https://static.oomol.com/assets/homepage/oomol-AI-use-skills-en.webm",
+} as const;
+
+type Copy = {
+ cli: {
+ eyebrow: string;
+ title: string;
+ description: string;
+ media: { title: string; note: string };
+ guide: string;
+ github: string;
+ };
+ studio: {
+ eyebrow: string;
+ title: string;
+ description: string;
+ media: { title: string; note: string };
+ primary: string;
+ secondary: string;
+ };
+ cloud: {
+ eyebrow: string;
+ title: string;
+ description: string;
+ cards: Array<{ title: string; text: string }>;
+ media: { title: string; note: string; pills: string[]; items: string[] };
+ primary: string;
+ secondary: string;
+ };
+ agent: {
+ eyebrow: string;
+ title: string;
+ description: string;
+ media: { title: string; note: string };
+ primary: string;
+ secondary: string;
+ };
+ cta: {
+ title: string;
+ description: string;
+ primary: string;
+ secondary: string;
+ };
+};
+
+type VideoCardProps = {
+ title: string;
+ note: string;
+ src: string;
+};
+
+type ImageCardProps = {
+ title: string;
+ note: string;
+ src: string;
+ pills: string[];
+};
+
+function VideoCard({ title, note, src }: VideoCardProps) {
+ return (
+
+ );
+}
+
+function ImageCard({ title, note, src, pills }: ImageCardProps) {
+ return (
+
+
+

+
+
+
{title}
+
{note}
+
+ {pills.map(pill => (
+
+ {pill}
+
+ ))}
+
+
+
+ );
+}
+
+const zhCopy: Copy = {
+ cli: {
+ eyebrow: "01 / oo-cli",
+ title: "先在 Codex 里装 oo-cli,直接开始用 Skill",
+ description:
+ "oo-cli 是最适合在 Codex 和 Claude Code 里开始使用 Skill 的入口。先把安装文档打开,再用右侧视频直接看真实使用过程。",
+ media: {
+ title: "Codex 演示视频",
+ note: "展示在 Codex 中安装、搜索、查看并运行 Skill。",
+ },
+ guide: "查看安装文档",
+ github: "查看 GitHub",
+ },
+ studio: {
+ eyebrow: "02 / OOMOL Studio",
+ title: "想做自己的 Skill,就用 OOMOL Studio",
+ description:
+ "直接告诉 Agent 你要生成什么,Studio 帮你把 Skill 生成出来,然后在本地完成验证。不会写平台 DSL,也能零门槛开始。",
+ media: {
+ title: "Studio + Agent Vibe 演示视频",
+ note: "展示从提需求到本地验证跑通的过程。",
+ },
+ primary: "安装 OOMOL Studio",
+ secondary: "了解 Studio",
+ },
+ cloud: {
+ eyebrow: "03 / Cloud",
+ title: "发布之后,Cloud 负责运行与交付",
+ description:
+ "Skill 发布之后,Cloud 在后台承接运行、订阅、配置和使用数据。你不需要再围着同一份实现重做一层产品外壳。",
+ cards: [
+ {
+ title: "交付给自己、团队或客户",
+ text: "通过订阅持续交付,而不是停留在本地脚本。",
+ },
+ {
+ title: "在一个后台里配置并观察",
+ text: "Secrets、权限、版本和使用数据集中管理。",
+ },
+ ],
+ media: {
+ title: "Cloud 控制台预览",
+ note: "把订阅、配置和运行数据放到同一个后台里。",
+ pills: ["订阅关系", "运行配置", "使用数据"],
+ items: ["按订阅持续交付与续费", "统一管理 Secrets、权限和版本"],
+ },
+ primary: "了解 Cloud",
+ secondary: "打开 Cloud 控制台",
+ },
+ agent: {
+ eyebrow: "04 / OOMOL AI",
+ title: "不想用 CLI,就直接用 OOMOL AI",
+ description:
+ "它可以理解成 oo-cli 的 GUI 版本。同一套 Skill,不同的消费入口。终端适合工作流,GUI 更适合直观使用。",
+ media: {
+ title: "OOMOL AI 演示视频",
+ note: "展示对话入口和参数入口的体验。",
+ },
+ primary: "体验 OOMOL AI",
+ secondary: "了解 OOMOL AI",
+ },
+ cta: {
+ title: "先用一个 Skill,再决定要不要自己做",
+ description:
+ "先通过 oo-cli 把使用路径跑通。需要自己的 Skill 时,再安装 Studio 生成、验证并发布。",
+ primary: "安装 OOMOL Studio",
+ secondary: "先用 oo-cli",
+ },
+};
+
+const enCopy: Copy = {
+ cli: {
+ eyebrow: "01 / oo-cli",
+ title: "Install oo-cli in Codex and start using skills",
+ description:
+ "oo-cli is the best entry point for using skills inside Codex and Claude Code. Open the install guide first, then use the video on the right to see the real flow.",
+ media: {
+ title: "Codex demo video",
+ note: "Show installing, searching, inspecting, and running a skill in Codex.",
+ },
+ guide: "Open install guide",
+ github: "View GitHub",
+ },
+ studio: {
+ eyebrow: "02 / OOMOL Studio",
+ title: "When you need your own skill, use OOMOL Studio",
+ description:
+ "Tell the agent what skill you want, let Studio generate the first version, then validate it locally. You do not need to learn a platform DSL before you begin.",
+ media: {
+ title: "Studio + Agent Vibe demo video",
+ note: "Show the path from prompting to local validation.",
+ },
+ primary: "Install OOMOL Studio",
+ secondary: "Explore Studio",
+ },
+ cloud: {
+ eyebrow: "03 / Cloud",
+ title: "After release, Cloud runs and delivers the skill",
+ description:
+ "After a skill is released, Cloud handles runtime, subscriptions, configuration, and usage data. You do not need a second product layer around the same implementation.",
+ cards: [
+ {
+ title: "Deliver it to yourself, your team, or customers",
+ text: "Keep the delivery loop running through subscriptions.",
+ },
+ {
+ title: "Configure and observe it in one backend",
+ text: "Keep secrets, access, releases, and usage in one place.",
+ },
+ ],
+ media: {
+ title: "Cloud console preview",
+ note: "Bring subscriptions, settings, and operational data into one backend.",
+ pills: ["Subscriptions", "Runtime settings", "Usage data"],
+ items: [
+ "Deliver and renew through subscriptions",
+ "Manage secrets, access, and releases in one console",
+ ],
+ },
+ primary: "Explore Cloud",
+ secondary: "Open Cloud Console",
+ },
+ agent: {
+ eyebrow: "04 / OOMOL AI",
+ title: "If you do not want CLI, use OOMOL AI",
+ description:
+ "Think of it as the GUI version of oo-cli. It uses the same skills through a more direct interface. CLI is better for workflows; GUI is better for straightforward use.",
+ media: {
+ title: "OOMOL AI demo video",
+ note: "Show both the chat surface and the structured surface.",
+ },
+ primary: "Try OOMOL AI",
+ secondary: "Explore OOMOL AI",
+ },
+ cta: {
+ title: "Use a skill first, then decide whether to build your own",
+ description:
+ "Start by getting the usage path working in oo-cli. When you need your own skill, install Studio to generate, validate, and publish it.",
+ primary: "Install OOMOL Studio",
+ secondary: "Start with oo-cli",
+ },
+};
+
+export default function CloudPageLinearFlow() {
+ const { i18n } = useDocusaurusContext() as unknown as DocusaurusContext & {
+ i18n: { currentLocale: string };
+ };
+ const copy = i18n.currentLocale === "zh-CN" ? zhCopy : enCopy;
+ const downloadButtonTexts =
+ i18n.currentLocale === "zh-CN"
+ ? {
+ macos: "下载适用于 macOS 的版本",
+ macosStable: "下载适用于 macOS 的版本(稳定版)",
+ macosNote: "仅支持 Apple Silicon Mac",
+ windows: "下载适用于 Windows 的版本",
+ windowsStable: "下载适用于 Windows 的版本(稳定版)",
+ windowsSubtitle: "仅支持 x64 版本",
+ }
+ : {
+ macos: "Download for macOS",
+ macosStable: "Download for macOS (Stable)",
+ macosNote: "Apple Silicon Mac only",
+ windows: "Download for Windows",
+ windowsStable: "Download for Windows (Stable)",
+ windowsSubtitle: "only supports x64",
+ };
+ const cloudConsoleImage = useBaseUrl(
+ i18n.currentLocale === "zh-CN"
+ ? "/img/pages/home/cloud-console-zh.png"
+ : "/img/pages/home/cloud-console-en.png"
+ );
+
+ return (
+
+ {/* ── Section: oo-cli ── */}
+
+
+
+
{copy.cli.eyebrow}
+
{copy.cli.title}
+
{copy.cli.description}
+
+
+
+
+
+
+
+
+
+ {/* ── Section: Studio ── */}
+
+
+
+
{copy.studio.eyebrow}
+
{copy.studio.title}
+
+ {copy.studio.description}
+
+
+
+ {copy.studio.primary}
+
+
+ {copy.studio.secondary}
+
+
+
+
+
+
+
+
+
+
+ {/* ── Section: Cloud ── */}
+
+
+
+
{copy.cloud.eyebrow}
+
{copy.cloud.title}
+
+ {copy.cloud.description}
+
+
+ {copy.cloud.cards.map(card => (
+
+ {card.title}
+ {card.text}
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+ {/* ── Section: OOMOL AI ── */}
+
+
+
+
{copy.agent.eyebrow}
+
{copy.agent.title}
+
+ {copy.agent.description}
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* ── CTA ── */}
+
+
+
{copy.cta.title}
+
{copy.cta.description}
+
+
+
+ {copy.cta.secondary}
+
+
+
+
+
+ );
+}
diff --git a/src/components/CloudPageLinearFlow/styles.module.scss b/src/components/CloudPageLinearFlow/styles.module.scss
new file mode 100644
index 0000000..05d8ea5
--- /dev/null
+++ b/src/components/CloudPageLinearFlow/styles.module.scss
@@ -0,0 +1,788 @@
+@use "../../css/custom.scss" as *;
+
+.flow {
+ display: grid;
+}
+
+.section {
+ padding: clamp(4rem, 7vw, 5.8rem) 0;
+}
+
+.cliSection {
+ .copyPanel {
+ gap: 1.05rem;
+ max-width: 36rem;
+ }
+
+ .sectionDescription {
+ max-width: 34rem;
+ }
+}
+
+.sectionTint {
+ background: linear-gradient(
+ 180deg,
+ color-mix(in srgb, var(--oomol-bg-base) 92%, #d7c8af 8%) 0%,
+ color-mix(in srgb, var(--oomol-bg-base) 96%, white 4%) 100%
+ );
+}
+
+.cloudSection {
+ .copyPanel {
+ max-width: 100%;
+ }
+
+ .sectionTitle {
+ max-width: 100%;
+ }
+
+ .sectionDescription {
+ max-width: 33rem;
+ }
+}
+
+.agentSection {
+ background:
+ radial-gradient(
+ circle at top right,
+ rgba(188, 167, 122, 0.12) 0%,
+ rgba(188, 167, 122, 0) 28%
+ ),
+ linear-gradient(
+ 180deg,
+ color-mix(in srgb, var(--oomol-bg-base) 96%, white 4%) 0%,
+ var(--oomol-bg-base) 100%
+ );
+}
+
+.container,
+.ctaInner {
+ width: min(1260px, calc(100% - 48px));
+ margin: 0 auto;
+}
+
+.container {
+ display: grid;
+ grid-template-columns: minmax(0, 0.84fr) minmax(0, 1.16fr);
+ gap: clamp(1.7rem, 3.2vw, 2.8rem);
+ align-items: start;
+}
+
+.copyPanel {
+ display: grid;
+ gap: 1rem;
+ align-content: start;
+ max-width: 40rem;
+}
+
+/* ── Eyebrow badge ── */
+
+.eyebrow {
+ display: inline-flex;
+ width: fit-content;
+ align-items: center;
+ gap: 0.65rem;
+ padding: 0.38rem 0.85rem 0.4rem;
+ border-radius: 999px;
+ border: 1px solid
+ color-mix(in srgb, var(--oomol-primary) 16%, var(--oomol-divider));
+ background: color-mix(in srgb, var(--oomol-primary-bg) 42%, white);
+ font-size: 0.82rem;
+ font-weight: 700;
+ letter-spacing: 0.06em;
+ color: var(--oomol-primary-text);
+}
+
+/* ── Section titles ── */
+
+.sectionTitle,
+.ctaTitle {
+ margin: 0;
+ max-width: 100%;
+ font-family: var(--oomol-font-display);
+ font-size: clamp(2.1rem, 3.5vw, 2.85rem);
+ line-height: 1.12;
+ letter-spacing: -0.04em;
+ text-wrap: pretty;
+ color: var(--oomol-text-primary);
+}
+
+.sectionDescription,
+.ctaDescription {
+ margin: 0;
+ max-width: 40rem;
+ font-size: 1.0625rem;
+ line-height: 1.7;
+ color: var(--oomol-text-secondary);
+}
+
+/* ── Action buttons ── */
+
+.inlineActions {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 1.2rem;
+ padding-top: 0.5rem;
+}
+
+.ctaActions {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: 0.9rem;
+ padding-top: 0.5rem;
+}
+
+.primaryLink,
+.secondaryLink {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.35rem;
+ font-size: 1rem;
+ font-weight: 600;
+ color: var(--oomol-primary-text);
+ text-decoration: none;
+ transition: opacity 0.15s ease;
+
+ &::after {
+ content: "→";
+ transition: transform 0.15s ease;
+ }
+
+ &:hover {
+ text-decoration: none;
+ opacity: 0.78;
+
+ &::after {
+ transform: translateX(3px);
+ }
+ }
+}
+
+.secondaryLink {
+ color: var(--oomol-text-secondary);
+}
+
+.ctaGhost {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ min-width: 12rem;
+ min-height: 52px;
+ padding: 0 1.35rem;
+ border-radius: 999px;
+ font-size: 1rem;
+ font-weight: 600;
+ text-decoration: none;
+ color: rgba(243, 239, 248, 0.94);
+ border: 1px solid rgba(243, 239, 248, 0.14);
+ background: rgba(243, 239, 248, 0.08);
+ transition: opacity 0.15s ease;
+
+ &:hover {
+ text-decoration: none;
+ opacity: 0.82;
+ }
+}
+
+/* ── Media panel + video card ── */
+
+.terminalPanel,
+.mediaPanel,
+.agentMediaCard {
+ border-radius: 1.5rem;
+ border: 1px solid var(--oomol-divider);
+ background: color-mix(in srgb, var(--oomol-bg-elevated) 94%, white 6%);
+ box-shadow: 0 16px 32px rgba(101, 118, 163, 0.1);
+ overflow: hidden;
+}
+
+.mediaPanel,
+.agentMediaCard {
+ min-height: clamp(24rem, 40vw, 33rem);
+}
+
+.videoCard {
+ height: 100%;
+ min-height: inherit;
+ display: grid;
+ grid-template-rows: 1fr auto;
+}
+
+.videoCardInner {
+ position: relative;
+ display: grid;
+ place-items: center;
+ background:
+ radial-gradient(
+ ellipse 70% 50% at 50% 40%,
+ rgba(84, 88, 135, 0.08) 0%,
+ transparent 70%
+ ),
+ linear-gradient(180deg, #1a1b28 0%, #12131d 100%);
+ min-height: 16rem;
+}
+
+.videoCardMedia {
+ min-height: 16rem;
+ background:
+ radial-gradient(
+ ellipse 70% 50% at 50% 40%,
+ rgba(84, 88, 135, 0.08) 0%,
+ transparent 70%
+ ),
+ linear-gradient(180deg, #1a1b28 0%, #12131d 100%);
+}
+
+.videoCardVideo {
+ width: 100%;
+ height: 100%;
+ min-height: inherit;
+ display: block;
+ object-fit: cover;
+ background: transparent;
+}
+
+.imageCardMedia {
+ min-height: 16rem;
+ background: color-mix(in srgb, var(--oomol-bg-container) 88%, black 12%);
+}
+
+.imageCardImage {
+ width: 100%;
+ height: 100%;
+ min-height: inherit;
+ display: block;
+ object-fit: cover;
+}
+
+.videoCardPlay {
+ width: 4.5rem;
+ height: 4.5rem;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 999px;
+ background: rgba(255, 255, 255, 0.92);
+ box-shadow:
+ 0 0 0 6px rgba(255, 255, 255, 0.08),
+ 0 12px 28px rgba(0, 0, 0, 0.25);
+ cursor: pointer;
+ transition: transform 0.2s ease;
+
+ &:hover {
+ transform: scale(1.06);
+ }
+}
+
+.videoCardTriangle {
+ width: 0;
+ height: 0;
+ margin-left: 0.2rem;
+ border-top: 0.7rem solid transparent;
+ border-bottom: 0.7rem solid transparent;
+ border-left: 1.1rem solid #1a1b28;
+}
+
+.videoCardMeta {
+ padding: 1.15rem 1.35rem 1.25rem;
+ border-top: 1px solid var(--oomol-divider);
+ background: color-mix(in srgb, var(--oomol-bg-elevated) 94%, white 6%);
+}
+
+.videoCardTitle {
+ margin: 0;
+ font-size: 1.05rem;
+ font-weight: 700;
+ line-height: 1.35;
+ letter-spacing: -0.01em;
+ color: var(--oomol-text-primary);
+}
+
+.videoCardNote {
+ margin: 0.35rem 0 0;
+ font-size: 0.92rem;
+ line-height: 1.6;
+ color: var(--oomol-text-tertiary);
+}
+
+/* ── Terminal panel (kept) ── */
+
+.terminalPanel {
+ display: grid;
+}
+
+.terminalChrome {
+ display: flex;
+ align-items: center;
+ gap: 0.45rem;
+ padding: 0.82rem 1rem;
+ border-bottom: 1px solid var(--oomol-divider);
+
+ span {
+ width: 0.58rem;
+ height: 0.58rem;
+ border-radius: 999px;
+ background: color-mix(in srgb, var(--oomol-text-secondary) 26%, white);
+ }
+}
+
+.terminalBody {
+ display: grid;
+ gap: 0.82rem;
+ padding: 1.1rem 1.2rem 1.25rem;
+}
+
+.terminalLabel {
+ font-size: 0.9rem;
+ font-weight: 700;
+ letter-spacing: 0.08em;
+ color: var(--oomol-text-tertiary);
+}
+
+.commandBlock {
+ margin: 0;
+ padding: 0;
+ white-space: pre-wrap;
+ font-family:
+ ui-monospace, "SFMono-Regular", "SF Mono", Menlo, Monaco, Consolas,
+ "Liberation Mono", monospace;
+ font-size: 1rem;
+ line-height: 1.9;
+ color: var(--oomol-text-primary);
+}
+
+.commandLine {
+ display: block;
+}
+
+.commentLine {
+ display: block;
+ margin: 0 0 0.3rem;
+ font-size: 0.9rem;
+ line-height: 1.5;
+ color: var(--oomol-text-tertiary);
+}
+
+.prompt {
+ color: var(--oomol-primary-text);
+}
+
+/* ── Placeholder card (Cloud section) ── */
+
+.placeholderCard {
+ height: 100%;
+ min-height: inherit;
+ display: grid;
+ align-content: start;
+ gap: 1.1rem;
+ padding: clamp(1.55rem, 3vw, 2.4rem);
+ padding-top: clamp(1.8rem, 3vw, 2.4rem);
+ position: relative;
+ overflow: hidden;
+ background:
+ linear-gradient(rgba(97, 113, 145, 0.06) 1px, transparent 1px),
+ linear-gradient(90deg, rgba(97, 113, 145, 0.06) 1px, transparent 1px),
+ linear-gradient(
+ 180deg,
+ color-mix(in srgb, var(--oomol-bg-elevated) 90%, white 10%) 0%,
+ color-mix(in srgb, var(--oomol-bg-container) 82%, white 18%) 100%
+ );
+ background-size:
+ 3.25rem 3.25rem,
+ 3.25rem 3.25rem,
+ auto;
+}
+
+.placeholderTitle {
+ margin: 0;
+ max-width: 18ch;
+ font-family: var(--oomol-font-display);
+ font-size: clamp(1.42rem, 1.9vw, 1.72rem);
+ line-height: 1.12;
+ letter-spacing: -0.03em;
+ color: var(--oomol-text-primary);
+ position: relative;
+ z-index: 1;
+}
+
+.placeholderNote {
+ margin: 0;
+ max-width: 34rem;
+ font-size: 1rem;
+ line-height: 1.66;
+ color: var(--oomol-text-secondary);
+ position: relative;
+ z-index: 1;
+}
+
+/* ── Cloud cards ── */
+
+.cloudCardStack {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 0.75rem;
+}
+
+.cloudCard {
+ padding: 1.1rem 1.1rem 1.15rem;
+ border-radius: 1rem;
+ border: 1px solid var(--oomol-divider);
+ background: color-mix(in srgb, var(--oomol-bg-elevated) 92%, white 8%);
+ box-shadow: 0 4px 12px rgba(101, 118, 163, 0.06);
+ transition:
+ box-shadow 0.2s ease,
+ border-color 0.2s ease;
+
+ &:hover {
+ border-color: color-mix(
+ in srgb,
+ var(--oomol-primary) 18%,
+ var(--oomol-divider)
+ );
+ box-shadow: 0 8px 20px rgba(101, 118, 163, 0.1);
+ }
+}
+
+.cloudTitle {
+ margin: 0;
+ font-size: 1.05rem;
+ line-height: 1.34;
+ letter-spacing: -0.01em;
+ color: var(--oomol-text-primary);
+}
+
+.cloudText {
+ margin: 0.55rem 0 0;
+ font-size: 0.96rem;
+ line-height: 1.62;
+ color: var(--oomol-text-secondary);
+}
+
+.cloudMetaRow {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.45rem;
+ margin-top: 0.25rem;
+}
+
+.cloudMetaPill {
+ display: inline-flex;
+ align-items: center;
+ min-height: 1.65rem;
+ padding: 0 0.65rem;
+ border-radius: 999px;
+ border: 1px solid color-mix(in srgb, var(--oomol-border-default) 82%, white);
+ background: color-mix(in srgb, var(--oomol-bg-elevated) 94%, white 6%);
+ font-size: 0.78rem;
+ font-weight: 700;
+ letter-spacing: 0.01em;
+ color: var(--oomol-text-tertiary);
+}
+
+/* ── CTA section ── */
+
+.ctaSection {
+ padding: clamp(4rem, 8vw, 5.8rem) 0 clamp(3rem, 6vw, 4.4rem);
+}
+
+.ctaInner {
+ display: grid;
+ gap: 1.1rem;
+ padding: clamp(2.1rem, 4.2vw, 3rem);
+ border-radius: 1.75rem;
+ border: 1px solid rgba(214, 221, 236, 0.12);
+ background:
+ radial-gradient(
+ circle at top left,
+ rgba(132, 138, 208, 0.18) 0%,
+ rgba(132, 138, 208, 0) 32%
+ ),
+ linear-gradient(180deg, #1a1b28 0%, #12131d 100%);
+ box-shadow: 0 18px 36px rgba(31, 28, 53, 0.22);
+}
+
+.ctaTitle {
+ max-width: 14ch;
+ color: rgba(243, 239, 248, 0.98);
+}
+
+.ctaDescription {
+ max-width: 42rem;
+ color: rgba(221, 214, 231, 0.8);
+}
+
+/* ── English overrides ── */
+
+:global(html[lang="en"]) .sectionTitle,
+:global(html[lang="en"]) .ctaTitle {
+ max-width: 100%;
+ font-size: clamp(2rem, 3.2vw, 2.85rem);
+ line-height: 1.1;
+}
+
+/* ── Tablet ── */
+
+@media (max-width: 996px) {
+ .container {
+ grid-template-columns: 1fr;
+ }
+
+ .cliSection {
+ .container {
+ grid-template-columns: 1fr;
+ }
+
+ .copyPanel {
+ max-width: 100%;
+ }
+
+ .terminalPanel {
+ max-width: 100%;
+ }
+ }
+
+ .cloudSection {
+ .container {
+ grid-template-columns: 1fr;
+ }
+ }
+
+ .cloudCardStack {
+ grid-template-columns: 1fr;
+ }
+}
+
+/* ── Mobile ── */
+
+@media (max-width: 768px) {
+ .container,
+ .ctaInner {
+ width: min(100%, calc(100% - 40px));
+ }
+
+ .section {
+ padding: 3rem 0;
+ }
+
+ .sectionTitle,
+ .ctaTitle {
+ max-width: 100%;
+ text-wrap: pretty;
+ }
+
+ .sectionDescription,
+ .ctaDescription {
+ font-size: 0.98rem;
+ line-height: 1.7;
+ }
+
+ .videoCardInner {
+ min-height: 12rem;
+ }
+
+ .videoCardMedia {
+ min-height: 12rem;
+ }
+
+ .imageCardMedia {
+ min-height: 12rem;
+ }
+
+ .videoCardPlay {
+ width: 3.5rem;
+ height: 3.5rem;
+ }
+
+ .videoCardTriangle {
+ border-top-width: 0.55rem;
+ border-bottom-width: 0.55rem;
+ border-left-width: 0.85rem;
+ }
+}
+
+/* ── Dark mode ── */
+
+[data-theme="dark"] {
+ .eyebrow {
+ border-color: color-mix(
+ in srgb,
+ var(--oomol-primary) 24%,
+ var(--oomol-divider)
+ );
+ background: color-mix(
+ in srgb,
+ var(--oomol-bg-elevated) 78%,
+ var(--oomol-primary-bg) 22%
+ );
+ }
+
+ .sectionTint {
+ background: linear-gradient(
+ 180deg,
+ color-mix(in srgb, var(--oomol-bg-base) 90%, #41372d 10%) 0%,
+ color-mix(in srgb, var(--oomol-bg-base) 96%, black 4%) 100%
+ );
+ }
+
+ .agentSection {
+ background:
+ radial-gradient(
+ circle at top right,
+ rgba(188, 167, 122, 0.08) 0%,
+ rgba(188, 167, 122, 0) 28%
+ ),
+ linear-gradient(
+ 180deg,
+ color-mix(in srgb, var(--oomol-bg-base) 96%, black 4%) 0%,
+ var(--oomol-bg-base) 100%
+ );
+ }
+
+ .stepCard,
+ .cloudCard,
+ .terminalPanel,
+ .mediaPanel,
+ .agentMediaCard {
+ border-color: color-mix(
+ in srgb,
+ var(--oomol-border-default) 72%,
+ var(--oomol-divider)
+ );
+ background: color-mix(
+ in srgb,
+ var(--oomol-bg-elevated) 86%,
+ var(--oomol-bg-container) 14%
+ );
+ }
+
+ .videoCardMeta {
+ border-top-color: color-mix(
+ in srgb,
+ var(--oomol-border-default) 68%,
+ var(--oomol-divider)
+ );
+ background: color-mix(
+ in srgb,
+ var(--oomol-bg-elevated) 86%,
+ var(--oomol-bg-container) 14%
+ );
+ }
+
+ .videoCardInner {
+ background:
+ radial-gradient(
+ ellipse 70% 50% at 50% 40%,
+ rgba(132, 138, 208, 0.08) 0%,
+ transparent 70%
+ ),
+ linear-gradient(
+ 180deg,
+ color-mix(
+ in srgb,
+ var(--oomol-bg-container) 82%,
+ var(--oomol-bg-spotlight) 18%
+ )
+ 0%,
+ color-mix(in srgb, var(--oomol-bg-elevated) 88%, black 12%) 100%
+ );
+ }
+
+ .videoCardMedia {
+ background:
+ radial-gradient(
+ ellipse 70% 50% at 50% 40%,
+ rgba(132, 138, 208, 0.08) 0%,
+ transparent 70%
+ ),
+ linear-gradient(
+ 180deg,
+ color-mix(
+ in srgb,
+ var(--oomol-bg-container) 82%,
+ var(--oomol-bg-spotlight) 18%
+ )
+ 0%,
+ color-mix(in srgb, var(--oomol-bg-elevated) 88%, black 12%) 100%
+ );
+ }
+
+ .imageCardMedia {
+ background: color-mix(
+ in srgb,
+ var(--oomol-bg-container) 72%,
+ var(--oomol-bg-elevated) 28%
+ );
+ }
+
+ .videoCardPlay {
+ background: rgba(255, 255, 255, 0.88);
+ }
+
+ .inlineNote {
+ border-color: color-mix(
+ in srgb,
+ var(--oomol-primary) 22%,
+ var(--oomol-divider)
+ );
+ background: color-mix(
+ in srgb,
+ var(--oomol-bg-elevated) 78%,
+ var(--oomol-primary-bg) 22%
+ );
+ color: color-mix(in srgb, var(--oomol-text-secondary) 92%, white 8%);
+ }
+
+ .cloudMetaPill {
+ border-color: color-mix(
+ in srgb,
+ var(--oomol-border-default) 72%,
+ var(--oomol-divider)
+ );
+ background: color-mix(
+ in srgb,
+ var(--oomol-bg-elevated) 82%,
+ var(--oomol-bg-container) 18%
+ );
+ }
+
+ .placeholderCard {
+ background:
+ linear-gradient(rgba(188, 194, 224, 0.07) 1px, transparent 1px),
+ linear-gradient(90deg, rgba(188, 194, 224, 0.07) 1px, transparent 1px),
+ linear-gradient(
+ 180deg,
+ color-mix(in srgb, var(--oomol-bg-elevated) 88%, black 12%) 0%,
+ color-mix(in srgb, var(--oomol-bg-container) 82%, black 18%) 100%
+ );
+ background-size:
+ 3.25rem 3.25rem,
+ 3.25rem 3.25rem,
+ auto;
+ }
+
+ .ctaInner {
+ border-color: color-mix(
+ in srgb,
+ var(--oomol-primary-border) 44%,
+ var(--oomol-divider)
+ );
+ background:
+ radial-gradient(
+ circle at top left,
+ rgba(132, 138, 208, 0.16) 0%,
+ rgba(132, 138, 208, 0) 34%
+ ),
+ linear-gradient(
+ 180deg,
+ color-mix(
+ in srgb,
+ var(--oomol-bg-container) 82%,
+ var(--oomol-bg-spotlight) 18%
+ )
+ 0%,
+ color-mix(in srgb, var(--oomol-bg-elevated) 88%, black 12%) 100%
+ );
+ }
+}
diff --git a/src/components/CloudPagePainPoints/index.tsx b/src/components/CloudPagePainPoints/index.tsx
new file mode 100644
index 0000000..dfb504b
--- /dev/null
+++ b/src/components/CloudPagePainPoints/index.tsx
@@ -0,0 +1,110 @@
+import styles from "./styles.module.scss";
+
+import type { DocusaurusContext } from "@docusaurus/types";
+
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
+import React from "react";
+
+const zhCopy = {
+ badge: "为什么要上云",
+ title: "你写的能力,不该在交付时失控",
+ card1: {
+ title: "本地执行 = 代码泄露",
+ description:
+ "现在 Codex、Claude Code 要调用你的能力,就得把代码拉到本地跑。你的算法、商业逻辑、调用链路,全部暴露给使用方。",
+ solution:
+ "Cloud Skill 让能力在云端执行,用户只调用接口,代码始终在你手里。",
+ },
+ card2: {
+ title: "想交付一个 Skill,却要搭一整套后端",
+ description:
+ "服务器、扩缩容、计费系统、订阅管理、Secrets 配置、使用数据……写核心逻辑只占 20%,剩下 80% 都在搭基础设施。",
+ solution: "Cloud 把运行时、订阅、配置和数据全部承接,你只管写核心逻辑。",
+ },
+};
+
+const enCopy = {
+ badge: "Why go cloud",
+ title: "Your code shouldn't leak when you deliver it",
+ card1: {
+ title: "Local execution = code exposure",
+ description:
+ "Today, when Codex or Claude Code calls your skill, it pulls the code to local and runs it there. Your algorithms, business logic, and call chains are fully exposed to the consumer.",
+ solution:
+ "A cloud skill runs in the cloud. Users call the interface; your code stays with you.",
+ },
+ card2: {
+ title: "You just want to deliver a skill, not build an entire backend",
+ description:
+ "Servers, auto-scaling, billing, subscription management, secrets, usage analytics… Writing the core logic is 20% of the work. The other 80% is delivery infrastructure.",
+ solution:
+ "Cloud handles runtime, subscriptions, configuration, and data. You just write the logic.",
+ },
+};
+
+export default function CloudPagePainPoints() {
+ const { i18n } = useDocusaurusContext() as unknown as DocusaurusContext & {
+ i18n: { currentLocale: string };
+ };
+ const copy = i18n.currentLocale === "zh-CN" ? zhCopy : enCopy;
+
+ return (
+
+
+
+
{copy.badge}
+
{copy.title}
+
+
+
+
+
+ {copy.card1.title}
+ {copy.card1.description}
+
+
{copy.card1.solution}
+
+
+
+
+
+ {copy.card2.title}
+ {copy.card2.description}
+
+
{copy.card2.solution}
+
+
+
+
+
+ );
+}
diff --git a/src/components/CloudPagePainPoints/styles.module.scss b/src/components/CloudPagePainPoints/styles.module.scss
new file mode 100644
index 0000000..127f3c1
--- /dev/null
+++ b/src/components/CloudPagePainPoints/styles.module.scss
@@ -0,0 +1,224 @@
+@use "../../css/custom.scss" as *;
+
+.section {
+ padding: clamp(4rem, 8vw, 6rem) 0;
+ position: relative;
+}
+
+.container {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 0 24px;
+ display: grid;
+ gap: clamp(1.6rem, 3.5vw, 2.4rem);
+}
+
+.header {
+ display: grid;
+ gap: 0.8rem;
+ text-align: center;
+ justify-items: center;
+}
+
+.badge {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.55rem;
+ font-size: 0.74rem;
+ font-weight: 700;
+ letter-spacing: 0.14em;
+ text-transform: uppercase;
+ color: var(--oomol-text-secondary);
+
+ &::before {
+ content: "";
+ width: 0.75rem;
+ height: 1px;
+ background: var(--oomol-primary);
+ }
+}
+
+.title {
+ margin: 0;
+ max-width: 20ch;
+ font-family: var(--oomol-font-display);
+ font-size: clamp(2.3rem, 4.2vw, 3.6rem);
+ line-height: 1.08;
+ letter-spacing: -0.04em;
+ color: var(--oomol-text-primary);
+}
+
+.grid {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 1.1rem;
+ max-width: 960px;
+ margin: 0 auto;
+}
+
+.card {
+ display: flex;
+ flex-direction: column;
+ gap: 0.9rem;
+ padding: 1.6rem 1.5rem 1.8rem;
+ border: 1px solid var(--oomol-divider);
+ border-radius: 1.7rem;
+ background: var(--oomol-surface-float);
+ box-shadow: var(--oomol-shadow-sm);
+ position: relative;
+ overflow: hidden;
+
+ &::before {
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 1.4rem;
+ right: 1.4rem;
+ height: 2px;
+ border-radius: 999px;
+ background: linear-gradient(
+ 90deg,
+ color-mix(in srgb, var(--oomol-text-secondary) 50%, transparent) 0%,
+ color-mix(in srgb, var(--oomol-text-secondary) 10%, transparent) 100%
+ );
+ }
+}
+
+.cardIcon {
+ width: 2.6rem;
+ height: 2.6rem;
+ display: grid;
+ place-items: center;
+ border-radius: 0.75rem;
+ background: color-mix(
+ in srgb,
+ var(--oomol-primary-bg) 50%,
+ var(--oomol-bg-elevated) 50%
+ );
+ color: var(--oomol-primary);
+}
+
+.cardTitle {
+ margin: 0;
+ font-size: 1.4rem;
+ line-height: 1.28;
+ font-weight: 650;
+ color: var(--oomol-text-primary);
+}
+
+.cardDescription {
+ margin: 0;
+ font-size: 1rem;
+ line-height: 1.75;
+ color: var(--oomol-text-secondary);
+}
+
+.solution {
+ margin-top: 0.25rem;
+ padding-left: 0.9rem;
+ border-left: 2px solid var(--oomol-primary);
+}
+
+.solutionText {
+ margin: 0;
+ font-size: 0.95rem;
+ line-height: 1.7;
+ color: var(--oomol-primary-text);
+ font-weight: 500;
+}
+
+/* ── Dark mode ── */
+
+[data-theme="dark"] {
+ .card {
+ border-color: color-mix(
+ in srgb,
+ var(--oomol-border-default) 72%,
+ var(--oomol-divider)
+ );
+ background: linear-gradient(
+ 180deg,
+ color-mix(
+ in srgb,
+ var(--oomol-bg-container) 84%,
+ var(--oomol-bg-elevated) 16%
+ )
+ 0%,
+ color-mix(in srgb, var(--oomol-bg-elevated) 88%, black 12%) 100%
+ );
+ box-shadow: var(--oomol-shadow-md);
+ }
+
+ .cardIcon {
+ background: color-mix(
+ in srgb,
+ var(--oomol-primary-bg) 40%,
+ var(--oomol-bg-container) 60%
+ );
+ }
+
+ .solution {
+ border-left-color: color-mix(
+ in srgb,
+ var(--oomol-primary) 72%,
+ var(--oomol-primary-border) 28%
+ );
+ }
+}
+
+/* ── English overrides ── */
+
+:global(html[lang="en"]) .title {
+ max-width: 28ch;
+ font-size: clamp(2.1rem, 3.8vw, 3.2rem);
+ line-height: 1.1;
+}
+
+:global(html[lang="en"]) .cardTitle {
+ font-size: 1.28rem;
+ line-height: 1.32;
+}
+
+/* ── Mobile ── */
+
+@media (max-width: 768px) {
+ .section {
+ padding: 2.8rem 0 2.4rem;
+ }
+
+ .container {
+ padding: 0 20px;
+ gap: 1.2rem;
+ }
+
+ .title {
+ max-width: 100%;
+ font-size: clamp(2rem, 8.5vw, 2.8rem);
+ line-height: 1.1;
+ letter-spacing: -0.03em;
+ }
+
+ .grid {
+ grid-template-columns: 1fr;
+ gap: 1rem;
+ }
+
+ .card {
+ padding: 1.2rem 1.15rem 1.4rem;
+ border-radius: 1.35rem;
+ gap: 0.8rem;
+ }
+
+ .cardTitle {
+ font-size: 1.2rem;
+ }
+
+ .cardDescription {
+ font-size: 0.94rem;
+ line-height: 1.65;
+ }
+
+ .solutionText {
+ font-size: 0.9rem;
+ }
+}
diff --git a/src/components/DownloadButton/index.tsx b/src/components/DownloadButton/index.tsx
index 286b112..f73e873 100644
--- a/src/components/DownloadButton/index.tsx
+++ b/src/components/DownloadButton/index.tsx
@@ -30,6 +30,14 @@ export interface DownloadButtonProps {
centered?: boolean;
showNote?: boolean;
noteTone?: "default" | "inverse";
+ texts?: Partial<{
+ macos: string;
+ macosStable: string;
+ macosNote: string;
+ windows: string;
+ windowsStable: string;
+ windowsSubtitle: string;
+ }>;
}
export const DownloadButton = ({
@@ -37,6 +45,7 @@ export const DownloadButton = ({
centered,
showNote = true,
noteTone = "default",
+ texts,
}: DownloadButtonProps) => {
const downloadIcon = (
@@ -57,6 +66,36 @@ export const DownloadButton = ({
noteTone === "inverse"
? `${styles.windowsSubtitle} ${styles.inverseNote}`
: styles.windowsSubtitle;
+ const macosLabel =
+ texts?.macos ??
+ translate({
+ message: "HOME.FirstScreen.download-macos",
+ });
+ const macosStableLabel =
+ texts?.macosStable ??
+ translate({
+ message: "HOME.FirstScreen.download-macos-stable",
+ });
+ const macosNote =
+ texts?.macosNote ??
+ translate({
+ message: "HOME.FirstScreen.download-macos-chip-note",
+ });
+ const windowsLabel =
+ texts?.windows ??
+ translate({
+ message: "HOME.FirstScreen.download-windows",
+ });
+ const windowsStableLabel =
+ texts?.windowsStable ??
+ translate({
+ message: "HOME.FirstScreen.download-windows-stable",
+ });
+ const windowsSubtitle =
+ texts?.windowsSubtitle ??
+ translate({
+ message: "HOME.FirstScreen.download-windows-subtitle",
+ });
return (
- {showNote ? (
-
- {translate({
- message: "HOME.FirstScreen.download-macos-chip-note",
- })}
-
- ) : null}
+ {showNote ? {macosNote} : null}
}
>
@@ -94,19 +123,11 @@ export const DownloadButton = ({
>
{downloadIcon}
- {translate({
- message: stableTag
- ? "HOME.FirstScreen.download-macos-stable"
- : "HOME.FirstScreen.download-macos",
- })}
+ {stableTag ? macosStableLabel : macosLabel}
{showNote ? (
-
- {translate({
- message: "HOME.FirstScreen.download-macos-chip-note",
- })}
-
+ {macosNote}
) : null}
) : (
@@ -120,18 +141,12 @@ export const DownloadButton = ({
>
{downloadIcon}
- {translate({
- message: stableTag
- ? "HOME.FirstScreen.download-windows-stable"
- : "HOME.FirstScreen.download-windows",
- })}
+ {stableTag ? windowsStableLabel : windowsLabel}
{showNote ? (
- {translate({
- message: "HOME.FirstScreen.download-windows-subtitle",
- })}
+ {windowsSubtitle}
) : null}
diff --git a/src/components/GetStartedPrompt/index.tsx b/src/components/GetStartedPrompt/index.tsx
index 12a96e5..377e536 100644
--- a/src/components/GetStartedPrompt/index.tsx
+++ b/src/components/GetStartedPrompt/index.tsx
@@ -22,7 +22,10 @@ export const GetStartedPrompt = () => {
-
+
{translate({ message: "HOME.Downloads.cli.action.guide" })}
diff --git a/src/components/HomePagePricing/style.module.scss b/src/components/HomePagePricing/style.module.scss
index 2d4afca..ee3695a 100644
--- a/src/components/HomePagePricing/style.module.scss
+++ b/src/components/HomePagePricing/style.module.scss
@@ -180,7 +180,11 @@
border-radius: 8px;
color: var(--oomol-text-primary);
cursor: pointer;
- transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease, transform 0.3s ease;
+ transition:
+ background-color 0.3s ease,
+ color 0.3s ease,
+ border-color 0.3s ease,
+ transform 0.3s ease;
&:hover {
background-color: var(--oomol-primary);
diff --git a/src/components/HomepageBrandBreak/index.tsx b/src/components/HomepageBrandBreak/index.tsx
index e434703..ca602eb 100644
--- a/src/components/HomepageBrandBreak/index.tsx
+++ b/src/components/HomepageBrandBreak/index.tsx
@@ -1,8 +1,8 @@
import styles from "./styles.module.scss";
-import { translate } from "@docusaurus/Translate";
-import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
import type { DocusaurusContext } from "@docusaurus/types";
+
+import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
import React from "react";
export default function HomepageBrandBreak() {
@@ -25,7 +25,16 @@ export default function HomepageBrandBreak() {