diff --git a/docs/spec/intro.mdx b/docs/spec/intro.mdx
index 95e6b78ff..66fadd911 100644
--- a/docs/spec/intro.mdx
+++ b/docs/spec/intro.mdx
@@ -6,143 +6,266 @@ hide_table_of_contents: true
---
import siteConfig from '@site/docusaurus.config';
-The RISC-V Library contains a comprehensive list of all of the ratified RISC-V technical publications.
-
-## Instruction Set (ISA) Specifications
-
-These are the current ratified versions of the ISA specifications. Previously published versions and the original ratification specifications for included extensions can be found on the [RISC-V Technical Specifications Archive page](https://lf-riscv.atlassian.net/wiki/spaces/HOME/pages/16154899/RISC-V+Technical+Specifications+Archive).
-
-
-
-
-
- Volume I
-
-
- Unprivileged Architecture
-
-
-
- Version: May 2024
-
-
-
-
-
-
-
-
- Volume II
-
-
- Privileged Architecture
-
-
-
- Version: May 2024
-
-
-
-
-
+
+# Overview
+
The RISC-V Library contains a comprehensive list of all of the ratified RISC-V technical publications.
+
-:::note
-Extensions that are ratified, but not yet included in the full specifications, can be found on the [RISC-V Ratified Extensions](https://lf-riscv.atlassian.net/wiki/spaces/HOME/pages/16154732/Ratified+Extensions) page.
-:::
+
+
+
+## RISC-V Instruction Set (ISA) Specifications
+These are the current ratified versions of the ISA specifications. Previously published versions and the original ratification specifications can be found at More details for each volume.
+
+
+
+
+ Version: 20250508
+ Published: May 2025
+
+ Version: 20250508
+ Published: May 2025
+
+
+ Version: 20250508
+ Published: May 2025
+
+
+ Find extensions that are ratified, but not included in the current, ratified specifications.
+
+
+
---
+
## Profiles
These are the current, published versions of the Profiles specifications.
-
-
-
- RVA23 Profile
-
-
- Focused on Servers and application class processors.
-
-
-
- Version: October 2024
-
-
-
-
-
-
-
-
- RVB23 Profile
-
-
- Focused on Edge embedded Devices.
-
-
-
- Version: October 2024
-
-
-
-
-
-
-
-
- RISC-V Profiles
-
-
- The older profiles. Archived for historical purposes
-
-
-
- Version: March 2023
-
-
-
-
+
+
+
+ RVA23 Profile
+
+
+ Focused on Servers and application class processors.
+
+
+
+ Version: October 2024
+
+
+
+
+
+
+
+
+ RVB23 Profile
+
+
+ Focused on Edge embedded Devices.
+
+
+
+ Version: October 2024
+
+
+
+
+
+
+
+
+ RISC-V Profiles
+
+
+ The older profiles. Archived for historical purposes
+
+
+
+ Version: March 2023
+
+
+
+
+
---
+
## Processor Infrastructure
-- [RISC-V Advanced Interrupt Architecture](./non-isa/advanced-interrupt)
-- [RISC-V IO Mapping Table Specification](./non-isa/io-mapping)
-- [RISC-V IOMMU Architecture Specification ](./non-isa/iommu-architecture)
-- [RISC-V Platform-Level Interrupt Controller Specification](./non-isa/platform-interrupt)
-- [RISC-V Server SOC Specification](./non-isa/server-soc)
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum imperdiet.
+
+
+ Lorem ipsum dolor sit amet, consectetur elit.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum imperdiet.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+
+
+
+
+---
+
## Debug, Trace, & RAS
-- [The RISC-V Debug Specification](./non-isa/debug)
-- [Efficient Trace for RISC-V](./non-isa/efficient-trace)
-- [RISC-V N-Trace (Nexus-based Trace)](./non-isa/n-trace)
-- [RISC-V Capacity and Bandwidth QoS Register Interface](./non-isa/qos)
-- [RISC-V RERI Architecture Specification](./non-isa/reri)
-- [RISC-V Trace Connectors](./non-isa/trace-conectors)
-- [RISC-V Trace Control Interface](./non-isa/trace-control-interface)
-- [Unformatted Trace & Diagnostic Data Packet Encapsulation for RISC-V](./non-isa/unformatted-trace)
+
+
+
+ The RISC-V Debug Specification
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque tincidunt.
+
+
+ View Spec
+
+
+
+
+
+
+
+ Efficient Trace for RISC-V
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+
+
+ View Spec
+
+
+
+
+
+
+
+ RISC-V N-Trace (Nexus-based Trace)
+ Lorem ipsum dolor sit amet, consectetur adipiscing.
+
+
+ View Spec
+
+
+
+
+
+
+
+ RISC-V Capacity and Bandwidth QoS Register Interface
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque tincidunt lorem nec.
+
+
+ View Spec
+
+
+
+
+
+
+
+ RISC-V RERI Architecture Specification
+ Lorem ipsum dolor sit amet, consectetur.
+
+
+ View Spec
+
+
+
+
+
+
+
+ RISC-V Trace Connectors
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+
+
+ View Spec
+
+
+
+
+
+
+
+ RISC-V Trace Control Interface
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+
+
+ View Spec
+
+
+
+
+
+
+
+ Unformatted Trace & Diagnostic Data Packet Encapsulation for RISC-V
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque.
+
+
+ View Spec
+
+
+
+
+
+
+
+---
+
## Platform Software
-- [RISC-V Functional Fixed Hardware Specification](./non-isa/functional-fixed)
-- [RISC-V Semihosting](./non-isa/semihosting)
-- [RISC-V Supervisor Binary Interface Specification](./non-isa/sbi)
-- [RISC-V UEFI Protocol Specification](./non-isa/uefi)
-## Application Software
-- [RISC-V ABIs Specification](./non-isa/abi)
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque imperdiet.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum imperdiet.
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+
+
+
-## Guides
-- [Authoring and Editing RISC-V Specifications](https://github.com/riscv/docs-dev-guide/releases/tag/v0.2.0-example)
+---
+
+## Application Software
-## Glossary
-- Terms
-- Acronyms
-- Alphabetical listing of Extensions
-- CSRs
+
+
+
+ RISC-V ABIs Specification
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque tincidunt.
+
+
+ View Spec
+
+
+
+
+
+
---
:::note
If you do not see a specification in this library, visit the [RISC-V GitHub `riscv-non-isa`](https://github.com/riscv-non-isa) organization to see a complete list of all specifications that have been developed or are presently under development.
:::
-
\ No newline at end of file
diff --git a/docs/spec/non-isa/io-mapping-table.mdx b/docs/spec/non-isa/io-mapping-table.mdx
index 001d4717a..356ea4666 100644
--- a/docs/spec/non-isa/io-mapping-table.mdx
+++ b/docs/spec/non-isa/io-mapping-table.mdx
@@ -7,5 +7,4 @@ pdf: /pdf/rimt-spec.pdf
Provides information about the RISC-V IOMMU and the relationship between the IO topology and the IOMMU in ACPI based RISC-V platforms. The RIMT identifies which components are behind IOMMU and how they are connected together.
-
-
\ No newline at end of file
+
diff --git a/docs/spec/non-isa/iommu-architecture.mdx b/docs/spec/non-isa/iommu-architecture.mdx
index 155d95934..84465ec1d 100644
--- a/docs/spec/non-isa/iommu-architecture.mdx
+++ b/docs/spec/non-isa/iommu-architecture.mdx
@@ -7,5 +7,5 @@ pdf: /pdf/riscv-iommu.pdf
Describes an Input-Output Memory Management Unit (IOMMU) that connects direct-memory-access-capable Input/Output (I/O) devices to system memory.
-
+
\ No newline at end of file
diff --git a/docusaurus.config.ts b/docusaurus.config.ts
index 03f2183d1..831b3b262 100644
--- a/docusaurus.config.ts
+++ b/docusaurus.config.ts
@@ -15,7 +15,9 @@ const config: Config = {
// Set the // pathname under which your site is served
// For GitHub pages deployment, it is often '//'
baseUrl: '/',
-
+ plugins: [
+ 'docusaurus-plugin-sass'
+ ],
// GitHub pages deployment config.
// If you aren't using GitHub pages, you don't need these.
organizationName: 'riscv', // Usually your GitHub org/user name.
@@ -24,7 +26,6 @@ const config: Config = {
onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
-
customFields:{
description: "Developer resources for the RISC-V ecosystem.",
},
@@ -65,7 +66,7 @@ const config: Config = {
onUntruncatedBlogPosts: 'warn',
},
theme: {
- customCss: './src/css/custom.css',
+ customCss: require.resolve('./src/css/custom.scss'),
},
googleTagManager: {
containerId: 'GTM-NXLCGZF4',
@@ -218,6 +219,7 @@ const config: Config = {
],
copyright: `Copyright © ${new Date().getFullYear()} RISC-V International`,
},
+
// plugins: [
// [
diff --git a/package-lock.json b/package-lock.json
index 87916ebb7..13ff876cb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,18 +10,28 @@
"dependencies": {
"@docusaurus/core": "3.7.0",
"@docusaurus/preset-classic": "3.7.0",
+ "@fontsource/open-sans": "^5.2.5",
+ "@fortawesome/fontawesome-svg-core": "^6.7.2",
+ "@fortawesome/free-brands-svg-icons": "^6.7.2",
+ "@fortawesome/free-solid-svg-icons": "^6.7.2",
+ "@fortawesome/react-fontawesome": "^0.2.2",
+ "@iconify/react": "^6.0.0",
"@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0",
"docusaurus-lunr-search": "^3.6.0",
+ "docusaurus-plugin-sass": "^0.2.6",
"prism-react-renderer": "^2.3.0",
"react": "^19.0.0",
- "react-dom": "^19.0.0"
+ "react-dom": "^19.0.0",
+ "sass": "^1.87.0",
+ "webpack": "^5.99.8"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.7.0",
"@docusaurus/tsconfig": "3.7.0",
"@docusaurus/types": "3.7.0",
- "typescript": "~5.6.2"
+ "typescript": "~5.6.2",
+ "webpack": "^5.99.8"
},
"engines": {
"node": ">=18.0"
@@ -3791,6 +3801,73 @@
"node": ">=18.0"
}
},
+ "node_modules/@fontsource/open-sans": {
+ "version": "5.2.6",
+ "resolved": "https://registry.npmjs.org/@fontsource/open-sans/-/open-sans-5.2.6.tgz",
+ "integrity": "sha512-mnfnUmBWQ+J220gqbibbzmKcc1kawV+lb3/Pspzu+Opnxza12oUffIg0ufG8g+3j1fnSznEWgyNV40MjtmJj6g==",
+ "license": "OFL-1.1",
+ "funding": {
+ "url": "https://github.com/sponsors/ayuhito"
+ }
+ },
+ "node_modules/@fortawesome/fontawesome-common-types": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.7.2.tgz",
+ "integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/fontawesome-svg-core": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.7.2.tgz",
+ "integrity": "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==",
+ "license": "MIT",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.7.2"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/free-brands-svg-icons": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.7.2.tgz",
+ "integrity": "sha512-zu0evbcRTgjKfrr77/2XX+bU+kuGfjm0LbajJHVIgBWNIDzrhpRxiCPNT8DW5AdmSsq7Mcf9D1bH0aSeSUSM+Q==",
+ "license": "(CC-BY-4.0 AND MIT)",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.7.2"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/free-solid-svg-icons": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.7.2.tgz",
+ "integrity": "sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA==",
+ "license": "(CC-BY-4.0 AND MIT)",
+ "dependencies": {
+ "@fortawesome/fontawesome-common-types": "6.7.2"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@fortawesome/react-fontawesome": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.6.tgz",
+ "integrity": "sha512-mtBFIi1UsYQo7rYonYFkjgYKGoL8T+fEH6NGUpvuqtY3ytMsAoDaPo5rk25KuMtKDipY4bGYM/CkmCHA1N3FUg==",
+ "license": "MIT",
+ "dependencies": {
+ "prop-types": "^15.8.1"
+ },
+ "peerDependencies": {
+ "@fortawesome/fontawesome-svg-core": "~1 || ~6 || ~7",
+ "react": "^16.3 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
"node_modules/@hapi/hoek": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
@@ -3806,6 +3883,27 @@
"@hapi/hoek": "^9.0.0"
}
},
+ "node_modules/@iconify/react": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@iconify/react/-/react-6.0.0.tgz",
+ "integrity": "sha512-eqNscABVZS8eCpZLU/L5F5UokMS9mnCf56iS1nM9YYHdH8ZxqZL9zyjSwW60IOQFsXZkilbBiv+1paMXBhSQnw==",
+ "license": "MIT",
+ "dependencies": {
+ "@iconify/types": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/cyberalien"
+ },
+ "peerDependencies": {
+ "react": ">=16"
+ }
+ },
+ "node_modules/@iconify/types": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
+ "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==",
+ "license": "MIT"
+ },
"node_modules/@jest/schemas": {
"version": "29.6.3",
"resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
@@ -3987,6 +4085,302 @@
"node": ">= 8"
}
},
+ "node_modules/@parcel/watcher": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
+ "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "detect-libc": "^1.0.3",
+ "is-glob": "^4.0.3",
+ "micromatch": "^4.0.5",
+ "node-addon-api": "^7.0.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "@parcel/watcher-android-arm64": "2.5.1",
+ "@parcel/watcher-darwin-arm64": "2.5.1",
+ "@parcel/watcher-darwin-x64": "2.5.1",
+ "@parcel/watcher-freebsd-x64": "2.5.1",
+ "@parcel/watcher-linux-arm-glibc": "2.5.1",
+ "@parcel/watcher-linux-arm-musl": "2.5.1",
+ "@parcel/watcher-linux-arm64-glibc": "2.5.1",
+ "@parcel/watcher-linux-arm64-musl": "2.5.1",
+ "@parcel/watcher-linux-x64-glibc": "2.5.1",
+ "@parcel/watcher-linux-x64-musl": "2.5.1",
+ "@parcel/watcher-win32-arm64": "2.5.1",
+ "@parcel/watcher-win32-ia32": "2.5.1",
+ "@parcel/watcher-win32-x64": "2.5.1"
+ }
+ },
+ "node_modules/@parcel/watcher-android-arm64": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz",
+ "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-darwin-arm64": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz",
+ "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-darwin-x64": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz",
+ "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-freebsd-x64": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz",
+ "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm-glibc": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz",
+ "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm-musl": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz",
+ "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm64-glibc": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz",
+ "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm64-musl": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz",
+ "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-x64-glibc": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz",
+ "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-x64-musl": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz",
+ "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-arm64": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz",
+ "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-ia32": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz",
+ "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-x64": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz",
+ "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
"node_modules/@pnpm/config.env-replace": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz",
@@ -4430,9 +4824,9 @@
}
},
"node_modules/@types/estree": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
- "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
"license": "MIT"
},
"node_modules/@types/estree-jsx": {
@@ -4972,9 +5366,9 @@
}
},
"node_modules/acorn": {
- "version": "8.14.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
- "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
@@ -4983,6 +5377,18 @@
"node": ">=0.4.0"
}
},
+ "node_modules/acorn-import-phases": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz",
+ "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "peerDependencies": {
+ "acorn": "^8.14.0"
+ }
+ },
"node_modules/acorn-jsx": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
@@ -7039,6 +7445,19 @@
"npm": "1.2.8000 || >= 1.4.16"
}
},
+ "node_modules/detect-libc": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+ "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
+ "license": "Apache-2.0",
+ "optional": true,
+ "bin": {
+ "detect-libc": "bin/detect-libc.js"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
"node_modules/detect-node": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
@@ -7280,6 +7699,19 @@
"url": "https://opencollective.com/unified"
}
},
+ "node_modules/docusaurus-plugin-sass": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/docusaurus-plugin-sass/-/docusaurus-plugin-sass-0.2.6.tgz",
+ "integrity": "sha512-2hKQQDkrufMong9upKoG/kSHJhuwd+FA3iAe/qzS/BmWpbIpe7XKmq5wlz4J5CJaOPu4x+iDJbgAxZqcoQf0kg==",
+ "license": "MIT",
+ "dependencies": {
+ "sass-loader": "^16.0.2"
+ },
+ "peerDependencies": {
+ "@docusaurus/core": "^2.0.0-beta || ^3.0.0-alpha",
+ "sass": "^1.30.0"
+ }
+ },
"node_modules/dom-converter": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
@@ -9640,6 +10072,12 @@
"url": "https://opencollective.com/immer"
}
},
+ "node_modules/immutable": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.3.tgz",
+ "integrity": "sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==",
+ "license": "MIT"
+ },
"node_modules/import-fresh": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
@@ -12904,6 +13342,13 @@
"tslib": "^2.0.3"
}
},
+ "node_modules/node-addon-api": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
+ "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/node-emoji": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.2.0.tgz",
@@ -16411,6 +16856,94 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
+ "node_modules/sass": {
+ "version": "1.91.0",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.91.0.tgz",
+ "integrity": "sha512-aFOZHGf+ur+bp1bCHZ+u8otKGh77ZtmFyXDo4tlYvT7PWql41Kwd8wdkPqhhT+h2879IVblcHFglIMofsFd1EA==",
+ "license": "MIT",
+ "dependencies": {
+ "chokidar": "^4.0.0",
+ "immutable": "^5.0.2",
+ "source-map-js": ">=0.6.2 <2.0.0"
+ },
+ "bin": {
+ "sass": "sass.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "optionalDependencies": {
+ "@parcel/watcher": "^2.4.1"
+ }
+ },
+ "node_modules/sass-loader": {
+ "version": "16.0.5",
+ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.5.tgz",
+ "integrity": "sha512-oL+CMBXrj6BZ/zOq4os+UECPL+bWqt6OAC6DWS8Ln8GZRcMDjlJ4JC3FBDuHJdYaFWIdKNIBYmtZtK2MaMkNIw==",
+ "license": "MIT",
+ "dependencies": {
+ "neo-async": "^2.6.2"
+ },
+ "engines": {
+ "node": ">= 18.12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "@rspack/core": "0.x || 1.x",
+ "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
+ "sass": "^1.3.0",
+ "sass-embedded": "*",
+ "webpack": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@rspack/core": {
+ "optional": true
+ },
+ "node-sass": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "webpack": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/sass/node_modules/chokidar": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
+ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+ "license": "MIT",
+ "dependencies": {
+ "readdirp": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/sass/node_modules/readdirp": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
+ "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.18.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
"node_modules/sax": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
@@ -18141,21 +18674,22 @@
}
},
"node_modules/webpack": {
- "version": "5.99.7",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.7.tgz",
- "integrity": "sha512-CNqKBRMQjwcmKR0idID5va1qlhrqVUKpovi+Ec79ksW8ux7iS1+A6VqzfZXgVYCFRKl7XL5ap3ZoMpwBJxcg0w==",
+ "version": "5.101.3",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.101.3.tgz",
+ "integrity": "sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A==",
"license": "MIT",
"dependencies": {
"@types/eslint-scope": "^3.7.7",
- "@types/estree": "^1.0.6",
+ "@types/estree": "^1.0.8",
"@types/json-schema": "^7.0.15",
"@webassemblyjs/ast": "^1.14.1",
"@webassemblyjs/wasm-edit": "^1.14.1",
"@webassemblyjs/wasm-parser": "^1.14.1",
- "acorn": "^8.14.0",
+ "acorn": "^8.15.0",
+ "acorn-import-phases": "^1.0.3",
"browserslist": "^4.24.0",
"chrome-trace-event": "^1.0.2",
- "enhanced-resolve": "^5.17.1",
+ "enhanced-resolve": "^5.17.3",
"es-module-lexer": "^1.2.1",
"eslint-scope": "5.1.1",
"events": "^3.2.0",
@@ -18169,7 +18703,7 @@
"tapable": "^2.1.1",
"terser-webpack-plugin": "^5.3.11",
"watchpack": "^2.4.1",
- "webpack-sources": "^3.2.3"
+ "webpack-sources": "^3.3.3"
},
"bin": {
"webpack": "bin/webpack.js"
@@ -18370,9 +18904,9 @@
}
},
"node_modules/webpack-sources": {
- "version": "3.2.3",
- "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
- "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz",
+ "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==",
"license": "MIT",
"engines": {
"node": ">=10.13.0"
diff --git a/src/components/DetailsTable/index.tsx b/src/components/DetailsTable/index.tsx
new file mode 100644
index 000000000..4daff78ef
--- /dev/null
+++ b/src/components/DetailsTable/index.tsx
@@ -0,0 +1,63 @@
+import { useState } from "react";
+
+export default function DetailsTable({ data, columns }) {
+ const [sortConfig, setSortConfig] = useState({ key: null, direction: "asc" });
+
+ const sortedData = [...data].sort((a, b) => {
+ if (!sortConfig.key) return 0;
+ const valA = a[sortConfig.key];
+ const valB = b[sortConfig.key];
+
+ if (valA < valB) return sortConfig.direction === "asc" ? -1 : 1;
+ if (valA > valB) return sortConfig.direction === "asc" ? 1 : -1;
+ return 0;
+ });
+
+ const handleSort = (col) => {
+ if (!col.sortable) return;
+ setSortConfig((prev) => {
+ if (prev.key === col.key) {
+ return {
+ key: col.key,
+ direction: prev.direction === "asc" ? "desc" : "asc",
+ };
+ }
+ return { key: col.key, direction: "asc" };
+ });
+ };
+
+ return (
+
+
+
+ {columns.map((col) => (
+ handleSort(col)}
+ style={{
+ cursor: col.sortable ? "pointer" : "default",
+ userSelect: "none",
+ }}
+ >
+ {col.label}
+ {sortConfig.key === col.key && (
+ {sortConfig.direction === "asc" ? " ▲" : " ▼"}
+ )}
+
+ ))}
+
+
+
+ {sortedData.map((row, i) => (
+
+ {columns.map((col) => (
+
+ {col.render ? col.render(row[col.key], row) : row[col.key]}
+
+ ))}
+
+ ))}
+
+
+ );
+}
diff --git a/src/components/HomepageFeatures/index.tsx b/src/components/HomepageFeatures/index.tsx
index 489b22eb4..69062939d 100644
--- a/src/components/HomepageFeatures/index.tsx
+++ b/src/components/HomepageFeatures/index.tsx
@@ -8,6 +8,8 @@ type FeatureItem = {
title: string;
Svg: React.ComponentType>;
description: ReactNode;
+ button: string;
+ link: string;
};
const FeatureList: FeatureItem[] = [
diff --git a/src/components/RvCard/RvPdfMenu/index.tsx b/src/components/RvCard/RvPdfMenu/index.tsx
new file mode 100644
index 000000000..3848f7bbe
--- /dev/null
+++ b/src/components/RvCard/RvPdfMenu/index.tsx
@@ -0,0 +1,113 @@
+import { useState, useRef, useEffect, useId } from "react";
+import "./styles.scss";
+
+export type DownloadItem = {
+ href: string;
+ label: string;
+};
+
+
+// NOTE: THIS FILE IS CURRENTLY NOT IN USE.
+
+export function RvPDFMenu({ items }: { items: DownloadItem[] }) {
+ const [open, setOpen] = useState(false);
+ const buttonRef = useRef(null);
+ const menuRef = useRef(null);
+ const itemsRef = useRef([]);
+ const menuId = useId();
+
+ // Close if clicking outside
+ useEffect(() => {
+ function handleClickOutside(e: Event) {
+ if (
+ menuRef.current &&
+ !menuRef.current.contains(e.target) &&
+ !buttonRef.current.contains(e.target)
+ ) {
+ setOpen(false);
+ }
+ }
+ document.addEventListener("mousedown", handleClickOutside);
+ return () => document.removeEventListener("mousedown", handleClickOutside);
+ }, []);
+
+ // Handle keyboard navigation
+ const handleKeyDown = (e) => {
+ const items = itemsRef.current;
+ const currentIndex = items.indexOf(document.activeElement);
+
+ switch (e.key) {
+ case "ArrowDown":
+ e.preventDefault();
+ items[(currentIndex + 1) % items.length].focus();
+ break;
+ case "ArrowUp":
+ e.preventDefault();
+ items[(currentIndex - 1 + items.length) % items.length].focus();
+ break;
+ case "Escape":
+ setOpen(false);
+ buttonRef.current.focus();
+ break;
+ default:
+ break;
+ }
+ };
+
+ return (
+
+
setOpen(!open)}
+ >
+ Download PDFs{" "}
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/RvCard/RvPdfMenu/styles.scss b/src/components/RvCard/RvPdfMenu/styles.scss
new file mode 100644
index 000000000..78751e27e
--- /dev/null
+++ b/src/components/RvCard/RvPdfMenu/styles.scss
@@ -0,0 +1,62 @@
+@use "../../../css/globals.scss" as *;
+@use "sass:map";
+
+.dropdown {
+ position: relative;
+ display: inline-block;
+ width: 100%;
+ height: 100%;
+}
+
+.dropdown-toggle {
+ padding: 0.6em 1.2em;
+ border: 2px solid map.get($map: $colors-neutral, $key: "gray-700");
+ border-radius: 0.5em;
+ background: $accent-light;
+ font-weight: 600;
+ cursor: pointer;
+}
+
+.dropdown-toggle:hover {
+ background: $accent;
+}
+
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ margin-top: 0.25em;
+ width: 220px;
+ border: 1px solid map.get($map: $colors-neutral, $key: "gray-400");
+ border-radius: 0.5em;
+ background: var(--color-bg);
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
+ padding: 0.25em 0;
+ list-style: none;
+ z-index: 1000;
+
+ /* animation setup */
+ opacity: 0;
+ transform: translateY(-5px);
+ pointer-events: none;
+ transition: opacity 0.2s ease, transform 0.2s ease;
+}
+
+.dropdown-menu.open {
+ opacity: 1;
+ transform: translateY(0);
+ pointer-events: auto;
+}
+
+.dropdown-item {
+ display: block;
+ padding: 0.5em 1em;
+ text-decoration: none;
+ color: var(--color-menu-item);
+}
+
+.dropdown-item:hover,
+.dropdown-item:focus {
+ background: #eee;
+ outline: none;
+}
diff --git a/src/components/RvCard/index.tsx b/src/components/RvCard/index.tsx
new file mode 100644
index 000000000..207730263
--- /dev/null
+++ b/src/components/RvCard/index.tsx
@@ -0,0 +1,51 @@
+import { JSX } from "react";
+import { RvPDFMenu, DownloadItem } from "./RvPdfMenu/index";
+import "./styles.scss";
+import Link from "@docusaurus/Link";
+
+interface RvCardProps {
+ title: string;
+ buttonLabel: string;
+ buttonHref: string;
+ children: React.ReactNode;
+ pdfLink?: string;
+ details?: string;
+ headingLevel?: keyof JSX.IntrinsicElements; // e.g. "h2" | "h3" | "h4"
+}
+
+export default function RvCard({
+ title,
+ children,
+ buttonLabel,
+ buttonHref,
+ headingLevel: Heading = "h2",
+ pdfLink,
+ details
+}: RvCardProps) {
+ // Generate a safe ID from the title (for aria-labelledby)
+ const headerId = `${title.replace(/\s+/g, "-").toLowerCase()}-header`;
+
+ return (
+
+
+
+
{children}
+
+
+ {details &&
More Details
}
+
+ );
+}
diff --git a/src/components/RvCard/styles.scss b/src/components/RvCard/styles.scss
new file mode 100644
index 000000000..95b991fa9
--- /dev/null
+++ b/src/components/RvCard/styles.scss
@@ -0,0 +1,103 @@
+@use "../../css/globals.scss" as *;
+
+.rv-card {
+ display: flex;
+ flex-direction: column;
+ border: 0.2rem solid var(--color-border);
+ border-radius: 0.7rem;
+ color: var(--color-text);
+ background: transparent;
+ height: 100%;
+ width: 100%;
+ align-items: flex-start;
+ margin-top: 1rem;
+ flex-grow: 1;
+ flex-basis: 0;
+
+ .rv-header {
+ font-weight: 700;
+ padding: 5px;
+ flex-grow: 0;
+ }
+
+ .rv-content {
+ flex-grow: 1;
+ line-height: 1.5;
+ padding: 0px 10px;
+ min-width: 0;
+ a {
+ color: var(--color-link);
+ font-weight: 600;
+ text-decoration: none;
+ transition: color 0.2s ease;
+
+ &:hover {
+ color: var(--color-link-hover);
+ }
+
+ &:focus {
+ color: var(--color-link-hover);
+ }
+ }
+ }
+ .rv-footer {
+ margin-top: auto;
+ align-self: center;
+ display: flex;
+ width: 90%;
+ height: auto;
+ margin-bottom: 10px;
+ flex-grow: 0;
+
+ .rv-a-button {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ color: --var(--color-link);
+ font-size: var(--text-sm);
+ border-radius: var(--radius-md);
+ font-weight: 600;
+ text-decoration: none;
+ transition: background 0.2s ease, color 0.2s ease, transform 0.1s ease,
+ box-shadow 0.2s ease;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ border: 2px solid var(--color-border);
+ border-radius: 0.5rem;
+ padding: 0.75rem;
+ width: 100%;
+ height: 100%;
+ &:hover {
+ background: var(--color-link-hover);
+ color: var(--color-primary);
+ transform: translateY(-1px);
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
+ }
+
+ &:focus {
+ outline: 2px solid var(--color-accent);
+ outline-offset: 2px;
+ }
+ }
+ .rv-button {
+ background-color: $accent;
+ height: 100%;
+ width: 100%;
+ }
+ .rv-pdf-button {
+ @extend .rv-a-button;
+ background-color: $accent-light;
+ &:hover {
+ background: var($accent);
+ color: var(--color-primary);
+ transform: translateY(-1px);
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
+ }
+ }
+ }
+ .rv-details {
+ display: flex;
+ justify-content: center;
+ width: 100%;
+ }
+}
diff --git a/src/components/RvCardGrid/index.tsx b/src/components/RvCardGrid/index.tsx
new file mode 100644
index 000000000..e1744e8c6
--- /dev/null
+++ b/src/components/RvCardGrid/index.tsx
@@ -0,0 +1,18 @@
+import clsx from "clsx";
+import "./styles.scss";
+
+interface RvCardGridProps {
+ children: React.ReactNode;
+ className?: string; // optional className for custom styling
+}
+
+export default function RvCardGrid({
+ children,
+ className,
+}: RvCardGridProps) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/src/components/RvCardGrid/styles.scss b/src/components/RvCardGrid/styles.scss
new file mode 100644
index 000000000..991747510
--- /dev/null
+++ b/src/components/RvCardGrid/styles.scss
@@ -0,0 +1,30 @@
+.rv-card-grid {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-evenly;
+ max-width: 100%;
+ margin: 0 auto;
+ align-items: stretch;
+
+ > * {
+ flex: 1 1 0;
+ max-width: 20rem;
+ min-width: 20rem;
+ height: auto;
+ }
+
+ @media (max-width: 1024px) {
+ > * {
+ flex: 1 1 18rem; /* slightly smaller cards on medium screens */
+ }
+ }
+
+ @media (max-width: 768px) {
+ flex-direction: column; /* stack vertically */
+
+ > * {
+ flex: 1 1 100%;
+ max-width: 100%; /* make each card full-width */
+ }
+ }
+}
diff --git a/src/components/RvCardVersioning/index.tsx b/src/components/RvCardVersioning/index.tsx
new file mode 100644
index 000000000..d9ede7f51
--- /dev/null
+++ b/src/components/RvCardVersioning/index.tsx
@@ -0,0 +1,7 @@
+import './styles.scss'
+
+export default function RvCardVersioning({children}){
+ return(
+ {children}
+ )
+}
\ No newline at end of file
diff --git a/src/components/RvCardVersioning/styles.scss b/src/components/RvCardVersioning/styles.scss
new file mode 100644
index 000000000..9cfa67f40
--- /dev/null
+++ b/src/components/RvCardVersioning/styles.scss
@@ -0,0 +1,7 @@
+.version{
+ font-style: italic;
+ font-size: 12px;
+ text-align: left;
+ display: flex;
+ justify-content: space-between;
+}
\ No newline at end of file
diff --git a/src/css/custom.css b/src/css/custom.css
deleted file mode 100644
index 8b957a991..000000000
--- a/src/css/custom.css
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * 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.
- */
-
-/* You can override the default Infima variables here. */
-:root {
- --ifm-color-primary: #003262;
- --ifm-color-primary-dark: #003262;
- --ifm-color-primary-darker: #011e41;
- --ifm-color-primary-darkest: #011e41;
- --ifm-color-primary-light: #FDB515;
- --ifm-color-primary-lighter: #fdda64;
- --ifm-color-primary-lightest: #fdda64;
- --ifm-code-font-size: 95%;
- --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
-}
-
-/* For readability concerns, you should choose a lighter palette in dark mode. */
-[data-theme='dark'] {
- --ifm-color-primary: #FDB515;
- --ifm-color-primary-dark: #21af90;
- --ifm-color-primary-darker: #1fa588;
- --ifm-color-primary-darkest: #1a8870;
- --ifm-color-primary-light: #62cbc9;
- --ifm-color-primary-lighter: #62cbc9;
- --ifm-color-primary-lightest: #62cbc9;
- --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
-}
-
-.hidden {
-display: none !important;
-}
-
-.row {
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-.card {
- min-height: 200px;
-}
\ No newline at end of file
diff --git a/src/css/custom.scss b/src/css/custom.scss
new file mode 100644
index 000000000..a75330a3e
--- /dev/null
+++ b/src/css/custom.scss
@@ -0,0 +1,8 @@
+/* ---------------------------------------------------
+ Imports
+ --------------------------------------------------- */
+
+@use './globals.scss';
+@use './gradient-backgrounds.scss';
+@use './headers.scss';
+@use './navbar.scss'
\ No newline at end of file
diff --git a/src/css/globals.scss b/src/css/globals.scss
new file mode 100644
index 000000000..050443f2e
--- /dev/null
+++ b/src/css/globals.scss
@@ -0,0 +1,138 @@
+@use "sass:map";
+/* ---------------------------------------------------
+ Variables
+ --------------------------------------------------- */
+:root {
+ /* Typography */
+ --font-sans: "Open Sans", system-ui, -apple-system, BlinkMacSystemFont,
+ "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
+}
+
+/* ---------------------------------------------------
+ SCSS Maps
+ --------------------------------------------------- */
+
+// Brand colors
+$primary: #003262; // Berkeley Blue
+$accent: #fdb515; // California Gold
+$primary-dark: #011e41;
+$accent-light: #fdda64;
+
+// Secondary (saturated / vivid)
+$colors-saturated: (
+ "teal": #0a6b7c,
+ "pink": #cb007b,
+ "purple": #60269e,
+);
+
+// Secondary (desaturated / lighter)
+$colors-desaturated: (
+ "teal": #62cbc9,
+ "pink": #fe9bb1,
+ "purple": #c2a6e1,
+);
+
+// Neutral grays
+$colors-neutral: (
+ "gray-900": #444444,
+ "gray-700": #666666,
+ "gray-400": #999999,
+);
+
+/* ---------------------------------------------------
+ Light & Dark Mode Definitions
+ --------------------------------------------------- */
+
+// Default light mode
+:root {
+ --color-bg: #ffffff;
+ --color-text: #222222;
+ --color-link: #2f00ff;
+ --color-link-hover: #fdb515;
+ --color-border: #30363d;
+ --color-menu-item: #666666;
+}
+
+// Dark mode
+[data-theme="dark"] {
+ --color-bg: #0d1117;
+ --color-text: #f0f6fc;
+ --color-link: #2f00ff;
+ --color-link-hover: #fdb515;
+ --color-border: #e5e7eb;
+ --color-menu-item: #999999;
+}
+
+/* ---------------------------------------------------
+ Base Styles
+ --------------------------------------------------- */
+html {
+ font-family: var(--font-sans);
+ font-size: 16px;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ scroll-behavior: smooth;
+}
+
+body {
+ margin: 0;
+ color: var(--color-text);
+ background-color: var(--color-bg);
+ font-size: 1rem;
+ line-height: 1.5;
+}
+
+a {
+ color: var(--color-link);
+ text-decoration-thickness: 2px;
+ text-underline-offset: 2px;
+ transition: color 0.2s ease;
+
+ &:hover {
+ color: var(--color-link-hover);
+ }
+}
+
+/**
+This is stuff from the old custom.css file. Merge into this for compatibility
+and organization sake.
+ */
+
+/* You can override the default Infima variables here. */
+:root {
+ --ifm-color-primary: #003262;
+ --ifm-color-primary-dark: #003262;
+ --ifm-color-primary-darker: #011e41;
+ --ifm-color-primary-darkest: #011e41;
+ --ifm-color-primary-light: #fdb515;
+ --ifm-color-primary-lighter: #fdda64;
+ --ifm-color-primary-lightest: #fdda64;
+ --ifm-code-font-size: 95%;
+ --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
+}
+
+/* For readability concerns, you should choose a lighter palette in dark mode. */
+[data-theme="dark"] {
+ --ifm-color-primary: #fdb515;
+ --ifm-color-primary-dark: #21af90;
+ --ifm-color-primary-darker: #1fa588;
+ --ifm-color-primary-darkest: #1a8870;
+ --ifm-color-primary-light: #62cbc9;
+ --ifm-color-primary-lighter: #62cbc9;
+ --ifm-color-primary-lightest: #62cbc9;
+ --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
+}
+
+.hidden {
+ display: none !important;
+}
+
+.row {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.card {
+ min-height: 200px;
+}
diff --git a/src/css/gradient-backgrounds.scss b/src/css/gradient-backgrounds.scss
new file mode 100644
index 000000000..954c32bc3
--- /dev/null
+++ b/src/css/gradient-backgrounds.scss
@@ -0,0 +1,45 @@
+@use "./globals.scss" as *;
+@use "sass:map";
+
+// Helper map
+$bg-order: (
+ 1: "teal",
+ 2: "pink",
+ 3: "purple",
+ 4: "teal",
+ 5: "pink",
+ 6: "purple",
+);
+/* -------------------
+ Light Mode (desaturated)
+ ------------------- */
+[data-theme="light"] {
+ @each $num, $key in $bg-order {
+ $color: map.get($colors-desaturated, $key);
+ $angle: if($num % 2 == 0, -135deg, 135deg); // alternate directions
+
+ .grid-bg-#{$num} {
+ background: linear-gradient($angle, $color, #ffffff);
+ color: #222222;
+ padding-top: 20px;
+ padding-bottom: 20px;
+ }
+ }
+}
+/* -------------------
+ Dark Mode (saturated)
+ ------------------- */
+[data-theme="dark"] {
+ @each $num, $key in $bg-order {
+ $color: map.get($colors-saturated, $key);
+ $angle: if($num % 2 == 0, -135deg, 135deg); // alternate directions
+
+ .grid-bg-#{$num} {
+ background: linear-gradient($angle, $color, #000000);
+ color: #f0f6fc;
+ padding-top: 20px;
+ padding-bottom: 20px;
+ }
+ }
+}
+
diff --git a/src/css/headers.scss b/src/css/headers.scss
new file mode 100644
index 000000000..e3f05c552
--- /dev/null
+++ b/src/css/headers.scss
@@ -0,0 +1,11 @@
+@use './globals.scss' as *;
+
+.page-header {
+ background-color: $primary;
+ color: $accent;
+ width: 100%;
+}
+
+.sub-header {
+ text-decoration: underline;
+}
\ No newline at end of file
diff --git a/src/css/navbar.scss b/src/css/navbar.scss
new file mode 100644
index 000000000..60d1894cb
--- /dev/null
+++ b/src/css/navbar.scss
@@ -0,0 +1,19 @@
+@use "./globals.scss" as *;
+
+.rv-navbar {
+ background-color: $accent;
+ display: flex;
+ flex-wrap: nowrap;
+ margin-top: 0;
+ font-size: 20px;
+ justify-content: space-evenly;
+ align-items: center;
+ gap: auto;
+ width: 100%;
+ padding: 20px 20px;
+ a {
+ color: black;
+ text-decoration: none;
+ text-align: center;
+ }
+}
diff --git a/src/pages/details/isa-priv/_data.js b/src/pages/details/isa-priv/_data.js
new file mode 100644
index 000000000..1a2e78875
--- /dev/null
+++ b/src/pages/details/isa-priv/_data.js
@@ -0,0 +1,19 @@
+export const columns = [
+ { key: "version", label: "Version", sortable: true },
+ { key: "publishDate", label: "Publish Date", sortable: true },
+ {
+ key: "pdfLink",
+ label: "PDF",
+ render: (val) => Download
+ },
+];
+
+export const data = [
+ { version: 2, publishDate: "01/2020", pdfLink: "/pdfs/doc-v2.pdf" },
+ { version: 3, publishDate: "06/2020", pdfLink: "/pdfs/doc-v3.pdf" },
+ { version: 4, publishDate: "12/2020", pdfLink: "/pdfs/doc-v4.pdf" },
+ { version: 5, publishDate: "05/2021", pdfLink: "/pdfs/doc-v5.pdf" },
+ { version: 6, publishDate: "11/2021", pdfLink: "/pdfs/doc-v6.pdf" },
+ { version: 7, publishDate: "04/2022", pdfLink: "/pdfs/doc-v7.pdf" },
+ { version: 8, publishDate: "09/2022", pdfLink: "/pdfs/doc-v8.pdf" },
+];
diff --git a/src/pages/details/isa-priv/index.tsx b/src/pages/details/isa-priv/index.tsx
new file mode 100644
index 000000000..f74509469
--- /dev/null
+++ b/src/pages/details/isa-priv/index.tsx
@@ -0,0 +1,12 @@
+import Layout from "@theme/Layout";
+import { data, columns } from "./_data.js";
+import DetailsTable from "@site/src/components/DetailsTable/index";
+
+export default function ISAPriv() {
+ return (
+
+ Isa Privilaged Details View
+
+
+ );
+}
diff --git a/src/pages/details/isa-priv/styles.scss b/src/pages/details/isa-priv/styles.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/pages/details/isa-unpriv/_data.js b/src/pages/details/isa-unpriv/_data.js
new file mode 100644
index 000000000..1a2e78875
--- /dev/null
+++ b/src/pages/details/isa-unpriv/_data.js
@@ -0,0 +1,19 @@
+export const columns = [
+ { key: "version", label: "Version", sortable: true },
+ { key: "publishDate", label: "Publish Date", sortable: true },
+ {
+ key: "pdfLink",
+ label: "PDF",
+ render: (val) => Download
+ },
+];
+
+export const data = [
+ { version: 2, publishDate: "01/2020", pdfLink: "/pdfs/doc-v2.pdf" },
+ { version: 3, publishDate: "06/2020", pdfLink: "/pdfs/doc-v3.pdf" },
+ { version: 4, publishDate: "12/2020", pdfLink: "/pdfs/doc-v4.pdf" },
+ { version: 5, publishDate: "05/2021", pdfLink: "/pdfs/doc-v5.pdf" },
+ { version: 6, publishDate: "11/2021", pdfLink: "/pdfs/doc-v6.pdf" },
+ { version: 7, publishDate: "04/2022", pdfLink: "/pdfs/doc-v7.pdf" },
+ { version: 8, publishDate: "09/2022", pdfLink: "/pdfs/doc-v8.pdf" },
+];
diff --git a/src/pages/details/isa-unpriv/index.mdx b/src/pages/details/isa-unpriv/index.mdx
new file mode 100644
index 000000000..47202941b
--- /dev/null
+++ b/src/pages/details/isa-unpriv/index.mdx
@@ -0,0 +1,5 @@
+import {data, columns} from './_data'
+
+# Unpriv
+
+
\ No newline at end of file
diff --git a/src/theme/MDXComponents.tsx b/src/theme/MDXComponents.tsx
index a593c9b30..403fdc9d3 100644
--- a/src/theme/MDXComponents.tsx
+++ b/src/theme/MDXComponents.tsx
@@ -27,6 +27,10 @@ import CardImage from '@site/src/components/Card/CardImage';
import Timeline from '@site/src/components/Timeline';
import TimelineItem from '@site/src/components/Timeline/TimelineItem';
import PDF from '@site/src/components/PDF';
+import RvCard from '../components/RvCard';
+import RvCardGrid from '../components/RvCardGrid';
+import RvCardVersioning from '../components/RvCardVersioning';
+import DetailsTable from '../components/DetailsTable';
library.add(fab, fas);
@@ -50,4 +54,8 @@ export default {
Timeline,
TimelineItem,
PDF,
+ RvCard,
+ RvCardGrid,
+ RvCardVersioning,
+ DetailsTable
};