This is an automated email from the ASF dual-hosted git repository.

PsiACE pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal.git


The following commit(s) were added to refs/heads/main by this push:
     new 32a67d2bb feat(website): introduce a design system and rebuild the 
homepage (#7638)
32a67d2bb is described below

commit 32a67d2bb30d007d5fc790dfa56f05b629625617
Author: Xuanwo <[email protected]>
AuthorDate: Sat May 30 06:13:54 2026 +0800

    feat(website): introduce a design system and rebuild the homepage (#7638)
    
    * feat(website): add design system and landing page
    
    Add a token-based design system in src/css/custom.css (color,
    typography, spacing, elevation, motion, and the OpenDAL bar motif),
    projected onto Infima so docs and blog inherit it, and document it in
    DESIGN_SYSTEM.md.
    
    Add a developer-focused landing page at "/" (hero, adopters, value
    props, the Operator contract, services, bindings, layers, community,
    CTA). Move docs from "/" to "/docs/" with backward-compatible redirects
    for legacy URLs, and enable the light/dark theme toggle.
    
    * feat(website): add adopter logo wall
    
    Add a "Used by" logo wall of real OpenDAL adopters taken from the core
    and binding users lists, ordered by GitHub star count and rendered as
    grayscale org logos (self-hosted under static/img/users/) that colorize
    on hover. The wall shows a responsive count by viewport (4/6/8) and an
    "+ add your logo" link to the users list.
    
    Also show the Java quickstart dependency as a plain Maven coordinate
    instead of a Gradle-specific implementation(...) line.
    
    * feat(website): replace operator verb table with a capabilities section
    
    Swap the abstract Operator verb table for a Capabilities section that
    groups what OpenDAL can do — Read, Write, Manage — drawn from the core
    features: byte-range and concurrent reads, adjacent-range merge, resumable
    reads, multipart and concurrent uploads, append, conditional writes,
    listing, batch delete, server-side copy/rename and presigned URLs.
    
    Also drop the duplicate hero code window and the services caption.
    
    * feat(website): add interactive capabilities explorer and used-by wall
    
    * feat(website): make layers an interactive explorer and polish landing 
sections
---
 website/DESIGN_SYSTEM.md                         | 230 +++++++
 website/docusaurus.config.js                     |  23 +-
 website/src/components/landing/CodeTabs.jsx      | 112 ++++
 website/src/components/landing/data.js           | 443 ++++++++++++++
 website/src/components/landing/sections.jsx      | 415 +++++++++++++
 website/src/components/landing/styles.module.css | 744 +++++++++++++++++++++++
 website/src/css/custom.css                       | 446 ++++++++++++--
 website/src/pages/index.jsx                      |  51 ++
 website/static/img/users/cratedb.png             | Bin 0 -> 711 bytes
 website/static/img/users/daft.png                | Bin 0 -> 6745 bytes
 website/static/img/users/databend.png            | Bin 0 -> 3579 bytes
 website/static/img/users/datafusion-comet.png    | Bin 0 -> 7018 bytes
 website/static/img/users/dify.png                | Bin 0 -> 2218 bytes
 website/static/img/users/gravitino.png           | Bin 0 -> 7018 bytes
 website/static/img/users/greptimedb.png          | Bin 0 -> 6539 bytes
 website/static/img/users/hasura.png              | Bin 0 -> 5428 bytes
 website/static/img/users/iceberg-rust.png        | Bin 0 -> 7018 bytes
 website/static/img/users/kubeflow-trainer.png    | Bin 0 -> 9460 bytes
 website/static/img/users/lance.png               | Bin 0 -> 3328 bytes
 website/static/img/users/llamaindex.png          | Bin 0 -> 6890 bytes
 website/static/img/users/lnx.png                 | Bin 0 -> 1895 bytes
 website/static/img/users/loco.png                | Bin 0 -> 5092 bytes
 website/static/img/users/octobase.png            | Bin 0 -> 11292 bytes
 website/static/img/users/openraft.png            | Bin 0 -> 3579 bytes
 website/static/img/users/pants.png               | Bin 0 -> 2676 bytes
 website/static/img/users/pathway.png             | Bin 0 -> 20187 bytes
 website/static/img/users/questdb.png             | Bin 0 -> 3767 bytes
 website/static/img/users/quickwit.png            | Bin 0 -> 3667 bytes
 website/static/img/users/ragflow.png             | Bin 0 -> 9257 bytes
 website/static/img/users/risingwave.png          | Bin 0 -> 5562 bytes
 website/static/img/users/robustmq.png            | Bin 0 -> 1540 bytes
 website/static/img/users/rustic.png              | Bin 0 -> 12204 bytes
 website/static/img/users/sccache.png             | Bin 0 -> 1356 bytes
 website/static/img/users/seatunnel.png           | Bin 0 -> 7018 bytes
 website/static/img/users/slatedb.png             | Bin 0 -> 4332 bytes
 website/static/img/users/spiceai.png             | Bin 0 -> 4518 bytes
 website/static/img/users/vaultwarden.png         | Bin 0 -> 18431 bytes
 website/static/img/users/vector.png              | Bin 0 -> 8211 bytes
 website/static/img/users/walrus.png              | Bin 0 -> 7880 bytes
 website/static/img/users/wrenai.png              | Bin 0 -> 2330 bytes
 website/static/img/users/zino.png                | Bin 0 -> 4517 bytes
 41 files changed, 2403 insertions(+), 61 deletions(-)

diff --git a/website/DESIGN_SYSTEM.md b/website/DESIGN_SYSTEM.md
new file mode 100644
index 000000000..e4636087f
--- /dev/null
+++ b/website/DESIGN_SYSTEM.md
@@ -0,0 +1,230 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+# OpenDAL Design System
+
+> **One Layer, All Storage.** A precise, engineering-grade visual language for
+> Apache OpenDAL™ — built to feel as dependable, fast and composable as the
+> library itself.
+
+This document is the source of truth for OpenDAL's web visual language. The
+landing page (`src/pages/index.jsx`) is its first full application; docs and
+blog inherit it through Infima variable mapping.
+
+---
+
+## 1. Design principles
+
+The visual system is a direct translation of OpenDAL's engineering values.
+
+| Library value             | Visual expression                                
                            |
+| ------------------------- | 
---------------------------------------------------------------------------- |
+| **One Layer, All Storage**| One accent, one type voice, one grid — 
convergence over decoration.          |
+| **Solid Foundation**      | Hairline structure, precise alignment, 
restraint. Nothing is decorative-only.|
+| **Fast Access (zero-cost)**| System fonts, no web-font requests, CSS-only 
motion. The page costs nothing it doesn't need. |
+| **Object Storage First**  | Content-first layout; code and capabilities 
lead, ornament follows.          |
+| **Extensible Architecture**| Tokens compose; components are presentational 
and reusable.                 |
+
+Operating posture: **engineering-minimal, light-first** (dark mode is a
+first-class, fully designed peer), near-monochrome **ink** with a single
+**precise-blue** accent, and the signature solid **bar** lifted from the
+OpenDAL wordmark.
+
+---
+
+## 2. Where the system lives
+
+| Concern                         | Location                                  |
+| ------------------------------- | ----------------------------------------- |
+| Tokens + Infima mapping + motif | `src/css/custom.css`                      |
+| Landing sections                | `src/components/landing/sections.jsx`     |
+| Code window / language tabs     | `src/components/landing/CodeTabs.jsx`     |
+| Landing styles                  | `src/components/landing/styles.module.css`|
+| Content model (copy, catalogs)  | `src/components/landing/data.js`          |
+
+All design decisions are encoded as CSS custom properties prefixed `--odl-*`.
+Components never hardcode raw hex; they consume tokens.
+
+---
+
+## 3. Color
+
+### 3.1 Primitives
+
+**Ink** — a cool, neutral near-black → white ramp (the monochrome backbone):
+
+`--odl-ink-{0,50,100,150,200,300,400,500,600,700,800,850,900,950}`
+from `#ffffff` to `#0a0d11`.
+
+**Precise blue** — the single brand accent:
+
+`--odl-blue-{50…900}` from `#edf3ff` to `#163172`; `--odl-blue-600 #1e54e0` is
+the canonical light-mode accent.
+
+Functional signals (`--odl-green/amber/red-*`) exist mostly so inherited docs
+UI (admonitions, etc.) stay on-system. They are intentionally muted.
+
+### 3.2 Semantic roles (theme-aware)
+
+Components consume **semantic** tokens, not primitives:
+
+| Token                 | Light                | Dark              | Use       
                   |
+| --------------------- | -------------------- | ----------------- | 
---------------------------- |
+| `--odl-bg`            | `ink-0`              | `#0a0d11`         | Page 
background              |
+| `--odl-bg-subtle`     | `ink-50`             | `#0e1218`         | 
Alternating section bands    |
+| `--odl-surface`       | `ink-0`              | `#11161c`         | Cards, 
code window           |
+| `--odl-fg`            | `ink-900`            | `#e7ebf0`         | Body text 
                   |
+| `--odl-fg-muted`      | `ink-600`            | `#9aa6b3`         | Secondary 
text               |
+| `--odl-border`        | `ink-200`            | `#242c35`         | 
Hairlines, dividers          |
+| `--odl-bar`           | `ink-950`            | `#f6f8fa`         | The bar 
motif                |
+| `--odl-accent`        | `blue-600`           | `blue-300`        | Links, 
emphasis              |
+| `--odl-action-bg`     | `blue-600`           | `blue-500`        | Solid CTA 
background         |
+
+### 3.3 Rules
+
+- **Black/white leads, blue accents.** Blue is for interaction, emphasis and
+  code highlight — never large fills (except the solid CTA).
+- **Contrast:** body and accent text meet WCAG AA (≥ 4.5:1) in both themes;
+  white-on-`action-bg` passes for buttons. Dark mode lifts the accent to a
+  lighter blue rather than inverting it.
+- **Never rely on color alone** — pair with the bar, an icon, or a label.
+
+---
+
+## 4. Typography
+
+### 4.1 Stacks & rationale
+
+```
+--odl-font-sans: system-ui, -apple-system, "Segoe UI", Roboto, …
+--odl-font-mono: ui-monospace, "SF Mono", "Cascadia Code", "JetBrains Mono", …
+```
+
+System stacks are a **deliberate** choice, not a fallback: zero third-party
+requests (ASF privacy-friendly), zero layout shift, instant and globally
+consistent rendering (OpenDAL has a large global user base). The wordmark
+already carries the brand letterforms.
+
+**Monospace is promoted to a brand voice.** It marks anything structural or
+technical — eyebrows/kickers, section indices, statistics, service names, code.
+This gives the minimal system its engineering character without a custom font.
+
+> To adopt **IBM Plex** instead: self-host via `@fontsource/ibm-plex-sans` and
+> `@fontsource/ibm-plex-mono`, `@import` the weights in `custom.css`, and set
+> `--odl-font-sans`/`--odl-font-mono` accordingly. The rest of the system needs
+> no changes.
+
+### 4.2 Scale
+
+`--odl-text-2xs (11px)` · `xs (12)` · `sm (14)` · `base (16)` · `md (18)` ·
+`lg (22)` · `xl (28)` · `2xl (36)` · `3xl (48)` · `display clamp(44–80px)`.
+
+Headings: weight `650–700`, tracking `-0.022em`. Body: `400`, line-height
+`1.6`. Mono labels: uppercase, tracking `0.12em`.
+
+---
+
+## 5. Spacing & layout
+
+- **4px rhythm:** `--odl-space-1…10` (`0.25rem` → `8rem`).
+- **Container:** `--odl-container 1200px`, `--odl-container-narrow 880px`,
+  fluid `--odl-gutter clamp(1.25–2.5rem)`. Use the global `.odl-container`.
+- **Section rhythm:** vertical padding `clamp(3.5rem, 7rem)`, every section
+  separated by a single hairline (`border-top: 1px var(--odl-border)`),
+  alternating with `--odl-bg-subtle` bands.
+
+---
+
+## 6. Radius & elevation
+
+- **Radius:** `--odl-radius-xs 3 / sm 5 / md 8 / lg 12 / pill`. Restrained by
+  design. **The bar motif is always sharp (radius 0).**
+- **Elevation:** `--odl-shadow-sm/md/lg`. Prefer **border-based** separation;
+  reserve real shadow for floating surfaces (the code window).
+
+---
+
+## 7. Motion
+
+- **Tokens:** `--odl-dur-fast 120ms / dur 200ms / dur-slow 320ms`;
+  `--odl-ease-out cubic-bezier(0.16,1,0.3,1)`, `--odl-ease`.
+- **Micro-interactions** 120–200ms (hover, tab change, button press).
+- **Reveal-on-scroll** (`.reveal`) is **pure CSS** via `animation-timeline:
+  view()` — progressive enhancement: browsers without support show content
+  immediately, and `prefers-reduced-motion` disables it entirely.
+- Animate only `opacity`/`transform`. Never block input.
+
+---
+
+## 8. The bar motif
+
+The solid rectangle from the OpenDAL wordmark is the system's signature mark.
+
+- `.odl-bar` — a sharp solid rectangle for dividers/emphasis.
+- `.odl-eyebrow` — the canonical section kicker: monospace, uppercase, led by a
+  small **accent bar**. Used above every section title.
+- As a top-border accent on principle cards, and as the section-title marker.
+
+Used consistently, the bar makes the minimal system unmistakably OpenDAL.
+
+---
+
+## 9. Component patterns
+
+| Component        | Class(es)                                  | Notes        
                                    |
+| ---------------- | ------------------------------------------ | 
------------------------------------------------ |
+| Primary button   | `.btn .btnPrimary`                         | Solid 
`action-bg`; one primary action per view.  |
+| Secondary button | `.btn .btnSecondary`                       | Hairline 
outline, ink text.                      |
+| On-dark buttons  | `.btnOnDark` / `.btnOnDarkGhost`           | For the dark 
CTA panel.                           |
+| Eyebrow          | `.odl-eyebrow` (global)                    | Mono + 
accent bar; section kicker.               |
+| Code window      | `CodeTabs`                                 | Window 
chrome + language tabs + Prism highlight. |
+| Value card       | `.valueCard`                               | Mono index, 
title, body; 1px-gap grid.           |
+| Service chip     | `.serviceChip`                             | Mono name + 
15px icon, grouped by family.        |
+| Binding / layer  | `.bindingCard` / `.layerItem`              | Icon + mono 
label in a hairline grid.            |
+
+Layout grids use a **1px gap over a border-colored background** to render crisp
+hairline dividers between cells — a precise, technical signature.
+
+---
+
+## 10. Do / Don't
+
+**Do**
+- Lead with ink; use blue for interaction and emphasis.
+- Use monospace for labels, indices, figures and code.
+- Keep one primary CTA per view; separate secondary actions.
+- Reach for hairlines and spacing before shadows and fills.
+- Design and test light **and** dark together.
+
+**Don't**
+- Introduce a second accent hue or gradients-as-decoration.
+- Use emoji as icons (use the existing SVG sets in `static/img/*`).
+- Hardcode hex in components — consume `--odl-*` tokens.
+- Add motion that conveys nothing or ignores `prefers-reduced-motion`.
+
+---
+
+## 11. Accessibility checklist
+
+- [ ] Text/accent contrast ≥ 4.5:1 (AA) in light and dark.
+- [ ] Visible `:focus-visible` ring (accent, 2px) on every interactive element.
+- [ ] Decorative icons use empty `alt`; meaning carried by adjacent text.
+- [ ] Code tabs are a proper `tablist`/`tab`/`tabpanel` with arrow-key support.
+- [ ] `prefers-reduced-motion` respected globally.
+- [ ] Layout holds at 375 / 768 / 1024 / 1440px without horizontal scroll.
diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js
index d32ff7f18..72e659482 100644
--- a/website/docusaurus.config.js
+++ b/website/docusaurus.config.js
@@ -96,7 +96,7 @@ const config = {
       /** @type {import('@docusaurus/preset-classic').Options} */
       ({
         docs: {
-          routeBasePath: "/",
+          routeBasePath: "docs",
           sidebarPath: require.resolve("./docs/sidebars.js"),
           editUrl: "https://github.com/apache/opendal/tree/main/website/";,
           showLastUpdateAuthor: true,
@@ -136,10 +136,6 @@ const config = {
       "@docusaurus/plugin-client-redirects",
       {
         redirects: [
-          {
-            from: "/docs/vision",
-            to: "/vision",
-          },
           {
             from: "/discord",
             to: "https://discord.com/invite/XQy8yGR2dg";,
@@ -149,6 +145,20 @@ const config = {
             to: "https://lists.apache.org/[email protected]";,
           },
         ],
+        // The landing page now owns "/", so docs moved from "/" to "/docs/".
+        // Keep every legacy doc URL working by redirecting the old prefix-less
+        // path to its new /docs/ location. The docs home ("/docs/") is 
excluded
+        // so it never collides with the landing page at "/".
+        createRedirects(existingPath) {
+          if (existingPath.startsWith("/docs/") && existingPath !== "/docs/") {
+            const legacy = existingPath.replace(/^\/docs\//, "/");
+            // Avoid colliding with root-level pages that are not docs.
+            if (legacy !== "/download/") {
+              return [legacy];
+            }
+          }
+          return undefined;
+        },
       },
     ],
     require.resolve("docusaurus-lunr-search"),
@@ -273,7 +283,8 @@ const config = {
       // image: 'img/opendal-social-card.jpg',
       colorMode: {
         defaultMode: "light",
-        disableSwitch: true,
+        disableSwitch: false,
+        respectPrefersColorScheme: true,
       },
       navbar: {
         logo: {
diff --git a/website/src/components/landing/CodeTabs.jsx 
b/website/src/components/landing/CodeTabs.jsx
new file mode 100644
index 000000000..cff47a506
--- /dev/null
+++ b/website/src/components/landing/CodeTabs.jsx
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useEffect, useId, useRef, useState } from "react";
+import CodeBlock from "@theme/CodeBlock";
+import styles from "./styles.module.css";
+
+// A framed "code window" with language tabs. Wraps Docusaurus' CodeBlock so 
the
+// snippets get the same Prism highlighting as the docs.
+//
+// The header doubles as a terminal-style prompt: a sample's `install` command
+// is shown there (tracking the active tab), so install lives in the title bar
+// rather than a separate band. With `equalize`, the code area animates its
+// height to fit the active snippet — no dead space for short snippets, and the
+// left hero column never reflows (its width is locked and it is the taller
+// column, so only the code window resizes).
+export default function CodeTabs({ samples, title, equalize = false }) {
+  const [active, setActive] = useState(0);
+  const baseId = useId();
+  const current = samples[active];
+  const heading = current.install || title;
+
+  const innerRef = useRef(null);
+  const [bodyHeight, setBodyHeight] = useState(undefined);
+
+  useEffect(() => {
+    if (!equalize || !innerRef.current) return undefined;
+    const measure = () => setBodyHeight(innerRef.current?.offsetHeight);
+    measure();
+    const ro =
+      typeof ResizeObserver !== "undefined"
+        ? new ResizeObserver(measure)
+        : null;
+    if (ro && innerRef.current) ro.observe(innerRef.current);
+    return () => ro?.disconnect();
+  }, [active, equalize]);
+
+  function onKeyDown(event) {
+    if (event.key !== "ArrowRight" && event.key !== "ArrowLeft") return;
+    event.preventDefault();
+    const dir = event.key === "ArrowRight" ? 1 : -1;
+    setActive((i) => (i + dir + samples.length) % samples.length);
+  }
+
+  return (
+    <div className={styles.codeWindow}>
+      <div className={styles.windowBar}>
+        <div className={styles.windowDots} aria-hidden="true">
+          <span />
+          <span />
+          <span />
+        </div>
+        <span className={styles.windowTitle}>{heading}</span>
+      </div>
+
+      <div
+        className={styles.codeTabs}
+        role="tablist"
+        aria-label="Choose a language"
+        onKeyDown={onKeyDown}
+      >
+        {samples.map((sample, i) => (
+          <button
+            key={sample.id}
+            type="button"
+            role="tab"
+            id={`${baseId}-tab-${sample.id}`}
+            aria-selected={i === active}
+            aria-controls={`${baseId}-panel`}
+            tabIndex={i === active ? 0 : -1}
+            className={`${styles.codeTab} ${
+              i === active ? styles.codeTabActive : ""
+            }`}
+            onClick={() => setActive(i)}
+          >
+            {sample.label}
+          </button>
+        ))}
+      </div>
+
+      <div
+        className={`${styles.codeBody} ${equalize ? styles.codeBodyAnimated : 
""}`}
+        style={
+          equalize && bodyHeight != null ? { height: bodyHeight } : undefined
+        }
+        role="tabpanel"
+        id={`${baseId}-panel`}
+        aria-labelledby={`${baseId}-tab-${current.id}`}
+      >
+        <div ref={innerRef}>
+          <CodeBlock language={current.language}>{current.code}</CodeBlock>
+        </div>
+      </div>
+    </div>
+  );
+}
diff --git a/website/src/components/landing/data.js 
b/website/src/components/landing/data.js
new file mode 100644
index 000000000..3a7b786fd
--- /dev/null
+++ b/website/src/components/landing/data.js
@@ -0,0 +1,443 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// Content model for the landing page. All copy and catalog data lives here so
+// the section components stay presentational. Code samples are taken from the
+// real binding APIs so the page never drifts from the libraries it advertises.
+
+export const REPO_URL = "https://github.com/apache/opendal";;
+export const DOCS_URL = "/docs/";
+export const DISCORD_URL = "https://discord.gg/XQy8yGR2dg";;
+
+export const heroStats = [
+  { value: "50+", label: "services" },
+  { value: "17", label: "languages" },
+  { value: "5k+", label: "stars" },
+  { value: "10M+", label: "downloads" },
+];
+
+// Same Operator contract, one mental model, every ecosystem.
+export const codeSamples = [
+  {
+    id: "rust",
+    label: "Rust",
+    language: "rust",
+    install: "$ cargo add opendal",
+    code: `use opendal::services::S3;
+use opendal::Operator;
+
+// Configure a backend once, then use one Operator.
+let builder = S3::default().bucket("data");
+let op = Operator::new(builder)?.finish();
+
+op.write("hello.txt", "Hello, World!").await?;
+let bytes = op.read("hello.txt").await?;`,
+  },
+  {
+    id: "python",
+    label: "Python",
+    language: "python",
+    install: "$ pip install opendal",
+    code: `import opendal
+
+# Configure a backend once, then use one Operator.
+op = opendal.Operator("s3", bucket="data")
+
+op.write("hello.txt", b"Hello, World!")
+data = op.read("hello.txt")`,
+  },
+  {
+    id: "go",
+    label: "Go",
+    language: "go",
+    install: "$ go get github.com/apache/opendal/bindings/go",
+    code: `import (
+    "github.com/apache/opendal-go-services/s3"
+    opendal "github.com/apache/opendal/bindings/go"
+)
+
+// Configure a backend once, then use one Operator.
+opts := opendal.OperatorOptions{"bucket": "data"}
+op, _ := opendal.NewOperator(s3.Scheme, opts)
+
+op.Write("hello.txt", []byte("Hello, World!"))
+data, _ := op.Read("hello.txt")`,
+  },
+  {
+    id: "java",
+    label: "Java",
+    language: "java",
+    install: "org.apache.opendal:opendal-java",
+    code: `import org.apache.opendal.AsyncOperator;
+import java.util.Map;
+
+// Configure a backend once, then use one Operator.
+var conf = Map.of("bucket", "data");
+try (var op = AsyncOperator.of("s3", conf)) {
+    op.write("hello.txt", "Hello, World!").join();
+    byte[] data = op.read("hello.txt").join();
+}`,
+  },
+  {
+    id: "node",
+    label: "Node.js",
+    language: "javascript",
+    install: "$ npm install opendal",
+    code: `import { Operator } from "opendal";
+
+// Configure a backend once, then use one Operator.
+const op = new Operator("s3", { bucket: "data" });
+
+await op.write("hello.txt", "Hello, World!");
+const data = await op.read("hello.txt");`,
+  },
+];
+
+export const valueProps = [
+  {
+    index: "01",
+    title: "One API, all storage",
+    body: "Object storage, file systems, cloud SaaS, databases, protocols and 
key-value services reached through a single Operator and one mental model.",
+  },
+  {
+    index: "02",
+    title: "Zero-cost core",
+    body: "Built in Rust with composable services and layers. Compile in only 
the backends and capabilities you use, and pay for nothing else.",
+  },
+  {
+    index: "03",
+    title: "Production-ready by composition",
+    body: "Stack retry, timeout, logging, tracing, metrics, throttling and 
concurrency limits as reusable layers — no rewrites, no glue code.",
+  },
+  {
+    index: "04",
+    title: "Open and extensible",
+    body: "Add services, layers and language bindings without forking the 
model. Developed in the open and governed the Apache Way.",
+  },
+];
+
+// What OpenDAL can do — grouped for the capabilities explorer. Each item pairs
+// a minimal, real snippet with its docs.rs reference. Grounded in the core
+// read / write / manage APIs (verified against types/operator + 
types/options).
+const RS = "https://docs.rs/opendal/latest/opendal";;
+const opDoc = (method) => `${RS}/struct.Operator.html#method.${method}`;
+const layerDoc = (name) => `${RS}/layers/struct.${name}.html`;
+
+export const capabilityThemes = [
+  {
+    title: "Read in parallel",
+    blurb: "Fetch a byte range, or a whole object in concurrent chunks.",
+    doc: opDoc("read_with"),
+    code: `let op = Operator::new(S3::default().bucket("data"))?.finish();
+
+// Read just the bytes you need.
+let head = op.read_with("logs/today").range(0..64 * 1024).await?;
+
+// Or pull a large object in parallel chunks.
+let full = op
+    .read_with("big.parquet")
+    .concurrent(8)
+    .chunk(8 * 1024 * 1024)
+    .await?;`,
+  },
+  {
+    title: "Upload in parts",
+    blurb: "Stream writes of any size as concurrent, multipart uploads.",
+    doc: opDoc("writer_with"),
+    code: `let op = Operator::new(S3::default().bucket("data"))?.finish();
+
+// Open a multipart writer with 8 concurrent parts.
+let mut w = op
+    .writer_with("big.bin")
+    .concurrent(8)
+    .chunk(8 * 1024 * 1024)
+    .await?;
+
+// Stream any number of buffers; close flushes the rest.
+w.write(part_one).await?;
+w.write(part_two).await?;
+w.close().await?;`,
+  },
+  {
+    title: "Recover from failure",
+    blurb: "Resume on retry, write atomically, and pin a version.",
+    doc: `${RS}/layers/struct.RetryLayer.html`,
+    code: `// Retries automatically resume interrupted transfers.
+let op = Operator::new(S3::default().bucket("data"))?
+    .layer(RetryLayer::new())
+    .finish();
+
+// Create only if absent.
+op.write_with("once.json", data).if_not_exists(true).await?;
+// Read only if unchanged.
+let doc = op.read_with("doc").if_match(etag).await?;
+// Pin an exact version.
+let pinned = op.read_with("doc").version(version_id).await?;`,
+  },
+  {
+    title: "Work with files",
+    blurb: "Inspect, list, move, and share — without moving bytes.",
+    doc: opDoc("list_with"),
+    code: `// Inspect a file without downloading it.
+let meta = op.stat("report.csv").await?;
+// List a prefix, recursing lazily through the tree.
+let mut entries = op.lister_with("logs/").recursive(true).await?;
+while let Some(entry) = entries.try_next().await? {
+    println!("{}", entry.path());
+}
+// Copy on the server — no download.
+op.copy("draft.md", "final.md").await?;
+// Recursively delete a subtree.
+op.delete_with("tmp/").recursive(true).await?;
+// Presign a temporary, shareable URL.
+let ttl = Duration::from_secs(3600);
+let url = op.presign_read("report.csv", ttl).await?;`,
+  },
+];
+
+// Real adopters from the project's users lists (core + bindings), ordered by
+// GitHub star count (highest first). Logos are the projects' GitHub org
+// avatars, self-hosted under static/img/users/. Refresh with scripts as the
+// ecosystem grows. The logo wall shows a responsive subset by viewport width.
+// Public projects with 1,000+ GitHub stars that depend on OpenDAL, sorted by
+// stars. Sourced via crates.io reverse deps + GitHub code search; logos are 
the
+// owner avatars, mirrored locally under static/img/users to avoid runtime 
calls.
+export const usedBy = [
+  { name: "Dify", icon: "/img/users/dify.png", href: 
"https://github.com/langgenius/dify"; },
+  { name: "RAGFlow", icon: "/img/users/ragflow.png", href: 
"https://github.com/infiniflow/ragflow"; },
+  { name: "Pathway", icon: "/img/users/pathway.png", href: 
"https://github.com/pathwaycom/pathway"; },
+  { name: "Vaultwarden", icon: "/img/users/vaultwarden.png", href: 
"https://github.com/dani-garcia/vaultwarden"; },
+  { name: "LlamaIndex", icon: "/img/users/llamaindex.png", href: 
"https://github.com/run-llama/llama_index"; },
+  { name: "Hasura", icon: "/img/users/hasura.png", href: 
"https://github.com/hasura/graphql-engine"; },
+  { name: "Vector", icon: "/img/users/vector.png", href: 
"https://github.com/vectordotdev/vector"; },
+  { name: "QuestDB", icon: "/img/users/questdb.png", href: 
"https://github.com/questdb/questdb"; },
+  { name: "WrenAI", icon: "/img/users/wrenai.png", href: 
"https://github.com/Canner/WrenAI"; },
+  { name: "Quickwit", icon: "/img/users/quickwit.png", href: 
"https://github.com/quickwit-oss/quickwit"; },
+  { name: "SeaTunnel", icon: "/img/users/seatunnel.png", href: 
"https://github.com/apache/seatunnel"; },
+  { name: "Databend", icon: "/img/users/databend.png", href: 
"https://github.com/databendlabs/databend"; },
+  { name: "RisingWave", icon: "/img/users/risingwave.png", href: 
"https://github.com/risingwavelabs/risingwave"; },
+  { name: "Loco", icon: "/img/users/loco.png", href: 
"https://github.com/loco-rs/loco"; },
+  { name: "sccache", icon: "/img/users/sccache.png", href: 
"https://github.com/mozilla/sccache"; },
+  { name: "Lance", icon: "/img/users/lance.png", href: 
"https://github.com/lance-format/lance"; },
+  { name: "GreptimeDB", icon: "/img/users/greptimedb.png", href: 
"https://github.com/GreptimeTeam/greptimedb"; },
+  { name: "Daft", icon: "/img/users/daft.png", href: 
"https://github.com/Eventual-Inc/Daft"; },
+  { name: "CrateDB", icon: "/img/users/cratedb.png", href: 
"https://github.com/crate/crate"; },
+  { name: "Pants", icon: "/img/users/pants.png", href: 
"https://github.com/pantsbuild/pants"; },
+  { name: "rustic", icon: "/img/users/rustic.png", href: 
"https://github.com/rustic-rs/rustic"; },
+  { name: "SlateDB", icon: "/img/users/slatedb.png", href: 
"https://github.com/slatedb/slatedb"; },
+  { name: "Gravitino", icon: "/img/users/gravitino.png", href: 
"https://github.com/apache/gravitino"; },
+  { name: "Spice.ai", icon: "/img/users/spiceai.png", href: 
"https://github.com/spiceai/spiceai"; },
+  { name: "Kubeflow Trainer", icon: "/img/users/kubeflow-trainer.png", href: 
"https://github.com/kubeflow/trainer"; },
+  { name: "OctoBase", icon: "/img/users/octobase.png", href: 
"https://github.com/toeverything/OctoBase"; },
+  { name: "Openraft", icon: "/img/users/openraft.png", href: 
"https://github.com/databendlabs/openraft"; },
+  { name: "Walrus", icon: "/img/users/walrus.png", href: 
"https://github.com/nubskr/walrus"; },
+  { name: "RobustMQ", icon: "/img/users/robustmq.png", href: 
"https://github.com/robustmq/robustmq"; },
+  { name: "lnx", icon: "/img/users/lnx.png", href: 
"https://github.com/lnx-search/lnx"; },
+  { name: "Iceberg Rust", icon: "/img/users/iceberg-rust.png", href: 
"https://github.com/apache/iceberg-rust"; },
+  { name: "DataFusion Comet", icon: "/img/users/datafusion-comet.png", href: 
"https://github.com/apache/datafusion-comet"; },
+  { name: "zino", icon: "/img/users/zino.png", href: 
"https://github.com/zino-rs/zino"; },
+];
+
+// Where people add their own project (PR to the users list).
+export const USERS_LIST_URL =
+  "https://github.com/apache/opendal/blob/main/core/users.md";;
+
+// Curated, icon-backed slice of the 50+ supported services, grouped by family.
+export const serviceGroups = [
+  {
+    category: "Object Storage",
+    services: [
+      { name: "s3", icon: "/img/services/s3.svg" },
+      { name: "gcs", icon: "/img/services/gcs.png" },
+      { name: "azblob", icon: "/img/services/azure.svg" },
+      { name: "oss", icon: "/img/services/oss.svg" },
+      { name: "cos", icon: "/img/services/cos.svg" },
+      { name: "obs", icon: "/img/services/obs.png" },
+      { name: "b2", icon: "/img/services/backblaze.png" },
+      { name: "tos", icon: "/img/services/volcengine.png" },
+    ],
+  },
+  {
+    category: "File Storage",
+    services: [
+      { name: "fs", icon: "/img/services/opendal.svg" },
+      { name: "hdfs", icon: "/img/services/hadoop.ico" },
+      { name: "alluxio", icon: "/img/services/alluxio.svg" },
+      { name: "lakefs", icon: "/img/services/lakefs.ico" },
+      { name: "ipfs", icon: "/img/services/ipfs.ico" },
+      { name: "dbfs", icon: "/img/services/databricks.png" },
+    ],
+  },
+  {
+    category: "Cloud SaaS",
+    services: [
+      { name: "gdrive", icon: "/img/services/gdrive.png" },
+      { name: "dropbox", icon: "/img/services/dropbox.ico" },
+      { name: "onedrive", icon: "/img/services/onedrive.svg" },
+      { name: "hf", icon: "/img/services/huggingface.ico" },
+      { name: "github", icon: "/img/services/github.svg" },
+      { name: "koofr", icon: "/img/services/koofr.ico" },
+    ],
+  },
+  {
+    category: "Protocols",
+    services: [
+      { name: "http", icon: "/img/services/http.png" },
+      { name: "ftp", icon: "/img/services/ftp.png" },
+      { name: "webdav", icon: "/img/services/webdav.png" },
+      { name: "sftp", icon: "/img/services/sftp.png" },
+    ],
+  },
+  {
+    category: "Databases",
+    services: [
+      { name: "sqlite", icon: "/img/services/sqlite.ico" },
+      { name: "mysql", icon: "/img/services/mysql.ico" },
+      { name: "postgresql", icon: "/img/services/postgresql.ico" },
+      { name: "mongodb", icon: "/img/services/mongodb.ico" },
+      { name: "surrealdb", icon: "/img/services/surrealdb.svg" },
+      { name: "d1", icon: "/img/services/cloudflare.ico" },
+    ],
+  },
+  {
+    category: "Key-Value",
+    services: [
+      { name: "redis", icon: "/img/services/redis.png" },
+      { name: "etcd", icon: "/img/services/etcd.png" },
+      { name: "rocksdb", icon: "/img/services/rocksdb.png" },
+      { name: "memcached", icon: "/img/services/memcached.png" },
+      { name: "tikv", icon: "/img/services/tikv.png" },
+      { name: "foundationdb", icon: "/img/services/foundationdb.png" },
+    ],
+  },
+];
+
+export const bindings = [
+  { name: "Rust", icon: "/img/bindings/rust.svg" },
+  { name: "Python", icon: "/img/bindings/python.svg" },
+  { name: "Java", icon: "/img/bindings/java.svg" },
+  { name: "Go", icon: "/img/bindings/go.svg" },
+  { name: "Node.js", icon: "/img/bindings/nodejs.svg" },
+  { name: "C", icon: "/img/bindings/c.svg" },
+  { name: "C++", icon: "/img/bindings/cpp.svg" },
+  { name: ".NET", icon: "/img/bindings/dotnet.svg" },
+  { name: "Ruby", icon: "/img/bindings/ruby.svg" },
+  { name: "PHP", icon: "/img/bindings/php.svg" },
+  { name: "Swift", icon: "/img/bindings/swift.svg" },
+  { name: "Haskell", icon: "/img/bindings/haskell.svg" },
+  { name: "OCaml", icon: "/img/bindings/ocaml.svg" },
+  { name: "Lua", icon: "/img/bindings/lua.svg" },
+  { name: "Dart", icon: "/img/bindings/dart.svg" },
+  { name: "D", icon: "/img/bindings/d.svg" },
+  { name: "Zig", icon: "/img/bindings/zig.svg" },
+];
+
+export const layers = [
+  {
+    name: "RetryLayer",
+    desc: "Recover from transient failures automatically.",
+    doc: layerDoc("RetryLayer"),
+    code: `use opendal::layers::RetryLayer;
+
+// Exponential backoff with jitter; interrupted
+// reads and writes resume where they left off.
+let op = op.layer(
+    RetryLayer::new().with_max_times(5).with_jitter(),
+);`,
+  },
+  {
+    name: "TimeoutLayer",
+    desc: "Bound slow or hanging operations.",
+    doc: layerDoc("TimeoutLayer"),
+    code: `use opendal::layers::TimeoutLayer;
+use std::time::Duration;
+
+// Abort operations that stall past a deadline.
+let op = op.layer(
+    TimeoutLayer::new()
+        .with_timeout(Duration::from_secs(10)),
+);`,
+  },
+  {
+    name: "LoggingLayer",
+    desc: "Emit structured operation logs.",
+    doc: layerDoc("LoggingLayer"),
+    code: `use opendal::layers::LoggingLayer;
+
+// Structured logs for every operation, via the
+// standard log crate facade.
+let op = op.layer(LoggingLayer::default());`,
+  },
+  {
+    name: "TracingLayer",
+    desc: "Trace requests across systems.",
+    doc: layerDoc("TracingLayer"),
+    code: `use opendal::layers::TracingLayer;
+
+// One span per operation, into whatever
+// tracing subscriber your app installs.
+let op = op.layer(TracingLayer::new());`,
+  },
+  {
+    name: "MetricsLayer",
+    desc: "Export operation metrics.",
+    doc: layerDoc("MetricsLayer"),
+    code: `use opendal::layers::MetricsLayer;
+
+// Latency and throughput via the metrics crate
+// facade — plug in any exporter you like.
+let op = op.layer(MetricsLayer::default());`,
+  },
+  {
+    name: "PrometheusLayer",
+    desc: "Expose Prometheus metrics.",
+    doc: layerDoc("PrometheusLayer"),
+    code: `use opendal::layers::PrometheusLayer;
+
+// Register operation metrics into a Prometheus
+// registry you already expose.
+let registry = prometheus::default_registry();
+let op = op.layer(
+    PrometheusLayer::builder().register(registry)?,
+);`,
+  },
+  {
+    name: "ConcurrentLimitLayer",
+    desc: "Cap in-flight concurrency.",
+    doc: layerDoc("ConcurrentLimitLayer"),
+    code: `use opendal::layers::ConcurrentLimitLayer;
+
+// Cap how many operations hit the backend at once —
+// back-pressure for the whole Operator.
+let op = op.layer(ConcurrentLimitLayer::new(1024));`,
+  },
+  {
+    name: "ThrottleLayer",
+    desc: "Throttle I/O bandwidth.",
+    doc: layerDoc("ThrottleLayer"),
+    code: `use opendal::layers::ThrottleLayer;
+
+// Token-bucket bandwidth limit: ~10 MiB/s steady,
+// with headroom to burst for short spikes.
+let op = op.layer(ThrottleLayer::new(
+    10 * 1024 * 1024,
+    32 * 1024 * 1024,
+));`,
+  },
+];
diff --git a/website/src/components/landing/sections.jsx 
b/website/src/components/landing/sections.jsx
new file mode 100644
index 000000000..f3f65506d
--- /dev/null
+++ b/website/src/components/landing/sections.jsx
@@ -0,0 +1,415 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React, { useState } from "react";
+import Link from "@docusaurus/Link";
+import { useBaseUrlUtils } from "@docusaurus/useBaseUrl";
+import CodeBlock from "@theme/CodeBlock";
+import CodeTabs from "./CodeTabs";
+import styles from "./styles.module.css";
+import {
+  REPO_URL,
+  DOCS_URL,
+  DISCORD_URL,
+  heroStats,
+  codeSamples,
+  valueProps,
+  capabilityThemes,
+  usedBy,
+  USERS_LIST_URL,
+  serviceGroups,
+  bindings,
+  layers,
+} from "./data";
+
+export function Hero() {
+  return (
+    <header className={styles.hero}>
+      <div className={`${styles.heroGrid} odl-grid-bg`} aria-hidden="true" />
+      <div className="odl-container">
+        <div className={styles.heroInner}>
+          <div>
+            <span className="odl-eyebrow">
+              Apache OpenDAL™ — Open Data Access Layer
+            </span>
+            <h1 className={styles.heroTitle}>
+              One Layer,
+              <br />
+              <span className={styles.heroTitleAccent}>All Storage.</span>
+            </h1>
+            <p className={styles.heroLede}>
+              One zero-cost Operator for object storage, file systems, 
databases
+              and more — in the language you already ship.
+            </p>
+            <div className={styles.heroActions}>
+              <Link
+                className={`${styles.btn} ${styles.btnPrimary}`}
+                to={DOCS_URL}
+              >
+                Get started <span className={styles.btnArrow}>→</span>
+              </Link>
+              <Link
+                className={`${styles.btn} ${styles.btnSecondary}`}
+                to={REPO_URL}
+              >
+                View on GitHub
+              </Link>
+            </div>
+            <div className={styles.heroStats}>
+              {heroStats.map((stat) => (
+                <div className={styles.heroStat} key={stat.label}>
+                  <span className={styles.heroStatValue}>{stat.value}</span>
+                  <span className={styles.heroStatLabel}>{stat.label}</span>
+                </div>
+              ))}
+            </div>
+          </div>
+          <div className={styles.heroAside}>
+            <CodeTabs samples={codeSamples} title="quickstart" equalize />
+          </div>
+        </div>
+      </div>
+    </header>
+  );
+}
+
+export function UsedBy() {
+  const { withBaseUrl } = useBaseUrlUtils();
+  return (
+    <section className={`${styles.section} ${styles.sectionSubtle}`}>
+      <div className="odl-container">
+        <div className={styles.sectionHead}>
+          <span className="odl-eyebrow">Used by</span>
+          <h2 className={styles.sectionTitle}>
+            Powering AI, analytics, and real-time data
+          </h2>
+          <p className={styles.sectionLede}>
+            OpenDAL runs in production across the open-source ecosystem. These
+            are some of the projects that build on it.
+          </p>
+        </div>
+        <ul className={styles.logoWall}>
+          {usedBy.map((u) => (
+            <li key={u.name}>
+              <Link className={styles.logoItem} to={u.href} title={u.name}>
+                <img
+                  className={styles.logoMark}
+                  src={withBaseUrl(u.icon)}
+                  alt=""
+                  width="28"
+                  height="28"
+                  loading="lazy"
+                />
+                <span className={styles.logoName}>{u.name}</span>
+              </Link>
+            </li>
+          ))}
+          <li>
+            <Link className={styles.addLogo} to={USERS_LIST_URL}>
+              + add your logo
+            </Link>
+          </li>
+        </ul>
+      </div>
+    </section>
+  );
+}
+
+export function ValueProps() {
+  return (
+    <section className={styles.section}>
+      <div className="odl-container">
+        <div className={styles.sectionHead}>
+          <span className="odl-eyebrow">Why OpenDAL</span>
+          <h2 className={styles.sectionTitle}>
+            A storage layer you can build production on.
+          </h2>
+          <p className={styles.sectionLede}>
+            OpenDAL turns one vision — <em>One Layer, All Storage</em> — into a
+            practical foundation for applications, libraries and data systems.
+          </p>
+        </div>
+        <div className={`${styles.valueGrid} ${styles.reveal}`}>
+          {valueProps.map((v) => (
+            <article className={styles.valueCard} key={v.index}>
+              <span className={styles.valueIndex}>{v.index}</span>
+              <h3 className={styles.valueCardTitle}>{v.title}</h3>
+              <p className={styles.valueCardBody}>{v.body}</p>
+            </article>
+          ))}
+        </div>
+      </div>
+    </section>
+  );
+}
+
+export function Capabilities() {
+  const [active, setActive] = useState(capabilityThemes[0]);
+  return (
+    <section className={`${styles.section} ${styles.sectionSubtle}`}>
+      <div className="odl-container">
+        <div className={styles.sectionHead}>
+          <span className="odl-eyebrow">Capabilities</span>
+          <h2 className={styles.sectionTitle}>Configure once. Access 
anything.</h2>
+          <p className={styles.sectionLede}>
+            One Operator is a full toolkit for real-world data — read and write
+            at scale, recover from failures, and work with files — the same way
+            on every backend.
+          </p>
+        </div>
+        <div className={styles.capabilityExplorer}>
+          <ul className={styles.capabilityNav}>
+            {capabilityThemes.map((theme) => {
+              const selected = active.title === theme.title;
+              return (
+                <li key={theme.title}>
+                  <Link
+                    className={`${styles.capabilityItem} ${
+                      selected ? styles.capabilityItemActive : ""
+                    }`}
+                    to={theme.doc}
+                    target="_blank"
+                    rel="noreferrer"
+                    aria-current={selected ? "true" : undefined}
+                    onMouseEnter={() => setActive(theme)}
+                    onFocus={() => setActive(theme)}
+                  >
+                    <span className={styles.capabilityText}>
+                      <span className={styles.capabilityItemTitle}>
+                        {theme.title}
+                      </span>
+                      <span className={styles.capabilityItemBlurb}>
+                        {theme.blurb}
+                      </span>
+                    </span>
+                    <span className={styles.capabilityArrow} 
aria-hidden="true">
+                      ↗
+                    </span>
+                  </Link>
+                </li>
+              );
+            })}
+          </ul>
+          <div className={styles.capabilityPreview}>
+            <div className={styles.codeWindow}>
+              <div className={styles.windowBar}>
+                <div className={styles.windowDots} aria-hidden="true">
+                  <span />
+                  <span />
+                  <span />
+                </div>
+                <span className={styles.windowTitle}>{active.title}</span>
+              </div>
+              <div className={`${styles.codeBody} 
${styles.capabilityCodeBody}`}>
+                <div className={styles.capabilityCodeFade} key={active.title}>
+                  <CodeBlock language="rust">{active.code}</CodeBlock>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </section>
+  );
+}
+
+export function Services() {
+  const { withBaseUrl } = useBaseUrlUtils();
+  return (
+    <section className={styles.section}>
+      <div className="odl-container">
+        <div className={styles.sectionHead}>
+          <span className="odl-eyebrow">Services</span>
+          <h2 className={styles.sectionTitle}>
+            50+ storage services, one interface.
+          </h2>
+          <p className={styles.sectionLede}>
+            Enable only the backends your application needs. The Operator
+            contract stays identical across every one.
+          </p>
+        </div>
+        <div className={`${styles.serviceGroups} ${styles.reveal}`}>
+          {serviceGroups.map((group) => (
+            <div className={styles.serviceGroup} key={group.category}>
+              <h3 className={styles.serviceGroupTitle}>{group.category}</h3>
+              <div className={styles.serviceChips}>
+                {group.services.map((s) => (
+                  <span className={styles.serviceChip} key={s.name}>
+                    <img
+                      src={withBaseUrl(s.icon)}
+                      alt=""
+                      width="15"
+                      height="15"
+                      loading="lazy"
+                    />
+                    {s.name}
+                  </span>
+                ))}
+              </div>
+            </div>
+          ))}
+        </div>
+        <div className={styles.servicesFoot}>
+          <Link
+            className={`${styles.btn} ${styles.btnSecondary}`}
+            to={DOCS_URL}
+          >
+            Browse all services <span className={styles.btnArrow}>→</span>
+          </Link>
+        </div>
+      </div>
+    </section>
+  );
+}
+
+export function Bindings() {
+  const { withBaseUrl } = useBaseUrlUtils();
+  return (
+    <section className={`${styles.section} ${styles.sectionSubtle}`}>
+      <div className="odl-container">
+        <div className={styles.sectionHead}>
+          <span className="odl-eyebrow">Bindings</span>
+          <h2 className={styles.sectionTitle}>Ship it in your language.</h2>
+          <p className={styles.sectionLede}>
+            Each binding exposes the same OpenDAL service model while following
+            its own ecosystem's conventions.
+          </p>
+        </div>
+        <div className={`${styles.bindingGrid} ${styles.reveal}`}>
+          {bindings.map((b) => (
+            <div className={styles.bindingCard} key={b.name}>
+              <img
+                src={withBaseUrl(b.icon)}
+                alt=""
+                width="30"
+                height="30"
+                loading="lazy"
+              />
+              <span className={styles.bindingName}>{b.name}</span>
+            </div>
+          ))}
+        </div>
+      </div>
+    </section>
+  );
+}
+
+export function Layers() {
+  const [active, setActive] = useState(layers[0]);
+  return (
+    <section className={styles.section}>
+      <div className="odl-container">
+        <div className={styles.sectionHead}>
+          <span className="odl-eyebrow">Layers</span>
+          <h2 className={styles.sectionTitle}>
+            Production behavior, composed — not coded.
+          </h2>
+          <p className={styles.sectionLede}>
+            Stack cross-cutting concerns as reusable layers. The order is
+            explicit and the core stays zero-cost.
+          </p>
+        </div>
+        <div className={styles.layerExplorer}>
+          <div className={styles.layerGrid}>
+            {layers.map((l) => {
+              const selected = active.name === l.name;
+              return (
+                <Link
+                  key={l.name}
+                  className={`${styles.layerItem} ${
+                    selected ? styles.layerItemActive : ""
+                  }`}
+                  to={l.doc}
+                  target="_blank"
+                  rel="noreferrer"
+                  aria-current={selected ? "true" : undefined}
+                  onMouseEnter={() => setActive(l)}
+                  onFocus={() => setActive(l)}
+                >
+                  <span className={styles.layerName}>{l.name}</span>
+                  <span className={styles.layerDesc}>{l.desc}</span>
+                </Link>
+              );
+            })}
+          </div>
+          <div className={styles.capabilityPreview}>
+            <div className={styles.codeWindow}>
+              <div className={styles.windowBar}>
+                <div className={styles.windowDots} aria-hidden="true">
+                  <span />
+                  <span />
+                  <span />
+                </div>
+                <span className={styles.windowTitle}>{active.name}</span>
+              </div>
+              <div className={`${styles.codeBody} ${styles.layerCodeBody}`}>
+                <div className={styles.capabilityCodeFade} key={active.name}>
+                  <CodeBlock language="rust">{active.code}</CodeBlock>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </section>
+  );
+}
+
+export function FinalCta() {
+  return (
+    <section className={`${styles.section} ${styles.sectionSubtle}`}>
+      <div className="odl-container">
+        <div className={styles.finalCta}>
+          <div className={`${styles.finalCtaInner} ${styles.finalCenter}`}>
+            <span className={`odl-eyebrow ${styles.finalEyebrow}`}>
+              Start building
+            </span>
+            <h2 className={styles.finalCtaTitle}>
+              One layer for all your storage.
+            </h2>
+            <p className={styles.finalCtaLede}>
+              Join the infrastructure builders, platform teams and application
+              developers accessing data freely, painlessly and efficiently.
+            </p>
+            <div className={styles.finalCtaActions}>
+              <Link
+                className={`${styles.btn} ${styles.btnPrimary}`}
+                to={DOCS_URL}
+              >
+                Get started <span className={styles.btnArrow}>→</span>
+              </Link>
+              <Link
+                className={`${styles.btn} ${styles.btnSecondary}`}
+                to={REPO_URL}
+              >
+                Star on GitHub
+              </Link>
+              <Link
+                className={`${styles.btn} ${styles.btnSecondary}`}
+                to={DISCORD_URL}
+              >
+                Join Discord
+              </Link>
+            </div>
+          </div>
+        </div>
+      </div>
+    </section>
+  );
+}
diff --git a/website/src/components/landing/styles.module.css 
b/website/src/components/landing/styles.module.css
new file mode 100644
index 000000000..8b1559bbe
--- /dev/null
+++ b/website/src/components/landing/styles.module.css
@@ -0,0 +1,744 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* ===== Shared building blocks ============================================ */
+.section {
+  padding-block: clamp(3.5rem, 2rem + 7vw, 7rem);
+  border-top: 1px solid var(--odl-border);
+}
+.sectionSubtle {
+  background: var(--odl-bg-subtle);
+}
+
+.sectionHead {
+  max-width: 46rem;
+  margin-bottom: var(--odl-space-7);
+}
+.sectionTitle {
+  font-size: var(--odl-text-2xl);
+  line-height: var(--odl-leading-snug);
+  font-weight: 650;
+  color: var(--odl-fg-strong);
+  margin: var(--odl-space-4) 0 0;
+}
+.sectionLede {
+  font-size: var(--odl-text-md);
+  line-height: var(--odl-leading-normal);
+  color: var(--odl-fg-muted);
+  margin: var(--odl-space-3) 0 0;
+  max-width: 40rem;
+}
+
+/* Buttons --------------------------------------------------------------- */
+.btn {
+  display: inline-flex;
+  align-items: center;
+  justify-content: center;
+  gap: var(--odl-space-2);
+  height: 2.875rem;
+  padding-inline: var(--odl-space-5);
+  border-radius: var(--odl-radius-md);
+  border: 1px solid transparent;
+  font-size: var(--odl-text-sm);
+  font-weight: 600;
+  letter-spacing: -0.005em;
+  text-decoration: none;
+  cursor: pointer;
+  transition: background-color var(--odl-dur) var(--odl-ease),
+    border-color var(--odl-dur) var(--odl-ease),
+    color var(--odl-dur) var(--odl-ease), transform var(--odl-dur-fast)
+      var(--odl-ease);
+}
+.btn:hover {
+  text-decoration: none;
+}
+.btn:active {
+  transform: translateY(1px);
+}
+.btnPrimary {
+  background: var(--odl-action-bg);
+  color: var(--odl-action-fg);
+}
+.btnPrimary:hover {
+  background: var(--odl-action-bg-hover);
+  color: var(--odl-action-fg);
+}
+.btnSecondary {
+  background: transparent;
+  color: var(--odl-fg-strong);
+  border-color: var(--odl-border-strong);
+}
+.btnSecondary:hover {
+  color: var(--odl-fg-strong);
+  border-color: var(--odl-fg-strong);
+  background: var(--odl-surface-2);
+}
+.btnArrow {
+  transition: transform var(--odl-dur) var(--odl-ease-out);
+}
+.btn:hover .btnArrow {
+  transform: translateX(3px);
+}
+
+/* ===== Hero ============================================================== */
+.hero {
+  position: relative;
+  overflow: hidden;
+  padding-top: clamp(1.75rem, 1rem + 2.4vw, 3rem);
+  padding-bottom: clamp(3rem, 2rem + 5vw, 5.5rem);
+}
+.heroGrid {
+  position: absolute;
+  inset: 0;
+  -webkit-mask-image: radial-gradient(
+    120% 90% at 70% 0%,
+    #000 0%,
+    transparent 72%
+  );
+  mask-image: radial-gradient(120% 90% at 70% 0%, #000 0%, transparent 72%);
+  pointer-events: none;
+}
+.heroInner {
+  position: relative;
+  display: grid;
+  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
+  gap: clamp(2rem, 1rem + 4vw, 4.5rem);
+  /* Column widths are locked by minmax(0, fr), so the left column never
+     reflows; center the columns to balance the fixed-height code window. */
+  align-items: center;
+}
+.heroTitle {
+  font-size: var(--odl-text-display);
+  line-height: var(--odl-leading-tight);
+  font-weight: 700;
+  letter-spacing: var(--odl-tracking-tight);
+  color: var(--odl-fg-strong);
+  margin: var(--odl-space-5) 0 0;
+}
+.heroTitleAccent {
+  color: var(--odl-accent);
+}
+.heroLede {
+  font-size: var(--odl-text-md);
+  line-height: var(--odl-leading-normal);
+  color: var(--odl-fg-muted);
+  margin: var(--odl-space-5) 0 0;
+  max-width: 34rem;
+}
+.heroActions {
+  display: flex;
+  flex-wrap: wrap;
+  gap: var(--odl-space-3);
+  margin-top: var(--odl-space-6);
+}
+.heroStats {
+  display: grid;
+  grid-template-columns: repeat(4, 1fr);
+  gap: var(--odl-space-4);
+  margin-top: var(--odl-space-8);
+  border-top: 1px solid var(--odl-border);
+  padding-top: var(--odl-space-5);
+}
+.heroStat {
+  display: flex;
+  flex-direction: column;
+  gap: 2px;
+}
+.heroStatValue {
+  font-family: var(--odl-font-mono);
+  font-size: var(--odl-text-xl);
+  font-weight: 600;
+  color: var(--odl-fg-strong);
+  font-variant-numeric: tabular-nums;
+}
+.heroStatLabel {
+  font-size: var(--odl-text-xs);
+  color: var(--odl-fg-subtle);
+}
+
+/* ===== Code window (shared by Hero & Operator) ========================== */
+.codeWindow {
+  border: 1px solid var(--odl-border);
+  border-radius: var(--odl-radius-lg);
+  background: var(--odl-surface);
+  box-shadow: var(--odl-shadow-lg);
+  overflow: hidden;
+}
+.windowBar {
+  display: flex;
+  align-items: center;
+  gap: var(--odl-space-3);
+  padding: var(--odl-space-3) var(--odl-space-4);
+  border-bottom: 1px solid var(--odl-border);
+  background: var(--odl-surface-2);
+}
+.windowDots {
+  display: flex;
+  gap: 6px;
+}
+.windowDots span {
+  width: 11px;
+  height: 11px;
+  border-radius: var(--odl-radius-pill);
+  background: var(--odl-border-strong);
+}
+.windowTitle {
+  flex: 1 1 auto;
+  min-width: 0;
+  font-family: var(--odl-font-mono);
+  font-size: var(--odl-text-xs);
+  color: var(--odl-fg-muted);
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.codeTabs {
+  display: flex;
+  gap: 2px;
+  padding: var(--odl-space-2) var(--odl-space-3) 0;
+  border-bottom: 1px solid var(--odl-border);
+  background: var(--odl-surface-2);
+  overflow-x: auto;
+  scrollbar-width: none;
+}
+.codeTabs::-webkit-scrollbar {
+  display: none;
+}
+.codeTab {
+  appearance: none;
+  background: transparent;
+  border: 0;
+  border-bottom: 2px solid transparent;
+  padding: var(--odl-space-2) var(--odl-space-3) var(--odl-space-3);
+  font-family: var(--odl-font-mono);
+  font-size: var(--odl-text-xs);
+  color: var(--odl-fg-subtle);
+  cursor: pointer;
+  white-space: nowrap;
+  transition: color var(--odl-dur) var(--odl-ease),
+    border-color var(--odl-dur) var(--odl-ease);
+}
+.codeTab:hover {
+  color: var(--odl-fg);
+}
+.codeTabActive {
+  color: var(--odl-fg-strong);
+  border-bottom-color: var(--odl-accent);
+}
+/* The code area animates its height to fit the active snippet: no dead space
+   for short snippets, and switching language glides between sizes. The left
+   hero column never moves (its width is locked and it is the taller column),
+   so only this window resizes. */
+.codeBodyAnimated {
+  overflow: hidden;
+  background: var(--odl-code-bg);
+  transition: height var(--odl-dur-slow) var(--odl-ease);
+}
+@media (prefers-reduced-motion: reduce) {
+  .codeBodyAnimated {
+    transition: none;
+  }
+}
+
+/* Tighten the embedded Docusaurus CodeBlock to fit the window chrome */
+.codeBody :global(.theme-code-block),
+.codeBody :global(div[class*="codeBlockContainer"]) {
+  margin: 0;
+  border: 0;
+  border-radius: 0;
+  box-shadow: none;
+}
+.codeBody :global(pre) {
+  border: 0 !important;
+  border-radius: 0 !important;
+  margin: 0;
+  background: var(--odl-code-bg) !important;
+  font-size: 0.8125rem;
+  /* Wrap long lines so code windows never scroll horizontally. */
+  white-space: pre-wrap;
+  overflow-wrap: anywhere;
+}
+.codeBody :global(pre code),
+.codeBody :global(.token-line) {
+  white-space: inherit;
+  overflow-wrap: inherit;
+}
+
+/* ===== Used-by wall ===================================================== */
+.logoWall {
+  list-style: none;
+  margin: 0;
+  padding: 0;
+  display: grid;
+  grid-template-columns: repeat(auto-fill, minmax(12.5rem, 1fr));
+  gap: var(--odl-space-3);
+}
+.logoWall > li {
+  display: flex;
+}
+.logoItem {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  gap: var(--odl-space-3);
+  padding: var(--odl-space-4);
+  background: var(--odl-surface);
+  border: 1px solid var(--odl-border);
+  border-radius: var(--odl-radius-md);
+  text-decoration: none;
+  filter: grayscale(1);
+  opacity: 0.72;
+  transition: opacity var(--odl-dur) var(--odl-ease),
+    filter var(--odl-dur) var(--odl-ease),
+    background-color var(--odl-dur) var(--odl-ease);
+}
+.logoItem:hover {
+  background: var(--odl-surface-2);
+  filter: grayscale(0);
+  opacity: 1;
+  text-decoration: none;
+}
+.logoMark {
+  width: 28px;
+  height: 28px;
+  object-fit: contain;
+  border-radius: var(--odl-radius-sm);
+  flex: none;
+}
+.logoName {
+  font-family: var(--odl-font-mono);
+  font-size: var(--odl-text-sm);
+  font-weight: 500;
+  color: var(--odl-fg-muted);
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+/* "+ add your logo" rendered as the final, dashed tile in the wall. */
+.addLogo {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: var(--odl-space-4);
+  border: 1px dashed var(--odl-border);
+  border-radius: var(--odl-radius-md);
+  font-family: var(--odl-font-mono);
+  font-size: var(--odl-text-xs);
+  letter-spacing: 0.04em;
+  color: var(--odl-fg-subtle);
+  text-decoration: none;
+  white-space: nowrap;
+  transition: color var(--odl-dur) var(--odl-ease),
+    border-color var(--odl-dur) var(--odl-ease);
+}
+.addLogo:hover {
+  color: var(--odl-accent);
+  border-color: var(--odl-accent);
+  text-decoration: none;
+}
+
+/* ===== Value props ====================================================== */
+.valueGrid {
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  gap: 1px;
+  background: var(--odl-border);
+  border: 1px solid var(--odl-border);
+  border-radius: var(--odl-radius-lg);
+  overflow: hidden;
+}
+.valueCard {
+  background: var(--odl-surface);
+  padding: clamp(1.5rem, 1rem + 2vw, 2.5rem);
+  display: flex;
+  flex-direction: column;
+  gap: var(--odl-space-3);
+  transition: background-color var(--odl-dur) var(--odl-ease);
+}
+.valueCard:hover {
+  background: var(--odl-surface-2);
+}
+.valueIndex {
+  font-family: var(--odl-font-mono);
+  font-size: var(--odl-text-xs);
+  font-weight: 500;
+  letter-spacing: var(--odl-tracking-label);
+  color: var(--odl-accent);
+}
+.valueCardTitle {
+  font-size: var(--odl-text-lg);
+  font-weight: 650;
+  color: var(--odl-fg-strong);
+  margin: 0;
+  letter-spacing: var(--odl-tracking-tight);
+}
+.valueCardBody {
+  font-size: var(--odl-text-base);
+  line-height: var(--odl-leading-normal);
+  color: var(--odl-fg-muted);
+  margin: 0;
+}
+
+/* ===== Capabilities (explorer) ========================================== */
+.capabilityExplorer {
+  display: grid;
+  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
+  gap: clamp(2rem, 1rem + 3vw, 3.5rem);
+  align-items: start;
+}
+.capabilityNav {
+  list-style: none;
+  margin: 0;
+  padding: 0;
+  display: flex;
+  flex-direction: column;
+  gap: var(--odl-space-2);
+}
+.capabilityItem {
+  display: flex;
+  align-items: flex-start;
+  justify-content: space-between;
+  gap: var(--odl-space-3);
+  padding: var(--odl-space-4);
+  border: 1px solid transparent;
+  border-radius: var(--odl-radius-md);
+  text-decoration: none;
+  transition: background-color var(--odl-dur) var(--odl-ease),
+    border-color var(--odl-dur) var(--odl-ease);
+}
+.capabilityItem:hover {
+  background: var(--odl-surface);
+  text-decoration: none;
+}
+.capabilityItemActive {
+  background: var(--odl-surface);
+  border-color: var(--odl-border);
+  box-shadow: var(--odl-shadow-sm);
+}
+.capabilityText {
+  display: flex;
+  flex-direction: column;
+  gap: 3px;
+  min-width: 0;
+}
+.capabilityItemTitle {
+  font-size: var(--odl-text-md);
+  font-weight: 650;
+  letter-spacing: var(--odl-tracking-tight);
+  color: var(--odl-fg-strong);
+}
+.capabilityItemBlurb {
+  font-size: var(--odl-text-sm);
+  line-height: var(--odl-leading-snug);
+  color: var(--odl-fg-muted);
+}
+.capabilityArrow {
+  font-family: var(--odl-font-mono);
+  font-size: var(--odl-text-sm);
+  color: var(--odl-accent);
+  opacity: 0;
+  transition: opacity var(--odl-dur) var(--odl-ease);
+}
+.capabilityItem:hover .capabilityArrow,
+.capabilityItemActive .capabilityArrow {
+  opacity: 1;
+}
+
+/* Sticky code preview that tracks the active capability */
+.capabilityPreview {
+  position: sticky;
+  top: 5rem;
+}
+.capabilityCodeBody {
+  height: 19rem;
+  overflow: auto;
+  background: var(--odl-code-bg);
+}
+/* Fade only the code itself; the panel background stays put, so switching
+   snippets never flashes the window surface behind it. */
+.capabilityCodeFade {
+  animation: odlFade var(--odl-dur) var(--odl-ease);
+}
+@keyframes odlFade {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
+@media (prefers-reduced-motion: reduce) {
+  .capabilityCodeFade {
+    animation: none;
+  }
+}
+
+/* ===== Services ========================================================= */
+.serviceGroups {
+  display: grid;
+  grid-template-columns: repeat(3, 1fr);
+  gap: 1px;
+  background: var(--odl-border);
+  border: 1px solid var(--odl-border);
+  border-radius: var(--odl-radius-lg);
+  overflow: hidden;
+}
+.serviceGroup {
+  background: var(--odl-surface);
+  padding: clamp(1.25rem, 1rem + 1vw, 1.75rem);
+}
+.serviceGroupTitle {
+  display: flex;
+  align-items: center;
+  gap: var(--odl-space-3);
+  font-family: var(--odl-font-mono);
+  font-size: var(--odl-text-xs);
+  font-weight: 500;
+  letter-spacing: var(--odl-tracking-label);
+  text-transform: uppercase;
+  color: var(--odl-fg-subtle);
+  margin-bottom: var(--odl-space-4);
+}
+.serviceGroupTitle::before {
+  content: "";
+  width: 0.875rem;
+  height: 0.375rem;
+  background: var(--odl-accent);
+  flex: none;
+}
+.serviceChips {
+  display: flex;
+  flex-wrap: wrap;
+  gap: var(--odl-space-2);
+}
+.serviceChip {
+  display: inline-flex;
+  align-items: center;
+  gap: var(--odl-space-2);
+  padding: 0.3rem 0.6rem;
+  border: 1px solid var(--odl-border);
+  border-radius: var(--odl-radius-sm);
+  background: var(--odl-bg);
+  font-family: var(--odl-font-mono);
+  font-size: var(--odl-text-xs);
+  color: var(--odl-fg);
+}
+.serviceChip img {
+  width: 15px;
+  height: 15px;
+  object-fit: contain;
+}
+.servicesFoot {
+  margin-top: var(--odl-space-6);
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
+  flex-wrap: wrap;
+  gap: var(--odl-space-3);
+}
+
+/* ===== Bindings ========================================================= */
+.bindingGrid {
+  display: grid;
+  grid-template-columns: repeat(auto-fill, minmax(118px, 1fr));
+  gap: 1px;
+  background: var(--odl-border);
+  border: 1px solid var(--odl-border);
+  border-radius: var(--odl-radius-lg);
+  overflow: hidden;
+}
+.bindingCard {
+  background: var(--odl-surface);
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  gap: var(--odl-space-3);
+  padding: var(--odl-space-5) var(--odl-space-3);
+  transition: background-color var(--odl-dur) var(--odl-ease);
+}
+.bindingCard:hover {
+  background: var(--odl-surface-2);
+}
+.bindingCard img {
+  width: 30px;
+  height: 30px;
+  object-fit: contain;
+}
+.bindingName {
+  font-family: var(--odl-font-mono);
+  font-size: var(--odl-text-xs);
+  color: var(--odl-fg-muted);
+}
+
+/* ===== Layers (tile grid left, live code preview right) ================= */
+.layerExplorer {
+  display: grid;
+  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
+  gap: clamp(2rem, 1rem + 3vw, 3.5rem);
+  align-items: start;
+}
+.layerGrid {
+  display: grid;
+  grid-template-columns: repeat(2, 1fr);
+  gap: 1px;
+  background: var(--odl-border);
+  border: 1px solid var(--odl-border);
+  border-radius: var(--odl-radius-lg);
+  overflow: hidden;
+}
+.layerItem {
+  display: flex;
+  flex-direction: column;
+  gap: 4px;
+  padding: var(--odl-space-4);
+  background: var(--odl-surface);
+  text-decoration: none;
+  transition: background-color var(--odl-dur) var(--odl-ease);
+}
+.layerItem:hover {
+  background: var(--odl-surface-2);
+  text-decoration: none;
+}
+.layerItemActive {
+  background: var(--odl-surface-2);
+}
+.layerName {
+  font-family: var(--odl-font-mono);
+  font-size: var(--odl-text-sm);
+  font-weight: 600;
+  color: var(--odl-fg-strong);
+  transition: color var(--odl-dur) var(--odl-ease);
+}
+.layerItemActive .layerName {
+  color: var(--odl-accent);
+}
+.layerDesc {
+  font-size: var(--odl-text-xs);
+  line-height: var(--odl-leading-snug);
+  color: var(--odl-fg-muted);
+}
+.layerCodeBody {
+  height: 13rem;
+  overflow: auto;
+  background: var(--odl-code-bg);
+}
+
+/* ===== Final CTA ======================================================== */
+.finalCta {
+  background: var(--odl-surface);
+  border: 1px solid var(--odl-border);
+  border-radius: var(--odl-radius-lg);
+  box-shadow: var(--odl-shadow-sm);
+  padding: clamp(2.5rem, 1.5rem + 5vw, 5rem);
+  text-align: center;
+}
+.finalCtaInner {
+  position: relative;
+}
+.finalCtaTitle {
+  font-size: clamp(2rem, 1.3rem + 3vw, 3.25rem);
+  font-weight: 700;
+  letter-spacing: var(--odl-tracking-tight);
+  margin: var(--odl-space-4) 0 0;
+  color: var(--odl-fg-strong);
+}
+.finalCtaLede {
+  font-size: var(--odl-text-md);
+  color: var(--odl-fg-muted);
+  margin: var(--odl-space-4) auto 0;
+  max-width: 34rem;
+}
+.finalCtaActions {
+  display: flex;
+  flex-wrap: wrap;
+  gap: var(--odl-space-3);
+  justify-content: center;
+  margin-top: var(--odl-space-6);
+}
+.finalEyebrow {
+  justify-content: center;
+}
+.finalCenter {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+/* ===== Reveal-on-scroll — pure CSS, progressive enhancement ============= */
+/* Content is never hidden without support: browsers lacking scroll-driven
+   animations (or users who prefer reduced motion) simply see it immediately. 
*/
+@media (prefers-reduced-motion: no-preference) {
+  @supports (animation-timeline: view()) {
+    .reveal {
+      animation: odlReveal linear both;
+      animation-timeline: view();
+      animation-range: entry 2% cover 18%;
+    }
+  }
+}
+@keyframes odlReveal {
+  from {
+    opacity: 0;
+    transform: translateY(18px);
+  }
+  to {
+    opacity: 1;
+    transform: none;
+  }
+}
+
+/* ===== Responsive ======================================================= */
+@media (max-width: 996px) {
+  .heroInner,
+  .capabilityExplorer,
+  .layerExplorer {
+    grid-template-columns: 1fr;
+  }
+  .capabilityPreview {
+    display: none;
+  }
+  .capabilityNav {
+    display: grid;
+    grid-template-columns: repeat(2, 1fr);
+    gap: var(--odl-space-3);
+  }
+  .serviceGroups {
+    grid-template-columns: repeat(2, 1fr);
+  }
+  .heroAside {
+    order: 2;
+  }
+}
+
+@media (max-width: 640px) {
+  .valueGrid,
+  .serviceGroups,
+  .capabilityNav {
+    grid-template-columns: 1fr;
+  }
+  .heroStats {
+    grid-template-columns: repeat(2, 1fr);
+    gap: var(--odl-space-5) var(--odl-space-4);
+  }
+  .heroActions .btn {
+    flex: 1 1 auto;
+  }
+}
diff --git a/website/src/css/custom.css b/website/src/css/custom.css
index ff706266e..2ee0a5aa6 100644
--- a/website/src/css/custom.css
+++ b/website/src/css/custom.css
@@ -17,86 +17,422 @@
  * under the License.
  */
 
-/**
- * Any CSS included here will be global. The classic template
- * bundles Infima by default. Infima is a CSS framework designed to
- * work well for content-centric websites.
- */
+/* ==========================================================================
+   OpenDAL Design System
+   --------------------------------------------------------------------------
+   "One Layer, All Storage." A precise, engineering-grade visual system built
+   on a near-monochrome ink scale, a single precise-blue accent, and the
+   signature solid "bar" lifted from the OpenDAL wordmark.
+
+   Token layers:
+     1. Primitives  — raw, theme-agnostic values (--odl-ink-*, --odl-blue-*)
+     2. Semantic    — meaning-bound, theme-aware roles (--odl-bg, --odl-fg ...)
+     3. Infima map  — semantic tokens projected onto Docusaurus/Infima vars so
+                      docs, blog and community pages inherit the same system.
+
+   Typography uses native system stacks on purpose: zero third-party requests
+   (ASF privacy-friendly), zero layout shift, instant global rendering. The
+   monospace stack is promoted to a brand motif (labels, indices, figures).
+   To adopt IBM Plex instead, self-host it and swap --odl-font-* below.
+   ========================================================================== 
*/
 
-/* You can override the default Infima variables here. */
+/* ---- 1. Primitive tokens ------------------------------------------------- 
*/
 :root {
-  --ifm-color-primary:  #44A1F6;
-  --ifm-color-primary-dark:  #2692F5;
-  --ifm-color-primary-darker:  #178AF4;
-  --ifm-color-primary-darkest:  #0A72D2;
-  --ifm-color-primary-light:  #62B0F7;
-  --ifm-color-primary-lighter:  #71B8F8;
-  --ifm-color-primary-lightest:  #9ECEFA;
-  --ifm-background-color:  #ffffff;
-  --ifm-code-font-size: 95%;
-  --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
-
-  --footer-font-color: black;
+  /* Ink — a cool, neutral near-black→white ramp */
+  --odl-ink-0: #ffffff;
+  --odl-ink-50: #f6f8fa;
+  --odl-ink-100: #edf1f5;
+  --odl-ink-150: #e4e9ef;
+  --odl-ink-200: #d8dee6;
+  --odl-ink-300: #c2cad4;
+  --odl-ink-400: #98a2b0;
+  --odl-ink-500: #6e7886;
+  --odl-ink-600: #4f5864;
+  --odl-ink-700: #39414b;
+  --odl-ink-800: #262c34;
+  --odl-ink-850: #1b2027;
+  --odl-ink-900: #12161b;
+  --odl-ink-950: #0a0d11;
+
+  /* Precise blue — the single brand accent */
+  --odl-blue-50: #edf3ff;
+  --odl-blue-100: #d8e5ff;
+  --odl-blue-200: #b4ccff;
+  --odl-blue-300: #85a9ff;
+  --odl-blue-400: #5384ff;
+  --odl-blue-500: #2c63f5;
+  --odl-blue-600: #1e54e0;
+  --odl-blue-700: #1846be;
+  --odl-blue-800: #163a97;
+  --odl-blue-900: #163172;
+
+  /* Functional signals (kept restrained, mostly for inherited docs UI) */
+  --odl-green-500: #1a8f5e;
+  --odl-green-400: #36c08a;
+  --odl-amber-500: #b7791f;
+  --odl-amber-400: #e0a93b;
+  --odl-red-500: #d23b3b;
+  --odl-red-400: #f06363;
+
+  /* Type families — system stacks with a clear engineering character */
+  --odl-font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
+    Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif,
+    "Apple Color Emoji", "Segoe UI Emoji";
+  --odl-font-mono: ui-monospace, "SF Mono", SFMono-Regular, "Cascadia Code",
+    "JetBrains Mono", "Roboto Mono", Menlo, Consolas, "Liberation Mono",
+    monospace;
+
+  /* Type scale */
+  --odl-text-2xs: 0.6875rem; /* 11px — mono micro-labels */
+  --odl-text-xs: 0.75rem; /* 12px */
+  --odl-text-sm: 0.875rem; /* 14px */
+  --odl-text-base: 1rem; /* 16px */
+  --odl-text-md: 1.125rem; /* 18px */
+  --odl-text-lg: 1.375rem; /* 22px */
+  --odl-text-xl: 1.75rem; /* 28px */
+  --odl-text-2xl: 2.25rem; /* 36px */
+  --odl-text-3xl: 3rem; /* 48px */
+  --odl-text-display: clamp(2.75rem, 1.6rem + 5.2vw, 5rem);
+  --odl-leading-tight: 1.08;
+  --odl-leading-snug: 1.28;
+  --odl-leading-normal: 1.6;
+  --odl-tracking-tight: -0.022em;
+  --odl-tracking-label: 0.12em;
+
+  /* Spacing — 4px rhythm */
+  --odl-space-1: 0.25rem;
+  --odl-space-2: 0.5rem;
+  --odl-space-3: 0.75rem;
+  --odl-space-4: 1rem;
+  --odl-space-5: 1.5rem;
+  --odl-space-6: 2rem;
+  --odl-space-7: 3rem;
+  --odl-space-8: 4rem;
+  --odl-space-9: 6rem;
+  --odl-space-10: 8rem;
+
+  /* Radius — restrained; the bar motif stays sharp (0) */
+  --odl-radius-xs: 3px;
+  --odl-radius-sm: 5px;
+  --odl-radius-md: 8px;
+  --odl-radius-lg: 12px;
+  --odl-radius-pill: 999px;
+
+  /* Layout */
+  --odl-container: 1200px;
+  --odl-container-narrow: 880px;
+  --odl-gutter: clamp(1.25rem, 1rem + 2vw, 2.5rem);
+
+  /* Motion */
+  --odl-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
+  --odl-ease: cubic-bezier(0.4, 0, 0.2, 1);
+  --odl-dur-fast: 120ms;
+  --odl-dur: 200ms;
+  --odl-dur-slow: 320ms;
+}
+
+/* ---- 2. Semantic tokens — light (default) -------------------------------- 
*/
+:root {
+  --odl-bg: var(--odl-ink-0);
+  --odl-bg-subtle: var(--odl-ink-50);
+  --odl-bg-inset: var(--odl-ink-100);
+  --odl-surface: var(--odl-ink-0);
+  --odl-surface-2: var(--odl-ink-50);
+  --odl-fg: var(--odl-ink-900);
+  --odl-fg-strong: var(--odl-ink-950);
+  --odl-fg-muted: var(--odl-ink-600);
+  --odl-fg-subtle: var(--odl-ink-500);
+  --odl-border: var(--odl-ink-200);
+  --odl-border-strong: var(--odl-ink-300);
+  --odl-bar: var(--odl-ink-950);
+
+  --odl-accent: var(--odl-blue-600);
+  --odl-accent-hover: var(--odl-blue-700);
+  --odl-accent-subtle: var(--odl-blue-50);
+  --odl-accent-border: var(--odl-blue-200);
+  --odl-link: var(--odl-blue-600);
+
+  /* Solid action surface — vivid blue with white text in both themes */
+  --odl-action-bg: var(--odl-blue-600);
+  --odl-action-bg-hover: var(--odl-blue-700);
+  --odl-action-fg: #ffffff;
+
+  --odl-code-bg: var(--odl-ink-50);
+  --odl-code-border: var(--odl-ink-150);
+  --odl-selection: var(--odl-blue-100);
+
+  --odl-grid-line: rgba(18, 22, 27, 0.05);
+  --odl-shadow-sm: 0 1px 2px rgba(10, 13, 17, 0.06),
+    0 1px 1px rgba(10, 13, 17, 0.04);
+  --odl-shadow-md: 0 4px 12px rgba(10, 13, 17, 0.07),
+    0 1px 3px rgba(10, 13, 17, 0.05);
+  --odl-shadow-lg: 0 18px 40px rgba(10, 13, 17, 0.1),
+    0 4px 12px rgba(10, 13, 17, 0.06);
+}
 
+/* ---- 2b. Semantic tokens — dark ------------------------------------------ 
*/
+[data-theme="dark"] {
+  --odl-bg: #0a0d11;
+  --odl-bg-subtle: #0e1218;
+  --odl-bg-inset: #12161d;
+  --odl-surface: #11161c;
+  --odl-surface-2: #161c24;
+  --odl-fg: #e7ebf0;
+  --odl-fg-strong: #f6f8fa;
+  --odl-fg-muted: #9aa6b3;
+  --odl-fg-subtle: #76828f;
+  --odl-border: #242c35;
+  --odl-border-strong: #313b46;
+  --odl-bar: #f6f8fa;
+
+  --odl-accent: var(--odl-blue-300);
+  --odl-accent-hover: var(--odl-blue-200);
+  --odl-accent-subtle: rgba(44, 99, 245, 0.14);
+  --odl-accent-border: rgba(133, 169, 255, 0.32);
+  --odl-link: var(--odl-blue-300);
+
+  --odl-action-bg: var(--odl-blue-500);
+  --odl-action-bg-hover: var(--odl-blue-400);
+  --odl-action-fg: #ffffff;
+
+  --odl-code-bg: #0e131a;
+  --odl-code-border: #232b35;
+  --odl-selection: rgba(44, 99, 245, 0.36);
+
+  --odl-grid-line: rgba(255, 255, 255, 0.045);
+  --odl-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
+  --odl-shadow-md: 0 6px 18px rgba(0, 0, 0, 0.5);
+  --odl-shadow-lg: 0 22px 48px rgba(0, 0, 0, 0.6);
+}
+
+/* ---- 3. Project onto Infima so docs/blog inherit the system -------------- 
*/
+:root {
+  --ifm-color-primary: #1e54e0;
+  --ifm-color-primary-dark: #1b4bca;
+  --ifm-color-primary-darker: #1846be;
+  --ifm-color-primary-darkest: #163a9c;
+  --ifm-color-primary-light: #3568ef;
+  --ifm-color-primary-lighter: #4c79f1;
+  --ifm-color-primary-lightest: #79a0f5;
+
+  --ifm-background-color: var(--odl-bg);
+  --ifm-background-surface-color: var(--odl-surface);
+  --ifm-font-color-base: var(--odl-fg);
+  --ifm-heading-color: var(--odl-fg-strong);
+  --ifm-font-family-base: var(--odl-font-sans);
+  --ifm-heading-font-family: var(--odl-font-sans);
+  --ifm-font-family-monospace: var(--odl-font-mono);
+  --ifm-font-size-base: 16px;
+  --ifm-line-height-base: 1.6;
+  --ifm-link-color: var(--odl-link);
+  --ifm-link-hover-color: var(--odl-accent-hover);
+
+  --ifm-heading-font-weight: 650;
+  --ifm-font-weight-semibold: 600;
+
+  --ifm-navbar-background-color: rgba(255, 255, 255, 0.82);
+  --ifm-navbar-shadow: inset 0 -1px 0 var(--odl-border);
+  --ifm-navbar-link-color: var(--odl-fg-muted);
+  --ifm-navbar-link-hover-color: var(--odl-fg-strong);
+
+  --ifm-toc-border-color: var(--odl-border);
+  --ifm-color-emphasis-200: var(--odl-border);
+  --ifm-color-emphasis-300: var(--odl-border-strong);
+
+  --ifm-code-font-size: 0.9em;
+  --ifm-code-background: var(--odl-code-bg);
+  --ifm-code-border-radius: var(--odl-radius-sm);
+  --ifm-pre-background: var(--odl-code-bg);
+
+  --ifm-button-border-radius: var(--odl-radius-md);
+  --ifm-global-radius: var(--odl-radius-md);
+
+  --docusaurus-highlighted-code-line-bg: rgba(30, 84, 224, 0.1);
+
+  --footer-font-color: var(--odl-fg-muted);
   --footer-column-width: unset;
-  --footer-row-max-width: 1000px;
+  --footer-row-max-width: 1100px;
 }
 
-/* For readability concerns, you should choose a lighter palette in dark mode. 
*/
-[data-theme='dark'] {
-  --ifm-color-primary: #25c2a0;
-  --ifm-color-primary-dark: #21af90;
-  --ifm-color-primary-darker: #1fa588;
-  --ifm-color-primary-darkest: #1a8870;
-  --ifm-color-primary-light: #29d5b0;
-  --ifm-color-primary-lighter: #32d8b4;
-  --ifm-color-primary-lightest: #4fddbf;
-  --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
+[data-theme="dark"] {
+  --ifm-color-primary: #5384ff;
+  --ifm-color-primary-dark: #3568ef;
+  --ifm-color-primary-darker: #2c63f5;
+  --ifm-color-primary-darkest: #1e54e0;
+  --ifm-color-primary-light: #79a0f5;
+  --ifm-color-primary-lighter: #95b5f8;
+  --ifm-color-primary-lightest: #b4ccff;
 
-  --footer-font-color: white;
+  --ifm-navbar-background-color: rgba(10, 13, 17, 0.78);
+  --ifm-navbar-shadow: inset 0 -1px 0 var(--odl-border);
+  --docusaurus-highlighted-code-line-bg: rgba(83, 132, 255, 0.16);
 }
 
-.header-github-link:hover {
-  opacity: 0.6;
+/* ---- 4. Base element styling --------------------------------------------- 
*/
+html {
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  text-rendering: optimizeLegibility;
 }
 
-.header-github-link::before {
-  content: '';
-  width: 24px;
-  height: 24px;
-  display: flex;
-  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' 
xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 
0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 
0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 
17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 
1.07 1.835 2.809 1.305 
3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 
0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.52 [...]
-  no-repeat;
+body {
+  background-color: var(--odl-bg);
+  color: var(--odl-fg);
+  font-feature-settings: "cv05" 1, "ss01" 1;
 }
 
-[data-theme='dark'] .header-github-link::before {
-  background: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' 
xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 
0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 
0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 
17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 
1.07 1.835 2.809 1.305 
3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 
0-1.31.465-2.38 1.235-3.22-.135- [...]
-  no-repeat;
+h1,
+h2,
+h3,
+h4 {
+  letter-spacing: var(--odl-tracking-tight);
 }
 
+::selection {
+  background: var(--odl-selection);
+}
+
+:focus-visible {
+  outline: 2px solid var(--odl-accent);
+  outline-offset: 2px;
+  border-radius: var(--odl-radius-xs);
+}
+
+/* Translucent, blurred navbar for a precise, layered feel */
+.navbar {
+  backdrop-filter: saturate(180%) blur(12px);
+  -webkit-backdrop-filter: saturate(180%) blur(12px);
+}
+
+.navbar__logo {
+  height: 1.85rem;
+}
+.navbar__logo img {
+  height: 100%;
+}
+.navbar__title {
+  font-weight: 650;
+  letter-spacing: var(--odl-tracking-tight);
+}
+
+/* Tabs/Prism code surfaces align to the system */
+.theme-code-block,
+pre[class*="language-"] {
+  border: 1px solid var(--odl-code-border);
+  border-radius: var(--odl-radius-md);
+}
+
+/* ---- 5. Brand motif: the solid "bar" ------------------------------------- 
*/
+/* The signature OpenDAL bar — a sharp solid rectangle used as a structural
+   marker, divider and emphasis throughout the system. */
+.odl-bar {
+  display: inline-block;
+  width: 2.25rem;
+  height: 0.5rem;
+  background: var(--odl-bar);
+  border-radius: 0;
+}
+
+/* Eyebrow / kicker label: monospace, uppercase, led by a small accent bar */
+.odl-eyebrow {
+  display: inline-flex;
+  align-items: center;
+  gap: var(--odl-space-3);
+  font-family: var(--odl-font-mono);
+  font-size: var(--odl-text-xs);
+  font-weight: 500;
+  letter-spacing: var(--odl-tracking-label);
+  text-transform: uppercase;
+  color: var(--odl-fg-muted);
+}
+.odl-eyebrow::before {
+  content: "";
+  width: 1.5rem;
+  height: 0.5rem;
+  background: var(--odl-accent);
+  flex: none;
+}
+
+/* Shared layout helpers used by landing sections */
+.odl-container {
+  width: 100%;
+  max-width: var(--odl-container);
+  margin-inline: auto;
+  padding-inline: var(--odl-gutter);
+}
+
+/* Faint blueprint grid — engineering texture for select surfaces */
+.odl-grid-bg {
+  background-image: linear-gradient(
+      var(--odl-grid-line) 1px,
+      transparent 1px
+    ),
+    linear-gradient(90deg, var(--odl-grid-line) 1px, transparent 1px);
+  background-size: 44px 44px;
+}
+
+/* Tabular figures for any numeric/metric display */
+.odl-tabular {
+  font-family: var(--odl-font-mono);
+  font-variant-numeric: tabular-nums;
+}
+
+/* ---- 6. Header icons (GitHub / Discord) ---------------------------------- 
*/
+.header-github-link:hover,
 .header-discord-link:hover {
   opacity: 0.6;
 }
 
-/* Already suitable for dark mode */
-.header-discord-link::before {
-  content: '';
-  width: 24px;
-  height: 24px;
+.header-github-link::before {
+  content: "";
+  width: 22px;
+  height: 22px;
   display: flex;
-  background: url("data:image/svg+xml,%3Csvg 
xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='currentColor' 
class='bi bi-discord' viewBox='0 0 16 16'%3E%3Cpath d='M13.545 2.907a13.227 
13.227 0 0 0-3.257-1.011.05.05 0 0 0-.052.025c-.141.25-.297.577-.406.833a12.19 
12.19 0 0 0-3.658 0 8.258 8.258 0 0 0-.412-.833.051.051 0 0 
0-.052-.025c-1.125.194-2.22.534-3.257 1.011a.041.041 0 0 0-.021.018C.356 
6.024-.213 9.047.066 12.032c.001.014.01.028.021.037a13.276 13.276 0 0 0 3.995 
2.0 [...]
-  no-repeat;
+  background-color: var(--odl-fg-muted);
+  -webkit-mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' 
xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 
0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 
0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 
17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 
1.07 1.835 2.809 1.305 
3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 
0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1. [...]
+    no-repeat center / contain;
+  mask: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' 
xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 
0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 
0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 
17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 
1.07 1.835 2.809 1.305 
3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 
0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105- [...]
+    no-repeat center / contain;
 }
 
-/* set copyright font size */
-.footer__copyright {
-  font-size: .7em;
+.header-discord-link::before {
+  content: "";
+  width: 22px;
+  height: 22px;
+  display: flex;
+  background-color: var(--odl-fg-muted);
+  -webkit-mask: url("data:image/svg+xml,%3Csvg 
xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='currentColor' 
viewBox='0 0 16 16'%3E%3Cpath d='M13.545 2.907a13.227 13.227 0 0 
0-3.257-1.011.05.05 0 0 0-.052.025c-.141.25-.297.577-.406.833a12.19 12.19 0 0 
0-3.658 0 8.258 8.258 0 0 0-.412-.833.051.051 0 0 
0-.052-.025c-1.125.194-2.22.534-3.257 1.011a.041.041 0 0 0-.021.018C.356 
6.024-.213 9.047.066 12.032c.001.014.01.028.021.037a13.276 13.276 0 0 0 3.995 
2.02.05.05 0 0 0 .056-. [...]
+    no-repeat center / contain;
+  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' 
width='24' height='24' fill='currentColor' viewBox='0 0 16 16'%3E%3Cpath 
d='M13.545 2.907a13.227 13.227 0 0 0-3.257-1.011.05.05 0 0 
0-.052.025c-.141.25-.297.577-.406.833a12.19 12.19 0 0 0-3.658 0 8.258 8.258 0 0 
0-.412-.833.051.051 0 0 0-.052-.025c-1.125.194-2.22.534-3.257 1.011a.041.041 0 
0 0-.021.018C.356 6.024-.213 9.047.066 12.032c.001.014.01.028.021.037a13.276 
13.276 0 0 0 3.995 2.02.05.05 0 0 0 .056-.019c.308 [...]
+    no-repeat center / contain;
 }
 
-.navbar__logo img {
-  height: 120%;
+/* ---- 7. Footer ----------------------------------------------------------- 
*/
+.footer {
+  background-color: var(--odl-bg-subtle);
+  border-top: 1px solid var(--odl-border);
+}
+.footer__copyright {
+  font-size: 0.75em;
+  color: var(--odl-fg-subtle);
+  margin-top: var(--odl-space-4);
 }
-
 .footer__logo {
   margin-top: unset;
+  max-width: 280px;
+}
+[data-theme="dark"] .footer__logo {
+  filter: brightness(0) invert(1) opacity(0.7);
+}
+
+/* ---- 8. Reduced motion --------------------------------------------------- 
*/
+@media (prefers-reduced-motion: reduce) {
+  *,
+  *::before,
+  *::after {
+    animation-duration: 0.01ms !important;
+    animation-iteration-count: 1 !important;
+    transition-duration: 0.01ms !important;
+    scroll-behavior: auto !important;
+  }
 }
diff --git a/website/src/pages/index.jsx b/website/src/pages/index.jsx
new file mode 100644
index 000000000..b6b6c7b88
--- /dev/null
+++ b/website/src/pages/index.jsx
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import React from "react";
+import Layout from "@theme/Layout";
+import {
+  Hero,
+  UsedBy,
+  ValueProps,
+  Capabilities,
+  Services,
+  Bindings,
+  Layers,
+  FinalCta,
+} from "../components/landing/sections";
+
+export default function Home() {
+  return (
+    <Layout
+      title="One Layer, All Storage"
+      description="Apache OpenDAL™ is an Open Data Access Layer that gives 
every language a unified, zero-cost way to access object storage, file systems, 
cloud SaaS, databases, protocols and key-value services."
+    >
+      <main>
+        <Hero />
+        <UsedBy />
+        <ValueProps />
+        <Capabilities />
+        <Services />
+        <Bindings />
+        <Layers />
+        <FinalCta />
+      </main>
+    </Layout>
+  );
+}
diff --git a/website/static/img/users/cratedb.png 
b/website/static/img/users/cratedb.png
new file mode 100644
index 000000000..f65bfd245
Binary files /dev/null and b/website/static/img/users/cratedb.png differ
diff --git a/website/static/img/users/daft.png 
b/website/static/img/users/daft.png
new file mode 100644
index 000000000..cd845656c
Binary files /dev/null and b/website/static/img/users/daft.png differ
diff --git a/website/static/img/users/databend.png 
b/website/static/img/users/databend.png
new file mode 100644
index 000000000..908975ca6
Binary files /dev/null and b/website/static/img/users/databend.png differ
diff --git a/website/static/img/users/datafusion-comet.png 
b/website/static/img/users/datafusion-comet.png
new file mode 100644
index 000000000..c8aaed47d
Binary files /dev/null and b/website/static/img/users/datafusion-comet.png 
differ
diff --git a/website/static/img/users/dify.png 
b/website/static/img/users/dify.png
new file mode 100644
index 000000000..d4c3195c1
Binary files /dev/null and b/website/static/img/users/dify.png differ
diff --git a/website/static/img/users/gravitino.png 
b/website/static/img/users/gravitino.png
new file mode 100644
index 000000000..c8aaed47d
Binary files /dev/null and b/website/static/img/users/gravitino.png differ
diff --git a/website/static/img/users/greptimedb.png 
b/website/static/img/users/greptimedb.png
new file mode 100644
index 000000000..de5d5eb61
Binary files /dev/null and b/website/static/img/users/greptimedb.png differ
diff --git a/website/static/img/users/hasura.png 
b/website/static/img/users/hasura.png
new file mode 100644
index 000000000..bfd043810
Binary files /dev/null and b/website/static/img/users/hasura.png differ
diff --git a/website/static/img/users/iceberg-rust.png 
b/website/static/img/users/iceberg-rust.png
new file mode 100644
index 000000000..c8aaed47d
Binary files /dev/null and b/website/static/img/users/iceberg-rust.png differ
diff --git a/website/static/img/users/kubeflow-trainer.png 
b/website/static/img/users/kubeflow-trainer.png
new file mode 100644
index 000000000..8cc9ba859
Binary files /dev/null and b/website/static/img/users/kubeflow-trainer.png 
differ
diff --git a/website/static/img/users/lance.png 
b/website/static/img/users/lance.png
new file mode 100644
index 000000000..ed288e5b1
Binary files /dev/null and b/website/static/img/users/lance.png differ
diff --git a/website/static/img/users/llamaindex.png 
b/website/static/img/users/llamaindex.png
new file mode 100644
index 000000000..731c902e4
Binary files /dev/null and b/website/static/img/users/llamaindex.png differ
diff --git a/website/static/img/users/lnx.png b/website/static/img/users/lnx.png
new file mode 100644
index 000000000..dfae753ef
Binary files /dev/null and b/website/static/img/users/lnx.png differ
diff --git a/website/static/img/users/loco.png 
b/website/static/img/users/loco.png
new file mode 100644
index 000000000..e952fa04e
Binary files /dev/null and b/website/static/img/users/loco.png differ
diff --git a/website/static/img/users/octobase.png 
b/website/static/img/users/octobase.png
new file mode 100644
index 000000000..aaf33dfe3
Binary files /dev/null and b/website/static/img/users/octobase.png differ
diff --git a/website/static/img/users/openraft.png 
b/website/static/img/users/openraft.png
new file mode 100644
index 000000000..908975ca6
Binary files /dev/null and b/website/static/img/users/openraft.png differ
diff --git a/website/static/img/users/pants.png 
b/website/static/img/users/pants.png
new file mode 100644
index 000000000..b9ebd5fbf
Binary files /dev/null and b/website/static/img/users/pants.png differ
diff --git a/website/static/img/users/pathway.png 
b/website/static/img/users/pathway.png
new file mode 100644
index 000000000..8939308f2
Binary files /dev/null and b/website/static/img/users/pathway.png differ
diff --git a/website/static/img/users/questdb.png 
b/website/static/img/users/questdb.png
new file mode 100644
index 000000000..663fb3c66
Binary files /dev/null and b/website/static/img/users/questdb.png differ
diff --git a/website/static/img/users/quickwit.png 
b/website/static/img/users/quickwit.png
new file mode 100644
index 000000000..230241887
Binary files /dev/null and b/website/static/img/users/quickwit.png differ
diff --git a/website/static/img/users/ragflow.png 
b/website/static/img/users/ragflow.png
new file mode 100644
index 000000000..5bc5c186f
Binary files /dev/null and b/website/static/img/users/ragflow.png differ
diff --git a/website/static/img/users/risingwave.png 
b/website/static/img/users/risingwave.png
new file mode 100644
index 000000000..ece3bd7d5
Binary files /dev/null and b/website/static/img/users/risingwave.png differ
diff --git a/website/static/img/users/robustmq.png 
b/website/static/img/users/robustmq.png
new file mode 100644
index 000000000..d13539b64
Binary files /dev/null and b/website/static/img/users/robustmq.png differ
diff --git a/website/static/img/users/rustic.png 
b/website/static/img/users/rustic.png
new file mode 100644
index 000000000..53e2a2773
Binary files /dev/null and b/website/static/img/users/rustic.png differ
diff --git a/website/static/img/users/sccache.png 
b/website/static/img/users/sccache.png
new file mode 100644
index 000000000..e5a7b2fc0
Binary files /dev/null and b/website/static/img/users/sccache.png differ
diff --git a/website/static/img/users/seatunnel.png 
b/website/static/img/users/seatunnel.png
new file mode 100644
index 000000000..c8aaed47d
Binary files /dev/null and b/website/static/img/users/seatunnel.png differ
diff --git a/website/static/img/users/slatedb.png 
b/website/static/img/users/slatedb.png
new file mode 100644
index 000000000..16b3d3e9c
Binary files /dev/null and b/website/static/img/users/slatedb.png differ
diff --git a/website/static/img/users/spiceai.png 
b/website/static/img/users/spiceai.png
new file mode 100644
index 000000000..19e0eceef
Binary files /dev/null and b/website/static/img/users/spiceai.png differ
diff --git a/website/static/img/users/vaultwarden.png 
b/website/static/img/users/vaultwarden.png
new file mode 100644
index 000000000..394dcae93
Binary files /dev/null and b/website/static/img/users/vaultwarden.png differ
diff --git a/website/static/img/users/vector.png 
b/website/static/img/users/vector.png
new file mode 100644
index 000000000..b8a7bf4d9
Binary files /dev/null and b/website/static/img/users/vector.png differ
diff --git a/website/static/img/users/walrus.png 
b/website/static/img/users/walrus.png
new file mode 100644
index 000000000..c87b21729
Binary files /dev/null and b/website/static/img/users/walrus.png differ
diff --git a/website/static/img/users/wrenai.png 
b/website/static/img/users/wrenai.png
new file mode 100644
index 000000000..5de193a81
Binary files /dev/null and b/website/static/img/users/wrenai.png differ
diff --git a/website/static/img/users/zino.png 
b/website/static/img/users/zino.png
new file mode 100644
index 000000000..df460333e
Binary files /dev/null and b/website/static/img/users/zino.png differ

Reply via email to