@for (additionalApiDoc of docItem.additionalApiDocs; track additionalApiDoc) {
       
     }
diff --git a/src/app/pages/component-viewer/component-overview.html b/src/app/pages/component-viewer/component-overview.html
index a962a3a6..aa152f39 100644
--- a/src/app/pages/component-viewer/component-overview.html
+++ b/src/app/pages/component-viewer/component-overview.html
@@ -2,7 +2,7 @@
   
diff --git a/src/app/pages/guide-viewer/guide-viewer.html b/src/app/pages/guide-viewer/guide-viewer.html
index 2e504ead..cb827c69 100644
--- a/src/app/pages/guide-viewer/guide-viewer.html
+++ b/src/app/pages/guide-viewer/guide-viewer.html
@@ -2,7 +2,7 @@
   
     
diff --git a/src/app/pages/system-variables/index.ts b/src/app/pages/system-variables/index.ts
new file mode 100644
index 00000000..3a226db5
--- /dev/null
+++ b/src/app/pages/system-variables/index.ts
@@ -0,0 +1 @@
+export * from './system-variables';
diff --git a/src/app/pages/system-variables/system-variables.html b/src/app/pages/system-variables/system-variables.html
new file mode 100644
index 00000000..a3174523
--- /dev/null
+++ b/src/app/pages/system-variables/system-variables.html
@@ -0,0 +1,242 @@
+
+  Angular Material components depend on system variables defined as CSS variables through the
+  material.theme
+  Sass mixin. This page provides guidance and documentation for using these variables to
+  customize components.
+
+
+
Colors
+
+
+  Material Design uses color to create accessible, personal color schemes
+  that communicate your product's hierarchy, state, and brand. See Material
+  Design's Color System
+  page to learn more about its use and purpose.
+
+
+  The following colors are the most often used in Angular Material components. Use these
+  colors and follow their uses to add theme colors to your application's custom components.
+
+
+
+  
+    
+      
Primary
+      
--mat-sys-primary
+    
+    
+      
+        The most common color used by Angular Material components to
+        participate in the application theme.
+      
+      
+        Examples include the background color
+        of filled buttons, the icon color of selected radio buttons, and the
+        outline color of form fields.
+      
+      
+        Use the color --mat-sys-on-primary for
+        icons, text, and other visual elements placed on a primary background. This
+        color is calculated to be optimal for accessibility and legibility.
+      
+    
+  
+
+  
+    
+      
Surface
+      
--mat-sys-surface
+    
+    
+      
+        A low-emphasis background color that provides a clear contrast for
+        both light and dark themes and their varied theme colors.
+      
+      
+        Examples include the background color of the application and most
+        components such as the dialog, card, table, and more.
+      
+      
+        Use the color --mat-sys-on-surface for
+        icons, text, and other visual elements placed on a surface background. This
+        color is calculated to be optimal for accessibility and legibility.
+      
+    
+  
+
+  
+    
+      
Error
+      
--mat-sys-error
+    
+    
+      
+        High-contrast color meant to alert the user to attract immediate attention.
+      
+      
+        Examples include the background color of the badge and the text color of invalid
+        form fields inputs.
+      
+      
+        Use the color --mat-sys-on-error for
+        icons, text, and other visual elements placed on an error background. This
+        color is calculated to be optimal for accessibility and legibility.
+      
+    
+  
+
+  
+    
+      
Outline
+      
--mat-sys-outline 
+    
+    
+      
+        Used for borders and dividers to help provide visual separation between
+        and around elements.
+      
+      
+        Examples include the color of the divider and border color of an outlined
+        form field.
+      
+      
+        Use the color --mat-sys-outline-variant for a less
+        prominent outline.
+      
+    
+  
+
+
+
+  Other available colors
+
+  
+    These colors are less commonly used in Angular Material components but
+    are available for adding color variety and creating additional emphasis
+    to components.
+  
+  
+    Colors may be paired with a --mat-sys-on- variable
+    that should be used for text and icons placed within a filled container.
+  
+
+  Alternative Theme Colors
+
+  
+
+  Surface Colors
+
+  
+    The following colors should be used for backgrounds and large,
+    low-emphasis areas of the screen.
+  
+
+  
+    Containers filled with a surface color should apply the
+    --mat-sys-on-surface color to text
+    and icons placed within.
+  
+
+  
+
+  Fixed Colors
+
+  
+    These colors are the same for both light and dark themes. They are unused
+    by any Angular Material components.
+  
+
+  
+
+
+
+
Typography
+
+
+  There are five categories of font types defined by Material Design: body, display, headline,
+  label, and title. Each category has three sizes: small, medium, and large.
+
+
+  Learn more about how these categories and their sizes should be used in your application by
+  visiting Material Design's
+  Typography documentation.
+
+
+
+@for (category of ['body', 'display', 'headline', 'label', 'title']; track $index) {
+  
+    
{{category}}
+    @for (size of ['small', 'medium', 'large']; track $index) {
+      
+        
+          
--mat-sys-{{category}}-{{size}}
+        
+        
Lorem ipsum dolor
+      
+    }
+  
+}
+
+
+  Each system variable can be applied to the "font" CSS style. Additionally, the parts of the variable definition
+  can be accessed individually by appending the keywords "font", "line-height", "size", "tracking", and "weight".
+
+
+  For example, the values for medium body text may be defined as follows:
+
+
+--mat-sys-body-medium: 400 0.875rem / 1.25rem Roboto, sans-serif;
+--mat-sys-body-medium-font: Roboto, sans-serif;
+--mat-sys-body-medium-line-height: 1.25rem;
+--mat-sys-body-medium-size: 0.875rem;
+--mat-sys-body-medium-tracking: 0.016rem;
+--mat-sys-body-medium-weight: 400;
+
+
+
Elevation
+
+
+  Material Design provides six levels of elevation that can be used to provide
+  a sense of depth and organization to an application's UI. Learn more at Material Design's
+  Elevation guide.
+
+
+
+  These levels are defined as CSS box-shadow values that can be styled to an element.
+
+
+@for (level of [0, 1, 2, 3, 4, 5]; track $index) {
+  
+    box-shadow: var(--mat-sys-level{{level}})
+  
+}
+
+
Overrides
+
+
+  The mat.theme-overrides mixin
+  can be included to emit different definitions for the system variables and
+  override the definitions emitted from mat.theme.
+
+
+
+  This example container has several system variables overridden by including the
+  following Sass code:
+
+  
+  @include mat.theme-overrides((
+    primary: #ebdcff,
+    on-primary: #230f46,
+    body-medium: 500 1.15rem/1.3rem Arial,
+    corner-large: 32px,
+    level3: 0 4px 6px 1px var(--mat-sys-surface-dim),
+  ));
+
diff --git a/src/app/pages/system-variables/system-variables.scss b/src/app/pages/system-variables/system-variables.scss
new file mode 100644
index 00000000..77a04674
--- /dev/null
+++ b/src/app/pages/system-variables/system-variables.scss
@@ -0,0 +1,196 @@
+@use '@angular/material' as mat;
+
+:host {
+  display: block;
+  max-width: 1000px;
+}
+
+h1 {
+  font: var(--mat-sys-title-large);
+  font-size: 28px;
+  padding-top: 32px;
+}
+
+h2 {
+  font: var(--mat-sys-title-large);
+}
+
+a {
+  color: var(--mat-sys-primary);
+}
+
+.demo-warn {
+  background: var(--mat-sys-error-container);
+  color: var(--mat-sys-on-error-container);
+  border: 1px solid var(--mat-sys-outline-variant);
+  border-radius: var(--mat-sys-corner-extra-small);
+  padding: 8px;
+}
+
+.demo-group {
+  display: grid;
+  grid-template-columns: 1fr 1fr;
+  grid-gap: 24px;
+  margin-top: 24px;
+}
+
+@media (max-width: 1000px) {
+  .demo-group {  grid-template-columns: auto;}
+}
+
+.demo-color-container {
+  border-radius: var(--mat-sys-corner-small);
+  display: inline-block;
+  font: var(--mat-sys-body-medium);
+  vertical-align: top;
+}
+
+.demo-heading {
+  color: var(--mat-sys-on-primary);
+  background: var(--mat-sys-primary);
+  border: 1px solid var(--mat-sys-outline);
+  border-top-right-radius: var(--mat-sys-corner-small);
+  border-top-left-radius: var(--mat-sys-corner-small);
+  border-bottom: none;
+  padding: 16px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+
+.demo-name {
+  font: var(--mat-sys-title-medium);
+}
+
+.demo-variable {
+  font: var(--mat-sys-title-small);
+  font-family: monospace;
+  text-align: right;
+}
+
+.demo-description {
+  border: 1px solid var(--mat-sys-outline);
+  border-bottom-right-radius: var(--mat-sys-corner-small);
+  border-bottom-left-radius: var(--mat-sys-corner-small);
+  padding: 0 16px;
+}
+
+.demo-code {
+  font-family: monospace;
+}
+
+.demo-surface-variable {
+  display: inline-block;
+  font-family: monospace;
+  background: var(--mat-sys-primary-container);
+  color: var(--mat-sys-on-primary-container);
+  padding: 2px 6px;
+  margin: 0 2px;
+  border-radius: 4px;
+}
+
+mat-expansion-panel {
+  margin-top: 24px;
+  overflow: visible;
+  @include mat.expansion-overrides((
+    'container-text-font': var(--mat-sys-body-medium-font),
+    'container-text-size': var(--mat-sys-body-medium-size),
+    'container-text-weight': var(--mat-sys-body-medium-weight),
+    'container-text-line-height': var(--mat-sys-body-medium-line-height),
+    'container-text-tracking': var(--mat-sys-body-medium-tracking),
+  ));
+}
+
+.demo-compact-color-container {
+  border-radius: var(--mat-sys-corner-small);
+  border: 1px solid var(--mat-sys-outline);
+  overflow: hidden; // Hide child heading background color
+  margin-top: 24px;
+
+  .demo-heading {
+    border: none;
+    border-radius: 0;
+
+    &:not(:nth-child(1)) {
+      border-top: 1px solid var(--mat-sys-outline);
+    }
+  }
+
+  .demo-variables {
+    text-align: end;
+  }
+}
+
+.demo-typography-group {
+  border: 1px solid var(--mat-sys-outline);
+  border-radius: var(--mat-sys-corner-small);
+  margin-top: 40px;
+  overflow: hidden;
+}
+
+.demo-typography-title {
+  text-transform: capitalize;
+  font: var(--mat-sys-title-medium);
+  padding: 16px;
+  border-bottom: 1px solid var(--mat-sys-outline);
+  background: var(--mat-sys-primary-container);
+  color: var(--mat-sys-on-primary-container);
+}
+
+.demo-typography-variable {
+  min-width: 240px;
+}
+
+.demo-typography-example {
+  padding: 16px;
+  display: flex;
+  align-items: baseline;
+  border-top: 1px solid var(--mat-sys-outline-variant);
+
+  &:nth-child(1) {
+    border: none;
+  }
+  .demo-surface-variable {
+    margin-right: 16px;
+  }
+}
+
+.demo-typography-text {
+  display: inline-block;
+}
+
+.demo-elevation {
+  height: 40px;
+  width: 300px;
+  margin: 32px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  background: var(--mat-sys-surface-container);
+  color: var(--mat-sys-on-surface);
+  border-radius: var(--mat-sys-corner-extra-small);
+}
+
+.demo-code-block {
+  background: var(--mat-sys-surface-container-low);
+  padding: 16px;
+  border-radius: var(--mat-sys-corner-small);
+  border: 1px solid var(--mat-sys-outline);
+}
+
+.demo-overrides {
+  background-color: var(--mat-sys-primary);
+  color: var(--mat-sys-on-primary);
+  font: var(--mat-sys-body-medium);
+  border-radius: var(--mat-sys-corner-large);
+  box-shadow: var(--mat-sys-level3);
+  padding: 16px;
+
+  @include mat.theme-overrides((
+    primary: #ebdcff,
+    on-primary: #230f46,
+    body-medium: 500 1.15rem/1.3rem Arial,
+    corner-large: 32px,
+    level3: 0 4px 6px 1px var(--mat-sys-surface-dim),
+  ));
+}
diff --git a/src/app/pages/system-variables/system-variables.ts b/src/app/pages/system-variables/system-variables.ts
new file mode 100644
index 00000000..5f2f66fa
--- /dev/null
+++ b/src/app/pages/system-variables/system-variables.ts
@@ -0,0 +1,158 @@
+import {ChangeDetectionStrategy, Component, input} from '@angular/core';
+import {MatCardModule} from '@angular/material/card';
+import {MatExpansionModule} from '@angular/material/expansion';
+import {MatIconModule} from '@angular/material/icon';
+
+interface Color {
+  name: string;
+  background: string;
+  text: string;
+  hideText?: boolean;
+}
+
+@Component({
+  selector: 'theme-demo-colors',
+  template: `
+    
+      @for (color of colors(); track $index) {
+      
+        
 {{color.name}} 
+        
+          
{{color.background}}
+          @if (!color.hideText) {
+      
{{color.text}}
+      }
+      
+    
+      }
+    
+  `,
+  styleUrl: 'system-variables.scss',
+  changeDetection: ChangeDetectionStrategy.OnPush,
+  standalone: true,
+})
+export class ThemeDemoColors {
+  colors = input
();
+}
+
+@Component({
+  selector: 'app-system-variables',
+  templateUrl: './system-variables.html',
+  styleUrls: ['./system-variables.scss'],
+  imports: [MatCardModule, MatExpansionModule, MatIconModule, ThemeDemoColors],
+  standalone: true,
+})
+export class SystemVariables {
+  alternativeThemeColors: Color[] = [
+    {
+      name: 'Primary Container',
+      background: '--mat-sys-primary-container',
+      text: '--mat-sys-on-primary-container',
+    },
+    {
+      name: 'Secondary',
+      background: '--mat-sys-secondary',
+      text: '--mat-sys-on-secondary',
+    },
+    {
+      name: 'Secondary Container',
+      background: '--mat-sys-secondary-container',
+      text: '--mat-sys-on-secondary-container',
+    },
+    {
+      name: 'Tertiary',
+      background: '--mat-sys-tertiary',
+      text: '--mat-sys-on-tertiary',
+    },
+    {
+      name: 'Tertiary Container',
+      background: '--mat-sys-tertiary-container',
+      text: '--mat-sys-on-tertiary-container',
+    },
+    {
+      name: 'Error Container',
+      background: '--mat-sys-error-container',
+      text: '--mat-sys-on-error-container',
+    },
+  ];
+
+  surfaceColors: Color[] = [
+    {
+      name: 'Surface Dim',
+      background: '--mat-sys-surface-dim',
+      text: '--mat-sys-on-surface',
+      hideText: true,
+    },
+    {
+      name: 'Surface Bright',
+      background: '--mat-sys-surface-bright',
+      text: '--mat-sys-on-surface',
+      hideText: true,
+    },
+    {
+      name: 'Surface Container Lowest',
+      background: '--mat-sys-surface-container-lowest',
+      text: '--mat-sys-on-surface',
+      hideText: true,
+    },
+    {
+      name: 'Surface Container Low',
+      background: '--mat-sys-surface-container-low',
+      text: '--mat-sys-on-surface',
+      hideText: true,
+    },
+    {
+      name: 'Surface Container',
+      background: '--mat-sys-surface-container',
+      text: '--mat-sys-on-surface',
+      hideText: true,
+    },
+    {
+      name: 'Surface Container High',
+      background: '--mat-sys-surface-container-high',
+      text: '--mat-sys-on-surface',
+      hideText: true,
+    },
+    {
+      name: 'Surface Container Highest',
+      background: '--mat-sys-surface-container-highest',
+      text: '--mat-sys-on-surface',
+      hideText: true,
+    },
+  ];
+
+  fixedColors: Color[] = [
+    {
+      name: 'Primary Fixed',
+      background: '--mat-sys-primary-fixed',
+      text: '--mat-sys-on-primary-fixed',
+    },
+    {
+      name: 'Primary Fixed Dim',
+      background: '--mat-sys-primary-fixed-dim',
+      text: '--mat-sys-on-primary-fixed',
+    },
+    {
+      name: 'Secondary Fixed',
+      background: '--mat-sys-secondary-fixed',
+      text: '--mat-sys-on-secondary-fixed',
+    },
+    {
+      name: 'Secondary Fixed Dim',
+      background: '--mat-sys-secondary-fixed-dim',
+      text: '--mat-sys-on-secondary-fixed',
+    },
+    {
+      name: 'Tertiary Fixed',
+      background: '--mat-sys-tertiary-fixed',
+      text: '--mat-sys-on-tertiary-fixed',
+    },
+    {
+      name: 'Tertiary Fixed Dim',
+      background: '--mat-sys-tertiary-fixed-dim',
+      text: '--mat-sys-on-tertiary-fixed',
+    },
+  ];
+}
diff --git a/src/app/shared/doc-viewer/doc-viewer.spec.ts b/src/app/shared/doc-viewer/doc-viewer.spec.ts
index 7ddf865e..c8b0c290 100644
--- a/src/app/shared/doc-viewer/doc-viewer.spec.ts
+++ b/src/app/shared/doc-viewer/doc-viewer.spec.ts
@@ -33,6 +33,15 @@ describe('DocViewer', () => {
     expect(docViewer.nativeElement.innerHTML).toBe('my docs page
');
   });
 
+  it('should load component', () => {
+    const fixture = TestBed.createComponent(DocViewerWithCompTestComponent);
+    fixture.detectChanges();
+
+    const docViewer = fixture.debugElement.query(By.directive(DocViewer));
+    expect(docViewer).not.toBeNull();
+    expect(docViewer.nativeElement.innerHTML).toContain(`TEST_COMPONENT_GUIDE`);
+  });
+
   it('should save textContent of the doc', () => {
     const fixture = TestBed.createComponent(DocViewerTestComponent);
     fixture.detectChanges();
@@ -145,7 +154,7 @@ describe('DocViewer', () => {
 
 @Component({
   selector: 'test',
-  template: ``,
+  template: ``,
   standalone: true,
   imports: [DocViewerModule, DocsAppTestingModule],
 })
@@ -170,3 +179,19 @@ const FAKE_DOCS: {[key: string]: string} = {
     '',
   /* eslint-enable @typescript-eslint/naming-convention */
 };
+
+@Component({
+  template: `TEST_COMPONENT_GUIDE`,
+  standalone: true,
+})
+class TestComponent {}
+
+@Component({
+  selector: 'test',
+  template: ``,
+  standalone: true,
+  imports: [DocViewerModule, DocsAppTestingModule, TestComponent],
+})
+class DocViewerWithCompTestComponent {
+  component = TestComponent;
+}
diff --git a/src/app/shared/doc-viewer/doc-viewer.ts b/src/app/shared/doc-viewer/doc-viewer.ts
index 8690fad8..a4e23d64 100644
--- a/src/app/shared/doc-viewer/doc-viewer.ts
+++ b/src/app/shared/doc-viewer/doc-viewer.ts
@@ -1,4 +1,10 @@
-import {ComponentPortal, DomPortalOutlet} from '@angular/cdk/portal';
+import {
+  ComponentType,
+  ComponentPortal,
+  DomPortalOutlet,
+  Portal,
+  PortalModule
+} from '@angular/cdk/portal';
 import {HttpClient, HttpErrorResponse} from '@angular/common/http';
 import {DomSanitizer} from '@angular/platform-browser';
 import {
@@ -40,20 +46,37 @@ class DocFetcher {
 
 @Component({
   selector: 'doc-viewer',
-  template: 'Loading document...',
+  template: `
+    @if (portal) {
+      
+    } @else {
+      Loading document...
+    }
+  `,
   standalone: true,
+  imports: [PortalModule]
 })
 export class DocViewer implements OnDestroy {
   private _portalHosts: DomPortalOutlet[] = [];
   private _documentFetchSubscription: Subscription | undefined;
+  protected portal: Portal | undefined;
 
   readonly name = input();
 
-  /** The URL of the document to display. */
+  /** The document to display, either as a URL to a markdown file or a component to create. */
   @Input()
-  set documentUrl(url: string | undefined) {
-    if (url !== undefined) {
-      this._fetchDocument(url);
+  set document(document: string | ComponentType | undefined) {
+    if (typeof document === 'string') {
+      this._fetchDocument(document);
+    } else if (document) {
+      this.portal = new ComponentPortal(document);
+
+      // Resolving and creating components dynamically in Angular happens synchronously, but since
+      // we want to emit the output if the components are actually rendered completely, we wait
+      // until the Angular zone becomes stable.
+      this._ngZone.onStable
+        .pipe(take(1))
+        .subscribe(() => this.contentRendered.next(this._elementRef.nativeElement));
     }
   }
 
diff --git a/src/app/shared/example-viewer/code-snippet.html b/src/app/shared/example-viewer/code-snippet.html
index 09b54722..61de6b25 100644
--- a/src/app/shared/example-viewer/code-snippet.html
+++ b/src/app/shared/example-viewer/code-snippet.html
@@ -1,3 +1,3 @@
 
diff --git a/src/app/shared/guide-items/guide-items.ts b/src/app/shared/guide-items/guide-items.ts
index 43563532..4790b901 100644
--- a/src/app/shared/guide-items/guide-items.ts
+++ b/src/app/shared/guide-items/guide-items.ts
@@ -1,13 +1,15 @@
 import {Injectable} from '@angular/core';
+import {SystemVariables} from '../../pages/system-variables';
+import {ComponentType} from '@angular/cdk/portal';
 
 export interface GuideItem {
   id: string;
   name: string;
-  document: string;
   overview: string;
+  document: string | ComponentType;
 }
 
-const GUIDES = [
+const GUIDES: GuideItem[] = [
   {
     id: 'getting-started',
     name: 'Getting started',
@@ -26,6 +28,12 @@ const GUIDES = [
     document: '/docs-content/guides/theming.html',
     overview: 'Customize your application with Angular Material\'s theming system.'
   },
+  {
+    id: 'system-variables',
+    name: 'System Variables',
+    document: SystemVariables,
+    overview: 'Understand the system variables available to use in your application.'
+  },
   {
     id: 'theming-your-components',
     name: 'Theming your own components',
diff --git a/src/app/shared/table-of-contents/table-of-contents.ts b/src/app/shared/table-of-contents/table-of-contents.ts
index 9bdc7814..5a9c4d60 100644
--- a/src/app/shared/table-of-contents/table-of-contents.ts
+++ b/src/app/shared/table-of-contents/table-of-contents.ts
@@ -130,7 +130,7 @@ export class TableOfContents implements OnInit, AfterViewInit, OnDestroy {
         id: header.id,
         active: false
       };
-    });
+    }).filter(link => link.id);
 
     this._linkSections[sectionIndex] = {name: sectionName, links};
     this._links.push(...links);
diff --git a/src/styles.scss b/src/styles.scss
index e4c7791e..6febe002 100644
--- a/src/styles.scss
+++ b/src/styles.scss
@@ -6,6 +6,9 @@
 @use './styles/general';
 
 html {
+  background-color: var(--mat-sys-surface);
+  color: var(--mat-sys-on-surface);
+
   @include mat.theme((
     color: (
       theme-type: light,