Repository: adobe/adobe-design-website
Pull request #88: feat: gradients and theme change, and rounded diamond themes
Author: login: jawinn
Labels: name: Ready for Squash & Merge
Created: 2025-05-22T19:10:55Z | Merged: 2025-05-23T19:42:52Z

## Summary of changes

### Theme and gradients system changes

Changes to implementation of gradients and themes:
- Theme names no longer need to be prefixed with `theme-` in the content metadata. Theme names from metadata are now automatically prefixed with `theme--` and the generic `theme` class is also added along with it to the body.
- Gradients were previously starting higher up than designed, because of the area underneath the sticky nav. To keep the existing gradients without having to change all of their colors, an overscroll color matching the starting gradient has been added 64px above using a second `linear-gradient`, since this area is visible on scroll bounce.
- SVGs used on the hero background areas can't be used as a URL in a `background-image`, or as an image source, because we need access to change the colors with CSS between both themes and light/dark mode. So a new function was added that creates a presentation only div with the inline SVG shapes needed for that theme.

### Completed background for home and story pack pages

The backgrounds for the home page and story pack pages are now working responsively and in light/dark, using the themes:
- `hero-indigo`
- `hero-green`

Other themes to be added in a followup PR.

## Relevant Links
- Designs: [Figma](https://www.figma.com/design/QzvOszpLGT7fwSd6N7gaDW/Adobe-Design?node-id=2047-12876&p=f&m=dev)
- Story: [ADB-XX](https://sparkbox.atlassian.net/browse/ADB-219)

## Test URLs:
- Before: https://main--adobe-design-website--adobe.aem.page/
- After: https://feat-gradients-updates--adobe-design-website--adobe.aem.page/

## Checklist
* [ ] This PR has visual changes, and has been reviewed by a designer.
* [x] This PR has code changes, and our linters still pass.
* [x] This PR has new code, so new tests were added or updated, and they pass.
* [ ] This PR affects production code, so it was browser tested (see below).
* [ ] This PR has copy changes, so copy was proofread and approved.
* [ ] The content of this PR requires documentation, so we added a detailed description of the component's purpose, requirements, quirks, and instructions for use by designers and developers. This includes accessibility information if pertinent.

## Validation

Compare against the new "Hero" section in Figma, as all of the shapes were recently adjusted for all the breakpoints.

1. Visit the [home page](https://feat-gradients-updates--adobe-design-website--adobe.aem.page/) and example story packs page [design systems](https://feat-gradients-updates--adobe-design-website--adobe.aem.page/ideas/design-systems/).
2. Compare against Hero section in Figma at different breakpoints. You should see the rounded diamond shape that fades at the bottom.
3. Compare against Hero section in Figma at both light and dark mode
4. Make sure to test at the largest 1920px breakpoint and above
---

## Browser Testing
We should aim to support the latest version of the listed browsers. For older versions or other browsers not on the list, content should be accessible, even if it doesn't completely match the designs.

Developers should test as they work in the browsers available on their machines. If they have access to other devices to test other browser/OS combinations, they should do that when possible.

**Windows**
* [ ] Firefox
* [ ] Chrome
* [ ] Edge

**MacOS**
* [x] Firefox
* [x] Chrome
* [x] Safari
* [ ] Edge

**Android**
* [ ] Firefox
* [ ] Chrome
* [ ] Edge

**iOS**
* [ ] Safari

---



Diff:
diff --git a/assets/themes/shapes.js b/assets/themes/shapes.js
new file mode 100644
index 00000000..9838de18
--- /dev/null
+++ b/assets/themes/shapes.js
@@ -0,0 +1,25 @@
+/**
+ * @file SVG strings for the page header backgrounds. 
+ */
+
+export const roundedDiamond = 
+`<svg role="presentation" class="shape-diamond" width="1292" height="895" viewBox="0 0 1292 895" fill="none" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none">
+    <g opacity="0.56">
+        <mask id="mask0_2047_12900" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="-114" width="2823" height="1826">
+            <path d="M1215.13 -59.7343C1329.53 -131.277 1474.47 -131.715 1589.29 -60.8653L2737.73 647.796C2850.2 717.202 2850.39 881.026 2738.07 950.694L1597.22 1658.35C1482.57 1729.46 1337.63 1729.37 1223.08 1658.1L84.5849 949.778C-27.1422 880.258 -27.3458 717.35 84.2443 647.569L1215.13 -59.7343Z" fill="url(#paint0_linear_2047_12900)"/>
+        </mask>
+        <g mask="url(#mask0_2047_12900)">
+            <path d="M1215.11 -59.7343C1329.5 -131.277 1474.44 -131.715 1589.27 -60.8653L2737.7 647.796C2850.17 717.202 2850.36 881.026 2738.04 950.694L1597.2 1658.35C1482.54 1729.46 1337.6 1729.37 1223.05 1658.1L84.557 949.778C-27.17 880.258 -27.3738 717.35 84.2162 647.569L1215.11 -59.7343Z" fill="var(--diamond-fill, #745BFC)"/>
+        </g>
+    </g>
+    <defs>
+        <linearGradient id="paint0_linear_2047_12900" x1="4865.08" y1="798.959" x2="-420.387" y2="496.212" gradientUnits="userSpaceOnUse">
+            <stop/>
+            <stop offset="1" stop-opacity="0"/>
+        </linearGradient>
+    </defs>
+</svg>`;
+
+export const allShapes = {
+    roundedDiamond,
+};
diff --git a/blocks/header/header.js b/blocks/header/header.js
index 48844d56..c2f69c72 100644
--- a/blocks/header/header.js
+++ b/blocks/header/header.js
@@ -55,11 +55,13 @@ const buildSmallScreenNav = (nav, homepageLink, pageLinks) => {
   let isPanelOpen = false;
   let removeNavFocusTrap = null;
 
+  let openNavMenu, closeNavMenu, handleEscapeKey;
+
   /**
    * Opens the Navigation Menu.
    * @function
    */
-  const openNavMenu = () => {
+  openNavMenu = () => {
     isPanelOpen = true;
 
     menuButton.setAttribute("aria-expanded", true);
@@ -83,7 +85,7 @@ const buildSmallScreenNav = (nav, homepageLink, pageLinks) => {
    * "close" can be called on escape keydown.
    * @function
    */
-  const closeNavMenu = () => {
+  closeNavMenu = () => {
     isPanelOpen = false;
 
     menuButton.focus();
@@ -107,7 +109,7 @@ const buildSmallScreenNav = (nav, homepageLink, pageLinks) => {
    * Pressing the escape key will close the menu.
    * @function
    */
-  const handleEscapeKey = (e) => {
+  handleEscapeKey = (e) => {
     if (e.key === "Escape") {
       closeNavMenu();
     }
diff --git a/scripts/aem.js b/scripts/aem.js
index 403a3d67..2515d861 100644
--- a/scripts/aem.js
+++ b/scripts/aem.js
@@ -11,6 +11,8 @@
  */
 
 /* eslint-env browser */
+import { decorateThemeBackgroundVisuals } from "./modules/themeBackgrounds.js";
+
 function sampleRUM(checkpoint, data) {
   // eslint-disable-next-line max-len
   const timeShift = () => (window.performance ? window.performance.now() : Date.now() - window.hlx.rum.firstReadTime);
@@ -300,17 +302,38 @@ function createOptimizedPicture(
  * Set template (page structure) and theme (page styles).
  */
 function decorateTemplateAndTheme() {
-  const addClasses = (element, classes) => {
+  /**
+   * Add cleaned comma separated classes to an element.
+   * @param {*} element HTML element to add classes to
+   * @param {string} classes CSV class(es)
+   * @param {string} classPrefix 
+   */
+  const addClasses = (element, classes, classPrefix = '') => {
     classes.split(',').forEach((c) => {
-      element.classList.add(toClassName(c.trim()));
+      element.classList.add(classPrefix + toClassName(c.trim()));
     });
   };
+
+  // Add template class(es) to body from metadata.
   const template = getMetadata('template');
-  if (template) addClasses(document.body, template);
+  if (template) {
+    addClasses(document.body, template);
+  }
+
+  // Add theme class(es) to body from metadata.
+  // And add any page background vectors needed for this theme.
   const theme = getMetadata('theme');
-  if (theme) addClasses(document.body, theme);
+  if (theme) {
+    document.body.classList.add('theme');
+    addClasses(document.body, theme, 'theme--');
+    decorateThemeBackgroundVisuals(theme);
+  }
+
+  // Add page specific color from the metadata in a root level CSS custom property.
   const color = getMetadata('color');
-  if (color) document.querySelector(":root").style.setProperty("--color-background", `var(--${color})`);
+  if (color) {
+    document.querySelector(":root").style.setProperty("--color-background", `var(--${color})`);
+  }
 }
 
 /**
diff --git a/scripts/modules/themeBackgrounds.js b/scripts/modules/themeBackgrounds.js
new file mode 100644
index 00000000..20bb7182
--- /dev/null
+++ b/scripts/modules/themeBackgrounds.js
@@ -0,0 +1,41 @@
+import { allShapes } from "../../assets/themes/shapes.js";
+
+/**
+ * Adds inline SVGs needed for the different hero page backgrounds within some themes.
+ * Appends a container element containing the SVG elements.
+ * 
+ * These are added as their own elements instead of in `background-image` because their
+ * fill colors are changed with CSS between themes and light/dark.
+ * 
+ * @param {string} theme - The name of the current theme (as stored in metadata).
+ */
+export async function decorateThemeBackgroundVisuals(theme) {
+    if (!theme) return;
+
+    // Array of SVG strings to load per theme name.
+    const graphicsMapping = {
+        'hero-indigo': [allShapes.roundedDiamond],
+        'hero-green': [allShapes.roundedDiamond],
+    };
+
+    // Return if theme does not need any SVGs.
+    if (!Object.keys(graphicsMapping).includes(theme)) {
+        return;
+    }
+
+    // Create presentation only container that holds SVGs, and append to the body.
+    const backgroundVisuals = document.createElement('div');
+    backgroundVisuals.className = 'bg-visuals';
+    backgroundVisuals.setAttribute('aria-hidden', 'true');
+
+    // Parse the SVG strings and append the necessary SVGs to the container, per theme.
+    const parser = new DOMParser();
+    graphicsMapping[theme].forEach(svgString => {
+        const svgDoc = parser.parseFromString(svgString, "image/svg+xml");
+        const svgElement = svgDoc?.documentElement;
+        if (svgElement) backgroundVisuals.appendChild(svgElement);
+    });
+
+    // Append our container to the body.
+    document.body.appendChild(backgroundVisuals);
+}
\ No newline at end of file
diff --git a/scripts/scripts.js b/scripts/scripts.js
index 6cc43915..13a4fb24 100644
--- a/scripts/scripts.js
+++ b/scripts/scripts.js
@@ -15,6 +15,7 @@ import {
   loadCSS,
   sampleRUM,
 } from './aem.js';
+import { decorateThemeBackgroundVisuals } from './modules/themeBackgrounds.js';
 
 import {
   debounce
@@ -137,6 +138,9 @@ async function loadLazy(doc) {
   window.addEventListener("resize", debounce(() => reloadHeader(headerElement), 150));
 
   loadFooter(doc.querySelector('footer'));
+
+  // Append any theme background SVGs.
+  decorateThemeBackgroundVisuals();
 }
 
 /**
diff --git a/styles/base.css b/styles/base.css
index 0529b2f4..f711f0dc 100644
--- a/styles/base.css
+++ b/styles/base.css
@@ -64,6 +64,7 @@
   --spectrum-gray-900: rgb(19 19 19);
   --spectrum-gray-1000: rgb(0 0 0);
 
+  --spectrum-indigo-100: rgb(247 248 255);
   --spectrum-indigo-400: rgb(192 201 255);
   --spectrum-indigo-500: rgb(167 178 255);
   --spectrum-indigo-1000: rgb(99 56 238);
@@ -113,6 +114,7 @@
     --spectrum-gray-900: rgb(242 242 242);
     --spectrum-gray-1000: rgb(255 255 255);
 
+    --spectrum-indigo-100: rgb(30 0 93);
     --spectrum-indigo-400: rgb(62 12 174);
     --spectrum-indigo-500: rgb(79 30 209);
     --spectrum-indigo-1000: rgb(139 141 254);
@@ -209,6 +211,7 @@
   );
 
   --gradient-indigo-dark: var(--gradient-indigo-500);
+  --gradient-indigo-dark-start: var(--spectrum-indigo-500);
   --gradient-indigo-light: var(--gradient-indigo-400);
 
   --gradient-multitone: linear-gradient(269deg, #eb1000 -0.72%, #4b75ff 81.56%);
@@ -233,6 +236,7 @@
     );
 
     --gradient-indigo-dark: var(--gradient-indigo-100);
+    --gradient-indigo-dark-start: var(--spectrum-indigo-100);
     --gradient-indigo-light: var(--gradient-indigo-200);
   }
 
@@ -601,6 +605,20 @@
   --page-constrained-text: 75ch;
   --page-nav-height: 4rem;
 
+  --page-bg-height: 48.813rem;
+  
+  @media (min-width: 48rem) {
+    --page-bg-height: 70.75rem;
+  }
+
+  @media (min-width: 80rem) {
+    --page-bg-height: 36.563rem;
+  }
+
+  @media (min-width: 105rem) {
+    --page-bg-height: 55.938rem;
+  }
+
   /* smallest screens */
   --page-gutters: 1.25rem;
 
diff --git a/styles/styles.css b/styles/styles.css
index 3d54de51..c9fa84f7 100644
--- a/styles/styles.css
+++ b/styles/styles.css
@@ -12,8 +12,8 @@
 
 body {
   background-color: var(--color-background);
-  background-size: 100% 34.5rem;
-  background-position: top;
+  background-size: var(--page-background-size, 100% var(--page-bg-height, 36.563rem));
+  background-position: var(--page-background-position, top);
   background-repeat: no-repeat;
   background-image: var(--page-background);
   display: none;
@@ -893,30 +893,106 @@ main > .section > .grid-container {
 
 /* ** Page Themes ** */
 
-.theme-green {
-  --page-background: var(--gradient-green);
+/* Theme gradient backgrounds also include a color above the gradient to account for overscroll area underneath the sticky nav. */
+.theme {
+  --page-bg-overscroll-color: var(--color-background);
+  --page-background: var(--page-bg-main-gradient), linear-gradient(var(--page-bg-overscroll-color) 0%, var(--page-bg-overscroll-color) 100%);
+  --page-background-position: left top var(--page-nav-height), left top;
+  --page-background-size: 100% calc(var(--page-bg-height) - var(--page-nav-height)), 100% var(--page-nav-height);
 }
 
-.theme-blue {
-  --page-background: var(--gradient-blue);
+/* -- Simple color themes with only a gradient. -- */
+.theme--green {
+  --page-bg-main-gradient: var(--gradient-green);
+  --page-bg-overscroll-color: var(--spectrum-green-300);
 }
 
-.theme-seafoam {
-  --page-background: var(--gradient-seafoam);
+.theme--blue {
+  --page-bg-main-gradient: var(--gradient-blue);
 }
 
-.theme-cyan-500 {
-  --page-background: var(--gradient-cyan-500);
+.theme--seafoam {
+  --page-bg-main-gradient: var(--gradient-seafoam);
 }
 
-.theme-cyan-600 {
-  --page-background: var(--gradient-cyan-600);
+.theme--cyan-500 {
+  --page-bg-main-gradient: var(--gradient-cyan-500);
 }
 
-.theme-indigo-dark {
-  --page-background: var(--gradient-indigo-dark);
+.theme--cyan-600 {
+  --page-bg-main-gradient: var(--gradient-cyan-600);
 }
 
-.theme-indigo-light {
-  --page-background: var(--gradient-indigo-dark);
+.theme--indigo-dark {
+  --page-bg-main-gradient: var(--gradient-indigo-dark);
+}
+
+.theme--indigo-light {
+  --page-bg-main-gradient: var(--gradient-indigo-light);
+}
+
+/* -- Main page "hero" themes' with overlaid SVG shapes. -- */
+.bg-visuals {
+  position: absolute;
+  overflow: hidden;
+  z-index: -1;
+  pointer-events: none;
+  left: 0;
+  top: 0;
+  width: 100%;
+  height: var(--page-bg-height, 0px);
+
+  /* Blend bottom to background, on top of shapes. */
+  &::after {
+    display: block;
+    content: '';
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    width: 100%;
+    height: 225px;
+    background: linear-gradient(180deg, rgb(from var(--color-background) r g b / 0) 0%, var(--color-background) 100%);
+  }
+}
+
+.theme--hero-indigo {
+  --page-bg-overscroll-color: var(--gradient-indigo-dark-start);
+  --page-bg-main-gradient: var(--gradient-indigo-dark);
+  --diamond-fill: rgb(116 91 252);
+
+  &:has(#color-scheme:checked) {
+    --diamond-fill: rgb(99 56 238);
+  }
+}
+
+.theme--hero-green {
+  --page-bg-overscroll-color: var(--spectrum-green-300);
+  --page-bg-main-gradient: var(--gradient-green);
+  --diamond-fill: var(--spectrum-green-600);
+}
+
+.theme--hero-indigo .bg-visuals .shape-diamond,
+.theme--hero-green .bg-visuals .shape-diamond {
+  position: absolute;
+  inset: -57px auto auto -327px;
+  min-height: 100%;
+
+  @media (min-width: 48rem) {
+    inset: -113px -316px auto auto;
+    width: 168%;
+  }
+
+  @media (min-width: 80rem) {
+    inset: -154px -320px auto auto;
+    width: auto;
+  }
+
+  @media (min-width: 105rem) {
+    inset: 0 0 auto auto;
+  }
+
+  @media (min-width: 120rem) {
+    inset: 0 0 auto 32.7%;
+    width: 67.3%;
+  }
 }


Reviews:
user: login: arnest00
body: I have a couple of questions, but this looks great!! Could you also update the "A note on background colors and themes" section on the Pattern Library page to reflect the changes and adding a note on the shapes?
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-05-23T07:23:29Z
user: login: jawinn
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-23T14:00:19Z
user: login: jawinn
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-05-23T14:00:25Z
user: login: arnest00
body: Fantastic work on this!!
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-05-23T19:21:29Z

Review comments:
diff_hunk: @@ -64,6 +64,7 @@
   --spectrum-gray-900: rgb(19 19 19);
   --spectrum-gray-1000: rgb(0 0 0);
 
+  --spectrum-indigo-100: rgb(247 248 255);
path: styles/base.css
user: login: arnest00
body: Thanks for adding the missing values in!
created_at: 2025-05-23T07:03:11Z
author_association: COLLABORATOR
diff_hunk: @@ -893,30 +893,106 @@ main > .section > .grid-container {
 
 /* ** Page Themes ** */
 
-.theme-green {
-  --page-background: var(--gradient-green);
+/* Theme gradient backgrounds also include a color above the gradient to account for overscroll area underneath the sticky nav. */
+.theme {
+  --page-bg-overscroll-color: var(--color-background);
+  --page-background: var(--page-bg-main-gradient), linear-gradient(var(--page-bg-overscroll-color) 0%, var(--page-bg-overscroll-color) 100%);
+  --page-background-position: left top 64px, left top;
path: styles/styles.css
user: login: arnest00
body: This and the line below are to make up for the nav, right? Can we make these explicit with something like a nav height variable?
created_at: 2025-05-23T07:10:44Z
author_association: COLLABORATOR
diff_hunk: @@ -300,17 +300,36 @@ function createOptimizedPicture(
  * Set template (page structure) and theme (page styles).
  */
 function decorateTemplateAndTheme() {
path: scripts/aem.js
user: login: arnest00
body: What do you think about importing `decorateThemeBackgroundVisuals()` here as part of decorating the theme?
created_at: 2025-05-23T07:14:23Z
author_association: COLLABORATOR
diff_hunk: @@ -300,17 +300,36 @@ function createOptimizedPicture(
  * Set template (page structure) and theme (page styles).
  */
 function decorateTemplateAndTheme() {
path: scripts/aem.js
user: login: jawinn
body: I've refactored this to run the function here as you've suggested.

I had it there originally but had moved it when considering when it should load. But after reading more about the factors of LCP and this may be considered in it, and seeing `loadEager` is documented as `Loads everything needed to get to LCP`, where it runs `decorateTemplateAndTheme`, I do think it's probably best to move it back.
created_at: 2025-05-23T14:00:19Z
author_association: COLLABORATOR
diff_hunk: @@ -893,30 +893,106 @@ main > .section > .grid-container {
 
 /* ** Page Themes ** */
 
-.theme-green {
-  --page-background: var(--gradient-green);
+/* Theme gradient backgrounds also include a color above the gradient to account for overscroll area underneath the sticky nav. */
+.theme {
+  --page-bg-overscroll-color: var(--color-background);
+  --page-background: var(--page-bg-main-gradient), linear-gradient(var(--page-bg-overscroll-color) 0%, var(--page-bg-overscroll-color) 100%);
+  --page-background-position: left top 64px, left top;
path: styles/styles.css
user: login: jawinn
body: 👍 I've added a variable for that.
created_at: 2025-05-23T14:00:25Z
author_association: COLLABORATOR

PR comments:
user: login: aem-code-sync[bot]
created_at: 2025-05-22T19:10:59Z
body: <!-- aem-bot-dash -->
Hello, I'm the AEM Code Sync Bot and I will run some actions to deploy your branch and validate page speed.
In case there are problems, just click a checkbox below to rerun the respective action.

- [ ] <!-- action-psi --> Re-run PSI checks
- [ ] <!-- action-sync --> Re-sync branch

<details>
<summary>Commits</summary>
<!-- commit-history -->

* [1a9c0f6](https://github.com/adobe/adobe-design-website/commit/1a9c0f6898e03d3195fa87def8cf54c9b5db2ed0) :white_check_mark: (latest)
* [6533808](https://github.com/adobe/adobe-design-website/commit/65338085a0ef267bc865194140cb4abccec58cee) :white_check_mark:
* [9906084](https://github.com/adobe/adobe-design-website/commit/99060849cd5d8f82cd365458fa5d5e346cb9aac6) :white_check_mark:
* [abe71bb](https://github.com/adobe/adobe-design-website/commit/abe71bbed8d51f96ecd42193f17991c3ef0ef35a) :white_check_mark:
* [e50e181](https://github.com/adobe/adobe-design-website/commit/e50e181129926a66019f00ce90e162e880071bb7) :white_check_mark:
* [7185a4b](https://github.com/adobe/adobe-design-website/commit/7185a4b00c8c402269ddb1c73ea83e15fdd74a3a) :white_check_mark:
* [9240750](https://github.com/adobe/adobe-design-website/commit/92407501c38880747a79d15e2803c1a59a112fb0) :white_check_mark:
* [7b1a17c](https://github.com/adobe/adobe-design-website/commit/7b1a17ce777d3b346b056c8dc9dedd31fbeaa3a4) :white_check_mark:

<!-- commit-history-end -->
</details>
author_association: NONE
user: login: aem-code-sync[bot]
created_at: 2025-05-22T19:15:28Z
body: <!-- aem-bot-psi -->
| | Page | Scores | Audits | Google |
|-|------|--------|--------|--------|
| :iphone: | [/](https://feat-gradients-updates--adobe-design-website--adobe.aem.page/) | [![PERFORMANCE](https://img.shields.io/badge/PERFORMANCE-80-orange?style=for-the-badge "Performance")](https://googlechrome.github.io/lighthouse/scorecalc/#device=mobile&version=12.6.0&SI=4537.643428534273&FCP=3195.0608800000005&LCP=3883.2590200000004&TBT=0&CLS=0 "See Calculator") ![A11Y](https://img.shields.io/badge/A11Y-100-green?style=for-the-badge "Accessibility") ![SEO](https://img.shields.io/badge/SEO-61-orange?style=for-the-badge "SEO") ![BEST PRACTICES](https://img.shields.io/badge/BEST%20PRACTICES-96-green?style=for-the-badge "Best Practices") | ![SI](https://img.shields.io/badge/SI-4.5s-orange?style=for-the-badge "Speed Index") ![FCP](https://img.shields.io/badge/FCP-3.2s-red?style=for-the-badge "First Contentful Paint") ![LCP](https://img.shields.io/badge/LCP-3.9s-orange?style=for-the-badge "Largest Contentful Paint") ![TBT](https://img.shields.io/badge/TBT-0ms-green?style=for-the-badge "Total Blocking Time") ![CLS](https://img.shields.io/badge/CLS-0-green?style=for-the-badge "Cumulative Layout Shift") | [![PSI](https://www.gstatic.com/images/icons/material/product/2x/pagespeed_16dp.png)](https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Ffeat-gradients-updates--adobe-design-website--adobe.aem.page%2F "Run again in Google PSI") |
| :desktop_computer: | [/](https://feat-gradients-updates--adobe-design-website--adobe.aem.page/) | ![](https://img.shields.io/badge/0-orange?style=for-the-badge) | Lighthouse returned error: Something went wrong. | [![PSI](https://www.gstatic.com/images/icons/material/product/2x/pagespeed_16dp.png)](https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Ffeat-gradients-updates--adobe-design-website--adobe.aem.page%2F "Run again in Google PSI") |
| :iphone: | [/ideas/design-systems/](https://feat-gradients-updates--adobe-design-website--adobe.aem.page/ideas/design-systems/) | [![PERFORMANCE](https://img.shields.io/badge/PERFORMANCE-94-green?style=for-the-badge "Performance")](https://googlechrome.github.io/lighthouse/scorecalc/#device=mobile&version=12.6.0&SI=2283.5&FCP=2283.5&LCP=2553.5&TBT=0&CLS=0.02936792544364044 "See Calculator") ![A11Y](https://img.shields.io/badge/A11Y-100-green?style=for-the-badge "Accessibility") ![SEO](https://img.shields.io/badge/SEO-66-orange?style=for-the-badge "SEO") ![BEST PRACTICES](https://img.shields.io/badge/BEST%20PRACTICES-96-green?style=for-the-badge "Best Practices") | ![SI](https://img.shields.io/badge/SI-2.3s-green?style=for-the-badge "Speed Index") ![FCP](https://img.shields.io/badge/FCP-2.3s-orange?style=for-the-badge "First Contentful Paint") ![LCP](https://img.shields.io/badge/LCP-2.6s-orange?style=for-the-badge "Largest Contentful Paint") ![TBT](https://img.shields.io/badge/TBT-0ms-green?style=for-the-badge "Total Blocking Time") ![CLS](https://img.shields.io/badge/CLS-0.029-green?style=for-the-badge "Cumulative Layout Shift") | [![PSI](https://www.gstatic.com/images/icons/material/product/2x/pagespeed_16dp.png)](https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Ffeat-gradients-updates--adobe-design-website--adobe.aem.page%2Fideas%2Fdesign-systems%2F "Run again in Google PSI") |
| :desktop_computer: | [/ideas/design-systems/](https://feat-gradients-updates--adobe-design-website--adobe.aem.page/ideas/design-systems/) | [![PERFORMANCE](https://img.shields.io/badge/PERFORMANCE-100-green?style=for-the-badge "Performance")](https://googlechrome.github.io/lighthouse/scorecalc/#device=mobile&version=12.6.0&SI=634.9346049999999&FCP=634.9346049999999&LCP=634.934605&TBT=0&CLS=0.00523342758006039 "See Calculator") ![A11Y](https://img.shields.io/badge/A11Y-96-green?style=for-the-badge "Accessibility") ![SEO](https://img.shields.io/badge/SEO-66-orange?style=for-the-badge "SEO") ![BEST PRACTICES](https://img.shields.io/badge/BEST%20PRACTICES-96-green?style=for-the-badge "Best Practices") | ![SI](https://img.shields.io/badge/SI-0.6s-green?style=for-the-badge "Speed Index") ![FCP](https://img.shields.io/badge/FCP-0.6s-green?style=for-the-badge "First Contentful Paint") ![LCP](https://img.shields.io/badge/LCP-0.6s-green?style=for-the-badge "Largest Contentful Paint") ![TBT](https://img.shields.io/badge/TBT-0ms-green?style=for-the-badge "Total Blocking Time") ![CLS](https://img.shields.io/badge/CLS-0.005-green?style=for-the-badge "Cumulative Layout Shift") | [![PSI](https://www.gstatic.com/images/icons/material/product/2x/pagespeed_16dp.png)](https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Ffeat-gradients-updates--adobe-design-website--adobe.aem.page%2Fideas%2Fdesign-systems%2F "Run again in Google PSI") |

author_association: NONE